diff --git a/.gitignore b/.gitignore index 26ba80e1ad..9734ac35c3 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ Makefile makefile data *.kdev4 +CMakeLists.txt.user diff --git a/.gitmodules b/.gitmodules index d2a4cf0d31..8b13789179 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1 @@ -[submodule "extern/shiny"] - path = extern/shiny - url = git://github.com/scrawl/shiny.git + diff --git a/apps/esmtool/record.cpp b/apps/esmtool/record.cpp index 856700f5e3..b5f97e979e 100644 --- a/apps/esmtool/record.cpp +++ b/apps/esmtool/record.cpp @@ -15,7 +15,7 @@ void printAIPackage(ESM::AIPackage p) std::cout << " Time of Day: " << (int)p.mWander.mTimeOfDay << std::endl; if (p.mWander.mUnk != 1) std::cout << " Unknown: " << (int)p.mWander.mUnk << std::endl; - + std::cout << " Idle: "; for (int i = 0; i != 8; i++) std::cout << (int)p.mWander.mIdle[i] << " "; @@ -28,7 +28,7 @@ void printAIPackage(ESM::AIPackage p) std::cout << " Travel Unknown: " << (int)p.mTravel.mUnk << std::endl; } else if (p.mType == ESM::AI_Follow || p.mType == ESM::AI_Escort) - { + { std::cout << " Follow Coordinates: (" << p.mTarget.mX << "," << p.mTarget.mY << "," << p.mTarget.mZ << ")" << std::endl; std::cout << " Duration: " << p.mTarget.mDuration << std::endl; @@ -43,7 +43,7 @@ void printAIPackage(ESM::AIPackage p) else { std::cout << " BadPackage: " << boost::format("0x%08x") % p.mType << std::endl; } - + if (p.mCellName != "") std::cout << " Cell Name: " << p.mCellName << std::endl; } @@ -51,13 +51,13 @@ void printAIPackage(ESM::AIPackage p) std::string ruleString(ESM::DialInfo::SelectStruct ss) { std::string rule = ss.mSelectRule; - + if (rule.length() < 5) return "INVALID"; - + char type = rule[1]; char indicator = rule[2]; - + std::string type_str = "INVALID"; std::string func_str = str(boost::format("INVALID=%s") % rule.substr(1,3)); int func; @@ -71,14 +71,14 @@ std::string ruleString(ESM::DialInfo::SelectStruct ss) func_str = ruleFunction(func); break; case '2': - if (indicator == 's') type_str = "Global short"; - else if (indicator == 'l') type_str = "Global long"; - else if (indicator == 'f') type_str = "Global float"; + if (indicator == 's') type_str = "Global short"; + else if (indicator == 'l') type_str = "Global long"; + else if (indicator == 'f') type_str = "Global float"; break; case '3': - if (indicator == 's') type_str = "Local short"; - else if (indicator == 'l') type_str = "Local long"; - else if (indicator == 'f') type_str = "Local float"; + if (indicator == 's') type_str = "Local short"; + else if (indicator == 'l') type_str = "Local long"; + else if (indicator == 'f') type_str = "Local float"; break; case '4': if (indicator == 'J') type_str = "Journal"; break; case '5': if (indicator == 'I') type_str = "Item type"; break; @@ -90,15 +90,15 @@ std::string ruleString(ESM::DialInfo::SelectStruct ss) case 'B': if (indicator == 'L') type_str = "Not Cell"; break; case 'C': if (indicator == 's') type_str = "Not Local"; break; } - + // Append the variable name to the function string if any. if (type != '1') func_str = rule.substr(5); - + // In the previous switch, we assumed that the second char was X // for all types not qual to one. If this wasn't true, go back to // the error message. if (type != '1' && rule[3] != 'X') - func_str = str(boost::format("INVALID=%s") % rule.substr(1,3)); + func_str = str(boost::format("INVALID=%s") % rule.substr(1,3)); char oper = rule[4]; std::string oper_str = "??"; @@ -117,8 +117,8 @@ std::string ruleString(ESM::DialInfo::SelectStruct ss) value_str = str(boost::format("%d") % ss.mI); else if (ss.mType == ESM::VT_Float) value_str = str(boost::format("%f") % ss.mF); - - std::string result = str(boost::format("%-12s %-32s %2s %s") + + std::string result = str(boost::format("%-12s %-32s %2s %s") % type_str % func_str % oper_str % value_str); return result; } @@ -136,7 +136,7 @@ void printEffectList(ESM::EffectList effects) << " (" << (int)eit->mSkill << ")" << std::endl; if (eit->mAttribute != -1) std::cout << " Attribute: " << attributeLabel(eit->mAttribute) - << " (" << (int)eit->mAttribute << ")" << std::endl; + << " (" << (int)eit->mAttribute << ")" << std::endl; std::cout << " Range: " << rangeTypeLabel(eit->mRange) << " (" << eit->mRange << ")" << std::endl; // Area is always zero if range type is "Self" @@ -412,7 +412,7 @@ void Record::print() std::cout << " Weight: " << mData.mData.mWeight << std::endl; std::cout << " Value: " << mData.mData.mValue << std::endl; std::cout << " Health: " << mData.mData.mHealth << std::endl; - std::cout << " Armor: " << mData.mData.mArmor << std::endl; + std::cout << " Armor: " << mData.mData.mArmor << std::endl; std::cout << " Enchantment Points: " << mData.mData.mEnchant << std::endl; std::vector::iterator pit; for (pit = mData.mParts.mParts.begin(); pit != mData.mParts.mParts.end(); pit++) @@ -483,7 +483,7 @@ void Record::print() std::cout << " Description: " << mData.mDescription << std::endl; std::vector::iterator pit; for (pit = mData.mPowers.mList.begin(); pit != mData.mPowers.mList.end(); pit++) - std::cout << " Power: " << *pit << std::endl; + std::cout << " Power: " << *pit << std::endl; } template<> @@ -495,12 +495,12 @@ void Record::print() if (mData.mRegion != "") std::cout << " Region: " << mData.mRegion << std::endl; std::cout << " Flags: " << cellFlags(mData.mData.mFlags) << std::endl; - + std::cout << " Coordinates: " << " (" << mData.getGridX() << "," << mData.getGridY() << ")" << std::endl; - - if (mData.mData.mFlags & ESM::Cell::Interior && - !(mData.mData.mFlags & ESM::Cell::QuasiEx)) + + if (mData.mData.mFlags & ESM::Cell::Interior && + !(mData.mData.mFlags & ESM::Cell::QuasiEx)) { std::cout << " Ambient Light Color: " << mData.mAmbi.mAmbient << std::endl; std::cout << " Sunlight Color: " << mData.mAmbi.mSunlight << std::endl; @@ -508,7 +508,7 @@ void Record::print() std::cout << " Fog Density: " << mData.mAmbi.mFogDensity << std::endl; std::cout << " Water Level: " << mData.mWater << std::endl; } - else + else std::cout << " Map Color: " << boost::format("0x%08X") % mData.mMapColor << std::endl; std::cout << " Water Level Int: " << mData.mWaterInt << std::endl; std::cout << " NAM0: " << mData.mNAM0 << std::endl; @@ -530,7 +530,7 @@ void Record::print() << " (" << mData.mData.mSpecialization << ")" << std::endl; for (int i = 0; i != 5; i++) std::cout << " Major Skill: " << skillLabel(mData.mData.mSkills[i][0]) - << " (" << mData.mData.mSkills[i][0] << ")" << std::endl; + << " (" << mData.mData.mSkills[i][0] << ")" << std::endl; for (int i = 0; i != 5; i++) std::cout << " Minor Skill: " << skillLabel(mData.mData.mSkills[i][1]) << " (" << mData.mData.mSkills[i][1] << ")" << std::endl; @@ -573,7 +573,7 @@ void Record::print() std::cout << " Weight: " << mData.mWeight << std::endl; std::vector::iterator cit; for (cit = mData.mInventory.mList.begin(); cit != mData.mInventory.mList.end(); cit++) - std::cout << " Inventory: Count: " << boost::format("%4d") % cit->mCount + std::cout << " Inventory: Count: " << boost::format("%4d") % cit->mCount << " Item: " << cit->mItem.toString() << std::endl; } @@ -608,17 +608,17 @@ void Record::print() std::cout << " Combat: " << mData.mData.mCombat << std::endl; std::cout << " Magic: " << mData.mData.mMagic << std::endl; std::cout << " Stealth: " << mData.mData.mStealth << std::endl; - std::cout << " Attack1: " << mData.mData.mAttack[0] + std::cout << " Attack1: " << mData.mData.mAttack[0] << "-" << mData.mData.mAttack[1] << std::endl; - std::cout << " Attack2: " << mData.mData.mAttack[2] + std::cout << " Attack2: " << mData.mData.mAttack[2] << "-" << mData.mData.mAttack[3] << std::endl; - std::cout << " Attack3: " << mData.mData.mAttack[4] + std::cout << " Attack3: " << mData.mData.mAttack[4] << "-" << mData.mData.mAttack[5] << std::endl; std::cout << " Gold: " << mData.mData.mGold << std::endl; std::vector::iterator cit; for (cit = mData.mInventory.mList.begin(); cit != mData.mInventory.mList.end(); cit++) - std::cout << " Inventory: Count: " << boost::format("%4d") % cit->mCount + std::cout << " Inventory: Count: " << boost::format("%4d") % cit->mCount << " Item: " << cit->mItem.toString() << std::endl; std::vector::iterator sit; @@ -694,15 +694,15 @@ void Record::print() if (mData.mRanks[i] != "") { std::cout << " Rank: " << mData.mRanks[i] << std::endl; - std::cout << " Attribute1 Requirement: " + std::cout << " Attribute1 Requirement: " << mData.mData.mRankData[i].mAttribute1 << std::endl; - std::cout << " Attribute2 Requirement: " + std::cout << " Attribute2 Requirement: " << mData.mData.mRankData[i].mAttribute2 << std::endl; std::cout << " One Skill at Level: " << mData.mData.mRankData[i].mSkill1 << std::endl; - std::cout << " Two Skills at Level: " + std::cout << " Two Skills at Level: " << mData.mData.mRankData[i].mSkill2 << std::endl; - std::cout << " Faction Reaction: " + std::cout << " Faction Reaction: " << mData.mData.mRankData[i].mFactReaction << std::endl; } std::vector::iterator rit; @@ -849,7 +849,7 @@ void Record::print() std::cout << " Number of items: " << mData.mList.size() << std::endl; std::vector::iterator iit; for (iit = mData.mList.begin(); iit != mData.mList.end(); iit++) - std::cout << " Creature: Level: " << iit->mLevel + std::cout << " Creature: Level: " << iit->mLevel << " Creature: " << iit->mId << std::endl; } @@ -1012,11 +1012,11 @@ void Record::print() std::cout << " Disposition: " << (int)mData.mNpdt12.mDisposition << std::endl; std::cout << " Faction: " << (int)mData.mNpdt52.mFactionID << std::endl; std::cout << " Rank: " << (int)mData.mNpdt12.mRank << std::endl; - std::cout << " Unknown1: " + std::cout << " Unknown1: " << (unsigned int)((unsigned char)mData.mNpdt12.mUnknown1) << std::endl; - std::cout << " Unknown2: " + std::cout << " Unknown2: " << (unsigned int)((unsigned char)mData.mNpdt12.mUnknown2) << std::endl; - std::cout << " Unknown3: " + std::cout << " Unknown3: " << (unsigned int)((unsigned char)mData.mNpdt12.mUnknown3) << std::endl; std::cout << " Gold: " << (int)mData.mNpdt12.mGold << std::endl; } @@ -1038,9 +1038,9 @@ void Record::print() std::cout << " Skills:" << std::endl; for (int i = 0; i != 27; i++) - std::cout << " " << skillLabel(i) << ": " - << (int)((unsigned char)mData.mNpdt52.mSkills[i]) << std::endl; - + std::cout << " " << skillLabel(i) << ": " + << (int)((unsigned char)mData.mNpdt52.mSkills[i]) << std::endl; + std::cout << " Health: " << mData.mNpdt52.mHealth << std::endl; std::cout << " Magicka: " << mData.mNpdt52.mMana << std::endl; std::cout << " Fatigue: " << mData.mNpdt52.mFatigue << std::endl; @@ -1050,9 +1050,9 @@ void Record::print() std::vector::iterator cit; for (cit = mData.mInventory.mList.begin(); cit != mData.mInventory.mList.end(); cit++) - std::cout << " Inventory: Count: " << boost::format("%4d") % cit->mCount + std::cout << " Inventory: Count: " << boost::format("%4d") % cit->mCount << " Item: " << cit->mItem.toString() << std::endl; - + std::vector::iterator sit; for (sit = mData.mSpells.mList.begin(); sit != mData.mSpells.mList.end(); sit++) std::cout << " Spell: " << *sit << std::endl; @@ -1060,18 +1060,18 @@ void Record::print() std::vector::iterator dit; for (dit = mData.mTransport.begin(); dit != mData.mTransport.end(); dit++) { - std::cout << " Destination Position: " + std::cout << " Destination Position: " << boost::format("%12.3f") % dit->mPos.pos[0] << "," << boost::format("%12.3f") % dit->mPos.pos[1] << "," << boost::format("%12.3f") % dit->mPos.pos[2] << ")" << std::endl; - std::cout << " Destination Rotation: " + std::cout << " Destination Rotation: " << boost::format("%9.6f") % dit->mPos.rot[0] << "," << boost::format("%9.6f") % dit->mPos.rot[1] << "," - << boost::format("%9.6f") % dit->mPos.rot[2] << ")" << std::endl; + << boost::format("%9.6f") % dit->mPos.rot[2] << ")" << std::endl; if (dit->mCellName != "") std::cout << " Destination Cell: " << dit->mCellName << std::endl; } - + std::cout << " Artifical Intelligence: " << mData.mHasAI << std::endl; std::cout << " AI Hello:" << (int)mData.mAiData.mHello << std::endl; std::cout << " AI Fight:" << (int)mData.mAiData.mFight << std::endl; @@ -1104,7 +1104,7 @@ void Record::print() for (pit = mData.mPoints.begin(); pit != mData.mPoints.end(); pit++) { std::cout << " Point[" << i << "]:" << std::endl; - std::cout << " Coordinates: (" << pit->mX << "," + std::cout << " Coordinates: (" << pit->mX << "," << pit->mY << "," << pit->mZ << ")" << std::endl; std::cout << " Auto-Generated: " << (int)pit->mAutogenerated << std::endl; std::cout << " Connections: " << (int)pit->mConnectionNum << std::endl; @@ -1213,7 +1213,7 @@ void Record::print() template<> void Record::print() { - std::cout << " Name: " << mData.mData.mName.toString() << std::endl; + std::cout << " Name: " << mData.mId << std::endl; std::cout << " Num Shorts: " << mData.mData.mNumShorts << std::endl; std::cout << " Num Longs: " << mData.mData.mNumLongs << std::endl; @@ -1267,7 +1267,7 @@ void Record::print() std::cout << " Sound: " << mData.mSound << std::endl; std::cout << " Volume: " << (int)mData.mData.mVolume << std::endl; if (mData.mData.mMinRange != 0 && mData.mData.mMaxRange != 0) - std::cout << " Range: " << (int)mData.mData.mMinRange << " - " + std::cout << " Range: " << (int)mData.mData.mMinRange << " - " << (int)mData.mData.mMaxRange << std::endl; } @@ -1308,7 +1308,7 @@ void Record::print() if (mData.mScript != "") std::cout << " Script: " << mData.mScript << std::endl; if (mData.mEnchant != "") - std::cout << " Enchantment: " << mData.mEnchant << std::endl; + std::cout << " Enchantment: " << mData.mEnchant << std::endl; std::cout << " Type: " << weaponTypeLabel(mData.mData.mType) << " (" << mData.mData.mType << ")" << std::endl; std::cout << " Flags: " << weaponFlags(mData.mData.mFlags) << std::endl; @@ -1319,23 +1319,14 @@ void Record::print() std::cout << " Reach: " << mData.mData.mReach << std::endl; std::cout << " Enchantment Points: " << mData.mData.mEnchant << std::endl; if (mData.mData.mChop[0] != 0 && mData.mData.mChop[1] != 0) - std::cout << " Chop: " << (int)mData.mData.mChop[0] << "-" + std::cout << " Chop: " << (int)mData.mData.mChop[0] << "-" << (int)mData.mData.mChop[1] << std::endl; if (mData.mData.mSlash[0] != 0 && mData.mData.mSlash[1] != 0) std::cout << " Slash: " << (int)mData.mData.mSlash[0] << "-" << (int)mData.mData.mSlash[1] << std::endl; if (mData.mData.mThrust[0] != 0 && mData.mData.mThrust[1] != 0) - std::cout << " Thrust: " << (int)mData.mData.mThrust[0] << "-" + std::cout << " Thrust: " << (int)mData.mData.mThrust[0] << "-" << (int)mData.mData.mThrust[1] << std::endl; } -template<> -void Record::print() -{ - std::cout << " Refnum: " << mData.mRefnum << std::endl; - std::cout << " ID: '" << mData.mRefID << "'\n"; - std::cout << " Owner: '" << mData.mOwner << "'\n"; - std::cout << " INTV: " << mData.mIntv << " NAM9: " << mData.mIntv << std::endl; -} - } // end namespace diff --git a/apps/launcher/model/datafilesmodel.cpp b/apps/launcher/model/datafilesmodel.cpp index 47811dcaf0..d85a15e73a 100644 --- a/apps/launcher/model/datafilesmodel.cpp +++ b/apps/launcher/model/datafilesmodel.cpp @@ -2,6 +2,8 @@ #include #include +#include + #include #include "esm/esmfile.hpp" diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 62b7acb265..ffc770b35f 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -20,6 +20,7 @@ #include "mwscript/scriptmanagerimp.hpp" #include "mwscript/extensions.hpp" +#include "mwscript/interpretercontext.hpp" #include "mwsound/soundmanagerimp.hpp" @@ -368,7 +369,7 @@ void OMW::Engine::go() // Create dialog system mEnvironment.setJournal (new MWDialogue::Journal); - mEnvironment.setDialogueManager (new MWDialogue::DialogueManager (mExtensions)); + mEnvironment.setDialogueManager (new MWDialogue::DialogueManager (mExtensions, mVerboseScripts)); // Sets up the input system mEnvironment.setInputManager (new MWInput::InputManager (*mOgre, diff --git a/apps/openmw/mwbase/dialoguemanager.hpp b/apps/openmw/mwbase/dialoguemanager.hpp index ccffc6b214..a205e78db7 100644 --- a/apps/openmw/mwbase/dialoguemanager.hpp +++ b/apps/openmw/mwbase/dialoguemanager.hpp @@ -33,13 +33,17 @@ namespace MWBase virtual void goodbye() = 0; - ///get the faction of the actor you are talking with - virtual std::string getFaction() const = 0; + virtual MWWorld::Ptr getActor() const = 0; + ///< Return the actor the player is currently talking to. //calbacks for the GUI virtual void keywordSelected (const std::string& keyword) = 0; virtual void goodbyeSelected() = 0; virtual void questionAnswered (const std::string& answer) = 0; + + virtual void persuade (int type) = 0; + virtual int getTemporaryDispositionChange () const = 0; + virtual void applyTemporaryDispositionChange (int delta) = 0; }; } diff --git a/apps/openmw/mwbase/mechanicsmanager.hpp b/apps/openmw/mwbase/mechanicsmanager.hpp index 750fc2fff8..a1023c9866 100644 --- a/apps/openmw/mwbase/mechanicsmanager.hpp +++ b/apps/openmw/mwbase/mechanicsmanager.hpp @@ -62,7 +62,7 @@ namespace MWBase virtual void setPlayerName (const std::string& name) = 0; ///< Set player name. - virtual void setPlayerRace (const std::string& id, bool male) = 0; + virtual void setPlayerRace (const std::string& id, bool male, const std::string &head, const std::string &hair) = 0; ///< Set player race. virtual void setPlayerBirthsign (const std::string& id) = 0; @@ -76,9 +76,28 @@ namespace MWBase virtual void restoreDynamicStats() = 0; ///< If the player is sleeping, this should be called every hour. + + virtual int getBarterOffer(const MWWorld::Ptr& ptr,int basePrice, bool buying) = 0; + ///< This is used by every service to determine the price of objects given the trading skills of the player and NPC. + + virtual int getDerivedDisposition(const MWWorld::Ptr& ptr) = 0; + ///< Calculate the diposition of an NPC toward the player. virtual int countDeaths (const std::string& id) const = 0; ///< Return the number of deaths for actors with the given ID. + + enum PersuasionType + { + PT_Admire, + PT_Intimidate, + PT_Taunt, + PT_Bribe10, + PT_Bribe100, + PT_Bribe1000 + }; + virtual void getPersuasionDispositionChange (const MWWorld::Ptr& npc, PersuasionType type, + float currentTemporaryDispositionDelta, bool& success, float& tempChange, float& permChange) = 0; + ///< Perform a persuasion action on NPC }; } diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 06c3002c7e..f594f05665 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -29,11 +29,7 @@ namespace ESM struct Class; struct Potion; struct Spell; -} - -namespace ESMS -{ - struct ESMStore; + struct NPC; } namespace MWRender @@ -48,6 +44,7 @@ namespace MWWorld class LocalScripts; class Ptr; class TimeStamp; + class ESMStore; } namespace MWBase @@ -68,7 +65,8 @@ namespace MWBase Render_CollisionDebug, Render_Wireframe, Render_Pathgrid, - Render_Compositors + Render_Compositors, + Render_BoundingBoxes }; struct DoorMarker @@ -104,7 +102,7 @@ namespace MWBase virtual MWWorld::Player& getPlayer() = 0; - virtual const ESMS::ESMStore& getStore() const = 0; + virtual const MWWorld::ESMStore& getStore() const = 0; virtual std::vector& getEsmReader() = 0; @@ -234,24 +232,28 @@ namespace MWBase ///< Toggle a render mode. ///< \return Resulting mode - virtual std::pair createRecord (const ESM::Potion& record) + virtual const ESM::Potion *createRecord (const ESM::Potion& record) = 0; ///< Create a new recrod (of type potion) in the ESM store. - /// \return ID, pointer to created record + /// \return pointer to created record - virtual std::pair createRecord (const ESM::Spell& record) + virtual const ESM::Spell *createRecord (const ESM::Spell& record) = 0; ///< Create a new recrod (of type spell) in the ESM store. - /// \return ID, pointer to created record + /// \return pointer to created record - virtual std::pair createRecord (const ESM::Class& record) + virtual const ESM::Class *createRecord (const ESM::Class& record) = 0; ///< Create a new recrod (of type class) in the ESM store. - /// \return ID, pointer to created record + /// \return pointer to created record virtual const ESM::Cell *createRecord (const ESM::Cell& record) = 0; ///< Create a new recrod (of type cell) in the ESM store. - /// \return ID, pointer to created record + /// \return pointer to created record + + virtual const ESM::NPC *createRecord(const ESM::NPC &record) = 0; + ///< Create a new recrod (of type npc) in the ESM store. + /// \return pointer to created record virtual void playAnimationGroup (const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number = 1) = 0; diff --git a/apps/openmw/mwclass/activator.cpp b/apps/openmw/mwclass/activator.cpp index 1f5c7c2174..26d286aa14 100644 --- a/apps/openmw/mwclass/activator.cpp +++ b/apps/openmw/mwclass/activator.cpp @@ -38,9 +38,9 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); - assert(ref->base != NULL); + assert(ref->mBase != NULL); - const std::string &model = ref->base->mModel; + const std::string &model = ref->mBase->mModel; if (!model.empty()) { return "meshes\\" + model; } @@ -52,7 +52,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mName; + return ref->mBase->mName; } std::string Activator::getScript (const MWWorld::Ptr& ptr) const @@ -60,7 +60,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mScript; + return ref->mBase->mScript; } void Activator::registerSelf() @@ -75,7 +75,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return (ref->base->mName != ""); + return (ref->mBase->mName != ""); } MWGui::ToolTipInfo Activator::getToolTipInfo (const MWWorld::Ptr& ptr) const @@ -84,11 +84,11 @@ namespace MWClass ptr.get(); MWGui::ToolTipInfo info; - info.caption = ref->base->mName + MWGui::ToolTips::getCountString(ptr.getRefData().getCount()); + info.caption = ref->mBase->mName + MWGui::ToolTips::getCountString(ptr.getRefData().getCount()); std::string text; if (MWBase::Environment::get().getWindowManager()->getFullHelp()) - text += MWGui::ToolTips::getMiscString(ref->base->mScript, "Script"); + text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script"); info.text = text; return info; @@ -100,6 +100,6 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return MWWorld::Ptr(&cell.activators.insert(*ref), &cell); + return MWWorld::Ptr(&cell.mActivators.insert(*ref), &cell); } } diff --git a/apps/openmw/mwclass/apparatus.cpp b/apps/openmw/mwclass/apparatus.cpp index 7205ab3955..06467bb21a 100644 --- a/apps/openmw/mwclass/apparatus.cpp +++ b/apps/openmw/mwclass/apparatus.cpp @@ -41,9 +41,9 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); - assert(ref->base != NULL); + assert(ref->mBase != NULL); - const std::string &model = ref->base->mModel; + const std::string &model = ref->mBase->mModel; if (!model.empty()) { return "meshes\\" + model; } @@ -55,7 +55,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mName; + return ref->mBase->mName; } boost::shared_ptr Apparatus::activate (const MWWorld::Ptr& ptr, @@ -74,7 +74,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mScript; + return ref->mBase->mScript; } int Apparatus::getValue (const MWWorld::Ptr& ptr) const @@ -82,7 +82,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mData.mValue; + return ref->mBase->mData.mValue; } void Apparatus::registerSelf() @@ -107,7 +107,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mIcon; + return ref->mBase->mIcon; } bool Apparatus::hasToolTip (const MWWorld::Ptr& ptr) const @@ -115,7 +115,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return (ref->base->mName != ""); + return (ref->mBase->mName != ""); } MWGui::ToolTipInfo Apparatus::getToolTipInfo (const MWWorld::Ptr& ptr) const @@ -124,17 +124,17 @@ namespace MWClass ptr.get(); MWGui::ToolTipInfo info; - info.caption = ref->base->mName + MWGui::ToolTips::getCountString(ptr.getRefData().getCount()); - info.icon = ref->base->mIcon; + info.caption = ref->mBase->mName + MWGui::ToolTips::getCountString(ptr.getRefData().getCount()); + info.icon = ref->mBase->mIcon; std::string text; - text += "\n#{sQuality}: " + MWGui::ToolTips::toString(ref->base->mData.mQuality); - text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->base->mData.mWeight); - text += MWGui::ToolTips::getValueString(ref->base->mData.mValue, "#{sValue}"); + text += "\n#{sQuality}: " + MWGui::ToolTips::toString(ref->mBase->mData.mQuality); + text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight); + text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}"); if (MWBase::Environment::get().getWindowManager()->getFullHelp()) { - text += MWGui::ToolTips::getMiscString(ref->ref.mOwner, "Owner"); - text += MWGui::ToolTips::getMiscString(ref->base->mScript, "Script"); + text += MWGui::ToolTips::getMiscString(ref->mRef.mOwner, "Owner"); + text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script"); } info.text = text; @@ -153,6 +153,6 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return MWWorld::Ptr(&cell.appas.insert(*ref), &cell); + return MWWorld::Ptr(&cell.mAppas.insert(*ref), &cell); } } diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp index 906d880709..704173b1c4 100644 --- a/apps/openmw/mwclass/armor.cpp +++ b/apps/openmw/mwclass/armor.cpp @@ -44,9 +44,9 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); - assert(ref->base != NULL); + assert(ref->mBase != NULL); - const std::string &model = ref->base->mModel; + const std::string &model = ref->mBase->mModel; if (!model.empty()) { return "meshes\\" + model; } @@ -58,7 +58,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mName; + return ref->mBase->mName; } boost::shared_ptr Armor::activate (const MWWorld::Ptr& ptr, @@ -81,7 +81,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mData.mHealth; + return ref->mBase->mData.mHealth; } std::string Armor::getScript (const MWWorld::Ptr& ptr) const @@ -89,7 +89,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mScript; + return ref->mBase->mScript; } std::pair, bool> Armor::getEquipmentSlots (const MWWorld::Ptr& ptr) const @@ -117,7 +117,7 @@ namespace MWClass }; for (int i=0; ibase->mData.mType) + if (sMapping[i][0]==ref->mBase->mData.mType) { slots.push_back (int (sMapping[i][1])); break; @@ -133,7 +133,7 @@ namespace MWClass std::string typeGmst; - switch (ref->base->mData.mType) + switch (ref->mBase->mData.mType) { case ESM::Armor::Helmet: typeGmst = "iHelmWeight"; break; case ESM::Armor::Cuirass: typeGmst = "iCuirassWeight"; break; @@ -151,14 +151,17 @@ namespace MWClass if (typeGmst.empty()) return -1; - float iWeight = MWBase::Environment::get().getWorld()->getStore().gameSettings.find (typeGmst)->getInt(); + const MWWorld::Store &gmst = + MWBase::Environment::get().getWorld()->getStore().get(); - if (iWeight * MWBase::Environment::get().getWorld()->getStore().gameSettings.find ("fLightMaxMod")->getFloat()>= - ref->base->mData.mWeight) + float iWeight = gmst.find (typeGmst)->getInt(); + + if (iWeight * gmst.find ("fLightMaxMod")->getFloat()>= + ref->mBase->mData.mWeight) return ESM::Skill::LightArmor; - if (iWeight * MWBase::Environment::get().getWorld()->getStore().gameSettings.find ("fMedMaxMod")->getFloat()>= - ref->base->mData.mWeight) + if (iWeight * gmst.find ("fMedMaxMod")->getFloat()>= + ref->mBase->mData.mWeight) return ESM::Skill::MediumArmor; return ESM::Skill::HeavyArmor; @@ -169,7 +172,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mData.mValue; + return ref->mBase->mData.mValue; } void Armor::registerSelf() @@ -206,7 +209,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mIcon; + return ref->mBase->mIcon; } bool Armor::hasToolTip (const MWWorld::Ptr& ptr) const @@ -214,7 +217,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return (ref->base->mName != ""); + return (ref->mBase->mName != ""); } MWGui::ToolTipInfo Armor::getToolTipInfo (const MWWorld::Ptr& ptr) const @@ -223,8 +226,8 @@ namespace MWClass ptr.get(); MWGui::ToolTipInfo info; - info.caption = ref->base->mName + MWGui::ToolTips::getCountString(ptr.getRefData().getCount()); - info.icon = ref->base->mIcon; + info.caption = ref->mBase->mName + MWGui::ToolTips::getCountString(ptr.getRefData().getCount()); + info.icon = ref->mBase->mIcon; std::string text; @@ -238,20 +241,20 @@ namespace MWClass else typeText = "#{sHeavy}"; - text += "\n#{sArmorRating}: " + MWGui::ToolTips::toString(ref->base->mData.mArmor); + text += "\n#{sArmorRating}: " + MWGui::ToolTips::toString(ref->mBase->mData.mArmor); /// \todo store the current armor health somewhere - text += "\n#{sCondition}: " + MWGui::ToolTips::toString(ref->base->mData.mHealth); + text += "\n#{sCondition}: " + MWGui::ToolTips::toString(ref->mBase->mData.mHealth); - text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->base->mData.mWeight) + " (" + typeText + ")"; - text += MWGui::ToolTips::getValueString(ref->base->mData.mValue, "#{sValue}"); + text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight) + " (" + typeText + ")"; + text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}"); if (MWBase::Environment::get().getWindowManager()->getFullHelp()) { - text += MWGui::ToolTips::getMiscString(ref->ref.mOwner, "Owner"); - text += MWGui::ToolTips::getMiscString(ref->base->mScript, "Script"); + text += MWGui::ToolTips::getMiscString(ref->mRef.mOwner, "Owner"); + text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script"); } - info.enchant = ref->base->mEnchant; + info.enchant = ref->mBase->mEnchant; info.text = text; @@ -263,7 +266,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mEnchant; + return ref->mBase->mEnchant; } boost::shared_ptr Armor::use (const MWWorld::Ptr& ptr) const @@ -281,6 +284,6 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return MWWorld::Ptr(&cell.armors.insert(*ref), &cell); + return MWWorld::Ptr(&cell.mArmors.insert(*ref), &cell); } } diff --git a/apps/openmw/mwclass/book.cpp b/apps/openmw/mwclass/book.cpp index b994634d86..6c3b7b86c3 100644 --- a/apps/openmw/mwclass/book.cpp +++ b/apps/openmw/mwclass/book.cpp @@ -40,9 +40,9 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); - assert(ref->base != NULL); + assert(ref->mBase != NULL); - const std::string &model = ref->base->mModel; + const std::string &model = ref->mBase->mModel; if (!model.empty()) { return "meshes\\" + model; } @@ -54,7 +54,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mName; + return ref->mBase->mName; } boost::shared_ptr Book::activate (const MWWorld::Ptr& ptr, @@ -69,7 +69,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mScript; + return ref->mBase->mScript; } int Book::getValue (const MWWorld::Ptr& ptr) const @@ -77,7 +77,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mData.mValue; + return ref->mBase->mData.mValue; } void Book::registerSelf() @@ -102,7 +102,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mIcon; + return ref->mBase->mIcon; } bool Book::hasToolTip (const MWWorld::Ptr& ptr) const @@ -110,7 +110,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return (ref->base->mName != ""); + return (ref->mBase->mName != ""); } MWGui::ToolTipInfo Book::getToolTipInfo (const MWWorld::Ptr& ptr) const @@ -119,20 +119,20 @@ namespace MWClass ptr.get(); MWGui::ToolTipInfo info; - info.caption = ref->base->mName + MWGui::ToolTips::getCountString(ptr.getRefData().getCount()); - info.icon = ref->base->mIcon; + info.caption = ref->mBase->mName + MWGui::ToolTips::getCountString(ptr.getRefData().getCount()); + info.icon = ref->mBase->mIcon; std::string text; - text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->base->mData.mWeight); - text += MWGui::ToolTips::getValueString(ref->base->mData.mValue, "#{sValue}"); + text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight); + text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}"); if (MWBase::Environment::get().getWindowManager()->getFullHelp()) { - text += MWGui::ToolTips::getMiscString(ref->ref.mOwner, "Owner"); - text += MWGui::ToolTips::getMiscString(ref->base->mScript, "Script"); + text += MWGui::ToolTips::getMiscString(ref->mRef.mOwner, "Owner"); + text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script"); } - info.enchant = ref->base->mEnchant; + info.enchant = ref->mBase->mEnchant; info.text = text; @@ -144,7 +144,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mEnchant; + return ref->mBase->mEnchant; } boost::shared_ptr Book::use (const MWWorld::Ptr& ptr) const @@ -158,6 +158,6 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return MWWorld::Ptr(&cell.books.insert(*ref), &cell); + return MWWorld::Ptr(&cell.mBooks.insert(*ref), &cell); } } diff --git a/apps/openmw/mwclass/clothing.cpp b/apps/openmw/mwclass/clothing.cpp index c902e8e8f0..c411bb1930 100644 --- a/apps/openmw/mwclass/clothing.cpp +++ b/apps/openmw/mwclass/clothing.cpp @@ -42,9 +42,9 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); - assert(ref->base != NULL); + assert(ref->mBase != NULL); - const std::string &model = ref->base->mModel; + const std::string &model = ref->mBase->mModel; if (!model.empty()) { return "meshes\\" + model; } @@ -56,7 +56,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mName; + return ref->mBase->mName; } boost::shared_ptr Clothing::activate (const MWWorld::Ptr& ptr, @@ -74,7 +74,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mScript; + return ref->mBase->mScript; } std::pair, bool> Clothing::getEquipmentSlots (const MWWorld::Ptr& ptr) const @@ -84,7 +84,7 @@ namespace MWClass std::vector slots; - if (ref->base->mData.mType==ESM::Clothing::Ring) + if (ref->mBase->mData.mType==ESM::Clothing::Ring) { slots.push_back (int (MWWorld::InventoryStore::Slot_LeftRing)); slots.push_back (int (MWWorld::InventoryStore::Slot_RightRing)); @@ -107,7 +107,7 @@ namespace MWClass }; for (int i=0; ibase->mData.mType) + if (sMapping[i][0]==ref->mBase->mData.mType) { slots.push_back (int (sMapping[i][1])); break; @@ -122,7 +122,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - if (ref->base->mData.mType==ESM::Clothing::Shoes) + if (ref->mBase->mData.mType==ESM::Clothing::Shoes) return ESM::Skill::Unarmored; return -1; @@ -133,7 +133,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mData.mValue; + return ref->mBase->mData.mValue; } void Clothing::registerSelf() @@ -148,7 +148,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - if (ref->base->mData.mType == 8) + if (ref->mBase->mData.mType == 8) { return std::string("Item Ring Up"); } @@ -160,7 +160,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - if (ref->base->mData.mType == 8) + if (ref->mBase->mData.mType == 8) { return std::string("Item Ring Down"); } @@ -172,7 +172,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mIcon; + return ref->mBase->mIcon; } bool Clothing::hasToolTip (const MWWorld::Ptr& ptr) const @@ -180,7 +180,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return (ref->base->mName != ""); + return (ref->mBase->mName != ""); } MWGui::ToolTipInfo Clothing::getToolTipInfo (const MWWorld::Ptr& ptr) const @@ -189,20 +189,20 @@ namespace MWClass ptr.get(); MWGui::ToolTipInfo info; - info.caption = ref->base->mName + MWGui::ToolTips::getCountString(ptr.getRefData().getCount()); - info.icon = ref->base->mIcon; + info.caption = ref->mBase->mName + MWGui::ToolTips::getCountString(ptr.getRefData().getCount()); + info.icon = ref->mBase->mIcon; std::string text; - text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->base->mData.mWeight); - text += MWGui::ToolTips::getValueString(ref->base->mData.mValue, "#{sValue}"); + text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight); + text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}"); if (MWBase::Environment::get().getWindowManager()->getFullHelp()) { - text += MWGui::ToolTips::getMiscString(ref->ref.mOwner, "Owner"); - text += MWGui::ToolTips::getMiscString(ref->base->mScript, "Script"); + text += MWGui::ToolTips::getMiscString(ref->mRef.mOwner, "Owner"); + text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script"); } - info.enchant = ref->base->mEnchant; + info.enchant = ref->mBase->mEnchant; info.text = text; @@ -214,7 +214,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mEnchant; + return ref->mBase->mEnchant; } boost::shared_ptr Clothing::use (const MWWorld::Ptr& ptr) const @@ -232,6 +232,6 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return MWWorld::Ptr(&cell.clothes.insert(*ref), &cell); + return MWWorld::Ptr(&cell.mClothes.insert(*ref), &cell); } } diff --git a/apps/openmw/mwclass/container.cpp b/apps/openmw/mwclass/container.cpp index 0d75b653d7..76c1c40f15 100644 --- a/apps/openmw/mwclass/container.cpp +++ b/apps/openmw/mwclass/container.cpp @@ -8,7 +8,7 @@ #include "../mwbase/windowmanager.hpp" #include "../mwworld/ptr.hpp" -#include "../mwworld/nullaction.hpp" +#include "../mwworld/failedaction.hpp" #include "../mwworld/containerstore.hpp" #include "../mwworld/customdata.hpp" #include "../mwworld/cellstore.hpp" @@ -73,9 +73,9 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); - assert(ref->base != NULL); + assert(ref->mBase != NULL); - const std::string &model = ref->base->mModel; + const std::string &model = ref->mBase->mModel; if (!model.empty()) { return "meshes\\" + model; } @@ -129,7 +129,7 @@ namespace MWClass { // Trap activation goes here std::cout << "Activated trap: " << ptr.getCellRef().mTrap << std::endl; - boost::shared_ptr action(new MWWorld::NullAction); + boost::shared_ptr action(new MWWorld::FailedAction); action->setSound(trapActivationSound); ptr.getCellRef().mTrap = ""; return action; @@ -137,7 +137,7 @@ namespace MWClass } else { - boost::shared_ptr action(new MWWorld::NullAction); + boost::shared_ptr action(new MWWorld::FailedAction); action->setSound(lockedSound); return action; } @@ -148,7 +148,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mName; + return ref->mBase->mName; } MWWorld::ContainerStore& Container::getContainerStore (const MWWorld::Ptr& ptr) @@ -164,7 +164,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mScript; + return ref->mBase->mScript; } void Container::registerSelf() @@ -179,7 +179,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return (ref->base->mName != ""); + return (ref->mBase->mName != ""); } MWGui::ToolTipInfo Container::getToolTipInfo (const MWWorld::Ptr& ptr) const @@ -188,17 +188,17 @@ namespace MWClass ptr.get(); MWGui::ToolTipInfo info; - info.caption = ref->base->mName; + info.caption = ref->mBase->mName; std::string text; - if (ref->ref.mLockLevel > 0) - text += "\n#{sLockLevel}: " + MWGui::ToolTips::toString(ref->ref.mLockLevel); - if (ref->ref.mTrap != "") + if (ref->mRef.mLockLevel > 0) + text += "\n#{sLockLevel}: " + MWGui::ToolTips::toString(ref->mRef.mLockLevel); + if (ref->mRef.mTrap != "") text += "\n#{sTrapped}"; if (MWBase::Environment::get().getWindowManager()->getFullHelp()) { - text += MWGui::ToolTips::getMiscString(ref->ref.mOwner, "Owner"); - text += MWGui::ToolTips::getMiscString(ref->base->mScript, "Script"); + text += MWGui::ToolTips::getMiscString(ref->mRef.mOwner, "Owner"); + text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script"); } info.text = text; @@ -211,7 +211,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mWeight; + return ref->mBase->mWeight; } float Container::getEncumbrance (const MWWorld::Ptr& ptr) const @@ -238,6 +238,6 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return MWWorld::Ptr(&cell.containers.insert(*ref), &cell); + return MWWorld::Ptr(&cell.mContainers.insert(*ref), &cell); } } diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index fce9511165..edf5dd25d6 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -48,28 +48,28 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); // creature stats - data->mCreatureStats.getAttribute(0).set (ref->base->mData.mStrength); - data->mCreatureStats.getAttribute(1).set (ref->base->mData.mIntelligence); - data->mCreatureStats.getAttribute(2).set (ref->base->mData.mWillpower); - data->mCreatureStats.getAttribute(3).set (ref->base->mData.mAgility); - data->mCreatureStats.getAttribute(4).set (ref->base->mData.mSpeed); - data->mCreatureStats.getAttribute(5).set (ref->base->mData.mEndurance); - data->mCreatureStats.getAttribute(6).set (ref->base->mData.mPersonality); - data->mCreatureStats.getAttribute(7).set (ref->base->mData.mLuck); - data->mCreatureStats.setHealth (ref->base->mData.mHealth); - data->mCreatureStats.setMagicka (ref->base->mData.mMana); - data->mCreatureStats.setFatigue (ref->base->mData.mFatigue); + data->mCreatureStats.getAttribute(0).set (ref->mBase->mData.mStrength); + data->mCreatureStats.getAttribute(1).set (ref->mBase->mData.mIntelligence); + data->mCreatureStats.getAttribute(2).set (ref->mBase->mData.mWillpower); + data->mCreatureStats.getAttribute(3).set (ref->mBase->mData.mAgility); + data->mCreatureStats.getAttribute(4).set (ref->mBase->mData.mSpeed); + data->mCreatureStats.getAttribute(5).set (ref->mBase->mData.mEndurance); + data->mCreatureStats.getAttribute(6).set (ref->mBase->mData.mPersonality); + data->mCreatureStats.getAttribute(7).set (ref->mBase->mData.mLuck); + data->mCreatureStats.setHealth (ref->mBase->mData.mHealth); + data->mCreatureStats.setMagicka (ref->mBase->mData.mMana); + data->mCreatureStats.setFatigue (ref->mBase->mData.mFatigue); - data->mCreatureStats.setLevel(ref->base->mData.mLevel); + data->mCreatureStats.setLevel(ref->mBase->mData.mLevel); - data->mCreatureStats.setHello(ref->base->mAiData.mHello); - data->mCreatureStats.setFight(ref->base->mAiData.mFight); - data->mCreatureStats.setFlee(ref->base->mAiData.mFlee); - data->mCreatureStats.setAlarm(ref->base->mAiData.mAlarm); + data->mCreatureStats.setAiSetting (0, ref->mBase->mAiData.mHello); + data->mCreatureStats.setAiSetting (1, ref->mBase->mAiData.mFight); + data->mCreatureStats.setAiSetting (2, ref->mBase->mAiData.mFlee); + data->mCreatureStats.setAiSetting (3, ref->mBase->mAiData.mAlarm); // spells - for (std::vector::const_iterator iter (ref->base->mSpells.mList.begin()); - iter!=ref->base->mSpells.mList.end(); ++iter) + for (std::vector::const_iterator iter (ref->mBase->mSpells.mList.begin()); + iter!=ref->mBase->mSpells.mList.end(); ++iter) data->mCreatureStats.getSpells().add (*iter); // store @@ -82,7 +82,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mId; + return ref->mBase->mId; } void Creature::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const @@ -103,9 +103,9 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); - assert (ref->base != NULL); + assert (ref->mBase != NULL); - const std::string &model = ref->base->mModel; + const std::string &model = ref->mBase->mModel; if (!model.empty()) { return "meshes\\" + model; } @@ -117,7 +117,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mName; + return ref->mBase->mName; } MWMechanics::CreatureStats& Creature::getCreatureStats (const MWWorld::Ptr& ptr) const @@ -149,7 +149,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mScript; + return ref->mBase->mScript; } bool Creature::isEssential (const MWWorld::Ptr& ptr) const @@ -157,7 +157,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mFlags & ESM::Creature::Essential; + return ref->mBase->mFlags & ESM::Creature::Essential; } void Creature::registerSelf() @@ -180,11 +180,11 @@ namespace MWClass ptr.get(); MWGui::ToolTipInfo info; - info.caption = ref->base->mName; + info.caption = ref->mBase->mName; std::string text; if (MWBase::Environment::get().getWindowManager()->getFullHelp()) - text += MWGui::ToolTips::getMiscString(ref->base->mScript, "Script"); + text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script"); info.text = text; return info; @@ -218,6 +218,6 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return MWWorld::Ptr(&cell.creatures.insert(*ref), &cell); + return MWWorld::Ptr(&cell.mCreatures.insert(*ref), &cell); } } diff --git a/apps/openmw/mwclass/door.cpp b/apps/openmw/mwclass/door.cpp index b03db4ec7d..843d1af4c9 100644 --- a/apps/openmw/mwclass/door.cpp +++ b/apps/openmw/mwclass/door.cpp @@ -10,6 +10,7 @@ #include "../mwworld/player.hpp" #include "../mwworld/ptr.hpp" #include "../mwworld/nullaction.hpp" +#include "../mwworld/failedaction.hpp" #include "../mwworld/actionteleport.hpp" #include "../mwworld/cellstore.hpp" #include "../mwworld/physicssystem.hpp" @@ -43,9 +44,9 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); - assert(ref->base != NULL); + assert(ref->mBase != NULL); - const std::string &model = ref->base->mModel; + const std::string &model = ref->mBase->mModel; if (!model.empty()) { return "meshes\\" + model; } @@ -57,10 +58,10 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - if (ref->ref.mTeleport && !ref->ref.mDestCell.empty()) // TODO doors that lead to exteriors - return ref->ref.mDestCell; + if (ref->mRef.mTeleport && !ref->mRef.mDestCell.empty()) // TODO doors that lead to exteriors + return ref->mRef.mDestCell; - return ref->base->mName; + return ref->mBase->mName; } boost::shared_ptr Door::activate (const MWWorld::Ptr& ptr, @@ -69,8 +70,8 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - const std::string &openSound = ref->base->mOpenSound; - //const std::string &closeSound = ref->base->closeSound; + const std::string &openSound = ref->mBase->mOpenSound; + //const std::string &closeSound = ref->mBase->closeSound; const std::string lockedSound = "LockedDoor"; const std::string trapActivationSound = "Disarm Trap Fail"; @@ -110,21 +111,20 @@ namespace MWClass // Trap activation std::cout << "Activated trap: " << ptr.getCellRef().mTrap << std::endl; - boost::shared_ptr action(new MWWorld::NullAction); - + boost::shared_ptr action(new MWWorld::FailedAction); action->setSound(trapActivationSound); ptr.getCellRef().mTrap = ""; return action; } - if (ref->ref.mTeleport) + if (ref->mRef.mTeleport) { // teleport door /// \todo remove this if clause once ActionTeleport can also support other actors if (MWBase::Environment::get().getWorld()->getPlayer().getPlayer()==actor) { - boost::shared_ptr action(new MWWorld::ActionTeleport (ref->ref.mDestCell, ref->ref.mDoorDest)); + boost::shared_ptr action(new MWWorld::ActionTeleport (ref->mRef.mDestCell, ref->mRef.mDoorDest)); action->setSound(openSound); @@ -133,7 +133,7 @@ namespace MWClass else { // another NPC or a creature is using the door - return boost::shared_ptr (new MWWorld::NullAction); + return boost::shared_ptr (new MWWorld::FailedAction); } } else @@ -152,7 +152,7 @@ namespace MWClass else { // locked, and we can't open. - boost::shared_ptr action(new MWWorld::NullAction); + boost::shared_ptr action(new MWWorld::FailedAction); action->setSound(lockedSound); return action; } @@ -176,7 +176,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mScript; + return ref->mBase->mScript; } void Door::registerSelf() @@ -191,7 +191,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return (ref->base->mName != ""); + return (ref->mBase->mName != ""); } MWGui::ToolTipInfo Door::getToolTipInfo (const MWWorld::Ptr& ptr) const @@ -200,31 +200,32 @@ namespace MWClass ptr.get(); MWGui::ToolTipInfo info; - info.caption = ref->base->mName; + info.caption = ref->mBase->mName; std::string text; - const ESMS::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); + const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); - if (ref->ref.mTeleport) + if (ref->mRef.mTeleport) { std::string dest; - if (ref->ref.mDestCell != "") + if (ref->mRef.mDestCell != "") { // door leads to an interior, use interior name as tooltip - dest = ref->ref.mDestCell; + dest = ref->mRef.mDestCell; } else { // door leads to exterior, use cell name (if any), otherwise translated region name int x,y; - MWBase::Environment::get().getWorld()->positionToIndex (ref->ref.mDoorDest.pos[0], ref->ref.mDoorDest.pos[1], x, y); - const ESM::Cell* cell = store.cells.findExt(x,y); + MWBase::Environment::get().getWorld()->positionToIndex (ref->mRef.mDoorDest.pos[0], ref->mRef.mDoorDest.pos[1], x, y); + const ESM::Cell* cell = store.get().find(x,y); if (cell->mName != "") dest = cell->mName; else { - const ESM::Region* region = store.regions.search(cell->mRegion); + const ESM::Region* region = + store.get().find(cell->mRegion); dest = region->mName; } } @@ -232,13 +233,13 @@ namespace MWClass text += "\n"+dest; } - if (ref->ref.mLockLevel > 0) - text += "\n#{sLockLevel}: " + MWGui::ToolTips::toString(ref->ref.mLockLevel); - if (ref->ref.mTrap != "") + if (ref->mRef.mLockLevel > 0) + text += "\n#{sLockLevel}: " + MWGui::ToolTips::toString(ref->mRef.mLockLevel); + if (ref->mRef.mTrap != "") text += "\n#{sTrapped}"; if (MWBase::Environment::get().getWindowManager()->getFullHelp()) - text += MWGui::ToolTips::getMiscString(ref->base->mScript, "Script"); + text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script"); info.text = text; @@ -251,6 +252,6 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return MWWorld::Ptr(&cell.doors.insert(*ref), &cell); + return MWWorld::Ptr(&cell.mDoors.insert(*ref), &cell); } } diff --git a/apps/openmw/mwclass/ingredient.cpp b/apps/openmw/mwclass/ingredient.cpp index e322fa3b8f..1be8d66b32 100644 --- a/apps/openmw/mwclass/ingredient.cpp +++ b/apps/openmw/mwclass/ingredient.cpp @@ -25,7 +25,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mId; + return ref->mBase->mId; } void Ingredient::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const @@ -49,9 +49,9 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); - assert(ref->base != NULL); + assert(ref->mBase != NULL); - const std::string &model = ref->base->mModel; + const std::string &model = ref->mBase->mModel; if (!model.empty()) { return "meshes\\" + model; } @@ -63,7 +63,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mName; + return ref->mBase->mName; } boost::shared_ptr Ingredient::activate (const MWWorld::Ptr& ptr, @@ -81,7 +81,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mScript; + return ref->mBase->mScript; } int Ingredient::getValue (const MWWorld::Ptr& ptr) const @@ -89,7 +89,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mData.mValue; + return ref->mBase->mData.mValue; } @@ -124,7 +124,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mIcon; + return ref->mBase->mIcon; } bool Ingredient::hasToolTip (const MWWorld::Ptr& ptr) const @@ -132,7 +132,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return (ref->base->mName != ""); + return (ref->mBase->mName != ""); } MWGui::ToolTipInfo Ingredient::getToolTipInfo (const MWWorld::Ptr& ptr) const @@ -141,28 +141,28 @@ namespace MWClass ptr.get(); MWGui::ToolTipInfo info; - info.caption = ref->base->mName + MWGui::ToolTips::getCountString(ptr.getRefData().getCount()); - info.icon = ref->base->mIcon; + info.caption = ref->mBase->mName + MWGui::ToolTips::getCountString(ptr.getRefData().getCount()); + info.icon = ref->mBase->mIcon; std::string text; - text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->base->mData.mWeight); - text += MWGui::ToolTips::getValueString(ref->base->mData.mValue, "#{sValue}"); + text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight); + text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}"); if (MWBase::Environment::get().getWindowManager()->getFullHelp()) { - text += MWGui::ToolTips::getMiscString(ref->ref.mOwner, "Owner"); - text += MWGui::ToolTips::getMiscString(ref->base->mScript, "Script"); + text += MWGui::ToolTips::getMiscString(ref->mRef.mOwner, "Owner"); + text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script"); } MWGui::Widgets::SpellEffectList list; for (int i=0; i<4; ++i) { - if (ref->base->mData.mEffectID[i] < 0) + if (ref->mBase->mData.mEffectID[i] < 0) continue; MWGui::Widgets::SpellEffectParams params; - params.mEffectID = ref->base->mData.mEffectID[i]; - params.mAttribute = ref->base->mData.mAttributes[i]; - params.mSkill = ref->base->mData.mSkills[i]; + params.mEffectID = ref->mBase->mData.mEffectID[i]; + params.mAttribute = ref->mBase->mData.mAttributes[i]; + params.mSkill = ref->mBase->mData.mSkills[i]; list.push_back(params); } info.effects = list; @@ -178,6 +178,6 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return MWWorld::Ptr(&cell.ingreds.insert(*ref), &cell); + return MWWorld::Ptr(&cell.mIngreds.insert(*ref), &cell); } } diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index fc545abaf8..b94b0d395b 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -12,6 +12,7 @@ #include "../mwworld/actiontake.hpp" #include "../mwworld/actionequip.hpp" #include "../mwworld/nullaction.hpp" +#include "../mwworld/failedaction.hpp" #include "../mwworld/inventorystore.hpp" #include "../mwworld/cellstore.hpp" #include "../mwworld/physicssystem.hpp" @@ -27,9 +28,9 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); - assert (ref->base != NULL); + assert (ref->mBase != NULL); - const std::string &model = ref->base->mModel; + const std::string &model = ref->mBase->mModel; MWRender::Objects& objects = renderingInterface.getObjects(); objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false); @@ -37,11 +38,11 @@ namespace MWClass if (!model.empty()) objects.insertMesh(ptr, "meshes\\" + model); - const int color = ref->base->mData.mColor; + const int color = ref->mBase->mData.mColor; const float r = ((color >> 0) & 0xFF) / 255.0f; const float g = ((color >> 8) & 0xFF) / 255.0f; const float b = ((color >> 16) & 0xFF) / 255.0f; - const float radius = float (ref->base->mData.mRadius); + const float radius = float (ref->mBase->mData.mRadius); objects.insertLight (ptr, r, g, b, radius); } @@ -49,24 +50,24 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); - assert (ref->base != NULL); + assert (ref->mBase != NULL); - const std::string &model = ref->base->mModel; + const std::string &model = ref->mBase->mModel; if(!model.empty()) physics.addObject(ptr); - - if (!ref->base->mSound.empty()) - MWBase::Environment::get().getSoundManager()->playSound3D(ptr, ref->base->mSound, 1.0, 1.0, MWBase::SoundManager::Play_Loop); + + if (!ref->mBase->mSound.empty()) + MWBase::Environment::get().getSoundManager()->playSound3D(ptr, ref->mBase->mSound, 1.0, 1.0, MWBase::SoundManager::Play_Loop); } std::string Light::getModel(const MWWorld::Ptr &ptr) const { MWWorld::LiveCellRef *ref = ptr.get(); - assert (ref->base != NULL); + assert (ref->mBase != NULL); - const std::string &model = ref->base->mModel; + const std::string &model = ref->mBase->mModel; if (!model.empty()) { return "meshes\\" + model; } @@ -78,10 +79,10 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - if (ref->base->mModel.empty()) + if (ref->mBase->mModel.empty()) return ""; - return ref->base->mName; + return ref->mBase->mName; } boost::shared_ptr Light::activate (const MWWorld::Ptr& ptr, @@ -90,8 +91,8 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - if (!(ref->base->mData.mFlags & ESM::Light::Carry)) - return boost::shared_ptr (new MWWorld::NullAction); + if (!(ref->mBase->mData.mFlags & ESM::Light::Carry)) + return boost::shared_ptr (new MWWorld::FailedAction); boost::shared_ptr action(new MWWorld::ActionTake (ptr)); @@ -105,7 +106,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mScript; + return ref->mBase->mScript; } std::pair, bool> Light::getEquipmentSlots (const MWWorld::Ptr& ptr) const @@ -115,7 +116,7 @@ namespace MWClass std::vector slots; - if (ref->base->mData.mFlags & ESM::Light::Carry) + if (ref->mBase->mData.mFlags & ESM::Light::Carry) slots.push_back (int (MWWorld::InventoryStore::Slot_CarriedLeft)); return std::make_pair (slots, false); @@ -126,7 +127,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mData.mValue; + return ref->mBase->mData.mValue; } void Light::registerSelf() @@ -152,7 +153,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mIcon; + return ref->mBase->mIcon; } bool Light::hasToolTip (const MWWorld::Ptr& ptr) const @@ -160,7 +161,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return (ref->base->mName != ""); + return (ref->mBase->mName != ""); } MWGui::ToolTipInfo Light::getToolTipInfo (const MWWorld::Ptr& ptr) const @@ -169,17 +170,17 @@ namespace MWClass ptr.get(); MWGui::ToolTipInfo info; - info.caption = ref->base->mName + MWGui::ToolTips::getCountString(ptr.getRefData().getCount()); - info.icon = ref->base->mIcon; + info.caption = ref->mBase->mName + MWGui::ToolTips::getCountString(ptr.getRefData().getCount()); + info.icon = ref->mBase->mIcon; std::string text; - text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->base->mData.mWeight); - text += MWGui::ToolTips::getValueString(ref->base->mData.mValue, "#{sValue}"); + text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight); + text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}"); if (MWBase::Environment::get().getWindowManager()->getFullHelp()) { - text += MWGui::ToolTips::getMiscString(ref->ref.mOwner, "Owner"); - text += MWGui::ToolTips::getMiscString(ref->base->mScript, "Script"); + text += MWGui::ToolTips::getMiscString(ref->mRef.mOwner, "Owner"); + text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script"); } info.text = text; @@ -202,6 +203,6 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return MWWorld::Ptr(&cell.lights.insert(*ref), &cell); + return MWWorld::Ptr(&cell.mLights.insert(*ref), &cell); } } diff --git a/apps/openmw/mwclass/lockpick.cpp b/apps/openmw/mwclass/lockpick.cpp index 71e2dbb12f..a667fefb2a 100644 --- a/apps/openmw/mwclass/lockpick.cpp +++ b/apps/openmw/mwclass/lockpick.cpp @@ -42,9 +42,9 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); - assert(ref->base != NULL); + assert(ref->mBase != NULL); - const std::string &model = ref->base->mModel; + const std::string &model = ref->mBase->mModel; if (!model.empty()) { return "meshes\\" + model; } @@ -56,7 +56,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mName; + return ref->mBase->mName; } boost::shared_ptr Lockpick::activate (const MWWorld::Ptr& ptr, @@ -74,7 +74,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mScript; + return ref->mBase->mScript; } std::pair, bool> Lockpick::getEquipmentSlots (const MWWorld::Ptr& ptr) const @@ -91,7 +91,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mData.mValue; + return ref->mBase->mData.mValue; } void Lockpick::registerSelf() @@ -116,7 +116,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mIcon; + return ref->mBase->mIcon; } bool Lockpick::hasToolTip (const MWWorld::Ptr& ptr) const @@ -124,7 +124,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return (ref->base->mName != ""); + return (ref->mBase->mName != ""); } MWGui::ToolTipInfo Lockpick::getToolTipInfo (const MWWorld::Ptr& ptr) const @@ -133,21 +133,21 @@ namespace MWClass ptr.get(); MWGui::ToolTipInfo info; - info.caption = ref->base->mName + MWGui::ToolTips::getCountString(ptr.getRefData().getCount()); - info.icon = ref->base->mIcon; + info.caption = ref->mBase->mName + MWGui::ToolTips::getCountString(ptr.getRefData().getCount()); + info.icon = ref->mBase->mIcon; std::string text; /// \todo store remaining uses somewhere - text += "\n#{sUses}: " + MWGui::ToolTips::toString(ref->base->mData.mUses); - text += "\n#{sQuality}: " + MWGui::ToolTips::toString(ref->base->mData.mQuality); - text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->base->mData.mWeight); - text += MWGui::ToolTips::getValueString(ref->base->mData.mValue, "#{sValue}"); + text += "\n#{sUses}: " + MWGui::ToolTips::toString(ref->mBase->mData.mUses); + text += "\n#{sQuality}: " + MWGui::ToolTips::toString(ref->mBase->mData.mQuality); + text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight); + text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}"); if (MWBase::Environment::get().getWindowManager()->getFullHelp()) { - text += MWGui::ToolTips::getMiscString(ref->ref.mOwner, "Owner"); - text += MWGui::ToolTips::getMiscString(ref->base->mScript, "Script"); + text += MWGui::ToolTips::getMiscString(ref->mRef.mOwner, "Owner"); + text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script"); } info.text = text; @@ -170,6 +170,6 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return MWWorld::Ptr(&cell.lockpicks.insert(*ref), &cell); + return MWWorld::Ptr(&cell.mLockpicks.insert(*ref), &cell); } } diff --git a/apps/openmw/mwclass/misc.cpp b/apps/openmw/mwclass/misc.cpp index ca7e073b1e..94d40bcb7c 100644 --- a/apps/openmw/mwclass/misc.cpp +++ b/apps/openmw/mwclass/misc.cpp @@ -45,9 +45,9 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); - assert(ref->base != NULL); + assert(ref->mBase != NULL); - const std::string &model = ref->base->mModel; + const std::string &model = ref->mBase->mModel; if (!model.empty()) { return "meshes\\" + model; } @@ -59,7 +59,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mName; + return ref->mBase->mName; } boost::shared_ptr Miscellaneous::activate (const MWWorld::Ptr& ptr, @@ -77,7 +77,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mScript; + return ref->mBase->mScript; } int Miscellaneous::getValue (const MWWorld::Ptr& ptr) const @@ -85,7 +85,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mData.mValue; + return ref->mBase->mData.mValue; } void Miscellaneous::registerSelf() @@ -100,7 +100,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - if (ref->base->mName == MWBase::Environment::get().getWorld()->getStore().gameSettings.find("sGold")->getString()) + if (ref->mBase->mName == MWBase::Environment::get().getWorld()->getStore().get().find("sGold")->getString()) { return std::string("Item Gold Up"); } @@ -112,7 +112,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - if (ref->base->mName == MWBase::Environment::get().getWorld()->getStore().gameSettings.find("sGold")->getString()) + if (ref->mBase->mName == MWBase::Environment::get().getWorld()->getStore().get().find("sGold")->getString()) { return std::string("Item Gold Down"); } @@ -124,7 +124,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mIcon; + return ref->mBase->mIcon; } bool Miscellaneous::hasToolTip (const MWWorld::Ptr& ptr) const @@ -132,7 +132,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return (ref->base->mName != ""); + return (ref->mBase->mName != ""); } MWGui::ToolTipInfo Miscellaneous::getToolTipInfo (const MWWorld::Ptr& ptr) const @@ -142,13 +142,13 @@ namespace MWClass MWGui::ToolTipInfo info; - const ESMS::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); + const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); int count = ptr.getRefData().getCount(); - bool isGold = (ref->base->mName == store.gameSettings.find("sGold")->getString()); + bool isGold = (ref->mBase->mName == store.get().find("sGold")->getString()); if (isGold && count == 1) - count = ref->base->mData.mValue; + count = ref->mBase->mData.mValue; std::string countString; if (!isGold) @@ -156,12 +156,12 @@ namespace MWClass else // gold displays its count also if it's 1. countString = " (" + boost::lexical_cast(count) + ")"; - info.caption = ref->base->mName + countString; - info.icon = ref->base->mIcon; + info.caption = ref->mBase->mName + countString; + info.icon = ref->mBase->mIcon; - if (ref->ref.mSoul != "") + if (ref->mRef.mSoul != "") { - const ESM::Creature *creature = store.creatures.search(ref->ref.mSoul); + const ESM::Creature *creature = store.get().find(ref->mRef.mSoul); info.caption += " (" + creature->mName + ")"; } @@ -169,13 +169,13 @@ namespace MWClass if (!isGold) { - text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->base->mData.mWeight); - text += MWGui::ToolTips::getValueString(ref->base->mData.mValue, "#{sValue}"); + text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight); + text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}"); } if (MWBase::Environment::get().getWindowManager()->getFullHelp()) { - text += MWGui::ToolTips::getMiscString(ref->ref.mOwner, "Owner"); - text += MWGui::ToolTips::getMiscString(ref->base->mScript, "Script"); + text += MWGui::ToolTips::getMiscString(ref->mRef.mOwner, "Owner"); + text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script"); } info.text = text; @@ -188,10 +188,10 @@ namespace MWClass { MWWorld::Ptr newPtr; - const ESMS::ESMStore &store = + const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); - if (MWWorld::Class::get(ptr).getName(ptr) == store.gameSettings.find("sGold")->getString()) { + if (MWWorld::Class::get(ptr).getName(ptr) == store.get().find("sGold")->getString()) { int goldAmount = ptr.getRefData().getCount(); std::string base = "Gold_001"; @@ -209,11 +209,11 @@ namespace MWClass MWWorld::ManualRef newRef(store, base); MWWorld::LiveCellRef *ref = newRef.getPtr().get(); - newPtr = MWWorld::Ptr(&cell.miscItems.insert(*ref), &cell); + newPtr = MWWorld::Ptr(&cell.mMiscItems.insert(*ref), &cell); } else { MWWorld::LiveCellRef *ref = ptr.get(); - newPtr = MWWorld::Ptr(&cell.miscItems.insert(*ref), &cell); + newPtr = MWWorld::Ptr(&cell.mMiscItems.insert(*ref), &cell); } return newPtr; } diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 7e554ee8af..83a0024476 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -62,39 +62,41 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); // NPC stats - if (!ref->base->mFaction.empty()) + if (!ref->mBase->mFaction.empty()) { - std::string faction = ref->base->mFaction; + std::string faction = ref->mBase->mFaction; boost::algorithm::to_lower(faction); - if(ref->base->mNpdt52.mGold != -10) + if(ref->mBase->mNpdt52.mGold != -10) { - data->mNpcStats.getFactionRanks()[faction] = (int)ref->base->mNpdt52.mRank; + data->mNpcStats.getFactionRanks()[faction] = (int)ref->mBase->mNpdt52.mRank; } else { - data->mNpcStats.getFactionRanks()[faction] = (int)ref->base->mNpdt12.mRank; + data->mNpcStats.getFactionRanks()[faction] = (int)ref->mBase->mNpdt12.mRank; } } // creature stats - if(ref->base->mNpdt52.mGold != -10) + if(ref->mBase->mNpdt52.mGold != -10) { for (int i=0; i<27; ++i) - data->mNpcStats.getSkill (i).setBase (ref->base->mNpdt52.mSkills[i]); + data->mNpcStats.getSkill (i).setBase (ref->mBase->mNpdt52.mSkills[i]); - data->mCreatureStats.getAttribute(0).set (ref->base->mNpdt52.mStrength); - data->mCreatureStats.getAttribute(1).set (ref->base->mNpdt52.mIntelligence); - data->mCreatureStats.getAttribute(2).set (ref->base->mNpdt52.mWillpower); - data->mCreatureStats.getAttribute(3).set (ref->base->mNpdt52.mAgility); - data->mCreatureStats.getAttribute(4).set (ref->base->mNpdt52.mSpeed); - data->mCreatureStats.getAttribute(5).set (ref->base->mNpdt52.mEndurance); - data->mCreatureStats.getAttribute(6).set (ref->base->mNpdt52.mPersonality); - data->mCreatureStats.getAttribute(7).set (ref->base->mNpdt52.mLuck); - data->mCreatureStats.setHealth (ref->base->mNpdt52.mHealth); - data->mCreatureStats.setMagicka (ref->base->mNpdt52.mMana); - data->mCreatureStats.setFatigue (ref->base->mNpdt52.mFatigue); + data->mCreatureStats.getAttribute(0).set (ref->mBase->mNpdt52.mStrength); + data->mCreatureStats.getAttribute(1).set (ref->mBase->mNpdt52.mIntelligence); + data->mCreatureStats.getAttribute(2).set (ref->mBase->mNpdt52.mWillpower); + data->mCreatureStats.getAttribute(3).set (ref->mBase->mNpdt52.mAgility); + data->mCreatureStats.getAttribute(4).set (ref->mBase->mNpdt52.mSpeed); + data->mCreatureStats.getAttribute(5).set (ref->mBase->mNpdt52.mEndurance); + data->mCreatureStats.getAttribute(6).set (ref->mBase->mNpdt52.mPersonality); + data->mCreatureStats.getAttribute(7).set (ref->mBase->mNpdt52.mLuck); + data->mCreatureStats.setHealth (ref->mBase->mNpdt52.mHealth); + data->mCreatureStats.setMagicka (ref->mBase->mNpdt52.mMana); + data->mCreatureStats.setFatigue (ref->mBase->mNpdt52.mFatigue); - data->mCreatureStats.setLevel(ref->base->mNpdt52.mLevel); + data->mCreatureStats.setLevel(ref->mBase->mNpdt52.mLevel); + data->mNpcStats.setBaseDisposition(ref->mBase->mNpdt52.mDisposition); + data->mNpcStats.setReputation(ref->mBase->mNpdt52.mReputation); } else { @@ -108,14 +110,14 @@ namespace MWClass data->mCreatureStats.setLevel (1); } - data->mCreatureStats.setHello(ref->base->mAiData.mHello); - data->mCreatureStats.setFight(ref->base->mAiData.mFight); - data->mCreatureStats.setFlee(ref->base->mAiData.mFlee); - data->mCreatureStats.setAlarm(ref->base->mAiData.mAlarm); + data->mCreatureStats.setAiSetting (0, ref->mBase->mAiData.mHello); + data->mCreatureStats.setAiSetting (1, ref->mBase->mAiData.mFight); + data->mCreatureStats.setAiSetting (2, ref->mBase->mAiData.mFlee); + data->mCreatureStats.setAiSetting (3, ref->mBase->mAiData.mAlarm); // spells - for (std::vector::const_iterator iter (ref->base->mSpells.mList.begin()); - iter!=ref->base->mSpells.mList.end(); ++iter) + for (std::vector::const_iterator iter (ref->mBase->mSpells.mList.begin()); + iter!=ref->mBase->mSpells.mList.end(); ++iter) data->mCreatureStats.getSpells().add (*iter); // store @@ -128,7 +130,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mId; + return ref->mBase->mId; } void Npc::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const @@ -146,9 +148,9 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); - assert(ref->base != NULL); + assert(ref->mBase != NULL); - std::string headID = ref->base->mHead; + std::string headID = ref->mBase->mHead; int end = headID.find_last_of("head_") - 4; std::string bodyRaceID = headID.substr(0, end); @@ -170,7 +172,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mName; + return ref->mBase->mName; } MWMechanics::CreatureStats& Npc::getCreatureStats (const MWWorld::Ptr& ptr) const @@ -217,7 +219,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mScript; + return ref->mBase->mScript; } void Npc::setForceStance (const MWWorld::Ptr& ptr, Stance stance, bool force) const @@ -325,7 +327,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mFlags & ESM::NPC::Essential; + return ref->mBase->mFlags & ESM::NPC::Essential; } void Npc::registerSelf() @@ -347,11 +349,11 @@ namespace MWClass ptr.get(); MWGui::ToolTipInfo info; - info.caption = ref->base->mName; + info.caption = ref->mBase->mName; std::string text; if (MWBase::Environment::get().getWindowManager()->getFullHelp()) - text += MWGui::ToolTips::getMiscString(ref->base->mScript, "Script"); + text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script"); info.text = text; return info; @@ -395,8 +397,10 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - const ESM::Class *class_ = MWBase::Environment::get().getWorld()->getStore().classes.find ( - ref->base->mClass); + const ESM::Class *class_ = + MWBase::Environment::get().getWorld()->getStore().get().find ( + ref->mBase->mClass + ); stats.useSkill (skill, *class_, usageType); } @@ -413,6 +417,6 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return MWWorld::Ptr(&cell.npcs.insert(*ref), &cell); + return MWWorld::Ptr(&cell.mNpcs.insert(*ref), &cell); } } diff --git a/apps/openmw/mwclass/potion.cpp b/apps/openmw/mwclass/potion.cpp index 6403765366..09d152de77 100644 --- a/apps/openmw/mwclass/potion.cpp +++ b/apps/openmw/mwclass/potion.cpp @@ -42,9 +42,9 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); - assert(ref->base != NULL); + assert(ref->mBase != NULL); - const std::string &model = ref->base->mModel; + const std::string &model = ref->mBase->mModel; if (!model.empty()) { return "meshes\\" + model; } @@ -56,7 +56,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mName; + return ref->mBase->mName; } boost::shared_ptr Potion::activate (const MWWorld::Ptr& ptr, @@ -75,7 +75,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mScript; + return ref->mBase->mScript; } int Potion::getValue (const MWWorld::Ptr& ptr) const @@ -83,7 +83,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mData.mValue; + return ref->mBase->mData.mValue; } void Potion::registerSelf() @@ -108,7 +108,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mIcon; + return ref->mBase->mIcon; } bool Potion::hasToolTip (const MWWorld::Ptr& ptr) const @@ -116,7 +116,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return (ref->base->mName != ""); + return (ref->mBase->mName != ""); } MWGui::ToolTipInfo Potion::getToolTipInfo (const MWWorld::Ptr& ptr) const @@ -125,20 +125,20 @@ namespace MWClass ptr.get(); MWGui::ToolTipInfo info; - info.caption = ref->base->mName + MWGui::ToolTips::getCountString(ptr.getRefData().getCount()); - info.icon = ref->base->mIcon; + info.caption = ref->mBase->mName + MWGui::ToolTips::getCountString(ptr.getRefData().getCount()); + info.icon = ref->mBase->mIcon; std::string text; - text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->base->mData.mWeight); - text += MWGui::ToolTips::getValueString(ref->base->mData.mValue, "#{sValue}"); + text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight); + text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}"); - info.effects = MWGui::Widgets::MWEffectList::effectListFromESM(&ref->base->mEffects); + info.effects = MWGui::Widgets::MWEffectList::effectListFromESM(&ref->mBase->mEffects); info.isPotion = true; if (MWBase::Environment::get().getWindowManager()->getFullHelp()) { - text += MWGui::ToolTips::getMiscString(ref->ref.mOwner, "Owner"); - text += MWGui::ToolTips::getMiscString(ref->base->mScript, "Script"); + text += MWGui::ToolTips::getMiscString(ref->mRef.mOwner, "Owner"); + text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script"); } info.text = text; @@ -156,7 +156,7 @@ namespace MWClass MWWorld::Ptr actor = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); boost::shared_ptr action ( - new MWWorld::ActionApply (actor, ref->base->mId)); + new MWWorld::ActionApply (actor, ref->mBase->mId)); action->setSound ("Drink"); @@ -169,6 +169,6 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return MWWorld::Ptr(&cell.potions.insert(*ref), &cell); + return MWWorld::Ptr(&cell.mPotions.insert(*ref), &cell); } } diff --git a/apps/openmw/mwclass/probe.cpp b/apps/openmw/mwclass/probe.cpp index 8961b8007f..0d8653aa87 100644 --- a/apps/openmw/mwclass/probe.cpp +++ b/apps/openmw/mwclass/probe.cpp @@ -42,9 +42,9 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); - assert(ref->base != NULL); + assert(ref->mBase != NULL); - const std::string &model = ref->base->mModel; + const std::string &model = ref->mBase->mModel; if (!model.empty()) { return "meshes\\" + model; } @@ -56,7 +56,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mName; + return ref->mBase->mName; } boost::shared_ptr Probe::activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const @@ -73,7 +73,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mScript; + return ref->mBase->mScript; } std::pair, bool> Probe::getEquipmentSlots (const MWWorld::Ptr& ptr) const @@ -90,7 +90,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mData.mValue; + return ref->mBase->mData.mValue; } void Probe::registerSelf() @@ -115,7 +115,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mIcon; + return ref->mBase->mIcon; } bool Probe::hasToolTip (const MWWorld::Ptr& ptr) const @@ -123,7 +123,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return (ref->base->mName != ""); + return (ref->mBase->mName != ""); } MWGui::ToolTipInfo Probe::getToolTipInfo (const MWWorld::Ptr& ptr) const @@ -132,21 +132,21 @@ namespace MWClass ptr.get(); MWGui::ToolTipInfo info; - info.caption = ref->base->mName + MWGui::ToolTips::getCountString(ptr.getRefData().getCount()); - info.icon = ref->base->mIcon; + info.caption = ref->mBase->mName + MWGui::ToolTips::getCountString(ptr.getRefData().getCount()); + info.icon = ref->mBase->mIcon; std::string text; /// \todo store remaining uses somewhere - text += "\n#{sUses}: " + MWGui::ToolTips::toString(ref->base->mData.mUses); - text += "\n#{sQuality}: " + MWGui::ToolTips::toString(ref->base->mData.mQuality); - text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->base->mData.mWeight); - text += MWGui::ToolTips::getValueString(ref->base->mData.mValue, "#{sValue}"); + text += "\n#{sUses}: " + MWGui::ToolTips::toString(ref->mBase->mData.mUses); + text += "\n#{sQuality}: " + MWGui::ToolTips::toString(ref->mBase->mData.mQuality); + text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight); + text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}"); if (MWBase::Environment::get().getWindowManager()->getFullHelp()) { - text += MWGui::ToolTips::getMiscString(ref->ref.mOwner, "Owner"); - text += MWGui::ToolTips::getMiscString(ref->base->mScript, "Script"); + text += MWGui::ToolTips::getMiscString(ref->mRef.mOwner, "Owner"); + text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script"); } info.text = text; @@ -169,6 +169,6 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return MWWorld::Ptr(&cell.probes.insert(*ref), &cell); + return MWWorld::Ptr(&cell.mProbes.insert(*ref), &cell); } } diff --git a/apps/openmw/mwclass/repair.cpp b/apps/openmw/mwclass/repair.cpp index 3c0361b0be..edb28d16c2 100644 --- a/apps/openmw/mwclass/repair.cpp +++ b/apps/openmw/mwclass/repair.cpp @@ -40,9 +40,9 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); - assert(ref->base != NULL); + assert(ref->mBase != NULL); - const std::string &model = ref->base->mModel; + const std::string &model = ref->mBase->mModel; if (!model.empty()) { return "meshes\\" + model; } @@ -54,7 +54,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mName; + return ref->mBase->mName; } boost::shared_ptr Repair::activate (const MWWorld::Ptr& ptr, @@ -72,7 +72,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mScript; + return ref->mBase->mScript; } int Repair::getValue (const MWWorld::Ptr& ptr) const @@ -80,7 +80,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mData.mValue; + return ref->mBase->mData.mValue; } void Repair::registerSelf() @@ -105,7 +105,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mIcon; + return ref->mBase->mIcon; } bool Repair::hasToolTip (const MWWorld::Ptr& ptr) const @@ -113,7 +113,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return (ref->base->mName != ""); + return (ref->mBase->mName != ""); } MWGui::ToolTipInfo Repair::getToolTipInfo (const MWWorld::Ptr& ptr) const @@ -122,21 +122,21 @@ namespace MWClass ptr.get(); MWGui::ToolTipInfo info; - info.caption = ref->base->mName + MWGui::ToolTips::getCountString(ptr.getRefData().getCount()); - info.icon = ref->base->mIcon; + info.caption = ref->mBase->mName + MWGui::ToolTips::getCountString(ptr.getRefData().getCount()); + info.icon = ref->mBase->mIcon; std::string text; /// \todo store remaining uses somewhere - text += "\n#{sUses}: " + MWGui::ToolTips::toString(ref->base->mData.mUses); - text += "\n#{sQuality}: " + MWGui::ToolTips::toString(ref->base->mData.mQuality); - text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->base->mData.mWeight); - text += MWGui::ToolTips::getValueString(ref->base->mData.mValue, "#{sValue}"); + text += "\n#{sUses}: " + MWGui::ToolTips::toString(ref->mBase->mData.mUses); + text += "\n#{sQuality}: " + MWGui::ToolTips::toString(ref->mBase->mData.mQuality); + text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight); + text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}"); if (MWBase::Environment::get().getWindowManager()->getFullHelp()) { - text += MWGui::ToolTips::getMiscString(ref->ref.mOwner, "Owner"); - text += MWGui::ToolTips::getMiscString(ref->base->mScript, "Script"); + text += MWGui::ToolTips::getMiscString(ref->mRef.mOwner, "Owner"); + text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script"); } info.text = text; @@ -150,6 +150,6 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return MWWorld::Ptr(&cell.repairs.insert(*ref), &cell); + return MWWorld::Ptr(&cell.mRepairs.insert(*ref), &cell); } } diff --git a/apps/openmw/mwclass/static.cpp b/apps/openmw/mwclass/static.cpp index 099b096572..026eada7b3 100644 --- a/apps/openmw/mwclass/static.cpp +++ b/apps/openmw/mwclass/static.cpp @@ -32,9 +32,9 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); - assert(ref->base != NULL); + assert(ref->mBase != NULL); - const std::string &model = ref->base->mModel; + const std::string &model = ref->mBase->mModel; if (!model.empty()) { return "meshes\\" + model; } @@ -59,6 +59,6 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return MWWorld::Ptr(&cell.statics.insert(*ref), &cell); + return MWWorld::Ptr(&cell.mStatics.insert(*ref), &cell); } } diff --git a/apps/openmw/mwclass/weapon.cpp b/apps/openmw/mwclass/weapon.cpp index 52dc91205d..c8fe0d2768 100644 --- a/apps/openmw/mwclass/weapon.cpp +++ b/apps/openmw/mwclass/weapon.cpp @@ -42,9 +42,9 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); - assert(ref->base != NULL); + assert(ref->mBase != NULL); - const std::string &model = ref->base->mModel; + const std::string &model = ref->mBase->mModel; if (!model.empty()) { return "meshes\\" + model; } @@ -56,7 +56,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mName; + return ref->mBase->mName; } boost::shared_ptr Weapon::activate (const MWWorld::Ptr& ptr, @@ -79,7 +79,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mData.mHealth; + return ref->mBase->mData.mHealth; } std::string Weapon::getScript (const MWWorld::Ptr& ptr) const @@ -87,7 +87,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mScript; + return ref->mBase->mScript; } std::pair, bool> Weapon::getEquipmentSlots (const MWWorld::Ptr& ptr) const @@ -98,12 +98,12 @@ namespace MWClass std::vector slots; bool stack = false; - if (ref->base->mData.mType==ESM::Weapon::Arrow || ref->base->mData.mType==ESM::Weapon::Bolt) + if (ref->mBase->mData.mType==ESM::Weapon::Arrow || ref->mBase->mData.mType==ESM::Weapon::Bolt) { slots.push_back (int (MWWorld::InventoryStore::Slot_Ammunition)); stack = true; } - else if (ref->base->mData.mType==ESM::Weapon::MarksmanThrown) + else if (ref->mBase->mData.mType==ESM::Weapon::MarksmanThrown) { slots.push_back (int (MWWorld::InventoryStore::Slot_CarriedRight)); stack = true; @@ -138,7 +138,7 @@ namespace MWClass }; for (int i=0; ibase->mData.mType) + if (sMapping[i][0]==ref->mBase->mData.mType) return sMapping[i][1]; return -1; @@ -149,7 +149,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mData.mValue; + return ref->mBase->mData.mValue; } void Weapon::registerSelf() @@ -164,7 +164,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - int type = ref->base->mData.mType; + int type = ref->mBase->mData.mType; // Ammo if (type == 12 || type == 13) { @@ -210,7 +210,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - int type = ref->base->mData.mType; + int type = ref->mBase->mData.mType; // Ammo if (type == 12 || type == 13) { @@ -256,7 +256,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mIcon; + return ref->mBase->mIcon; } bool Weapon::hasToolTip (const MWWorld::Ptr& ptr) const @@ -264,7 +264,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return (ref->base->mName != ""); + return (ref->mBase->mName != ""); } MWGui::ToolTipInfo Weapon::getToolTipInfo (const MWWorld::Ptr& ptr) const @@ -273,15 +273,15 @@ namespace MWClass ptr.get(); MWGui::ToolTipInfo info; - info.caption = ref->base->mName + MWGui::ToolTips::getCountString(ptr.getRefData().getCount()); - info.icon = ref->base->mIcon; + info.caption = ref->mBase->mName + MWGui::ToolTips::getCountString(ptr.getRefData().getCount()); + info.icon = ref->mBase->mIcon; - const ESMS::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); + const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); std::string text; // weapon type & damage. arrows / bolts don't have his info. - if (ref->base->mData.mType < 12) + if (ref->mBase->mData.mType < 12) { text += "\n#{sType} "; @@ -299,49 +299,49 @@ namespace MWClass mapping[ESM::Weapon::MarksmanCrossbow] = std::make_pair("sSkillMarksman", ""); mapping[ESM::Weapon::MarksmanThrown] = std::make_pair("sSkillMarksman", ""); - std::string type = mapping[ref->base->mData.mType].first; - std::string oneOrTwoHanded = mapping[ref->base->mData.mType].second; + std::string type = mapping[ref->mBase->mData.mType].first; + std::string oneOrTwoHanded = mapping[ref->mBase->mData.mType].second; - text += store.gameSettings.find(type)->getString() + - ((oneOrTwoHanded != "") ? ", " + store.gameSettings.find(oneOrTwoHanded)->getString() : ""); + text += store.get().find(type)->getString() + + ((oneOrTwoHanded != "") ? ", " + store.get().find(oneOrTwoHanded)->getString() : ""); // weapon damage - if (ref->base->mData.mType >= 9) + if (ref->mBase->mData.mType >= 9) { // marksman text += "\n#{sAttack}: " - + MWGui::ToolTips::toString(static_cast(ref->base->mData.mChop[0])) - + " - " + MWGui::ToolTips::toString(static_cast(ref->base->mData.mChop[1])); + + MWGui::ToolTips::toString(static_cast(ref->mBase->mData.mChop[0])) + + " - " + MWGui::ToolTips::toString(static_cast(ref->mBase->mData.mChop[1])); } else { // Chop text += "\n#{sChop}: " - + MWGui::ToolTips::toString(static_cast(ref->base->mData.mChop[0])) - + " - " + MWGui::ToolTips::toString(static_cast(ref->base->mData.mChop[1])); + + MWGui::ToolTips::toString(static_cast(ref->mBase->mData.mChop[0])) + + " - " + MWGui::ToolTips::toString(static_cast(ref->mBase->mData.mChop[1])); // Slash text += "\n#{sSlash}: " - + MWGui::ToolTips::toString(static_cast(ref->base->mData.mSlash[0])) - + " - " + MWGui::ToolTips::toString(static_cast(ref->base->mData.mSlash[1])); + + MWGui::ToolTips::toString(static_cast(ref->mBase->mData.mSlash[0])) + + " - " + MWGui::ToolTips::toString(static_cast(ref->mBase->mData.mSlash[1])); // Thrust text += "\n#{sThrust}: " - + MWGui::ToolTips::toString(static_cast(ref->base->mData.mThrust[0])) - + " - " + MWGui::ToolTips::toString(static_cast(ref->base->mData.mThrust[1])); + + MWGui::ToolTips::toString(static_cast(ref->mBase->mData.mThrust[0])) + + " - " + MWGui::ToolTips::toString(static_cast(ref->mBase->mData.mThrust[1])); } } /// \todo store the current weapon health somewhere - if (ref->base->mData.mType < 11) // thrown weapons and arrows/bolts don't have health, only quantity - text += "\n#{sCondition}: " + MWGui::ToolTips::toString(ref->base->mData.mHealth); + if (ref->mBase->mData.mType < 11) // thrown weapons and arrows/bolts don't have health, only quantity + text += "\n#{sCondition}: " + MWGui::ToolTips::toString(ref->mBase->mData.mHealth); - text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->base->mData.mWeight); - text += MWGui::ToolTips::getValueString(ref->base->mData.mValue, "#{sValue}"); + text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight); + text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}"); - info.enchant = ref->base->mEnchant; + info.enchant = ref->mBase->mEnchant; if (MWBase::Environment::get().getWindowManager()->getFullHelp()) { - text += MWGui::ToolTips::getMiscString(ref->ref.mOwner, "Owner"); - text += MWGui::ToolTips::getMiscString(ref->base->mScript, "Script"); + text += MWGui::ToolTips::getMiscString(ref->mRef.mOwner, "Owner"); + text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script"); } info.text = text; @@ -354,7 +354,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->base->mEnchant; + return ref->mBase->mEnchant; } boost::shared_ptr Weapon::use (const MWWorld::Ptr& ptr) const @@ -372,6 +372,6 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return MWWorld::Ptr(&cell.weapons.insert(*ref), &cell); + return MWWorld::Ptr(&cell.mWeapons.insert(*ref), &cell); } } diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp index 62f7df679b..a97cf98ded 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp @@ -6,23 +6,7 @@ #include #include - -#include - -#include "../mwbase/environment.hpp" -#include "../mwbase/world.hpp" -#include "../mwbase/scriptmanager.hpp" -#include "../mwbase/journal.hpp" -#include "../mwbase/windowmanager.hpp" - -#include "../mwworld/class.hpp" -#include "../mwworld/refdata.hpp" -#include "../mwworld/player.hpp" -#include "../mwworld/containerstore.hpp" - -#include "../mwgui/dialogue.hpp" - -#include +#include #include #include @@ -30,15 +14,31 @@ #include #include #include + #include +#include "../mwbase/environment.hpp" +#include "../mwbase/world.hpp" +#include "../mwbase/scriptmanager.hpp" +#include "../mwbase/windowmanager.hpp" +#include "../mwbase/mechanicsmanager.hpp" + +#include "../mwworld/class.hpp" +#include "../mwworld/containerstore.hpp" +#include "../mwworld/esmstore.hpp" +#include "../mwworld/player.hpp" + +#include "../mwgui/dialogue.hpp" + #include "../mwscript/compilercontext.hpp" #include "../mwscript/interpretercontext.hpp" #include "../mwscript/extensions.hpp" -#include "../mwclass/npc.hpp" +#include "../mwmechanics/creaturestats.hpp" #include "../mwmechanics/npcstats.hpp" +#include "filter.hpp" + namespace { std::string toLower (const std::string& name) @@ -66,86 +66,6 @@ namespace return false; } - template - bool selectCompare (char comp, T1 value1, T2 value2) - { - switch (comp) - { - case '0': return value1==value2; - case '1': return value1!=value2; - case '2': return value1>value2; - case '3': return value1>=value2; - case '4': return value1 - bool checkLocal (char comp, const std::string& name, T value, const MWWorld::Ptr& actor, - const ESMS::ESMStore& store) - { - std::string scriptName = MWWorld::Class::get (actor).getScript (actor); - - if (scriptName.empty()) - return false; // no script - - const ESM::Script *script = store.scripts.find (scriptName); - - int i = 0; - - for (; i (script->mVarNames.size()); ++i) - if (script->mVarNames[i]==name) - break; - - if (i>=static_cast (script->mVarNames.size())) - return false; // script does not have a variable of this name - - const MWScript::Locals& locals = actor.getRefData().getLocals(); - - if (imData.mNumShorts) - return selectCompare (comp, locals.mShorts[i], value); - else - i -= script->mData.mNumShorts; - - if (imData.mNumLongs) - return selectCompare (comp, locals.mLongs[i], value); - else - i -= script->mData.mNumShorts; - - return selectCompare (comp, locals.mFloats.at (i), value); - } - - template - bool checkGlobal (char comp, const std::string& name, T value) - { - switch (MWBase::Environment::get().getWorld()->getGlobalVariableType (name)) - { - case 's': - return selectCompare (comp, MWBase::Environment::get().getWorld()->getGlobalVariable (name).mShort, value); - - case 'l': - - return selectCompare (comp, MWBase::Environment::get().getWorld()->getGlobalVariable (name).mLong, value); - - case 'f': - - return selectCompare (comp, MWBase::Environment::get().getWorld()->getGlobalVariable (name).mFloat, value); - - case ' ': - - MWBase::Environment::get().getWorld()->getGlobalVariable (name); // trigger exception - break; - - default: - - throw std::runtime_error ("unsupported gobal variable type"); - } - - return false; - } - //helper function std::string::size_type find_str_ci(const std::string& str, const std::string& substr,size_t pos) { @@ -155,445 +75,25 @@ namespace namespace MWDialogue { - - - bool DialogueManager::functionFilter(const MWWorld::Ptr& actor, const ESM::DialInfo& info,bool choice) - { - bool isCreature = (actor.getTypeName() != typeid(ESM::NPC).name()); - - for (std::vector::const_iterator iter (info.mSelects.begin()); - iter != info.mSelects.end(); ++iter) - { - ESM::DialInfo::SelectStruct select = *iter; - char type = select.mSelectRule[1]; - if(type == '1') - { - char comp = select.mSelectRule[4]; - std::string name = select.mSelectRule.substr (5); - std::string function = select.mSelectRule.substr(2,2); - - int ifunction; - std::istringstream iss(function); - iss >> ifunction; - switch(ifunction) - { - case 39://PC Expelled - if(!selectCompare(comp,0,select.mI)) return false; - break; - - case 40://PC Common Disease - if(!selectCompare(comp,0,select.mI)) return false; - break; - - case 41://PC Blight Disease - if(!selectCompare(comp,0,select.mI)) return false; - break; - - case 43://PC Crime level - if(!selectCompare(comp,0,select.mI)) return false; - break; - - case 46://Same faction - { - if (isCreature) - return false; - - MWMechanics::NpcStats PCstats = MWWorld::Class::get(MWBase::Environment::get().getWorld()->getPlayer().getPlayer()).getNpcStats(MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); - MWMechanics::NpcStats NPCstats = MWWorld::Class::get(actor).getNpcStats(actor); - int sameFaction = 0; - if(!NPCstats.getFactionRanks().empty()) - { - std::string NPCFaction = NPCstats.getFactionRanks().begin()->first; - if(PCstats.getFactionRanks().find(toLower(NPCFaction)) != PCstats.getFactionRanks().end()) sameFaction = 1; - } - if(!selectCompare(comp,sameFaction,select.mI)) return false; - } - break; - - case 48://Detected - if(!selectCompare(comp,1,select.mI)) return false; - break; - - case 49://Alarmed - if(!selectCompare(comp,0,select.mI)) return false; - break; - - case 50://choice - if(choice) - { - if(!selectCompare(comp,mChoice,select.mI)) return false; - } - break; - - case 60://PC Vampire - if(!selectCompare(comp,0,select.mI)) return false; - break; - - case 61://Level - if(!selectCompare(comp,1,select.mI)) return false; - break; - - case 62://Attacked - if(!selectCompare(comp,0,select.mI)) return false; - break; - - case 63://Talked to PC - if(!selectCompare(comp,0,select.mI)) return false; - break; - - case 64://PC Health - if(!selectCompare(comp,50,select.mI)) return false; - break; - - case 65://Creature target - if(!selectCompare(comp,0,select.mI)) return false; - break; - - case 66://Friend hit - if(!selectCompare(comp,0,select.mI)) return false; - break; - - case 67://Fight - if(!selectCompare(comp,0,select.mI)) return false; - break; - - case 68://Hello???? - if(!selectCompare(comp,0,select.mI)) return false; - break; - - case 69://Alarm - if(!selectCompare(comp,0,select.mI)) return false; - break; - - case 70://Flee - if(!selectCompare(comp,0,select.mI)) return false; - break; - - case 71://Should Attack - if(!selectCompare(comp,0,select.mI)) return false; - break; - - default: - break; - - } - } - } - - return true; - } - - bool DialogueManager::isMatching (const MWWorld::Ptr& actor, - const ESM::DialInfo::SelectStruct& select) const - { - bool isCreature = (actor.getTypeName() != typeid(ESM::NPC).name()); - - char type = select.mSelectRule[1]; - - if (type!='0') - { - char comp = select.mSelectRule[4]; - std::string name = select.mSelectRule.substr (5); - std::string function = select.mSelectRule.substr(1,2); - - switch (type) - { - case '1': // function - - return true; // Done elsewhere. - - case '2': // global - - if (select.mType==ESM::VT_Short || select.mType==ESM::VT_Int || - select.mType==ESM::VT_Long) - { - if (!checkGlobal (comp, toLower (name), select.mI)) - return false; - } - else if (select.mType==ESM::VT_Float) - { - if (!checkGlobal (comp, toLower (name), select.mF)) - return false; - } - else - throw std::runtime_error ( - "unsupported variable type in dialogue info select"); - - return true; - - case '3': // local - - if (select.mType==ESM::VT_Short || select.mType==ESM::VT_Int || - select.mType==ESM::VT_Long) - { - if (!checkLocal (comp, toLower (name), select.mI, actor, - MWBase::Environment::get().getWorld()->getStore())) - return false; - } - else if (select.mType==ESM::VT_Float) - { - if (!checkLocal (comp, toLower (name), select.mF, actor, - MWBase::Environment::get().getWorld()->getStore())) - return false; - } - else - throw std::runtime_error ( - "unsupported variable type in dialogue info select"); - - return true; - - case '4'://journal - if(select.mType==ESM::VT_Int) - { - if(!selectCompare(comp,MWBase::Environment::get().getJournal()->getJournalIndex(toLower(name)),select.mI)) return false; - } - else - throw std::runtime_error ( - "unsupported variable type in dialogue info select"); - - return true; - - case '5'://item - { - MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); - MWWorld::ContainerStore& store = MWWorld::Class::get (player).getContainerStore (player); - - int sum = 0; - - for (MWWorld::ContainerStoreIterator iter (store.begin()); iter!=store.end(); ++iter) - if (toLower(iter->getCellRef().mRefID) == toLower(name)) - sum += iter->getRefData().getCount(); - if(!selectCompare(comp,sum,select.mI)) return false; - } - - return true; - - - case '6'://dead - if(!selectCompare(comp,0,select.mI)) return false; - - case '7':// not ID - if(select.mType==ESM::VT_String ||select.mType==ESM::VT_Int)//bug in morrowind here? it's not a short, it's a string - { - int isID = int(toLower(name)==toLower(MWWorld::Class::get (actor).getId (actor))); - if (selectCompare(comp,!isID,select.mI)) return false; - } - else - throw std::runtime_error ( - "unsupported variable type in dialogue info select"); - - return true; - - case '8':// not faction - if (isCreature) - return false; - - if(select.mType==ESM::VT_Int) - { - MWWorld::LiveCellRef* npc = actor.get(); - int isFaction = int(toLower(npc->base->mFaction) == toLower(name)); - if(selectCompare(comp,!isFaction,select.mI)) - return false; - } - else - throw std::runtime_error ( - "unsupported variable type in dialogue info select"); - - return true; - - case '9':// not class - if (isCreature) - return false; - - if(select.mType==ESM::VT_Int) - { - MWWorld::LiveCellRef* npc = actor.get(); - int isClass = int(toLower(npc->base->mClass) == toLower(name)); - if(selectCompare(comp,!isClass,select.mI)) - return false; - } - else - throw std::runtime_error ( - "unsupported variable type in dialogue info select"); - - return true; - - case 'A'://not Race - if (isCreature) - return false; - - if(select.mType==ESM::VT_Int) - { - MWWorld::LiveCellRef* npc = actor.get(); - int isRace = int(toLower(npc->base->mRace) == toLower(name)); - if(selectCompare(comp,!isRace,select.mI)) - return false; - } - else - throw std::runtime_error ( - "unsupported variable type in dialogue info select"); - - return true; - - case 'B'://not Cell - if(select.mType==ESM::VT_Int) - { - int isCell = int(toLower(actor.getCell()->cell->mName) == toLower(name)); - if(selectCompare(comp,!isCell,select.mI)) - return false; - } - else - throw std::runtime_error ( - "unsupported variable type in dialogue info select"); - return true; - - case 'C'://not local - if (select.mType==ESM::VT_Short || select.mType==ESM::VT_Int || - select.mType==ESM::VT_Long) - { - if (checkLocal (comp, toLower (name), select.mI, actor, - MWBase::Environment::get().getWorld()->getStore())) - return false; - } - else if (select.mType==ESM::VT_Float) - { - if (checkLocal (comp, toLower (name), select.mF, actor, - MWBase::Environment::get().getWorld()->getStore())) - return false; - } - else - throw std::runtime_error ( - "unsupported variable type in dialogue info select"); - return true; - - - default: - - std::cout << "unchecked select: " << type << " " << comp << " " << name << std::endl; - } - } - - return true; - } - - bool DialogueManager::isMatching (const MWWorld::Ptr& actor, const ESM::DialInfo& info) const - { - bool isCreature = (actor.getTypeName() != typeid(ESM::NPC).name()); - - // actor id - if (!info.mActor.empty()) - if (toLower (info.mActor)!=MWWorld::Class::get (actor).getId (actor)) - return false; - - //NPC race - if (!info.mRace.empty()) - { - if (isCreature) - return false; - - MWWorld::LiveCellRef *cellRef = actor.get(); - - if (!cellRef) - return false; - - if (toLower (info.mRace)!=toLower (cellRef->base->mRace)) - return false; - } - - //NPC class - if (!info.mClass.empty()) - { - if (isCreature) - return false; - - MWWorld::LiveCellRef *cellRef = actor.get(); - - if (!cellRef) - return false; - - if (toLower (info.mClass)!=toLower (cellRef->base->mClass)) - return false; - } - - //NPC faction - if (!info.mNpcFaction.empty()) - { - if (isCreature) - return false; - - //MWWorld::Class npcClass = MWWorld::Class::get(actor); - MWMechanics::NpcStats stats = MWWorld::Class::get(actor).getNpcStats(actor); - std::map::iterator it = stats.getFactionRanks().find(toLower(info.mNpcFaction)); - if(it!=stats.getFactionRanks().end()) - { - //check rank - if(it->second < (int)info.mData.mRank) return false; - } - else - { - //not in the faction - return false; - } - } - - // TODO check player faction - if(!info.mPcFaction.empty()) - { - MWMechanics::NpcStats stats = MWWorld::Class::get(MWBase::Environment::get().getWorld()->getPlayer().getPlayer()).getNpcStats(MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); - std::map::iterator it = stats.getFactionRanks().find(toLower(info.mPcFaction)); - if(it!=stats.getFactionRanks().end()) - { - //check rank - if(it->second < (int)info.mData.mPCrank) return false; - } - else - { - //not in the faction - return false; - } - } - - //check gender - if (!isCreature) - { - MWWorld::LiveCellRef* npc = actor.get(); - if(npc->base->mFlags & npc->base->Female) - { - if(static_cast (info.mData.mGender)==0) return false; - } - else - { - if(static_cast (info.mData.mGender)==1) return false; - } - } - - // check cell - if (!info.mCell.empty()) - if (MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getCell()->cell->mName != info.mCell) - return false; - - // TODO check DATAstruct - for (std::vector::const_iterator iter (info.mSelects.begin()); - iter != info.mSelects.end(); ++iter) - if (!isMatching (actor, *iter)) - return false; - - return true; - } - - DialogueManager::DialogueManager (const Compiler::Extensions& extensions) : + DialogueManager::DialogueManager (const Compiler::Extensions& extensions, bool scriptVerbose) : mCompilerContext (MWScript::CompilerContext::Type_Dialgoue), mErrorStream(std::cout.rdbuf()),mErrorHandler(mErrorStream) + , mTemporaryDispositionChange(0.f) + , mPermanentDispositionChange(0.f), mScriptVerbose (scriptVerbose) { mChoice = -1; mIsInChoice = false; mCompilerContext.setExtensions (&extensions); mDialogueMap.clear(); mActorKnownTopics.clear(); - ESMS::RecListCaseT::MapType dialogueList = MWBase::Environment::get().getWorld()->getStore().dialogs.list; - for(ESMS::RecListCaseT::MapType::iterator it = dialogueList.begin(); it!=dialogueList.end();it++) + + const MWWorld::Store &dialogs = + MWBase::Environment::get().getWorld()->getStore().get(); + + MWWorld::Store::iterator it = dialogs.begin(); + for (; it != dialogs.end(); ++it) { - mDialogueMap[toLower(it->first)] = it->second; + mDialogueMap[toLower(it->mId)] = *it; } } @@ -602,7 +102,7 @@ namespace MWDialogue mKnownTopics[toLower(topic)] = true; } - void DialogueManager::parseText (std::string text) + void DialogueManager::parseText (const std::string& text) { std::list::iterator it; for(it = mActorKnownTopics.begin();it != mActorKnownTopics.end();++it) @@ -610,14 +110,7 @@ namespace MWDialogue size_t pos = find_str_ci(text,*it,0); if(pos !=std::string::npos) { - if(pos==0) - { - mKnownTopics[*it] = true; - } - else if(text.substr(pos -1,1) == " ") - { - mKnownTopics[*it] = true; - } + mKnownTopics[*it] = true; } } updateTopics(); @@ -630,6 +123,10 @@ namespace MWDialogue mActor = actor; + MWMechanics::CreatureStats& creatureStats = MWWorld::Class::get (actor).getCreatureStats (actor); + mTalkedTo = creatureStats.hasTalkedToPlayer(); + creatureStats.talkedToPlayer(); + mActorKnownTopics.clear(); //initialise the GUI @@ -641,34 +138,28 @@ namespace MWDialogue updateTopics(); //greeting - bool greetingFound = false; - //ESMS::RecListT::MapType dialogueList = MWBase::Environment::get().getWorld()->getStore().dialogs.list; - ESMS::RecListCaseT::MapType dialogueList = MWBase::Environment::get().getWorld()->getStore().dialogs.list; - for(ESMS::RecListCaseT::MapType::iterator it = dialogueList.begin(); it!=dialogueList.end();it++) - { - ESM::Dialogue ndialogue = it->second; - if(ndialogue.mType == ESM::Dialogue::Greeting) - { - if (greetingFound) break; - for (std::vector::const_iterator iter (it->second.mInfo.begin()); - iter!=it->second.mInfo.end(); ++iter) - { - if (isMatching (actor, *iter) && functionFilter(mActor,*iter,true)) - { - if (!iter->mSound.empty()) - { - // TODO play sound - } + const MWWorld::Store &dialogs = + MWBase::Environment::get().getWorld()->getStore().get(); - std::string text = iter->mResponse; - parseText(text); - win->addText(iter->mResponse); - executeScript(iter->mResultScript); - greetingFound = true; - mLastTopic = it->first; - mLastDialogue = *iter; - break; + Filter filter (actor, mChoice, mTalkedTo); + + for (MWWorld::Store::iterator it = dialogs.begin(); it != dialogs.end(); ++it) + { + if(it->mType == ESM::Dialogue::Greeting) + { + if (const ESM::DialInfo *info = filter.search (*it)) + { + if (!info->mSound.empty()) + { + // TODO play sound } + + parseText (info->mResponse); + win->addText (info->mResponse); + executeScript (info->mResultScript); + mLastTopic = it->mId; + mLastDialogue = *info; + break; } } } @@ -676,6 +167,8 @@ namespace MWDialogue bool DialogueManager::compile (const std::string& cmd,std::vector& code) { + bool success = true; + try { mErrorHandler.reset(); @@ -697,26 +190,36 @@ namespace MWDialogue Compiler::ScriptParser parser(mErrorHandler,mCompilerContext, locals, false); scanner.scan (parser); - if(mErrorHandler.isGood()) - { - parser.getCode(code); - return true; - } - return false; + + if (!mErrorHandler.isGood()) + success = false; + + if (success) + parser.getCode (code); } catch (const Compiler::SourceException& /* error */) { // error has already been reported via error handler + success = false; } catch (const std::exception& error) { - printError (std::string ("An exception has been thrown: ") + error.what()); + std::cerr << std::string ("Dialogue error: An exception has been thrown: ") + error.what() << std::endl; + success = false; } - return false; + if (!success && mScriptVerbose) + { + std::cerr + << "compiling failed (dialogue script)" << std::endl + << cmd + << std::endl << std::endl; + } + + return success; } - void DialogueManager::executeScript(std::string script) + void DialogueManager::executeScript (const std::string& script) { std::vector code; if(compile(script,code)) @@ -730,7 +233,7 @@ namespace MWDialogue } catch (const std::exception& error) { - printError (std::string ("An exception has been thrown: ") + error.what()); + std::cerr << std::string ("Dialogue error: An exception has been thrown: ") + error.what(); } } } @@ -741,25 +244,24 @@ namespace MWDialogue int choice = mChoice; mChoice = -1; mActorKnownTopics.clear(); - MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow(); - ESMS::RecListCaseT::MapType dialogueList = MWBase::Environment::get().getWorld()->getStore().dialogs.list; - for(ESMS::RecListCaseT::MapType::iterator it = dialogueList.begin(); it!=dialogueList.end();it++) + + const MWWorld::Store &dialogs = + MWBase::Environment::get().getWorld()->getStore().get(); + + Filter filter (mActor, mChoice, mTalkedTo); + + for (MWWorld::Store::iterator iter = dialogs.begin(); iter != dialogs.end(); ++iter) { - ESM::Dialogue ndialogue = it->second; - if(ndialogue.mType == ESM::Dialogue::Topic) + if (iter->mType == ESM::Dialogue::Topic) { - for (std::vector::const_iterator iter (it->second.mInfo.begin()); - iter!=it->second.mInfo.end(); ++iter) + if (filter.search (*iter)) { - if (isMatching (mActor, *iter) && functionFilter(mActor,*iter,true)) + mActorKnownTopics.push_back (toLower (iter->mId)); + + //does the player know the topic? + if (mKnownTopics.find (toLower (iter->mId)) != mKnownTopics.end()) { - mActorKnownTopics.push_back(toLower(it->first)); - //does the player know the topic? - if(mKnownTopics.find(toLower(it->first)) != mKnownTopics.end()) - { - keywordList.push_back(it->first); - break; - } + keywordList.push_back (iter->mId); } } } @@ -770,14 +272,14 @@ namespace MWDialogue if (mActor.getTypeName() == typeid(ESM::NPC).name()) { MWWorld::LiveCellRef* ref = mActor.get(); - if (ref->base->mHasAI) - services = ref->base->mAiData.mServices; + if (ref->mBase->mHasAI) + services = ref->mBase->mAiData.mServices; } else if (mActor.getTypeName() == typeid(ESM::Creature).name()) { MWWorld::LiveCellRef* ref = mActor.get(); - if (ref->base->mHasAI) - services = ref->base->mAiData.mServices; + if (ref->mBase->mHasAI) + services = ref->mBase->mAiData.mServices; } int windowServices = 0; @@ -795,7 +297,7 @@ namespace MWDialogue || services & ESM::NPC::Misc) windowServices |= MWGui::DialogueWindow::Service_Trade; - if( !mActor.get()->base->mTransport.empty()) + if(mActor.getTypeName() == typeid(ESM::NPC).name() && !mActor.get()->mBase->mTransport.empty()) windowServices |= MWGui::DialogueWindow::Service_Travel; if (services & ESM::NPC::Spells) @@ -810,6 +312,8 @@ namespace MWDialogue if (services & ESM::NPC::Enchanting) windowServices |= MWGui::DialogueWindow::Service_Enchant; + MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow(); + win->setServices (windowServices); // sort again, because the previous sort was case-sensitive @@ -826,28 +330,25 @@ namespace MWDialogue if(mDialogueMap.find(keyword) != mDialogueMap.end()) { ESM::Dialogue ndialogue = mDialogueMap[keyword]; - if(ndialogue.mType == ESM::Dialogue::Topic) + if (mDialogueMap[keyword].mType == ESM::Dialogue::Topic) { - for (std::vector::const_iterator iter = ndialogue.mInfo.begin(); - iter!=ndialogue.mInfo.end(); ++iter) + Filter filter (mActor, mChoice, mTalkedTo); + + if (const ESM::DialInfo *info = filter.search (mDialogueMap[keyword])) { - if (isMatching (mActor, *iter) && functionFilter(mActor,*iter,true)) - { - std::string text = iter->mResponse; - std::string script = iter->mResultScript; + std::string text = info->mResponse; + std::string script = info->mResultScript; - parseText(text); + parseText (text); - MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow(); - win->addTitle(keyword); - win->addText(iter->mResponse); + MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow(); + win->addTitle (keyword); + win->addText (info->mResponse); - executeScript(script); + executeScript (script); - mLastTopic = keyword; - mLastDialogue = *iter; - break; - } + mLastTopic = keyword; + mLastDialogue = *info; } } } @@ -859,45 +360,49 @@ namespace MWDialogue void DialogueManager::goodbyeSelected() { MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_Dialogue); + + // Apply disposition change to NPC's base disposition + if (mActor.getTypeName() == typeid(ESM::NPC).name()) + { + MWMechanics::NpcStats& npcStats = MWWorld::Class::get(mActor).getNpcStats(mActor); + npcStats.setBaseDisposition(npcStats.getBaseDisposition() + mPermanentDispositionChange); + } + mPermanentDispositionChange = 0; + mTemporaryDispositionChange = 0; } void DialogueManager::questionAnswered (const std::string& answer) { - if(mChoiceMap.find(answer) != mChoiceMap.end()) + if (mChoiceMap.find(answer) != mChoiceMap.end()) { mChoice = mChoiceMap[answer]; - std::vector::const_iterator iter; - if(mDialogueMap.find(mLastTopic) != mDialogueMap.end()) + if (mDialogueMap.find(mLastTopic) != mDialogueMap.end()) { - ESM::Dialogue ndialogue = mDialogueMap[mLastTopic]; - if(ndialogue.mType == ESM::Dialogue::Topic) + if (mDialogueMap[mLastTopic].mType == ESM::Dialogue::Topic) { - for (std::vector::const_iterator iter = ndialogue.mInfo.begin(); - iter!=ndialogue.mInfo.end(); ++iter) + Filter filter (mActor, mChoice, mTalkedTo); + + if (const ESM::DialInfo *info = filter.search (mDialogueMap[mLastTopic])) { - if (isMatching (mActor, *iter) && functionFilter(mActor,*iter,true)) - { - mChoiceMap.clear(); - mChoice = -1; - mIsInChoice = false; - MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow(); - std::string text = iter->mResponse; - parseText(text); - win->addText(text); - executeScript(iter->mResultScript); - mLastTopic = mLastTopic; - mLastDialogue = *iter; - break; - } + mChoiceMap.clear(); + mChoice = -1; + mIsInChoice = false; + std::string text = info->mResponse; + parseText (text); + MWBase::Environment::get().getWindowManager()->getDialogueWindow()->addText (text); + executeScript (info->mResultScript); + mLastTopic = mLastTopic; + mLastDialogue = *info; } } } + updateTopics(); } } - void DialogueManager::printError (std::string error) + void DialogueManager::printError (const std::string& error) { MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow(); win->addText(error); @@ -911,22 +416,9 @@ namespace MWDialogue mIsInChoice = true; } - std::string DialogueManager::getFaction() const + MWWorld::Ptr DialogueManager::getActor() const { - if (mActor.getTypeName() != typeid(ESM::NPC).name()) - return ""; - - std::string factionID(""); - MWMechanics::NpcStats stats = MWWorld::Class::get(mActor).getNpcStats(mActor); - if(stats.getFactionRanks().empty()) - { - std::cout << "No faction for this actor!"; - } - else - { - factionID = stats.getFactionRanks().begin()->first; - } - return factionID; + return mActor; } void DialogueManager::goodbye() @@ -935,4 +427,57 @@ namespace MWDialogue win->goodbye(); } + + void DialogueManager::persuade(int type) + { + bool success; + float temp, perm; + MWBase::Environment::get().getMechanicsManager()->getPersuasionDispositionChange( + mActor, MWBase::MechanicsManager::PersuasionType(type), mTemporaryDispositionChange, + success, temp, perm); + mTemporaryDispositionChange += temp; + mPermanentDispositionChange += perm; + + // change temp disposition so that final disposition is between 0...100 + int curDisp = MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(mActor); + if (curDisp + mTemporaryDispositionChange < 0) + mTemporaryDispositionChange = -curDisp; + else if (curDisp + mTemporaryDispositionChange > 100) + mTemporaryDispositionChange = 100 - curDisp; + + // practice skill + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + + if (success) + MWWorld::Class::get(player).skillUsageSucceeded(player, ESM::Skill::Speechcraft, 0); + + // add status message to dialogue window + std::string text; + + if (type == MWBase::MechanicsManager::PT_Admire) + text = "sAdmire"; + else if (type == MWBase::MechanicsManager::PT_Taunt) + text = "sTaunt"; + else if (type == MWBase::MechanicsManager::PT_Intimidate) + text = "sIntimidate"; + else + text = "sBribe"; + + text += (success ? "Success" : "Fail"); + + MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow(); + win->addTitle(MyGUI::LanguageManager::getInstance().replaceTags("#{"+text+"}")); + + /// \todo text from INFO record, how to get the ID? + } + + int DialogueManager::getTemporaryDispositionChange() const + { + return mTemporaryDispositionChange; + } + + void DialogueManager::applyTemporaryDispositionChange(int delta) + { + mTemporaryDispositionChange += delta; + } } diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.hpp b/apps/openmw/mwdialogue/dialoguemanagerimp.hpp index e3e9fd7529..9e1971b0fc 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.hpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.hpp @@ -3,55 +3,52 @@ #include "../mwbase/dialoguemanager.hpp" -#include +#include +#include #include -#include "../mwscript/compilercontext.hpp" -#include "../mwscript/interpretercontext.hpp" -#include #include "../mwworld/ptr.hpp" -#include +#include "../mwscript/compilercontext.hpp" namespace MWDialogue { class DialogueManager : public MWBase::DialogueManager { - bool isMatching (const MWWorld::Ptr& actor, const ESM::DialInfo::SelectStruct& select) const; - - bool isMatching (const MWWorld::Ptr& actor, const ESM::DialInfo& info) const; - - bool functionFilter(const MWWorld::Ptr& actor, const ESM::DialInfo& info,bool choice); - - void parseText(std::string text); - - void updateTopics(); - - std::map mDialogueMap; - std::map mKnownTopics;// Those are the topics the player knows. + std::map mDialogueMap; + std::map mKnownTopics;// Those are the topics the player knows. std::list mActorKnownTopics; MWScript::CompilerContext mCompilerContext; std::ostream mErrorStream; Compiler::StreamErrorHandler mErrorHandler; - - - bool compile (const std::string& cmd,std::vector& code); - void executeScript(std::string script); + MWWorld::Ptr mActor; - - void printError(std::string error); + bool mTalkedTo; int mChoice; - std::map mChoiceMap; + std::map mChoiceMap; std::string mLastTopic; ESM::DialInfo mLastDialogue; bool mIsInChoice; + float mTemporaryDispositionChange; + float mPermanentDispositionChange; + bool mScriptVerbose; + + void parseText (const std::string& text); + + void updateTopics(); + + bool compile (const std::string& cmd,std::vector& code); + void executeScript (const std::string& script); + + void printError (const std::string& error); + public: - DialogueManager (const Compiler::Extensions& extensions); + DialogueManager (const Compiler::Extensions& extensions, bool scriptVerbose); virtual void startDialogue (const MWWorld::Ptr& actor); @@ -61,14 +58,17 @@ namespace MWDialogue virtual void goodbye(); - ///get the faction of the actor you are talking with - virtual std::string getFaction() const; + virtual MWWorld::Ptr getActor() const; + ///< Return the actor the player is currently talking to. //calbacks for the GUI virtual void keywordSelected (const std::string& keyword); virtual void goodbyeSelected(); virtual void questionAnswered (const std::string& answer); + virtual void persuade (int type); + virtual int getTemporaryDispositionChange () const; + virtual void applyTemporaryDispositionChange (int delta); }; } diff --git a/apps/openmw/mwdialogue/filter.cpp b/apps/openmw/mwdialogue/filter.cpp new file mode 100644 index 0000000000..0deef7fd03 --- /dev/null +++ b/apps/openmw/mwdialogue/filter.cpp @@ -0,0 +1,570 @@ + +#include "filter.hpp" + +#include "../mwbase/environment.hpp" +#include "../mwbase/world.hpp" +#include "../mwbase/journal.hpp" +#include "../mwbase/mechanicsmanager.hpp" + +#include "../mwworld/class.hpp" +#include "../mwworld/player.hpp" +#include "../mwworld/containerstore.hpp" +#include "../mwworld/inventorystore.hpp" + +#include "../mwmechanics/npcstats.hpp" +#include "../mwmechanics/creaturestats.hpp" +#include "../mwmechanics/magiceffects.hpp" + +#include "selectwrapper.hpp" + +namespace +{ + std::string toLower (const std::string& name) + { + std::string lowerCase; + + std::transform (name.begin(), name.end(), std::back_inserter (lowerCase), + (int(*)(int)) std::tolower); + + return lowerCase; + } +} + +bool MWDialogue::Filter::testActor (const ESM::DialInfo& info) const +{ + // actor id + if (!info.mActor.empty()) + if (toLower (info.mActor)!=MWWorld::Class::get (mActor).getId (mActor)) + return false; + + bool isCreature = (mActor.getTypeName() != typeid (ESM::NPC).name()); + + // NPC race + if (!info.mRace.empty()) + { + if (isCreature) + return false; + + MWWorld::LiveCellRef *cellRef = mActor.get(); + + if (toLower (info.mRace)!=toLower (cellRef->mBase->mRace)) + return false; + } + + // NPC class + if (!info.mClass.empty()) + { + if (isCreature) + return false; + + MWWorld::LiveCellRef *cellRef = mActor.get(); + + if (toLower (info.mClass)!=toLower (cellRef->mBase->mClass)) + return false; + } + + // NPC faction + if (!info.mNpcFaction.empty()) + { + if (isCreature) + return false; + + MWMechanics::NpcStats& stats = MWWorld::Class::get (mActor).getNpcStats (mActor); + std::map::iterator iter = stats.getFactionRanks().find (toLower (info.mNpcFaction)); + + if (iter==stats.getFactionRanks().end()) + return false; + + // check rank + if (iter->second < info.mData.mRank) + return false; + } + + // Gender + if (!isCreature) + { + MWWorld::LiveCellRef* npc = mActor.get(); + if (info.mData.mGender==(npc->mBase->mFlags & npc->mBase->Female ? 0 : 1)) + return false; + } + + return true; +} + +bool MWDialogue::Filter::testPlayer (const ESM::DialInfo& info) const +{ + const MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + + // check player faction + if (!info.mPcFaction.empty()) + { + MWMechanics::NpcStats& stats = MWWorld::Class::get (player).getNpcStats (player); + std::map::iterator iter = stats.getFactionRanks().find (toLower (info.mPcFaction)); + + if(iter==stats.getFactionRanks().end()) + return false; + + // check rank + if (iter->second < info.mData.mPCrank) + return false; + } + + // check cell + if (!info.mCell.empty()) + if (toLower (player.getCell()->mCell->mName) != toLower (info.mCell)) + return false; + + return true; +} + +bool MWDialogue::Filter::testSelectStructs (const ESM::DialInfo& info) const +{ + for (std::vector::const_iterator iter (info.mSelects.begin()); + iter != info.mSelects.end(); ++iter) + if (!testSelectStruct (*iter)) + return false; + + return true; +} + +bool MWDialogue::Filter::testSelectStruct (const SelectWrapper& select) const +{ + if (select.isNpcOnly() && mActor.getTypeName()!=typeid (ESM::NPC).name()) + return select.isInverted(); + + switch (select.getType()) + { + case SelectWrapper::Type_None: return true; + case SelectWrapper::Type_Integer: return select.selectCompare (getSelectStructInteger (select)); + case SelectWrapper::Type_Numeric: return testSelectStructNumeric (select); + case SelectWrapper::Type_Boolean: return select.selectCompare (getSelectStructBoolean (select)); + } + + return true; +} + +bool MWDialogue::Filter::testSelectStructNumeric (const SelectWrapper& select) const +{ + switch (select.getFunction()) + { + case SelectWrapper::Function_Global: + + // internally all globals are float :( + return select.selectCompare ( + MWBase::Environment::get().getWorld()->getGlobalVariable (select.getName()).mFloat); + + case SelectWrapper::Function_Local: + { + std::string scriptName = MWWorld::Class::get (mActor).getScript (mActor); + + if (scriptName.empty()) + return false; // no script + + const ESM::Script *script = + MWBase::Environment::get().getWorld()->getStore().get().find (scriptName); + + std::string name = select.getName(); + + int i = 0; + + for (; i (script->mVarNames.size()); ++i) + if (script->mVarNames[i]==name) + break; + + if (i>=static_cast (script->mVarNames.size())) + return false; // script does not have a variable of this name + + const MWScript::Locals& locals = mActor.getRefData().getLocals(); + + if (imData.mNumShorts) + return select.selectCompare (static_cast (locals.mShorts[i])); + + i -= script->mData.mNumShorts; + + if (imData.mNumLongs) + return select.selectCompare (locals.mLongs[i]); + + i -= script->mData.mNumShorts; + + return select.selectCompare (locals.mFloats.at (i)); + } + + case SelectWrapper::Function_PcHealthPercent: + { + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + + float ratio = MWWorld::Class::get (player).getCreatureStats (player).getHealth().getCurrent() / + MWWorld::Class::get (player).getCreatureStats (player).getHealth().getModified(); + + return select.selectCompare (ratio); + } + + case SelectWrapper::Function_PcDynamicStat: + { + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + + float value = MWWorld::Class::get (player).getCreatureStats (player). + getDynamic (select.getArgument()).getCurrent(); + + return select.selectCompare (value); + } + + case SelectWrapper::Function_HealthPercent: + { + float ratio = MWWorld::Class::get (mActor).getCreatureStats (mActor).getHealth().getCurrent() / + MWWorld::Class::get (mActor).getCreatureStats (mActor).getHealth().getModified(); + + return select.selectCompare (ratio); + } + + default: + + throw std::runtime_error ("unknown numeric select function"); + } +} + +int MWDialogue::Filter::getSelectStructInteger (const SelectWrapper& select) const +{ + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + + switch (select.getFunction()) + { + case SelectWrapper::Function_Journal: + + return MWBase::Environment::get().getJournal()->getJournalIndex (select.getName()); + + case SelectWrapper::Function_Item: + { + MWWorld::ContainerStore& store = MWWorld::Class::get (player).getContainerStore (player); + + int sum = 0; + + std::string name = select.getName(); + + for (MWWorld::ContainerStoreIterator iter (store.begin()); iter!=store.end(); ++iter) + if (toLower(iter->getCellRef().mRefID) == name) + sum += iter->getRefData().getCount(); + + return sum; + } + + case SelectWrapper::Function_Dead: + + return MWBase::Environment::get().getMechanicsManager()->countDeaths (select.getName()); + + case SelectWrapper::Function_Choice: + + return mChoice; + + case SelectWrapper::Function_AiSetting: + + return MWWorld::Class::get (mActor).getCreatureStats (mActor).getAiSetting (select.getArgument()); + + case SelectWrapper::Function_PcAttribute: + + return MWWorld::Class::get (player).getCreatureStats (player). + getAttribute (select.getArgument()).getModified(); + + case SelectWrapper::Function_PcSkill: + + return static_cast (MWWorld::Class::get (player). + getNpcStats (player).getSkill (select.getArgument()).getModified()); + + case SelectWrapper::Function_FriendlyHit: + { + int hits = MWWorld::Class::get (mActor).getCreatureStats (mActor).getFriendlyHits(); + + return hits>4 ? 4 : hits; + } + + case SelectWrapper::Function_PcLevel: + + return MWWorld::Class::get (player).getCreatureStats (player).getLevel(); + + case SelectWrapper::Function_PcGender: + + return player.get()->mBase->mFlags & ESM::NPC::Female ? 0 : 1; + + case SelectWrapper::Function_PcClothingModifier: + { + MWWorld::InventoryStore& store = MWWorld::Class::get (player).getInventoryStore (player); + + int value = 0; + + for (int i=0; i<=15; ++i) // everything except thigns held in hands and amunition + { + MWWorld::ContainerStoreIterator slot = store.getSlot (i); + + if (slot!=store.end()) + value += MWWorld::Class::get (*slot).getValue (*slot); + } + + return value; + } + + case SelectWrapper::Function_PcCrimeLevel: + + return MWWorld::Class::get (player).getNpcStats (player).getBounty(); + + case SelectWrapper::Function_RankRequirement: + { + if (MWWorld::Class::get (mActor).getNpcStats (mActor).getFactionRanks().empty()) + return 0; + + std::string faction = + MWWorld::Class::get (mActor).getNpcStats (mActor).getFactionRanks().begin()->first; + + int rank = getFactionRank (player, faction); + + if (rank>=9) + return 0; // max rank + + int result = 0; + + if (hasFactionRankSkillRequirements (player, faction, rank+1)) + result += 1; + + if (hasFactionRankReputationRequirements (player, faction, rank+1)) + result += 2; + + return result; + } + + case SelectWrapper::Function_Level: + + return MWWorld::Class::get (mActor).getCreatureStats (mActor).getLevel(); + + case SelectWrapper::Function_PCReputation: + + return MWWorld::Class::get (player).getNpcStats (player).getReputation(); + + case SelectWrapper::Function_Weather: + + return MWBase::Environment::get().getWorld()->getCurrentWeather(); + + case SelectWrapper::Function_Reputation: + + return MWWorld::Class::get (mActor).getNpcStats (mActor).getReputation(); + + case SelectWrapper::Function_FactionRankDiff: + { + if (MWWorld::Class::get (mActor).getNpcStats (mActor).getFactionRanks().empty()) + return 0; + + std::pair faction = + *MWWorld::Class::get (mActor).getNpcStats (mActor).getFactionRanks().begin(); + + int rank = getFactionRank (player, faction.first); + + return rank-faction.second; + } + + case SelectWrapper::Function_WerewolfKills: + + return MWWorld::Class::get (player).getNpcStats (player).getWerewolfKills(); + + case SelectWrapper::Function_RankLow: + case SelectWrapper::Function_RankHigh: + { + bool low = select.getFunction()==SelectWrapper::Function_RankLow; + + if (MWWorld::Class::get (mActor).getNpcStats (mActor).getFactionRanks().empty()) + return 0; + + std::string factionId = + MWWorld::Class::get (mActor).getNpcStats (mActor).getFactionRanks().begin()->first; + + int value = 0; + + const ESM::Faction& faction = + *MWBase::Environment::get().getWorld()->getStore().get().find (factionId); + + MWMechanics::NpcStats& playerStats = MWWorld::Class::get (player).getNpcStats (player); + + for (std::vector::const_iterator iter (faction.mReactions.begin()); + iter!=faction.mReactions.end(); ++iter) + if (playerStats.getFactionRanks().find (iter->mFaction)!=playerStats.getFactionRanks().end()) + if (low ? iter->mReactionmReaction>value) + value = iter->mReaction; + + return value; + } + + default: + + throw std::runtime_error ("unknown integer select function"); + } +} + +bool MWDialogue::Filter::getSelectStructBoolean (const SelectWrapper& select) const +{ + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + + switch (select.getFunction()) + { + case SelectWrapper::Function_False: + + return false; + + case SelectWrapper::Function_Id: + + return select.getName()==toLower (MWWorld::Class::get (mActor).getId (mActor)); + + case SelectWrapper::Function_Faction: + + return toLower (mActor.get()->mBase->mFaction)==select.getName(); + + case SelectWrapper::Function_Class: + + return toLower (mActor.get()->mBase->mClass)==select.getName(); + + case SelectWrapper::Function_Race: + + return toLower (mActor.get()->mBase->mRace)==select.getName(); + + case SelectWrapper::Function_Cell: + + return toLower (mActor.getCell()->mCell->mName)==select.getName(); + + case SelectWrapper::Function_SameGender: + + return (player.get()->mBase->mFlags & ESM::NPC::Female)== + (mActor.get()->mBase->mFlags & ESM::NPC::Female); + + case SelectWrapper::Function_SameRace: + + return toLower (mActor.get()->mBase->mRace)!= + toLower (player.get()->mBase->mRace); + + case SelectWrapper::Function_SameFaction: + + return MWWorld::Class::get (mActor).getNpcStats (mActor).isSameFaction ( + MWWorld::Class::get (player).getNpcStats (player)); + + case SelectWrapper::Function_PcCommonDisease: + + return MWWorld::Class::get (player).getCreatureStats (player).hasCommonDisease(); + + case SelectWrapper::Function_PcBlightDisease: + + return MWWorld::Class::get (player).getCreatureStats (player).hasBlightDisease(); + + case SelectWrapper::Function_PcCorprus: + + return MWWorld::Class::get (player).getCreatureStats (player). + getMagicEffects().get (132).mMagnitude!=0; + + case SelectWrapper::Function_PcExpelled: + { + if (MWWorld::Class::get (mActor).getNpcStats (mActor).getFactionRanks().empty()) + return false; + + std::string faction = + MWWorld::Class::get (mActor).getNpcStats (mActor).getFactionRanks().begin()->first; + + std::set& expelled = MWWorld::Class::get (player).getNpcStats (player).getExpelled(); + + return expelled.find (faction)!=expelled.end(); + } + + case SelectWrapper::Function_PcVampire: + + return MWWorld::Class::get (player).getNpcStats (player).isVampire(); + + case SelectWrapper::Function_TalkedToPc: + + return mTalkedToPlayer; + + case SelectWrapper::Function_Alarmed: + + return MWWorld::Class::get (mActor).getCreatureStats (mActor).isAlarmed(); + + case SelectWrapper::Function_Detected: + + return MWWorld::Class::get (mActor).hasDetected (mActor, player); + + case SelectWrapper::Function_Attacked: + + return MWWorld::Class::get (mActor).getCreatureStats (mActor).getAttacked(); + + case SelectWrapper::Function_ShouldAttack: + + return MWWorld::Class::get (mActor).getCreatureStats (mActor).isHostile(); + + case SelectWrapper::Function_CreatureTargetted: + + return MWWorld::Class::get (mActor).getCreatureStats (mActor).getCreatureTargetted(); + + case SelectWrapper::Function_PCWerewolf: + + return MWWorld::Class::get (player).getNpcStats (player).isWerewolf(); + + default: + + throw std::runtime_error ("unknown boolean select function"); + } +} + +int MWDialogue::Filter::getFactionRank (const MWWorld::Ptr& actor, const std::string& factionId) const +{ + MWMechanics::NpcStats& stats = MWWorld::Class::get (actor).getNpcStats (actor); + + std::map::const_iterator iter = stats.getFactionRanks().find (factionId); + + if (iter==stats.getFactionRanks().end()) + return -1; + + return iter->second; +} + +bool MWDialogue::Filter::hasFactionRankSkillRequirements (const MWWorld::Ptr& actor, + const std::string& factionId, int rank) const +{ + if (rank<0 || rank>=10) + throw std::runtime_error ("rank index out of range"); + + if (!MWWorld::Class::get (actor).getNpcStats (actor).hasSkillsForRank (factionId, rank)) + return false; + + const ESM::Faction& faction = + *MWBase::Environment::get().getWorld()->getStore().get().find (factionId); + + MWMechanics::CreatureStats& stats = MWWorld::Class::get (actor).getCreatureStats (actor); + + return stats.getAttribute (faction.mData.mAttribute1).getBase()>=faction.mData.mRankData[rank].mAttribute1 && + stats.getAttribute (faction.mData.mAttribute2).getBase()>=faction.mData.mRankData[rank].mAttribute2; +} + +bool MWDialogue::Filter::hasFactionRankReputationRequirements (const MWWorld::Ptr& actor, + const std::string& factionId, int rank) const +{ + if (rank<0 || rank>=10) + throw std::runtime_error ("rank index out of range"); + + MWMechanics::NpcStats& stats = MWWorld::Class::get (actor).getNpcStats (actor); + + const ESM::Faction& faction = + *MWBase::Environment::get().getWorld()->getStore().get().find (factionId); + + return stats.getFactionReputation (factionId)>=faction.mData.mRankData[rank].mFactReaction; +} + +MWDialogue::Filter::Filter (const MWWorld::Ptr& actor, int choice, bool talkedToPlayer) +: mActor (actor), mChoice (choice), mTalkedToPlayer (talkedToPlayer) +{} + +bool MWDialogue::Filter::operator() (const ESM::DialInfo& info) const +{ + return testActor (info) && testPlayer (info) && testSelectStructs (info); +} + +const ESM::DialInfo *MWDialogue::Filter::search (const ESM::Dialogue& dialogue) const +{ + for (std::vector::const_iterator iter = dialogue.mInfo.begin(); + iter!=dialogue.mInfo.end(); ++iter) + if ((*this) (*iter)) + return &*iter; + + return 0; +} + diff --git a/apps/openmw/mwdialogue/filter.hpp b/apps/openmw/mwdialogue/filter.hpp new file mode 100644 index 0000000000..7c8f1116fb --- /dev/null +++ b/apps/openmw/mwdialogue/filter.hpp @@ -0,0 +1,58 @@ +#ifndef GAME_MWDIALOGUE_FILTER_H +#define GAME_MWDIALOGUE_FILTER_H + +#include "../mwworld/ptr.hpp" + +namespace ESM +{ + struct DialInfo; + struct Dialogue; +} + +namespace MWDialogue +{ + class SelectWrapper; + + class Filter + { + MWWorld::Ptr mActor; + int mChoice; + bool mTalkedToPlayer; + + bool testActor (const ESM::DialInfo& info) const; + ///< Is this the right actor for this \a info? + + bool testPlayer (const ESM::DialInfo& info) const; + ///< Do the player and the cell the player is currently in match \a info? + + bool testSelectStructs (const ESM::DialInfo& info) const; + ///< Are all select structs matching? + + bool testSelectStruct (const SelectWrapper& select) const; + + bool testSelectStructNumeric (const SelectWrapper& select) const; + + int getSelectStructInteger (const SelectWrapper& select) const; + + bool getSelectStructBoolean (const SelectWrapper& select) const; + + int getFactionRank (const MWWorld::Ptr& actor, const std::string& factionId) const; + + bool hasFactionRankSkillRequirements (const MWWorld::Ptr& actor, const std::string& factionId, + int rank) const; + + bool hasFactionRankReputationRequirements (const MWWorld::Ptr& actor, const std::string& factionId, + int rank) const; + + public: + + Filter (const MWWorld::Ptr& actor, int choice, bool talkedToPlayer); + + bool operator() (const ESM::DialInfo& info) const; + ///< \return does the dialogue match? + + const ESM::DialInfo *search (const ESM::Dialogue& dialogue) const; + }; +} + +#endif diff --git a/apps/openmw/mwdialogue/journalentry.cpp b/apps/openmw/mwdialogue/journalentry.cpp index 1c6addb6eb..e6141884cb 100644 --- a/apps/openmw/mwdialogue/journalentry.cpp +++ b/apps/openmw/mwdialogue/journalentry.cpp @@ -3,11 +3,11 @@ #include -#include - #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" +#include "../mwworld/esmstore.hpp" + namespace MWDialogue { JournalEntry::JournalEntry() {} @@ -16,9 +16,10 @@ namespace MWDialogue : mTopic (topic), mInfoId (infoId) {} - std::string JournalEntry::getText (const ESMS::ESMStore& store) const + std::string JournalEntry::getText (const MWWorld::ESMStore& store) const { - const ESM::Dialogue *dialogue = store.dialogs.find (mTopic); + const ESM::Dialogue *dialogue = + store.get().find (mTopic); for (std::vector::const_iterator iter (dialogue->mInfo.begin()); iter!=dialogue->mInfo.end(); ++iter) @@ -35,7 +36,8 @@ namespace MWDialogue std::string JournalEntry::idFromIndex (const std::string& topic, int index) { - const ESM::Dialogue *dialogue = MWBase::Environment::get().getWorld()->getStore().dialogs.find (topic); + const ESM::Dialogue *dialogue = + MWBase::Environment::get().getWorld()->getStore().get().find (topic); for (std::vector::const_iterator iter (dialogue->mInfo.begin()); iter!=dialogue->mInfo.end(); ++iter) diff --git a/apps/openmw/mwdialogue/journalentry.hpp b/apps/openmw/mwdialogue/journalentry.hpp index 3e86401852..19a9f42b5d 100644 --- a/apps/openmw/mwdialogue/journalentry.hpp +++ b/apps/openmw/mwdialogue/journalentry.hpp @@ -3,7 +3,7 @@ #include -namespace ESMS +namespace MWWorld { struct ESMStore; } @@ -20,7 +20,7 @@ namespace MWDialogue JournalEntry (const std::string& topic, const std::string& infoId); - std::string getText (const ESMS::ESMStore& store) const; + std::string getText (const MWWorld::ESMStore& store) const; static JournalEntry makeFromQuest (const std::string& topic, int index); diff --git a/apps/openmw/mwdialogue/journalimp.cpp b/apps/openmw/mwdialogue/journalimp.cpp index ac4b7a6ded..2b2c603819 100644 --- a/apps/openmw/mwdialogue/journalimp.cpp +++ b/apps/openmw/mwdialogue/journalimp.cpp @@ -1,7 +1,7 @@ #include "journalimp.hpp" -#include +#include "../mwworld/esmstore.hpp" #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" diff --git a/apps/openmw/mwdialogue/quest.cpp b/apps/openmw/mwdialogue/quest.cpp index b4f02e1283..5e2739be16 100644 --- a/apps/openmw/mwdialogue/quest.cpp +++ b/apps/openmw/mwdialogue/quest.cpp @@ -1,7 +1,7 @@ #include "quest.hpp" -#include +#include "../mwworld/esmstore.hpp" #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" @@ -18,7 +18,8 @@ namespace MWDialogue const std::string Quest::getName() const { - const ESM::Dialogue *dialogue = MWBase::Environment::get().getWorld()->getStore().dialogs.find (mTopic); + const ESM::Dialogue *dialogue = + MWBase::Environment::get().getWorld()->getStore().get().find (mTopic); for (std::vector::const_iterator iter (dialogue->mInfo.begin()); iter!=dialogue->mInfo.end(); ++iter) @@ -35,7 +36,8 @@ namespace MWDialogue void Quest::setIndex (int index) { - const ESM::Dialogue *dialogue = MWBase::Environment::get().getWorld()->getStore().dialogs.find (mTopic); + const ESM::Dialogue *dialogue = + MWBase::Environment::get().getWorld()->getStore().get().find (mTopic); for (std::vector::const_iterator iter (dialogue->mInfo.begin()); iter!=dialogue->mInfo.end(); ++iter) @@ -63,7 +65,8 @@ namespace MWDialogue { int index = -1; - const ESM::Dialogue *dialogue = MWBase::Environment::get().getWorld()->getStore().dialogs.find (entry.mTopic); + const ESM::Dialogue *dialogue = + MWBase::Environment::get().getWorld()->getStore().get().find (entry.mTopic); for (std::vector::const_iterator iter (dialogue->mInfo.begin()); iter!=dialogue->mInfo.end(); ++iter) diff --git a/apps/openmw/mwdialogue/selectwrapper.cpp b/apps/openmw/mwdialogue/selectwrapper.cpp new file mode 100644 index 0000000000..1462ee8ba2 --- /dev/null +++ b/apps/openmw/mwdialogue/selectwrapper.cpp @@ -0,0 +1,311 @@ + +#include "selectwrapper.hpp" + +#include + +#include +#include +#include +#include + +namespace +{ + std::string toLower (const std::string& name) + { + std::string lowerCase; + + std::transform (name.begin(), name.end(), std::back_inserter (lowerCase), + (int(*)(int)) std::tolower); + + return lowerCase; + } + + template + bool selectCompareImp (char comp, T1 value1, T2 value2) + { + switch (comp) + { + case '0': return value1==value2; + case '1': return value1!=value2; + case '2': return value1>value2; + case '3': return value1>=value2; + case '4': return value1 + bool selectCompareImp (const ESM::DialInfo::SelectStruct& select, T value1) + { + if (select.mType==ESM::VT_Short || select.mType==ESM::VT_Int || + select.mType==ESM::VT_Long) + { + return selectCompareImp (select.mSelectRule[4], value1, select.mI); + } + else if (select.mType==ESM::VT_Float) + { + return selectCompareImp (select.mSelectRule[4], value1, select.mF); + } + else + throw std::runtime_error ( + "unsupported variable type in dialogue info select"); + } +} + +MWDialogue::SelectWrapper::Function MWDialogue::SelectWrapper::decodeFunction() const +{ + int index = 0; + + std::istringstream (mSelect.mSelectRule.substr(2,2)) >> index; + + switch (index) + { + case 0: return Function_RankLow; + case 1: return Function_RankHigh; + case 2: return Function_RankRequirement; + case 3: return Function_Reputation; + case 4: return Function_HealthPercent; + case 5: return Function_PCReputation; + case 6: return Function_PcLevel; + case 7: return Function_PcHealthPercent; + case 8: case 9: return Function_PcDynamicStat; + case 10: return Function_PcAttribute; + case 11: case 12: case 13: case 14: case 15: case 16: case 17: case 18: case 19: case 20: + case 21: case 22: case 23: case 24: case 25: case 26: case 27: case 28: case 29: case 30: + case 31: case 32: case 33: case 34: case 35: case 36: case 37: return Function_PcSkill; + case 38: return Function_PcGender; + case 39: return Function_PcExpelled; + case 40: return Function_PcCommonDisease; + case 41: return Function_PcBlightDisease; + case 42: return Function_PcClothingModifier; + case 43: return Function_PcCrimeLevel; + case 44: return Function_SameGender; + case 45: return Function_SameRace; + case 46: return Function_SameFaction; + case 47: return Function_FactionRankDiff; + case 48: return Function_Detected; + case 49: return Function_Alarmed; + case 50: return Function_Choice; + case 51: case 52: case 53: case 54: case 55: case 56: case 57: return Function_PcAttribute; + case 58: return Function_PcCorprus; + case 59: return Function_Weather; + case 60: return Function_PcVampire; + case 61: return Function_Level; + case 62: return Function_Attacked; + case 63: return Function_TalkedToPc; + case 64: return Function_PcDynamicStat; + case 65: return Function_CreatureTargetted; + case 66: return Function_FriendlyHit; + case 67: case 68: case 69: case 70: return Function_AiSetting; + case 71: return Function_ShouldAttack; + case 72: return Function_PCWerewolf; + case 73: return Function_WerewolfKills; + } + + return Function_False; +} + +MWDialogue::SelectWrapper::SelectWrapper (const ESM::DialInfo::SelectStruct& select) : mSelect (select) {} + +MWDialogue::SelectWrapper::Function MWDialogue::SelectWrapper::getFunction() const +{ + char type = mSelect.mSelectRule[1]; + + switch (type) + { + case '1': return decodeFunction(); + case '2': return Function_Global; + case '3': return Function_Local; + case '4': return Function_Journal; + case '5': return Function_Item; + case '6': return Function_Dead; + case '7': return Function_Id; + case '8': return Function_Faction; + case '9': return Function_Class; + case 'A': return Function_Race; + case 'B': return Function_Cell; + case 'C': return Function_Local; + } + + return Function_None; +} + +int MWDialogue::SelectWrapper::getArgument() const +{ + if (mSelect.mSelectRule[1]!='1') + return 0; + + int index = 0; + + std::istringstream (mSelect.mSelectRule.substr(2,2)) >> index; + + switch (index) + { + // AI settings + case 67: return 1; + case 68: return 0; + case 69: return 3; + case 70: return 2; + + // attributes + case 10: return 0; + case 51: return 1; + case 52: return 2; + case 53: return 3; + case 54: return 4; + case 55: return 5; + case 56: return 6; + case 57: return 7; + + // skills + case 11: return 0; + case 12: return 1; + case 13: return 2; + case 14: return 3; + case 15: return 4; + case 16: return 5; + case 17: return 6; + case 18: return 7; + case 19: return 8; + case 20: return 9; + case 21: return 10; + case 22: return 11; + case 23: return 12; + case 24: return 13; + case 25: return 14; + case 26: return 15; + case 27: return 16; + case 28: return 17; + case 29: return 18; + case 30: return 19; + case 31: return 20; + case 32: return 21; + case 33: return 22; + case 34: return 23; + case 35: return 24; + case 36: return 25; + case 37: return 26; + + // dynamic stats + case 8: return 1; + case 9: return 2; + case 64: return 0; + } + + return 0; +} + +MWDialogue::SelectWrapper::Type MWDialogue::SelectWrapper::getType() const +{ + static const Function integerFunctions[] = + { + Function_Journal, Function_Item, Function_Dead, + Function_Choice, + Function_AiSetting, + Function_PcAttribute, Function_PcSkill, + Function_FriendlyHit, + Function_PcLevel, Function_PcGender, Function_PcClothingModifier, + Function_PcCrimeLevel, + Function_RankRequirement, + Function_Level, Function_PCReputation, + Function_Weather, + Function_Reputation, Function_FactionRankDiff, + Function_WerewolfKills, + Function_RankLow, Function_RankHigh, + Function_None // end marker + }; + + static const Function numericFunctions[] = + { + Function_Global, Function_Local, + Function_PcDynamicStat, Function_PcHealthPercent, + Function_HealthPercent, + Function_None // end marker + }; + + static const Function booleanFunctions[] = + { + Function_False, + Function_Id, Function_Faction, Function_Class, Function_Race, Function_Cell, + Function_SameGender, Function_SameRace, Function_SameFaction, + Function_PcCommonDisease, Function_PcBlightDisease, Function_PcCorprus, + Function_PcExpelled, + Function_PcVampire, Function_TalkedToPc, + Function_Alarmed, Function_Detected, + Function_Attacked, Function_ShouldAttack, + Function_CreatureTargetted, + Function_PCWerewolf, + Function_None // end marker + }; + + Function function = getFunction(); + + for (int i=0; integerFunctions[i]!=Function_None; ++i) + if (integerFunctions[i]==function) + return Type_Integer; + + for (int i=0; numericFunctions[i]!=Function_None; ++i) + if (numericFunctions[i]==function) + return Type_Numeric; + + for (int i=0; booleanFunctions[i]!=Function_None; ++i) + if (booleanFunctions[i]==function) + return Type_Boolean; + + return Type_None; +} + +bool MWDialogue::SelectWrapper::isInverted() const +{ + char type = mSelect.mSelectRule[1]; + + return type=='7' || type=='8' || type=='9' || type=='A' || type=='B' || type=='C'; +} + +bool MWDialogue::SelectWrapper::isNpcOnly() const +{ + static const Function functions[] = + { + Function_Faction, SelectWrapper::Function_Class, SelectWrapper::Function_Race, + Function_SameGender, Function_SameRace, Function_SameFaction, + Function_PcSkill, + Function_PcExpelled, + Function_PcVampire, + Function_PcCrimeLevel, + Function_RankRequirement, + Function_Reputation, Function_FactionRankDiff, + Function_PCWerewolf, Function_WerewolfKills, + Function_RankLow, Function_RankHigh, + Function_None // end marker + }; + + Function function = getFunction(); + + for (int i=0; functions[i]!=Function_None; ++i) + if (functions[i]==function) + return true; + + return false; +} + +bool MWDialogue::SelectWrapper::selectCompare (int value) const +{ + return selectCompareImp (mSelect, value)!=isInverted(); // logic XOR +} + +bool MWDialogue::SelectWrapper::selectCompare (float value) const +{ + return selectCompareImp (mSelect, value)!=isInverted(); // logic XOR +} + +bool MWDialogue::SelectWrapper::selectCompare (bool value) const +{ + return selectCompareImp (mSelect, static_cast (value))!=isInverted(); // logic XOR +} + +std::string MWDialogue::SelectWrapper::getName() const +{ + return toLower (mSelect.mSelectRule.substr (5)); +} diff --git a/apps/openmw/mwdialogue/selectwrapper.hpp b/apps/openmw/mwdialogue/selectwrapper.hpp new file mode 100644 index 0000000000..b77ed7985a --- /dev/null +++ b/apps/openmw/mwdialogue/selectwrapper.hpp @@ -0,0 +1,86 @@ +#ifndef GAME_MWDIALOGUE_SELECTWRAPPER_H +#define GAME_MWDIALOGUE_SELECTWRAPPER_H + +#include + +namespace MWDialogue +{ + class SelectWrapper + { + const ESM::DialInfo::SelectStruct& mSelect; + + public: + + enum Function + { + Function_None, Function_False, + Function_Journal, + Function_Item, + Function_Dead, + Function_Id, + Function_Faction, + Function_Class, + Function_Race, + Function_Cell, + Function_Local, + Function_Global, + Function_SameGender, Function_SameRace, Function_SameFaction, + Function_Choice, + Function_PcCommonDisease, Function_PcBlightDisease, Function_PcCorprus, + Function_AiSetting, + Function_PcAttribute, Function_PcSkill, + Function_PcExpelled, + Function_PcVampire, + Function_FriendlyHit, + Function_TalkedToPc, + Function_PcLevel, Function_PcHealthPercent, Function_PcDynamicStat, + Function_PcGender, Function_PcClothingModifier, Function_PcCrimeLevel, + Function_RankRequirement, + Function_HealthPercent, Function_Level, Function_PCReputation, + Function_Weather, + Function_Reputation, Function_Alarmed, Function_FactionRankDiff, Function_Detected, + Function_Attacked, Function_ShouldAttack, + Function_CreatureTargetted, + Function_PCWerewolf, Function_WerewolfKills, + Function_RankLow, Function_RankHigh + }; + + enum Type + { + Type_None, + Type_Integer, + Type_Numeric, + Type_Boolean + }; + + private: + + Function decodeFunction() const; + + public: + + SelectWrapper (const ESM::DialInfo::SelectStruct& select); + + Function getFunction() const; + + int getArgument() const; + + Type getType() const; + + bool isInverted() const; + + bool isNpcOnly() const; + ///< \attention Do not call any of the select functions for this select struct! + + bool selectCompare (int value) const; + + bool selectCompare (float value) const; + + bool selectCompare (bool value) const; + + std::string getName() const; + ///< Return case-smashed name. + }; +} + +#endif diff --git a/apps/openmw/mwdialogue/topic.cpp b/apps/openmw/mwdialogue/topic.cpp index 8c1dfafb8a..b6e7c07ae2 100644 --- a/apps/openmw/mwdialogue/topic.cpp +++ b/apps/openmw/mwdialogue/topic.cpp @@ -1,7 +1,7 @@ #include "topic.hpp" -#include +#include "../mwworld/esmstore.hpp" namespace MWDialogue { diff --git a/apps/openmw/mwgui/birth.cpp b/apps/openmw/mwgui/birth.cpp index e7862c4e7f..4837821e0a 100644 --- a/apps/openmw/mwgui/birth.cpp +++ b/apps/openmw/mwgui/birth.cpp @@ -3,7 +3,7 @@ #include #include -#include "components/esm_store/store.hpp" +#include "../mwworld/esmstore.hpp" #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" @@ -130,19 +130,18 @@ void BirthDialog::updateBirths() { mBirthList->removeAllItems(); - const ESMS::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); + const MWWorld::Store &signs = + MWBase::Environment::get().getWorld()->getStore().get(); - ESMS::RecListT::MapType::const_iterator it = store.birthSigns.list.begin(); - ESMS::RecListT::MapType::const_iterator end = store.birthSigns.list.end(); int index = 0; // sort by name std::vector < std::pair > birthSigns; - for (; it!=end; ++it) + + MWWorld::Store::iterator it = signs.begin(); + for (; it != signs.end(); ++it) { - std::string id = it->first; - const ESM::BirthSign* sign = &it->second; - birthSigns.push_back(std::make_pair(id, sign)); + birthSigns.push_back(std::make_pair(it->mId, &(*it))); } std::sort(birthSigns.begin(), birthSigns.end(), sortBirthSigns); @@ -170,8 +169,11 @@ void BirthDialog::updateSpells() const int lineHeight = 18; MyGUI::IntCoord coord(0, 0, mSpellArea->getWidth(), 18); - const ESMS::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); - const ESM::BirthSign *birth = store.birthSigns.find(mCurrentBirthId); + const MWWorld::ESMStore &store = + MWBase::Environment::get().getWorld()->getStore(); + + const ESM::BirthSign *birth = + store.get().find(mCurrentBirthId); std::string texturePath = std::string("textures\\") + birth->mTexture; fixTexturePath(texturePath); @@ -184,7 +186,7 @@ void BirthDialog::updateSpells() for (; it != end; ++it) { const std::string &spellId = *it; - const ESM::Spell *spell = store.spells.search(spellId); + const ESM::Spell *spell = store.get().search(spellId); if (!spell) continue; // Skip spells which cannot be found ESM::Spell::SpellType type = static_cast(spell->mData.mType); @@ -200,11 +202,17 @@ void BirthDialog::updateSpells() } int i = 0; - struct{ const std::vector &spells; const char *label; } categories[3] = { + + struct { + const std::vector &spells; + const char *label; + } + categories[3] = { {abilities, "sBirthsignmenu1"}, {powers, "sPowers"}, {spells, "sBirthsignmenu2"} }; + for (int category = 0; category < 3; ++category) { if (!categories[category].spells.empty()) diff --git a/apps/openmw/mwgui/bookwindow.cpp b/apps/openmw/mwgui/bookwindow.cpp index cb142db602..bc3cd7b404 100644 --- a/apps/openmw/mwgui/bookwindow.cpp +++ b/apps/openmw/mwgui/bookwindow.cpp @@ -60,7 +60,7 @@ void BookWindow::open (MWWorld::Ptr book) MWWorld::LiveCellRef *ref = mBook.get(); BookTextParser parser; - std::vector results = parser.split(ref->base->mText, mLeftPage->getSize().width, mLeftPage->getSize().height); + std::vector results = parser.split(ref->mBase->mText, mLeftPage->getSize().width, mLeftPage->getSize().height); int i=0; for (std::vector::iterator it=results.begin(); diff --git a/apps/openmw/mwgui/charactercreation.cpp b/apps/openmw/mwgui/charactercreation.cpp index e4b77287c3..1719c57687 100644 --- a/apps/openmw/mwgui/charactercreation.cpp +++ b/apps/openmw/mwgui/charactercreation.cpp @@ -7,6 +7,7 @@ #include "review.hpp" #include "dialogue.hpp" #include "mode.hpp" +#include "inventorywindow.hpp" #include "../mwbase/environment.hpp" #include "../mwbase/soundmanager.hpp" @@ -357,7 +358,9 @@ void CharacterCreation::onPickClassDialogDone(WindowBase* parWindow) const std::string &classId = mPickClassDialog->getClassId(); if (!classId.empty()) MWBase::Environment::get().getMechanicsManager()->setPlayerClass(classId); - const ESM::Class *klass = MWBase::Environment::get().getWorld()->getStore().classes.find(classId); + + const ESM::Class *klass = + MWBase::Environment::get().getWorld()->getStore().get().find(classId); if (klass) { mPlayerClass = *klass; @@ -457,9 +460,16 @@ void CharacterCreation::onRaceDialogBack() { if (mRaceDialog) { - mPlayerRaceId = mRaceDialog->getRaceId(); - if (!mPlayerRaceId.empty()) - MWBase::Environment::get().getMechanicsManager()->setPlayerRace(mPlayerRaceId, mRaceDialog->getGender() == RaceDialog::GM_Male); + const ESM::NPC &data = mRaceDialog->getResult(); + mPlayerRaceId = data.mRace; + if (!mPlayerRaceId.empty()) { + MWBase::Environment::get().getMechanicsManager()->setPlayerRace( + data.mRace, + data.isMale(), + data.mHead, + data.mHair + ); + } mWM->removeDialog(mRaceDialog); mRaceDialog = 0; } @@ -472,10 +482,18 @@ void CharacterCreation::onRaceDialogDone(WindowBase* parWindow) { if (mRaceDialog) { - mPlayerRaceId = mRaceDialog->getRaceId(); - mWM->setValue("race", mPlayerRaceId); - if (!mPlayerRaceId.empty()) - MWBase::Environment::get().getMechanicsManager()->setPlayerRace(mPlayerRaceId, mRaceDialog->getGender() == RaceDialog::GM_Male); + const ESM::NPC &data = mRaceDialog->getResult(); + mPlayerRaceId = data.mRace; + if (!mPlayerRaceId.empty()) { + MWBase::Environment::get().getMechanicsManager()->setPlayerRace( + data.mRace, + data.isMale(), + data.mHead, + data.mHair + ); + } + mWM->getInventoryWindow()->rebuildAvatar(); + mWM->removeDialog(mRaceDialog); mRaceDialog = 0; } @@ -557,6 +575,7 @@ void CharacterCreation::onCreateClassDialogDone(WindowBase* parWindow) klass.mData.mSkills[i][1] = majorSkills[i]; klass.mData.mSkills[i][0] = minorSkills[i]; } + MWBase::Environment::get().getMechanicsManager()->setPlayerClass(klass); mPlayerClass = klass; mWM->setPlayerClass(klass); @@ -729,7 +748,10 @@ void CharacterCreation::onGenerateClassDone(WindowBase* parWindow) mGenerateClassResultDialog = 0; MWBase::Environment::get().getMechanicsManager()->setPlayerClass(mGenerateClass); - const ESM::Class *klass = MWBase::Environment::get().getWorld()->getStore().classes.find(mGenerateClass); + + const ESM::Class *klass = + MWBase::Environment::get().getWorld()->getStore().get().find(mGenerateClass); + mPlayerClass = *klass; mWM->setPlayerClass(mPlayerClass); diff --git a/apps/openmw/mwgui/charactercreation.hpp b/apps/openmw/mwgui/charactercreation.hpp index 28ced2e70a..9653aeede5 100644 --- a/apps/openmw/mwgui/charactercreation.hpp +++ b/apps/openmw/mwgui/charactercreation.hpp @@ -1,7 +1,7 @@ #ifndef CHARACTER_CREATION_HPP #define CHARACTER_CREATION_HPP -#include +#include "../mwworld/esmstore.hpp" #include "../mwbase/world.hpp" #include "../mwbase/windowmanager.hpp" diff --git a/apps/openmw/mwgui/class.cpp b/apps/openmw/mwgui/class.cpp index f020010ec5..c14c7f74b5 100644 --- a/apps/openmw/mwgui/class.cpp +++ b/apps/openmw/mwgui/class.cpp @@ -5,7 +5,7 @@ #include #include -#include +#include "../mwworld/esmstore.hpp" #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" @@ -50,7 +50,7 @@ void GenerateClassResultDialog::setClassId(const std::string &classId) { mCurrentClassId = classId; mClassImage->setImageTexture(std::string("textures\\levelup\\") + mCurrentClassId + ".dds"); - mClassName->setCaption(MWBase::Environment::get().getWorld()->getStore().classes.find(mCurrentClassId)->mName); + mClassName->setCaption(MWBase::Environment::get().getWorld()->getStore().get().find(mCurrentClassId)->mName); } // widget controls @@ -185,20 +185,18 @@ void PickClassDialog::updateClasses() { mClassList->removeAllItems(); - const ESMS::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); + const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); - ESMS::RecListT::MapType::const_iterator it = store.classes.list.begin(); - ESMS::RecListT::MapType::const_iterator end = store.classes.list.end(); int index = 0; - for (; it != end; ++it) + MWWorld::Store::iterator it = store.get().begin(); + for (; it != store.get().end(); ++it) { - const ESM::Class &klass = it->second; - bool playable = (klass.mData.mIsPlayable != 0); + bool playable = (it->mData.mIsPlayable != 0); if (!playable) // Only display playable classes continue; - const std::string &id = it->first; - mClassList->addItem(klass.mName, id); + const std::string &id = it->mId; + mClassList->addItem(it->mName, id); if (boost::iequals(id, mCurrentClassId)) mClassList->setIndexSelected(index); ++index; @@ -209,8 +207,8 @@ void PickClassDialog::updateStats() { if (mCurrentClassId.empty()) return; - const ESMS::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); - const ESM::Class *klass = store.classes.search(mCurrentClassId); + const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); + const ESM::Class *klass = store.get().search(mCurrentClassId); if (!klass) return; diff --git a/apps/openmw/mwgui/console.cpp b/apps/openmw/mwgui/console.cpp index b939284dd8..b2281d87e6 100644 --- a/apps/openmw/mwgui/console.cpp +++ b/apps/openmw/mwgui/console.cpp @@ -4,11 +4,10 @@ #include #include -#include -#include - #include +#include "../mwworld/esmstore.hpp" + #include "../mwscript/extensions.hpp" #include "../mwbase/environment.hpp" @@ -93,12 +92,12 @@ namespace MWGui scanner.listKeywords (mNames); // identifier - const ESMS::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); + const MWWorld::ESMStore& store = + MWBase::Environment::get().getWorld()->getStore(); - for (ESMS::RecListList::const_iterator iter (store.recLists.begin()); - iter!=store.recLists.end(); ++iter) + for (MWWorld::ESMStore::iterator it = store.begin(); it != store.end(); ++it) { - iter->second->listIdentifier (mNames); + it->second->listIdentifier (mNames); } // sort diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 5c202941f5..20bc95445b 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -127,10 +127,13 @@ 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) == MWBase::Environment::get().getWorld()->getStore().gameSettings.find("sGold")->getString()) + MWWorld::Class::get(object).getName(object) == gmst.find("sGold")->getString()) { // user notification "i don't buy this item" MWBase::Environment::get().getWindowManager()-> @@ -274,7 +277,7 @@ void ContainerBase::onContainerClicked(MyGUI::Widget* _sender) if (mPtr.getTypeName() == typeid(ESM::Container).name()) { MWWorld::LiveCellRef* ref = mPtr.get(); - if (ref->base->mFlags & ESM::Container::Organic) + if (ref->mBase->mFlags & ESM::Container::Organic) { // user notification MWBase::Environment::get().getWindowManager()-> diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index 27c3288ae7..08d425032f 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -1,7 +1,7 @@ #ifndef MGUI_CONTAINER_H #define MGUI_CONTAINER_H -#include +#include "../mwworld/esmstore.hpp" #include "window_base.hpp" #include "referenceinterface.hpp" diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index c82513093c..827da10852 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -6,12 +6,15 @@ #include #include -#include +#include "../mwworld/esmstore.hpp" #include "../mwbase/environment.hpp" #include "../mwbase/dialoguemanager.hpp" #include "../mwbase/world.hpp" #include "../mwbase/windowmanager.hpp" +#include "../mwbase/mechanicsmanager.hpp" + +#include "../mwmechanics/npcstats.hpp" #include "dialogue_history.hpp" #include "widgets.hpp" @@ -45,17 +48,95 @@ std::string::size_type find_str_ci(const std::string& str, const std::string& su return lower_string(str).find(lower_string(substr),pos); } +bool sortByLength (const std::string& left, const std::string& right) +{ + return left.size() > right.size(); +} + } + +PersuasionDialog::PersuasionDialog(MWBase::WindowManager &parWindowManager) + : WindowModal("openmw_persuasion_dialog.layout", parWindowManager) +{ + getWidget(mCancelButton, "CancelButton"); + getWidget(mAdmireButton, "AdmireButton"); + getWidget(mIntimidateButton, "IntimidateButton"); + getWidget(mTauntButton, "TauntButton"); + getWidget(mBribe10Button, "Bribe10Button"); + getWidget(mBribe100Button, "Bribe100Button"); + getWidget(mBribe1000Button, "Bribe1000Button"); + getWidget(mGoldLabel, "GoldLabel"); + + mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &PersuasionDialog::onCancel); + mAdmireButton->eventMouseButtonClick += MyGUI::newDelegate(this, &PersuasionDialog::onPersuade); + mIntimidateButton->eventMouseButtonClick += MyGUI::newDelegate(this, &PersuasionDialog::onPersuade); + mTauntButton->eventMouseButtonClick += MyGUI::newDelegate(this, &PersuasionDialog::onPersuade); + mBribe10Button->eventMouseButtonClick += MyGUI::newDelegate(this, &PersuasionDialog::onPersuade); + mBribe100Button->eventMouseButtonClick += MyGUI::newDelegate(this, &PersuasionDialog::onPersuade); + mBribe1000Button->eventMouseButtonClick += MyGUI::newDelegate(this, &PersuasionDialog::onPersuade); +} + +void PersuasionDialog::onCancel(MyGUI::Widget *sender) +{ + setVisible(false); +} + +void PersuasionDialog::onPersuade(MyGUI::Widget *sender) +{ + MWBase::MechanicsManager::PersuasionType type; + if (sender == mAdmireButton) type = MWBase::MechanicsManager::PT_Admire; + else if (sender == mIntimidateButton) type = MWBase::MechanicsManager::PT_Intimidate; + else if (sender == mTauntButton) type = MWBase::MechanicsManager::PT_Taunt; + else if (sender == mBribe10Button) + { + mWindowManager.getTradeWindow()->addOrRemoveGold(-10); + type = MWBase::MechanicsManager::PT_Bribe10; + } + else if (sender == mBribe100Button) + { + mWindowManager.getTradeWindow()->addOrRemoveGold(-100); + type = MWBase::MechanicsManager::PT_Bribe100; + } + else /*if (sender == mBribe1000Button)*/ + { + mWindowManager.getTradeWindow()->addOrRemoveGold(-1000); + type = MWBase::MechanicsManager::PT_Bribe1000; + } + + MWBase::Environment::get().getDialogueManager()->persuade(type); + + setVisible(false); +} + +void PersuasionDialog::open() +{ + WindowModal::open(); + center(); + + int playerGold = mWindowManager.getInventoryWindow()->getPlayerGold(); + + mBribe10Button->setEnabled (playerGold >= 10); + mBribe100Button->setEnabled (playerGold >= 100); + mBribe1000Button->setEnabled (playerGold >= 1000); + + mGoldLabel->setCaptionWithReplacing("#{sGold}: " + boost::lexical_cast(playerGold)); +} + +// -------------------------------------------------------------------------------------------------- + DialogueWindow::DialogueWindow(MWBase::WindowManager& parWindowManager) : WindowBase("openmw_dialogue_window.layout", parWindowManager) - , mEnabled(true) + , mPersuasionDialog(parWindowManager) + , mEnabled(false) , mServices(0) { // Centre dialog center(); + mPersuasionDialog.setVisible(false); + //History view getWidget(mHistory, "History"); mHistory->setOverflowToTheLeft(true); @@ -127,33 +208,40 @@ void DialogueWindow::onSelectTopic(std::string topic) { if (!mEnabled) return; - if (topic == MWBase::Environment::get().getWorld()->getStore().gameSettings.find("sBarter")->getString()) + const MWWorld::Store &gmst = + MWBase::Environment::get().getWorld()->getStore().get(); + + if (topic == gmst.find("sBarter")->getString()) { /// \todo check if the player is allowed to trade with this actor (e.g. faction rank high enough)? mWindowManager.pushGuiMode(GM_Barter); mWindowManager.getTradeWindow()->startTrade(mPtr); } - else if (topic == MWBase::Environment::get().getWorld()->getStore().gameSettings.find("sSpells")->getString()) + if (topic == gmst.find("sPersuasion")->getString()) + { + mPersuasionDialog.setVisible(true); + } + else if (topic == gmst.find("sSpells")->getString()) { mWindowManager.pushGuiMode(GM_SpellBuying); mWindowManager.getSpellBuyingWindow()->startSpellBuying(mPtr); } - else if (topic == MWBase::Environment::get().getWorld()->getStore().gameSettings.find("sTravel")->getString()) + else if (topic == gmst.find("sTravel")->getString()) { mWindowManager.pushGuiMode(GM_Travel); mWindowManager.getTravelWindow()->startTravel(mPtr); } - else if (topic == MWBase::Environment::get().getWorld()->getStore().gameSettings.find("sSpellMakingMenuTitle")->getString()) + else if (topic == gmst.find("sSpellMakingMenuTitle")->getString()) { mWindowManager.pushGuiMode(GM_SpellCreation); mWindowManager.startSpellMaking (mPtr); } - else if (topic == MWBase::Environment::get().getWorld()->getStore().gameSettings.find("sEnchanting")->getString()) + else if (topic == gmst.find("sEnchanting")->getString()) { mWindowManager.pushGuiMode(GM_Enchanting); mWindowManager.startEnchanting (mPtr); } - else if (topic == MWBase::Environment::get().getWorld()->getStore().gameSettings.find("sServiceTrainingTitle")->getString()) + else if (topic == gmst.find("sServiceTrainingTitle")->getString()) { mWindowManager.pushGuiMode(GM_Training); mWindowManager.startTraining (mPtr); @@ -180,25 +268,31 @@ void DialogueWindow::setKeywords(std::list keyWords) bool anyService = mServices > 0; + const MWWorld::Store &gmst = + MWBase::Environment::get().getWorld()->getStore().get(); + + if (mPtr.getTypeName() == typeid(ESM::NPC).name()) + mTopicsList->addItem(gmst.find("sPersuasion")->getString()); + if (mServices & Service_Trade) - mTopicsList->addItem(MWBase::Environment::get().getWorld()->getStore().gameSettings.find("sBarter")->getString()); + mTopicsList->addItem(gmst.find("sBarter")->getString()); if (mServices & Service_BuySpells) - mTopicsList->addItem(MWBase::Environment::get().getWorld()->getStore().gameSettings.find("sSpells")->getString()); + mTopicsList->addItem(gmst.find("sSpells")->getString()); if (mServices & Service_Travel) - mTopicsList->addItem(MWBase::Environment::get().getWorld()->getStore().gameSettings.find("sTravel")->getString()); + mTopicsList->addItem(gmst.find("sTravel")->getString()); if (mServices & Service_CreateSpells) - mTopicsList->addItem(MWBase::Environment::get().getWorld()->getStore().gameSettings.find("sSpellmakingMenuTitle")->getString()); + mTopicsList->addItem(gmst.find("sSpellmakingMenuTitle")->getString()); // if (mServices & Service_Enchant) -// mTopicsList->addItem(MWBase::Environment::get().getWorld()->getStore().gameSettings.find("sEnchanting")->getString()); +// mTopicsList->addItem(gmst.find("sEnchanting")->getString()); if (mServices & Service_Training) - mTopicsList->addItem(MWBase::Environment::get().getWorld()->getStore().gameSettings.find("sServiceTrainingTitle")->getString()); + mTopicsList->addItem(gmst.find("sServiceTrainingTitle")->getString()); - if (anyService) + if (anyService || mPtr.getTypeName() == typeid(ESM::NPC).name()) mTopicsList->addSeparator(); for(std::list::iterator it = keyWords.begin(); it != keyWords.end(); ++it) @@ -222,43 +316,36 @@ void addColorInString(std::string& str, const std::string& keyword,std::string c size_t pos = 0; while((pos = find_str_ci(str,keyword, pos)) != std::string::npos) { - if(pos==0) - { - str.insert(pos,color1); - pos += color1.length(); - pos += keyword.length(); - str.insert(pos,color2); - pos+= color2.length(); - } - else - { - if(str.substr(pos -1,1) == " ") - { - str.insert(pos,color1); - pos += color1.length(); - pos += keyword.length(); - str.insert(pos,color2); - pos+= color2.length(); - } - else - { - pos += keyword.length(); - } - } + str.insert(pos,color1); + pos += color1.length(); + pos += keyword.length(); + str.insert(pos,color2); + pos+= color2.length(); } } std::string DialogueWindow::parseText(std::string text) { bool separatorReached = false; // only parse topics that are below the separator (this prevents actions like "Barter" that are not topics from getting blue-colored) + + std::vector topics; + for(unsigned int i = 0;igetItemCount();i++) { std::string keyWord = mTopicsList->getItemNameAt(i); - if (separatorReached && keyWord != "") - addColorInString(text,keyWord,"#686EBA","#B29154"); - else + if (separatorReached) + topics.push_back(keyWord); + else if (keyWord == "") separatorReached = true; } + + // sort by length to make sure longer topics are replaced first + std::sort(topics.begin(), topics.end(), sortByLength); + + for(std::vector::const_iterator it = topics.begin(); it != topics.end(); ++it) + { + addColorInString(text,*it,"#686EBA","#B29154"); + } return text; } @@ -293,15 +380,18 @@ void DialogueWindow::updateOptions() mTopicsList->clear(); mHistory->eraseText(0, mHistory->getTextLength()); - mDispositionBar->setProgressRange(100); - mDispositionBar->setProgressPosition(40); - mDispositionText->eraseText(0, mDispositionText->getTextLength()); - mDispositionText->addText("#B29154"+std::string("40/100")+"#B29154"); + if (mPtr.getTypeName() == typeid(ESM::NPC).name()) + { + mDispositionBar->setProgressRange(100); + mDispositionBar->setProgressPosition(MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(mPtr)); + mDispositionText->eraseText(0, mDispositionText->getTextLength()); + mDispositionText->addText("#B29154"+boost::lexical_cast(MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(mPtr))+std::string("/100")+"#B29154"); + } } void DialogueWindow::goodbye() { - mHistory->addDialogText("\n#572D21" + MWBase::Environment::get().getWorld()->getStore().gameSettings.find("sGoodbye")->getString()); + mHistory->addDialogText("\n#572D21" + MWBase::Environment::get().getWorld()->getStore().get().find("sGoodbye")->getString()); mTopicsList->setEnabled(false); mEnabled = false; } @@ -310,3 +400,17 @@ void DialogueWindow::onReferenceUnavailable() { mWindowManager.removeGuiMode(GM_Dialogue); } + +void DialogueWindow::onFrame() +{ + if(mEnabled && mPtr.getTypeName() == typeid(ESM::NPC).name()) + { + int disp = std::max(0, std::min(100, + MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(mPtr) + + MWBase::Environment::get().getDialogueManager()->getTemporaryDispositionChange())); + mDispositionBar->setProgressRange(100); + mDispositionBar->setProgressPosition(disp); + mDispositionText->eraseText(0, mDispositionText->getTextLength()); + mDispositionText->addText("#B29154"+boost::lexical_cast(disp)+std::string("/100")+"#B29154"); + } +} diff --git a/apps/openmw/mwgui/dialogue.hpp b/apps/openmw/mwgui/dialogue.hpp index 3a89409cac..082d925246 100644 --- a/apps/openmw/mwgui/dialogue.hpp +++ b/apps/openmw/mwgui/dialogue.hpp @@ -26,6 +26,27 @@ namespace MWGui { class DialogueHistory; + class PersuasionDialog : public WindowModal + { + public: + PersuasionDialog(MWBase::WindowManager& parWindowManager); + + virtual void open(); + + private: + MyGUI::Button* mCancelButton; + MyGUI::Button* mAdmireButton; + MyGUI::Button* mIntimidateButton; + MyGUI::Button* mTauntButton; + MyGUI::Button* mBribe10Button; + MyGUI::Button* mBribe100Button; + MyGUI::Button* mBribe1000Button; + MyGUI::TextBox* mGoldLabel; + + void onCancel (MyGUI::Widget* sender); + void onPersuade (MyGUI::Widget* sender); + }; + class DialogueWindow: public WindowBase, public ReferenceInterface { public: @@ -47,6 +68,7 @@ namespace MWGui void addTitle(std::string text); void askQuestion(std::string question); void goodbye(); + void onFrame(); // make sure to call these before setKeywords() void setServices(int services) { mServices = services; } @@ -85,6 +107,8 @@ namespace MWGui Widgets::MWList* mTopicsList; MyGUI::ProgressPtr mDispositionBar; MyGUI::EditPtr mDispositionText; + + PersuasionDialog mPersuasionDialog; }; } #endif diff --git a/apps/openmw/mwgui/dialogue_history.cpp b/apps/openmw/mwgui/dialogue_history.cpp index 4ca764c82b..13f72545e2 100644 --- a/apps/openmw/mwgui/dialogue_history.cpp +++ b/apps/openmw/mwgui/dialogue_history.cpp @@ -3,7 +3,8 @@ #include "../mwbase/windowmanager.hpp" #include "widgets.hpp" -#include "components/esm_store/store.hpp" + +#include "../mwworld/esmstore.hpp" #include #include diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index 66cc6b21ad..9b4075f576 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -341,7 +341,9 @@ void HUD::onResChange(int width, int height) void HUD::setSelectedSpell(const std::string& spellId, int successChancePercent) { - const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(spellId); + const ESM::Spell* spell = + MWBase::Environment::get().getWorld()->getStore().get().find(spellId); + std::string spellName = spell->mName; if (spellName != mSpellName && mSpellVisible) { @@ -361,7 +363,9 @@ void HUD::setSelectedSpell(const std::string& spellId, int successChancePercent) mSpellBox->setUserString("Spell", spellId); // use the icon of the first effect - const ESM::MagicEffect* effect = MWBase::Environment::get().getWorld()->getStore().magicEffects.find(spell->mEffects.mList.front().mEffectID); + const ESM::MagicEffect* effect = + MWBase::Environment::get().getWorld()->getStore().get().find(spell->mEffects.mList.front().mEffectID); + std::string icon = effect->mIcon; int slashPos = icon.find("\\"); icon.insert(slashPos+1, "b_"); diff --git a/apps/openmw/mwgui/inventorywindow.hpp b/apps/openmw/mwgui/inventorywindow.hpp index 84b576a58c..6b45a99800 100644 --- a/apps/openmw/mwgui/inventorywindow.hpp +++ b/apps/openmw/mwgui/inventorywindow.hpp @@ -28,6 +28,10 @@ namespace MWGui MWWorld::Ptr getAvatarSelectedItem(int x, int y); + void rebuildAvatar() { + mPreview.rebuild(); + } + protected: MyGUI::Widget* mAvatar; MyGUI::ImageBox* mAvatarImage; diff --git a/apps/openmw/mwgui/levelupdialog.cpp b/apps/openmw/mwgui/levelupdialog.cpp index 7dced94f50..45890b89fe 100644 --- a/apps/openmw/mwgui/levelupdialog.cpp +++ b/apps/openmw/mwgui/levelupdialog.cpp @@ -8,14 +8,12 @@ #include "../mwworld/player.hpp" #include "../mwworld/class.hpp" +#include "../mwworld/esmstore.hpp" #include "../mwmechanics/creaturestats.hpp" #include "../mwmechanics/npcstats.hpp" #include "../mwmechanics/stat.hpp" -#include -#include - namespace MWGui { @@ -110,7 +108,8 @@ namespace MWGui void LevelupDialog::open() { - MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayer().getPlayer(); + MWBase::World *world = MWBase::Environment::get().getWorld(); + MWWorld::Ptr player = world->getPlayer().getPlayer(); MWMechanics::CreatureStats& creatureStats = MWWorld::Class::get(player).getCreatureStats (player); MWMechanics::NpcStats& pcStats = MWWorld::Class::get(player).getNpcStats (player); @@ -121,17 +120,13 @@ namespace MWGui setAttributeValues(); + const ESM::NPC *playerData = player.get()->mBase; + // set class image - const ESM::Class& playerClass = MWBase::Environment::get().getWorld ()->getPlayer ().getClass (); - // retrieve the ID to this class - std::string classId; - std::map list = MWBase::Environment::get().getWorld()->getStore ().classes.list; - for (std::map::iterator it = list.begin(); it != list.end(); ++it) - { - if (playerClass.mName == it->second.mName) - classId = it->first; - } - mClassImage->setImageTexture ("textures\\levelup\\" + classId + ".dds"); + const ESM::Class *cls = + world->getStore().get().find(playerData->mClass); + + mClassImage->setImageTexture ("textures\\levelup\\" + cls->mId + ".dds"); /// \todo replace this with INI-imported texts int level = creatureStats.getLevel ()+1; diff --git a/apps/openmw/mwgui/map_window.cpp b/apps/openmw/mwgui/map_window.cpp index 1913ed8dd6..0a26ebb8f4 100644 --- a/apps/openmw/mwgui/map_window.cpp +++ b/apps/openmw/mwgui/map_window.cpp @@ -269,10 +269,12 @@ MapWindow::MapWindow(MWBase::WindowManager& parWindowManager, const std::string& getWidget(mLocalMap, "LocalMap"); getWidget(mGlobalMap, "GlobalMap"); getWidget(mGlobalMapImage, "GlobalMapImage"); + getWidget(mGlobalMapOverlay, "GlobalMapOverlay"); getWidget(mPlayerArrowLocal, "CompassLocal"); getWidget(mPlayerArrowGlobal, "CompassGlobal"); mGlobalMapImage->setImageTexture("GlobalMap.png"); + mGlobalMapOverlay->setImageTexture("GlobalMapOverlay"); mGlobalMap->setVisible (false); @@ -328,6 +330,11 @@ void MapWindow::addVisitedLocation(const std::string& name, int x, int y) markerWidget->setUserString("Caption_Text", name); } +void MapWindow::cellExplored(int x, int y) +{ + mGlobalMapRender->exploreCell(x,y); +} + void MapWindow::onDragStart(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id) { if (_id!=MyGUI::MouseButton::Left) return; diff --git a/apps/openmw/mwgui/map_window.hpp b/apps/openmw/mwgui/map_window.hpp index 73eaad1cd7..4e2dd67567 100644 --- a/apps/openmw/mwgui/map_window.hpp +++ b/apps/openmw/mwgui/map_window.hpp @@ -70,6 +70,7 @@ namespace MWGui void setCellName(const std::string& cellName); void addVisitedLocation(const std::string& name, int x, int y); // adds the marker to the global map + void cellExplored(int x, int y); virtual void open(); @@ -82,6 +83,7 @@ namespace MWGui MyGUI::ScrollView* mGlobalMap; MyGUI::ImageBox* mGlobalMapImage; + MyGUI::ImageBox* mGlobalMapOverlay; MyGUI::ImageBox* mPlayerArrowLocal; MyGUI::ImageBox* mPlayerArrowGlobal; MyGUI::Button* mButton; diff --git a/apps/openmw/mwgui/quickkeysmenu.cpp b/apps/openmw/mwgui/quickkeysmenu.cpp index e927af95d3..02512425de 100644 --- a/apps/openmw/mwgui/quickkeysmenu.cpp +++ b/apps/openmw/mwgui/quickkeysmenu.cpp @@ -29,8 +29,11 @@ namespace bool sortSpells(const std::string& left, const std::string& right) { - const ESM::Spell* a = MWBase::Environment::get().getWorld()->getStore().spells.find(left); - const ESM::Spell* b = MWBase::Environment::get().getWorld()->getStore().spells.find(right); + const MWWorld::Store &spells = + MWBase::Environment::get().getWorld()->getStore().get(); + + const ESM::Spell* a = spells.find(left); + const ESM::Spell* b = spells.find(right); int cmp = a->mName.compare(b->mName); return cmp < 0; @@ -234,9 +237,15 @@ namespace MWGui MyGUI::ImageBox* image = frame->createWidget("ImageBox", MyGUI::IntCoord(5, 5, 32, 32), MyGUI::Align::Default); + const MWWorld::ESMStore &esmStore = + MWBase::Environment::get().getWorld()->getStore(); + // use the icon of the first effect - const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(spellId); - const ESM::MagicEffect* effect = MWBase::Environment::get().getWorld()->getStore().magicEffects.find(spell->mEffects.mList.front().mEffectID); + const ESM::Spell* spell = esmStore.get().find(spellId); + + const ESM::MagicEffect* effect = + esmStore.get().find(spell->mEffects.mList.front().mEffectID); + std::string path = effect->mIcon; int slashPos = path.find("\\"); path.insert(slashPos+1, "b_"); @@ -434,11 +443,14 @@ namespace MWGui spellList.push_back(*it); } + const MWWorld::ESMStore &esmStore = + MWBase::Environment::get().getWorld()->getStore(); + std::vector powers; std::vector::iterator it = spellList.begin(); while (it != spellList.end()) { - const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(*it); + const ESM::Spell* spell = esmStore.get().find(*it); if (spell->mData.mType == ESM::Spell::ST_Power) { powers.push_back(*it); @@ -465,7 +477,9 @@ namespace MWGui if (enchantId != "") { // only add items with "Cast once" or "Cast on use" - const ESM::Enchantment* enchant = MWBase::Environment::get().getWorld()->getStore().enchants.find(enchantId); + const ESM::Enchantment* enchant = + esmStore.get().find(enchantId); + int type = enchant->mData.mType; if (type != ESM::Enchantment::CastOnce && type != ESM::Enchantment::WhenUsed) @@ -487,7 +501,7 @@ namespace MWGui for (std::vector::const_iterator it = powers.begin(); it != powers.end(); ++it) { - const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(*it); + const ESM::Spell* spell = esmStore.get().find(*it); MyGUI::Button* t = mMagicList->createWidget("SpellText", MyGUI::IntCoord(4, mHeight, mWidth-8, spellHeight), MyGUI::Align::Left | MyGUI::Align::Top); t->setCaption(spell->mName); @@ -504,7 +518,7 @@ namespace MWGui addGroup("#{sSpells}", ""); for (std::vector::const_iterator it = spellList.begin(); it != spellList.end(); ++it) { - const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(*it); + const ESM::Spell* spell = esmStore.get().find(*it); MyGUI::Button* t = mMagicList->createWidget("SpellText", MyGUI::IntCoord(4, mHeight, mWidth-8, spellHeight), MyGUI::Align::Left | MyGUI::Align::Top); t->setCaption(spell->mName); diff --git a/apps/openmw/mwgui/race.cpp b/apps/openmw/mwgui/race.cpp index d681bc69dc..d2714fb510 100644 --- a/apps/openmw/mwgui/race.cpp +++ b/apps/openmw/mwgui/race.cpp @@ -5,8 +5,9 @@ #include #include +#include -#include +#include "../mwworld/esmstore.hpp" #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" @@ -108,6 +109,16 @@ void RaceDialog::open() MWBase::Environment::get().getWorld ()->setupExternalRendering (*mPreview); mPreview->update (0); + const ESM::NPC proto = mPreview->getPrototype(); + setRaceId(proto.mRace); + recountParts(); + + std::string index = proto.mHead.substr(proto.mHead.size() - 2, 2); + mFaceIndex = boost::lexical_cast(index) - 1; + + index = proto.mHair.substr(proto.mHair.size() - 2, 2); + mHairIndex = boost::lexical_cast(index) - 1; + mPreviewImage->setImageTexture ("CharacterHeadPreview"); } @@ -143,6 +154,35 @@ int wrap(int index, int max) 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; @@ -174,31 +214,41 @@ void RaceDialog::onHeadRotate(MyGUI::ScrollBar*, size_t _position) void RaceDialog::onSelectPreviousGender(MyGUI::Widget*) { mGenderIndex = wrap(mGenderIndex - 1, 2); + + recountParts(); + updatePreview(); } void RaceDialog::onSelectNextGender(MyGUI::Widget*) { mGenderIndex = wrap(mGenderIndex + 1, 2); + + recountParts(); + updatePreview(); } void RaceDialog::onSelectPreviousFace(MyGUI::Widget*) { mFaceIndex = wrap(mFaceIndex - 1, mFaceCount); + updatePreview(); } void RaceDialog::onSelectNextFace(MyGUI::Widget*) { mFaceIndex = wrap(mFaceIndex + 1, mFaceCount); + updatePreview(); } void RaceDialog::onSelectPreviousHair(MyGUI::Widget*) { mHairIndex = wrap(mHairIndex - 1, mHairCount); + updatePreview(); } void RaceDialog::onSelectNextHair(MyGUI::Widget*) { - mHairIndex = wrap(mHairIndex - 1, mHairCount); + mHairIndex = wrap(mHairIndex + 1, mHairCount); + updatePreview(); } void RaceDialog::onSelectRace(MyGUI::ListBox* _sender, size_t _index) @@ -214,30 +264,67 @@ void RaceDialog::onSelectRace(MyGUI::ListBox* _sender, size_t _index) return; mCurrentRaceId = *raceId; + + recountParts(); + + updatePreview(); updateSkills(); updateSpellPowers(); } +void RaceDialog::recountParts() +{ + mFaceIndex = 0; + mHairIndex = 0; + + mFaceCount = countParts("head", mCurrentRaceId, mGenderIndex == 0); + mHairCount = countParts("hair", mCurrentRaceId, mGenderIndex == 0); +} + // update widget content +void RaceDialog::updatePreview() +{ + ESM::NPC record = mPreview->getPrototype(); + record.mRace = mCurrentRaceId; + record.setIsMale(mGenderIndex == 0); + + std::string prefix = + "b_n_" + mCurrentRaceId + ((record.isMale()) ? "_m_" : "_f_"); + + std::string headIndex = (boost::format("%02d") % (mFaceIndex + 1)).str(); + std::string hairIndex = (boost::format("%02d") % (mHairIndex + 1)).str(); + + record.mHead = prefix + "head_" + headIndex; + record.mHair = prefix + "hair_" + hairIndex; + + const MWWorld::Store &parts = + MWBase::Environment::get().getWorld()->getStore().get(); + + if (parts.search(record.mHair) == 0) { + record.mHair = prefix + "hair" + hairIndex; + } + mPreview->setPrototype(record); +} + void RaceDialog::updateRaces() { mRaceList->removeAllItems(); - const ESMS::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); + const MWWorld::Store &races = + MWBase::Environment::get().getWorld()->getStore().get(); - ESMS::RecListT::MapType::const_iterator it = store.races.list.begin(); - ESMS::RecListT::MapType::const_iterator end = store.races.list.end(); + int index = 0; - for (; it != end; ++it) + MWWorld::Store::iterator it = races.begin(); + for (; it != races.end(); ++it) { - const ESM::Race &race = it->second; - bool playable = race.mData.mFlags & ESM::Race::Playable; + bool playable = it->mData.mFlags & ESM::Race::Playable; if (!playable) // Only display playable races continue; - mRaceList->addItem(race.mName, it->first); - if (boost::iequals(it->first, mCurrentRaceId)) + mRaceList->addItem(it->mName, it->mId); + if (boost::iequals(it->mId, mCurrentRaceId)) mRaceList->setIndexSelected(index); ++index; } @@ -258,8 +345,8 @@ void RaceDialog::updateSkills() const int lineHeight = 18; MyGUI::IntCoord coord1(0, 0, mSkillList->getWidth(), 18); - const ESMS::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); - const ESM::Race *race = store.races.find(mCurrentRaceId); + const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); + const ESM::Race *race = store.get().find(mCurrentRaceId); int count = sizeof(race->mData.mBonus)/sizeof(race->mData.mBonus[0]); // TODO: Find a portable macro for this ARRAYSIZE? for (int i = 0; i < count; ++i) { @@ -296,8 +383,8 @@ void RaceDialog::updateSpellPowers() const int lineHeight = 18; MyGUI::IntCoord coord(0, 0, mSpellPowerList->getWidth(), 18); - const ESMS::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); - const ESM::Race *race = store.races.find(mCurrentRaceId); + const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); + const ESM::Race *race = store.get().find(mCurrentRaceId); std::vector::const_iterator it = race->mPowers.mList.begin(); std::vector::const_iterator end = race->mPowers.mList.end(); diff --git a/apps/openmw/mwgui/race.hpp b/apps/openmw/mwgui/race.hpp index c4734eae8c..e0dc3306a8 100644 --- a/apps/openmw/mwgui/race.hpp +++ b/apps/openmw/mwgui/race.hpp @@ -4,7 +4,7 @@ #include -#include +#include "../mwworld/esmstore.hpp" #include "../mwrender/characterpreview.hpp" @@ -34,6 +34,7 @@ namespace MWGui GM_Female }; + const ESM::NPC &getResult() const { return mPreview->getPrototype(); } const std::string &getRaceId() const { return mCurrentRaceId; } Gender getGender() const { return mGenderIndex == 0 ? GM_Male : GM_Female; } // getFace() @@ -77,6 +78,8 @@ namespace MWGui void updateRaces(); void updateSkills(); void updateSpellPowers(); + void updatePreview(); + void recountParts(); MyGUI::ImageBox* mPreviewImage; MyGUI::ListBox* mRaceList; diff --git a/apps/openmw/mwgui/review.cpp b/apps/openmw/mwgui/review.cpp index 984c7d1aea..45adb53832 100644 --- a/apps/openmw/mwgui/review.cpp +++ b/apps/openmw/mwgui/review.cpp @@ -5,7 +5,7 @@ #include #include -#include +#include "../mwworld/esmstore.hpp" #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" @@ -108,7 +108,9 @@ void ReviewDialog::setPlayerName(const std::string &name) void ReviewDialog::setRace(const std::string &raceId) { mRaceId = raceId; - const ESM::Race *race = MWBase::Environment::get().getWorld()->getStore().races.search(mRaceId); + + const ESM::Race *race = + MWBase::Environment::get().getWorld()->getStore().get().search(mRaceId); if (race) { ToolTips::createRaceToolTip(mRaceWidget, race); @@ -126,7 +128,9 @@ void ReviewDialog::setClass(const ESM::Class& class_) void ReviewDialog::setBirthSign(const std::string& signId) { mBirthSignId = signId; - const ESM::BirthSign *sign = MWBase::Environment::get().getWorld()->getStore().birthSigns.search(mBirthSignId); + + const ESM::BirthSign *sign = + MWBase::Environment::get().getWorld()->getStore().get().search(mBirthSignId); if (sign) { mBirthSignWidget->setCaption(sign->mName); @@ -281,7 +285,7 @@ void ReviewDialog::addSkills(const SkillList &skills, const std::string &titleId if (skillId < 0 || skillId > ESM::Skill::Length) // Skip unknown skill indexes continue; assert(skillId >= 0 && skillId < ESM::Skill::Length); - const std::string &skillNameId = ESMS::Skill::sSkillNameIds[skillId]; + const std::string &skillNameId = ESM::Skill::sSkillNameIds[skillId]; const MWMechanics::Stat &stat = mSkillValues.find(skillId)->second; float base = stat.getBase(); float modified = stat.getModified(); diff --git a/apps/openmw/mwgui/scrollwindow.cpp b/apps/openmw/mwgui/scrollwindow.cpp index c839e9b736..8317025e0b 100644 --- a/apps/openmw/mwgui/scrollwindow.cpp +++ b/apps/openmw/mwgui/scrollwindow.cpp @@ -36,7 +36,7 @@ void ScrollWindow::open (MWWorld::Ptr scroll) MWWorld::LiveCellRef *ref = mScroll.get(); BookTextParser parser; - MyGUI::IntSize size = parser.parse(ref->base->mText, mTextView, 390); + MyGUI::IntSize size = parser.parse(ref->mBase->mText, mTextView, 390); if (size.height > mTextView->getSize().height) mTextView->setCanvasSize(MyGUI::IntSize(410, size.height)); diff --git a/apps/openmw/mwgui/spellbuyingwindow.cpp b/apps/openmw/mwgui/spellbuyingwindow.cpp index ece19cdc38..a41f401a57 100644 --- a/apps/openmw/mwgui/spellbuyingwindow.cpp +++ b/apps/openmw/mwgui/spellbuyingwindow.cpp @@ -8,6 +8,7 @@ #include "../mwbase/world.hpp" #include "../mwbase/soundmanager.hpp" #include "../mwbase/windowmanager.hpp" +#include "../mwbase/mechanicsmanager.hpp" #include "../mwworld/player.hpp" #include "../mwworld/manualref.hpp" @@ -49,8 +50,12 @@ namespace MWGui void SpellBuyingWindow::addSpell(const std::string& spellId) { - const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(spellId); - int price = spell->mData.mCost*MWBase::Environment::get().getWorld()->getStore().gameSettings.find("fSpellValueMult")->getFloat(); + const MWWorld::ESMStore &store = + MWBase::Environment::get().getWorld()->getStore(); + + const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().get().find(spellId); + int price = spell->mData.mCost*store.get().find("fSpellValueMult")->getFloat(); + price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr,price,true); MyGUI::Button* toAdd = mSpellsView->createWidget( @@ -63,7 +68,6 @@ namespace MWGui ); mCurrentY += sLineHeight; - /// \todo price adjustment depending on merchantile skill toAdd->setUserData(price); toAdd->setCaptionWithReplacing(spell->mName+" - "+boost::lexical_cast(price)+"#{sgp}"); @@ -97,7 +101,8 @@ namespace MWGui for (MWMechanics::Spells::TIterator iter = merchantSpells.begin(); iter!=merchantSpells.end(); ++iter) { - const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find (*iter); + const ESM::Spell* spell = + MWBase::Environment::get().getWorld()->getStore().get().find (*iter); if (spell->mData.mType!=ESM::Spell::ST_Spell) continue; // don't try to sell diseases, curses or powers diff --git a/apps/openmw/mwgui/spellcreationdialog.cpp b/apps/openmw/mwgui/spellcreationdialog.cpp index 1aa20adae1..69d69519f9 100644 --- a/apps/openmw/mwgui/spellcreationdialog.cpp +++ b/apps/openmw/mwgui/spellcreationdialog.cpp @@ -2,14 +2,14 @@ #include -#include - #include "../mwbase/windowmanager.hpp" #include "../mwbase/world.hpp" #include "../mwbase/environment.hpp" #include "../mwbase/soundmanager.hpp" +#include "../mwbase/mechanicsmanager.hpp" +#include "../mwworld/esmstore.hpp" #include "../mwworld/player.hpp" #include "../mwworld/class.hpp" @@ -29,8 +29,11 @@ namespace bool sortMagicEffects (short id1, short id2) { - return MWBase::Environment::get().getWorld ()->getStore ().gameSettings.find(ESM::MagicEffect::effectIdToString (id1))->getString() - < MWBase::Environment::get().getWorld ()->getStore ().gameSettings.find(ESM::MagicEffect::effectIdToString (id2))->getString(); + const MWWorld::Store &gmst = + MWBase::Environment::get().getWorld()->getStore().get(); + + return gmst.find(ESM::MagicEffect::effectIdToString (id1))->getString() + < gmst.find(ESM::MagicEffect::effectIdToString (id2))->getString(); } } @@ -106,7 +109,8 @@ namespace MWGui void EditEffectDialog::editEffect (ESM::ENAMstruct effect) { - const ESM::MagicEffect* magicEffect = MWBase::Environment::get().getWorld()->getStore().magicEffects.find(effect.mEffectID); + const ESM::MagicEffect* magicEffect = + MWBase::Environment::get().getWorld()->getStore().get().find(effect.mEffectID); setMagicEffect(magicEffect); @@ -333,12 +337,12 @@ namespace MWGui MWBase::Environment::get().getSoundManager()->playSound ("Item Gold Up", 1.0, 1.0); - std::pair result = MWBase::Environment::get().getWorld()->createRecord(mSpell); + const ESM::Spell* spell = MWBase::Environment::get().getWorld()->createRecord(mSpell); MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player); MWMechanics::Spells& spells = stats.getSpells(); - spells.add (result.first); + spells.add (spell->mId); MWBase::Environment::get().getSoundManager()->playSound ("Item Gold Up", 1.0, 1.0); @@ -360,16 +364,23 @@ namespace MWGui { float y = 0; + const MWWorld::ESMStore &store = + MWBase::Environment::get().getWorld()->getStore(); + for (std::vector::const_iterator it = mEffects.begin(); it != mEffects.end(); ++it) { float x = 0.5 * it->mMagnMin + it->mMagnMax; - const ESM::MagicEffect* effect = MWBase::Environment::get().getWorld()->getStore().magicEffects.find(it->mEffectID); + const ESM::MagicEffect* effect = + store.get().find(it->mEffectID); + x *= 0.1 * effect->mData.mBaseCost; x *= 1 + it->mDuration; x += 0.05 * std::max(1, it->mArea) * effect->mData.mBaseCost; - float fEffectCostMult = MWBase::Environment::get().getWorld()->getStore().gameSettings.find("fEffectCostMult")->getFloat(); + float fEffectCostMult = + store.get().find("fEffectCostMult")->getFloat(); + y += x * fEffectCostMult; y = std::max(1.f,y); @@ -386,10 +397,10 @@ namespace MWGui mMagickaCost->setCaption(boost::lexical_cast(int(y))); - float fSpellMakingValueMult = MWBase::Environment::get().getWorld()->getStore().gameSettings.find("fSpellMakingValueMult")->getFloat(); + float fSpellMakingValueMult = + store.get().find("fSpellMakingValueMult")->getFloat(); - /// \todo mercantile - int price = int(y) * fSpellMakingValueMult; + int price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr,int(y) * fSpellMakingValueMult,true); mPriceLabel->setCaption(boost::lexical_cast(int(price))); @@ -424,7 +435,8 @@ namespace MWGui for (MWMechanics::Spells::TIterator it = spells.begin(); it != spells.end(); ++it) { - const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(*it); + const ESM::Spell* spell = + MWBase::Environment::get().getWorld()->getStore().get().find(*it); // only normal spells count if (spell->mData.mType != ESM::Spell::ST_Spell) @@ -444,14 +456,14 @@ namespace MWGui for (std::vector::const_iterator it = knownEffects.begin(); it != knownEffects.end(); ++it) { - mAvailableEffectsList->addItem(MWBase::Environment::get().getWorld ()->getStore ().gameSettings.find( + mAvailableEffectsList->addItem(MWBase::Environment::get().getWorld ()->getStore ().get().find( ESM::MagicEffect::effectIdToString (*it))->getString()); } mAvailableEffectsList->adjustSize (); for (std::vector::const_iterator it = knownEffects.begin(); it != knownEffects.end(); ++it) { - std::string name = MWBase::Environment::get().getWorld ()->getStore ().gameSettings.find( + std::string name = MWBase::Environment::get().getWorld ()->getStore ().get().find( ESM::MagicEffect::effectIdToString (*it))->getString(); MyGUI::Widget* w = mAvailableEffectsList->getItemWidget(name); w->setUserData(*it); @@ -517,7 +529,8 @@ namespace MWGui } } - const ESM::MagicEffect* effect = MWBase::Environment::get().getWorld()->getStore().magicEffects.find(effectId); + const ESM::MagicEffect* effect = + MWBase::Environment::get().getWorld()->getStore().get().find(effectId); mAddEffectDialog.newEffect (effect); diff --git a/apps/openmw/mwgui/spellwindow.cpp b/apps/openmw/mwgui/spellwindow.cpp index a203ac92b7..d62b23de47 100644 --- a/apps/openmw/mwgui/spellwindow.cpp +++ b/apps/openmw/mwgui/spellwindow.cpp @@ -4,7 +4,7 @@ #include #include -#include +#include "../mwworld/esmstore.hpp" #include "../mwbase/world.hpp" #include "../mwbase/environment.hpp" @@ -26,8 +26,11 @@ namespace { bool sortSpells(const std::string& left, const std::string& right) { - const ESM::Spell* a = MWBase::Environment::get().getWorld()->getStore().spells.find(left); - const ESM::Spell* b = MWBase::Environment::get().getWorld()->getStore().spells.find(right); + const MWWorld::Store &spells = + MWBase::Environment::get().getWorld()->getStore().get(); + + const ESM::Spell* a = spells.find(left); + const ESM::Spell* b = spells.find(right); int cmp = a->mName.compare(b->mName); return cmp < 0; @@ -139,11 +142,15 @@ namespace MWGui spellList.push_back(*it); } + const MWWorld::ESMStore &esmStore = + MWBase::Environment::get().getWorld()->getStore(); + std::vector powers; std::vector::iterator it = spellList.begin(); while (it != spellList.end()) { - const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(*it); + const ESM::Spell* spell = esmStore.get().find(*it); + if (spell->mData.mType == ESM::Spell::ST_Power) { powers.push_back(*it); @@ -170,7 +177,9 @@ namespace MWGui if (enchantId != "") { // only add items with "Cast once" or "Cast on use" - const ESM::Enchantment* enchant = MWBase::Environment::get().getWorld()->getStore().enchants.find(enchantId); + const ESM::Enchantment* enchant = + esmStore.get().find(enchantId); + int type = enchant->mData.mType; if (type != ESM::Enchantment::CastOnce && type != ESM::Enchantment::WhenUsed) @@ -191,7 +200,7 @@ namespace MWGui for (std::vector::const_iterator it = powers.begin(); it != powers.end(); ++it) { - const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(*it); + const ESM::Spell* spell = esmStore.get().find(*it); MyGUI::Button* t = mSpellView->createWidget("SpellText", MyGUI::IntCoord(4, mHeight, mWidth-8, spellHeight), MyGUI::Align::Left | MyGUI::Align::Top); t->setCaption(spell->mName); @@ -211,7 +220,7 @@ namespace MWGui addGroup("#{sSpells}", "#{sCostChance}"); for (std::vector::const_iterator it = spellList.begin(); it != spellList.end(); ++it) { - const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(*it); + const ESM::Spell* spell = esmStore.get().find(*it); MyGUI::Button* t = mSpellView->createWidget("SpellText", MyGUI::IntCoord(4, mHeight, mWidth-8, spellHeight), MyGUI::Align::Left | MyGUI::Align::Top); t->setCaption(spell->mName); @@ -244,7 +253,8 @@ namespace MWGui { MWWorld::Ptr item = *it; - const ESM::Enchantment* enchant = MWBase::Environment::get().getWorld()->getStore().enchants.find(MWWorld::Class::get(item).getEnchantment(item)); + const ESM::Enchantment* enchant = + esmStore.get().find(MWWorld::Class::get(item).getEnchantment(item)); // check if the item is currently equipped (will display in a different color) bool equipped = false; @@ -378,7 +388,9 @@ namespace MWGui if (MyGUI::InputManager::getInstance().isShiftPressed()) { // delete spell, if allowed - const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(spellId); + const ESM::Spell* spell = + MWBase::Environment::get().getWorld()->getStore().get().find(spellId); + if (spell->mData.mFlags & ESM::Spell::F_Always || spell->mData.mType == ESM::Spell::ST_Power) { diff --git a/apps/openmw/mwgui/stats_window.cpp b/apps/openmw/mwgui/stats_window.cpp index 665caaae1a..38a06940f4 100644 --- a/apps/openmw/mwgui/stats_window.cpp +++ b/apps/openmw/mwgui/stats_window.cpp @@ -54,10 +54,10 @@ StatsWindow::StatsWindow (MWBase::WindowManager& parWindowManager) { 0, 0 } }; - const ESMS::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); + const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); for (int i=0; names[i][0]; ++i) { - setText (names[i][0], store.gameSettings.find (names[i][1])->getString()); + setText (names[i][0], store.get().find (names[i][1])->getString()); } getWidget(mSkillView, "SkillView"); @@ -253,7 +253,12 @@ void StatsWindow::onFrame () setFactions(PCstats.getFactionRanks()); - setBirthSign(MWBase::Environment::get().getWorld()->getPlayer().getBirthsign()); + const std::string &signId = + MWBase::Environment::get().getWorld()->getPlayer().getBirthSign(); + + setBirthSign(signId); + setReputation (PCstats.getReputation ()); + setBounty (PCstats.getBounty ()); if (mChanged) updateSkillArea(); @@ -357,18 +362,22 @@ void StatsWindow::addSkills(const SkillList &skills, const std::string &titleId, if (skillId < 0 || skillId > ESM::Skill::Length) // Skip unknown skill indexes continue; assert(skillId >= 0 && skillId < ESM::Skill::Length); - const std::string &skillNameId = ESMS::Skill::sSkillNameIds[skillId]; + const std::string &skillNameId = ESM::Skill::sSkillNameIds[skillId]; const MWMechanics::Stat &stat = mSkillValues.find(skillId)->second; float base = stat.getBase(); float modified = stat.getModified(); int progressPercent = (modified - float(static_cast(modified))) * 100; - const ESM::Skill* skill = MWBase::Environment::get().getWorld()->getStore().skills.search(skillId); + const MWWorld::ESMStore &esmStore = + MWBase::Environment::get().getWorld()->getStore(); + + const ESM::Skill* skill = esmStore.get().find(skillId); assert(skill); std::string icon = "icons\\k\\" + ESM::Skill::sIconNames[skillId]; - const ESM::Attribute* attr = MWBase::Environment::get().getWorld()->getStore().attributes.search(skill->mData.mAttribute); + const ESM::Attribute* attr = + esmStore.get().find(skill->mData.mAttribute); assert(attr); std::string state = "normal"; @@ -422,10 +431,14 @@ void StatsWindow::updateSkillArea() if (!mMiscSkills.empty()) addSkills(mMiscSkills, "sSkillClassMisc", "Misc Skills", coord1, coord2); - const ESMS::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); + MWBase::World *world = MWBase::Environment::get().getWorld(); + const MWWorld::ESMStore &store = world->getStore(); + const ESM::NPC *player = + world->getPlayer().getPlayer().get()->mBase; // race tooltip - const ESM::Race* playerRace = store.races.find (MWBase::Environment::get().getWorld()->getPlayer().getRace()); + const ESM::Race* playerRace = store.get().find(player->mRace); + MyGUI::Widget* raceWidget; getWidget(raceWidget, "RaceText"); ToolTips::createRaceToolTip(raceWidget, playerRace); @@ -434,11 +447,14 @@ void StatsWindow::updateSkillArea() // class tooltip MyGUI::Widget* classWidget; - const ESM::Class& playerClass = MWBase::Environment::get().getWorld()->getPlayer().getClass(); + + const ESM::Class *playerClass = + store.get().find(player->mClass); + getWidget(classWidget, "ClassText"); - ToolTips::createClassToolTip(classWidget, playerClass); + ToolTips::createClassToolTip(classWidget, *playerClass); getWidget(classWidget, "Class_str"); - ToolTips::createClassToolTip(classWidget, playerClass); + ToolTips::createClassToolTip(classWidget, *playerClass); if (!mFactions.empty()) { @@ -450,7 +466,8 @@ void StatsWindow::updateSkillArea() FactionList::const_iterator end = mFactions.end(); for (FactionList::const_iterator it = mFactions.begin(); it != end; ++it) { - const ESM::Faction *faction = store.factions.find(it->first); + const ESM::Faction *faction = + store.get().find(it->first); MyGUI::Widget* w = addItem(faction->mName, coord1, coord2); std::string text; @@ -464,8 +481,8 @@ void StatsWindow::updateSkillArea() text += std::string("\n\n#DDC79E#{sNextRank} ") + faction->mRanks[it->second+1]; ESM::RankData rankData = faction->mData.mRankData[it->second+1]; - const ESM::Attribute* attr1 = MWBase::Environment::get().getWorld()->getStore().attributes.search(faction->mData.mAttribute1); - const ESM::Attribute* attr2 = MWBase::Environment::get().getWorld()->getStore().attributes.search(faction->mData.mAttribute2); + const ESM::Attribute* attr1 = store.get().find(faction->mData.mAttribute1); + const ESM::Attribute* attr2 = store.get().find(faction->mData.mAttribute2); assert(attr1 && attr2); text += "\n#BF9959#{" + attr1->mName + "}: " + boost::lexical_cast(rankData.mAttribute1) @@ -501,7 +518,8 @@ void StatsWindow::updateSkillArea() addSeparator(coord1, coord2); addGroup(mWindowManager.getGameSettingString("sBirthSign", "Sign"), coord1, coord2); - const ESM::BirthSign *sign = store.birthSigns.find(mBirthSignId); + const ESM::BirthSign *sign = + store.get().find(mBirthSignId); MyGUI::Widget* w = addItem(sign->mName, coord1, coord2); ToolTips::createBirthsignToolTip(w, mBirthSignId); diff --git a/apps/openmw/mwgui/stats_window.hpp b/apps/openmw/mwgui/stats_window.hpp index 75f8c568bf..f43682c96b 100644 --- a/apps/openmw/mwgui/stats_window.hpp +++ b/apps/openmw/mwgui/stats_window.hpp @@ -1,7 +1,7 @@ #ifndef MWGUI_STATS_WINDOW_H #define MWGUI_STATS_WINDOW_H -#include +#include "../mwworld/esmstore.hpp" #include #include @@ -38,8 +38,8 @@ namespace MWGui void setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::Stat& value); void configureSkills (const SkillList& major, const SkillList& minor); - void setReputation (int reputation) { this->mReputation = reputation; } - void setBounty (int bounty) { this->mBounty = bounty; } + void setReputation (int reputation) { if (reputation != mReputation) mChanged = true; this->mReputation = reputation; } + void setBounty (int bounty) { if (bounty != mBounty) mChanged = true; this->mBounty = bounty; } void updateSkillArea(); private: diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp index 02a4f0c39d..510bcb58f5 100644 --- a/apps/openmw/mwgui/tooltips.cpp +++ b/apps/openmw/mwgui/tooltips.cpp @@ -179,7 +179,9 @@ void ToolTips::onFrame(float frameDuration) else if (type == "Spell") { ToolTipInfo info; - const ESM::Spell *spell = MWBase::Environment::get().getWorld()->getStore().spells.find(focus->getUserString("Spell")); + + const ESM::Spell *spell = + MWBase::Environment::get().getWorld()->getStore().get().find(focus->getUserString("Spell")); info.caption = spell->mName; Widgets::SpellEffectList effects; std::vector::const_iterator end = spell->mEffects.mList.end(); @@ -368,10 +370,10 @@ IntSize ToolTips::createToolTip(const MWGui::ToolTipInfo& info) caption[0] = toupper(caption[0]); const ESM::Enchantment* enchant = 0; - const ESMS::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); + const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); if (info.enchant != "") { - enchant = store.enchants.search(info.enchant); + enchant = store.get().find(info.enchant); if (enchant->mData.mType == ESM::Enchantment::CastOnce) text += "\n#{sItemCastOnce}"; else if (enchant->mData.mType == ESM::Enchantment::WhenStrikes) @@ -574,10 +576,15 @@ void ToolTips::createSkillToolTip(MyGUI::Widget* widget, int skillId) if (skillId == -1) return; - const std::string &skillNameId = ESMS::Skill::sSkillNameIds[skillId]; - const ESM::Skill* skill = MWBase::Environment::get().getWorld()->getStore().skills.search(skillId); + const MWWorld::ESMStore &store = + MWBase::Environment::get().getWorld()->getStore(); + + const std::string &skillNameId = ESM::Skill::sSkillNameIds[skillId]; + const ESM::Skill* skill = store.get().find(skillId); assert(skill); - const ESM::Attribute* attr = MWBase::Environment::get().getWorld()->getStore().attributes.search(skill->mData.mAttribute); + + const ESM::Attribute* attr = + store.get().find(skill->mData.mAttribute); assert(attr); std::string icon = "icons\\k\\" + ESM::Skill::sIconNames[skillId]; @@ -610,12 +617,14 @@ void ToolTips::createSpecializationToolTip(MyGUI::Widget* widget, const std::str widget->setUserString("Caption_CenteredCaption", name); std::string specText; // get all skills of this specialisation - std::map skills = MWBase::Environment::get().getWorld()->getStore().skills.list; - for (std::map::const_iterator it = skills.begin(); - it != skills.end(); ++it) + const MWWorld::Store &skills = + MWBase::Environment::get().getWorld()->getStore().get(); + + MWWorld::Store::iterator it = skills.begin(); + for (; it != skills.end(); ++it) { - if (it->second.mData.mSpecialization == specId) - specText += std::string("\n#{") + ESM::Skill::sSkillNameIds[it->second.mIndex] + "}"; + if (it->mData.mSpecialization == specId) + specText += std::string("\n#{") + ESM::Skill::sSkillNameIds[it->mIndex] + "}"; } widget->setUserString("Caption_CenteredCaptionText", specText); widget->setUserString("ToolTipLayout", "TextWithCenteredCaptionToolTip"); @@ -624,7 +633,10 @@ void ToolTips::createSpecializationToolTip(MyGUI::Widget* widget, const std::str void ToolTips::createBirthsignToolTip(MyGUI::Widget* widget, const std::string& birthsignId) { - const ESM::BirthSign *sign = MWBase::Environment::get().getWorld()->getStore().birthSigns.find(birthsignId); + const MWWorld::ESMStore &store = + MWBase::Environment::get().getWorld()->getStore(); + + const ESM::BirthSign *sign = store.get().find(birthsignId); widget->setUserString("ToolTipType", "Layout"); widget->setUserString("ToolTipLayout", "BirthSignToolTip"); @@ -643,7 +655,7 @@ void ToolTips::createBirthsignToolTip(MyGUI::Widget* widget, const std::string& for (; it != end; ++it) { const std::string &spellId = *it; - const ESM::Spell *spell = MWBase::Environment::get().getWorld()->getStore().spells.search(spellId); + const ESM::Spell *spell = store.get().search(spellId); if (!spell) continue; // Skip spells which cannot be found ESM::Spell::SpellType type = static_cast(spell->mData.mType); @@ -658,7 +670,11 @@ void ToolTips::createBirthsignToolTip(MyGUI::Widget* widget, const std::string& spells.push_back(spellId); } - struct{ const std::vector &spells; std::string label; } categories[3] = { + struct { + const std::vector &spells; + std::string label; + } + categories[3] = { {abilities, "sBirthsignmenu1"}, {powers, "sPowers"}, {spells, "sBirthsignmenu2"} @@ -675,7 +691,7 @@ void ToolTips::createBirthsignToolTip(MyGUI::Widget* widget, const std::string& const std::string &spellId = *it; - const ESM::Spell *spell = MWBase::Environment::get().getWorld()->getStore().spells.search(spellId); + const ESM::Spell *spell = store.get().find(spellId); text += "\n#BF9959" + spell->mName; } } @@ -714,7 +730,8 @@ void ToolTips::createClassToolTip(MyGUI::Widget* widget, const ESM::Class& playe void ToolTips::createMagicEffectToolTip(MyGUI::Widget* widget, short id) { - const ESM::MagicEffect* effect = MWBase::Environment::get().getWorld ()->getStore ().magicEffects.find(id); + const ESM::MagicEffect* effect = + MWBase::Environment::get().getWorld ()->getStore ().get().find(id); const std::string &name = ESM::MagicEffect::effectIdToString (id); std::string icon = effect->mIcon; diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index 64710c2794..c6a21c461f 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -6,10 +6,17 @@ #include "../mwbase/world.hpp" #include "../mwbase/soundmanager.hpp" #include "../mwbase/windowmanager.hpp" +#include "../mwbase/mechanicsmanager.hpp" +#include "../mwbase/dialoguemanager.hpp" #include "../mwworld/inventorystore.hpp" #include "../mwworld/manualref.hpp" +#include "../mwmechanics/creaturestats.hpp" +#include "../mwmechanics/npcstats.hpp" + +#include "../mwworld/player.hpp" + #include "inventorywindow.hpp" namespace MWGui @@ -52,6 +59,8 @@ namespace MWGui mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onCancelButtonClicked); mOfferButton->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onOfferButtonClicked); + mIncreaseButton->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onIncreaseButtonClicked); + mDecreaseButton->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onDecreaseButtonClicked); setCoord(400, 0, 400, 300); @@ -63,6 +72,7 @@ namespace MWGui setTitle(MWWorld::Class::get(actor).getName(actor)); mCurrentBalance = 0; + mCurrentMerchantOffer = 0; mWindowManager.getInventoryWindow()->startTrade(); @@ -107,10 +117,14 @@ namespace MWGui bool goldFound = false; 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) == MWBase::Environment::get().getWorld()->getStore().gameSettings.find("sGold")->getString()) + if (MWWorld::Class::get(*it).getName(*it) == gmst.find("sGold")->getString()) { goldFound = true; gold = *it; @@ -131,6 +145,9 @@ namespace MWGui void TradeWindow::onOfferButtonClicked(MyGUI::Widget* _sender) { + const MWWorld::Store &gmst = + MWBase::Environment::get().getWorld()->getStore().get(); + // were there any items traded at all? MWWorld::ContainerStore& playerBought = mWindowManager.getInventoryWindow()->getBoughtItems(); MWWorld::ContainerStore& merchantBought = getBoughtItems(); @@ -156,15 +173,15 @@ namespace MWGui if (mPtr.getTypeName() == typeid(ESM::NPC).name()) { MWWorld::LiveCellRef* ref = mPtr.get(); - if (ref->base->mNpdt52.mGold == -10) - merchantgold = ref->base->mNpdt12.mGold; + if (ref->mBase->mNpdt52.mGold == -10) + merchantgold = ref->mBase->mNpdt12.mGold; else - merchantgold = ref->base->mNpdt52.mGold; + merchantgold = ref->mBase->mNpdt52.mGold; } else // ESM::Creature { MWWorld::LiveCellRef* ref = mPtr.get(); - merchantgold = ref->base->mData.mGold; + merchantgold = ref->mBase->mData.mGold; } if (mCurrentBalance > 0 && merchantgold < mCurrentBalance) { @@ -174,6 +191,59 @@ namespace MWGui return; } + if(mCurrentBalance > mCurrentMerchantOffer) + { + //if npc is a creature: reject (no haggle) + if (mPtr.getTypeName() != typeid(ESM::NPC).name()) + { + MWBase::Environment::get().getWindowManager()-> + messageBox("#{sNotifyMessage9}", std::vector()); + return; + } + + int a = abs(mCurrentMerchantOffer); + int b = abs(mCurrentBalance); + int d = 0; + if (mCurrentMerchantOffer<0) d = int(100 * (a - b) / a); + else d = int(100 * (b - a) / a); + + float clampedDisposition = std::max(0,std::min(int(MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(mPtr) + + MWBase::Environment::get().getDialogueManager()->getTemporaryDispositionChange()),100)); + + MWMechanics::NpcStats sellerSkill = MWWorld::Class::get(mPtr).getNpcStats(mPtr); + MWMechanics::CreatureStats sellerStats = MWWorld::Class::get(mPtr).getCreatureStats(mPtr); + MWWorld::Ptr playerPtr = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + MWMechanics::NpcStats playerSkill = MWWorld::Class::get(playerPtr).getNpcStats(playerPtr); + MWMechanics::CreatureStats playerStats = MWWorld::Class::get(playerPtr).getCreatureStats(playerPtr); + + float a1 = std::min(playerSkill.getSkill(ESM::Skill::Mercantile).getModified(), 100.f); + float b1 = std::min(0.1f * playerStats.getAttribute(ESM::Attribute::Luck).getModified(), 10.f); + float c1 = std::min(0.2f * playerStats.getAttribute(ESM::Attribute::Personality).getModified(), 10.f); + float d1 = std::min(sellerSkill.getSkill(ESM::Skill::Mercantile).getModified(), 100.f); + float e1 = std::min(0.1f * sellerStats.getAttribute(ESM::Attribute::Luck).getModified(), 10.f); + float f1 = std::min(0.2f * sellerStats.getAttribute(ESM::Attribute::Personality).getModified(), 10.f); + + float pcTerm = (clampedDisposition - 50 + a1 + b1 + c1) * playerStats.getFatigueTerm(); + float npcTerm = (d1 + e1 + f1) * sellerStats.getFatigueTerm(); + float x = gmst.find("fBargainOfferMulti")->getFloat() * d + gmst.find("fBargainOfferBase")->getFloat(); + if (mCurrentMerchantOffer<0) x += abs(int(pcTerm - npcTerm)); + else x += abs(int(npcTerm - pcTerm)); + + int roll = std::rand()%100 + 1; + if(roll > x) //trade refused + { + MWBase::Environment::get().getWindowManager()-> + messageBox("#{sNotifyMessage9}", std::vector()); + + int iBarterFailDisposition = gmst.find("iBarterFailDisposition")->getInt(); + MWBase::Environment::get().getDialogueManager()->applyTemporaryDispositionChange(iBarterFailDisposition); + return; + } + } + + int iBarterSuccessDisposition = gmst.find("iBarterSuccessDisposition")->getInt(); + MWBase::Environment::get().getDialogueManager()->applyTemporaryDispositionChange(iBarterSuccessDisposition); + // success! make the item transfer. transferBoughtItems(); mWindowManager.getInventoryWindow()->transferBoughtItems(); @@ -198,6 +268,20 @@ namespace MWGui mWindowManager.removeGuiMode(GM_Barter); } + void TradeWindow::onIncreaseButtonClicked(MyGUI::Widget* _sender) + { + if(mCurrentBalance<=-1) mCurrentBalance -= 1; + if(mCurrentBalance>=1) mCurrentBalance += 1; + updateLabels(); + } + + void TradeWindow::onDecreaseButtonClicked(MyGUI::Widget* _sender) + { + if(mCurrentBalance<-1) mCurrentBalance += 1; + if(mCurrentBalance>1) mCurrentBalance -= 1; + updateLabels(); + } + void TradeWindow::updateLabels() { mPlayerGold->setCaptionWithReplacing("#{sYourGold} " + boost::lexical_cast(mWindowManager.getInventoryWindow()->getPlayerGold())); @@ -217,15 +301,15 @@ namespace MWGui if (mPtr.getTypeName() == typeid(ESM::NPC).name()) { MWWorld::LiveCellRef* ref = mPtr.get(); - if (ref->base->mNpdt52.mGold == -10) - merchantgold = ref->base->mNpdt12.mGold; + if (ref->mBase->mNpdt52.mGold == -10) + merchantgold = ref->mBase->mNpdt12.mGold; else - merchantgold = ref->base->mNpdt52.mGold; + merchantgold = ref->mBase->mNpdt52.mGold; } else // ESM::Creature { MWWorld::LiveCellRef* ref = mPtr.get(); - merchantgold = ref->base->mData.mGold; + merchantgold = ref->mBase->mData.mGold; } mMerchantGold->setCaptionWithReplacing("#{sSellerGold} " + boost::lexical_cast(merchantgold)); @@ -261,14 +345,14 @@ namespace MWGui if (mPtr.getTypeName() == typeid(ESM::NPC).name()) { MWWorld::LiveCellRef* ref = mPtr.get(); - if (ref->base->mHasAI) - services = ref->base->mAiData.mServices; + if (ref->mBase->mHasAI) + services = ref->mBase->mAiData.mServices; } else if (mPtr.getTypeName() == typeid(ESM::Creature).name()) { MWWorld::LiveCellRef* ref = mPtr.get(); - if (ref->base->mHasAI) - services = ref->base->mAiData.mServices; + if (ref->mBase->mHasAI) + services = ref->mBase->mAiData.mServices; } /// \todo what about potions, there doesn't seem to be a flag for them?? @@ -316,19 +400,17 @@ namespace MWGui void TradeWindow::sellToNpc(MWWorld::Ptr item, int count) { - /// \todo price adjustment depending on merchantile skill - - mCurrentBalance -= MWWorld::Class::get(item).getValue(item) * count; + mCurrentBalance -= MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr, MWWorld::Class::get(item).getValue(item) * count,true); + mCurrentMerchantOffer -= MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr, MWWorld::Class::get(item).getValue(item) * count,true); updateLabels(); } void TradeWindow::buyFromNpc(MWWorld::Ptr item, int count) { - /// \todo price adjustment depending on merchantile skill - - mCurrentBalance += MWWorld::Class::get(item).getValue(item) * count; + mCurrentBalance += MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr, MWWorld::Class::get(item).getValue(item) * count,false); + mCurrentMerchantOffer += MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr, MWWorld::Class::get(item).getValue(item) * count,false); updateLabels(); } diff --git a/apps/openmw/mwgui/tradewindow.hpp b/apps/openmw/mwgui/tradewindow.hpp index 4ec55045c5..db386d8b6f 100644 --- a/apps/openmw/mwgui/tradewindow.hpp +++ b/apps/openmw/mwgui/tradewindow.hpp @@ -55,11 +55,14 @@ namespace MWGui MyGUI::TextBox* mMerchantGold; int mCurrentBalance; + int mCurrentMerchantOffer; void onWindowResize(MyGUI::Window* _sender); void onFilterChanged(MyGUI::Widget* _sender); void onOfferButtonClicked(MyGUI::Widget* _sender); void onCancelButtonClicked(MyGUI::Widget* _sender); + void onIncreaseButtonClicked(MyGUI::Widget* _sender); + void onDecreaseButtonClicked(MyGUI::Widget* _sender); // don't show items that the NPC has equipped in his trade-window. virtual bool ignoreEquippedItems() { return true; } diff --git a/apps/openmw/mwgui/trainingwindow.cpp b/apps/openmw/mwgui/trainingwindow.cpp index af61b3487b..ba39ee601c 100644 --- a/apps/openmw/mwgui/trainingwindow.cpp +++ b/apps/openmw/mwgui/trainingwindow.cpp @@ -7,6 +7,7 @@ #include "../mwbase/windowmanager.hpp" #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" +#include "../mwbase/mechanicsmanager.hpp" #include "../mwworld/player.hpp" @@ -73,10 +74,13 @@ namespace MWGui MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer (); MWMechanics::NpcStats& pcStats = MWWorld::Class::get(player).getNpcStats (player); + const MWWorld::Store &gmst = + MWBase::Environment::get().getWorld()->getStore().get(); + for (int i=0; i<3; ++i) { - /// \todo mercantile skill - int price = pcStats.getSkill (bestSkills[i].first).getBase() * MWBase::Environment::get().getWorld ()->getStore ().gameSettings.find("iTrainingMod")->getInt (); + int price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer + (mPtr,pcStats.getSkill (bestSkills[i].first).getBase() * gmst.find("iTrainingMod")->getInt (),true); std::string skin = (price > mWindowManager.getInventoryWindow ()->getPlayerGold ()) ? "SandTextGreyedOut" : "SandTextButton"; @@ -113,8 +117,11 @@ namespace MWGui MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer (); MWMechanics::NpcStats& pcStats = MWWorld::Class::get(player).getNpcStats (player); - /// \todo mercantile skill - int price = pcStats.getSkill (skillId).getBase() * MWBase::Environment::get().getWorld ()->getStore ().gameSettings.find("iTrainingMod")->getInt (); + const MWWorld::ESMStore &store = + MWBase::Environment::get().getWorld()->getStore(); + + int price = pcStats.getSkill (skillId).getBase() * store.get().find("iTrainingMod")->getInt (); + price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr,price,true); if (mWindowManager.getInventoryWindow()->getPlayerGold() *playerRef = player.get(); - const ESM::Class *class_ = MWBase::Environment::get().getWorld()->getStore().classes.find ( - playerRef->base->mClass); + + const ESM::Class *class_ = + store.get().find(playerRef->mBase->mClass); pcStats.increaseSkill (skillId, *class_, true); // remove gold diff --git a/apps/openmw/mwgui/travelwindow.cpp b/apps/openmw/mwgui/travelwindow.cpp index c19639aa6a..abbc6172fe 100644 --- a/apps/openmw/mwgui/travelwindow.cpp +++ b/apps/openmw/mwgui/travelwindow.cpp @@ -54,21 +54,25 @@ namespace MWGui { int price = 0; + const MWWorld::Store &gmst = + MWBase::Environment::get().getWorld()->getStore().get(); + if(interior) { - price = MWBase::Environment::get().getWorld()->getStore().gameSettings.find("fMagesGuildTravel")->getFloat(); + price = gmst.find("fMagesGuildTravel")->getFloat(); } else { MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); ESM::Position PlayerPos = player.getRefData().getPosition(); float d = sqrt( pow(pos.pos[0] - PlayerPos.pos[0],2) + pow(pos.pos[1] - PlayerPos.pos[1],2) + pow(pos.pos[2] - PlayerPos.pos[2],2) ); - price = d/MWBase::Environment::get().getWorld()->getStore().gameSettings.find("fTravelMult")->getFloat(); + price = d/gmst.find("fTravelMult")->getFloat(); } + price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr,price,true); + MyGUI::Button* toAdd = mDestinationsView->createWidget((price>mWindowManager.getInventoryWindow()->getPlayerGold()) ? "SandTextGreyedOut" : "SandTextButton", 0, mCurrentY, 200, sLineHeight, MyGUI::Align::Default); mCurrentY += sLineHeight; - /// \todo price adjustment depending on merchantile skill if(interior) toAdd->setUserString("interior","y"); else @@ -104,15 +108,15 @@ namespace MWGui MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); - for(unsigned int i = 0;i()->base->mTransport.size();i++) + for(unsigned int i = 0;i()->mBase->mTransport.size();i++) { - std::string cellname = mPtr.get()->base->mTransport[i].mCellName; + std::string cellname = mPtr.get()->mBase->mTransport[i].mCellName; bool interior = true; int x,y; - MWBase::Environment::get().getWorld()->positionToIndex(mPtr.get()->base->mTransport[i].mPos.pos[0], - mPtr.get()->base->mTransport[i].mPos.pos[1],x,y); - if(cellname == "") {cellname = MWBase::Environment::get().getWorld()->getExterior(x,y)->cell->mName; interior= false;} - addDestination(cellname,mPtr.get()->base->mTransport[i].mPos,interior); + MWBase::Environment::get().getWorld()->positionToIndex(mPtr.get()->mBase->mTransport[i].mPos.pos[0], + mPtr.get()->mBase->mTransport[i].mPos.pos[1],x,y); + if(cellname == "") {cellname = MWBase::Environment::get().getWorld()->getExterior(x,y)->mCell->mName; interior= false;} + addDestination(cellname,mPtr.get()->mBase->mTransport[i].mPos,interior); } updateLabels(); @@ -142,7 +146,7 @@ namespace MWGui cell = MWBase::Environment::get().getWorld()->getExterior(x,y); ESM::Position PlayerPos = player.getRefData().getPosition(); float d = sqrt( pow(pos.pos[0] - PlayerPos.pos[0],2) + pow(pos.pos[1] - PlayerPos.pos[1],2) + pow(pos.pos[2] - PlayerPos.pos[2],2) ); - int time = int(d /MWBase::Environment::get().getWorld()->getStore().gameSettings.find("fTravelTimeMult")->getFloat()); + int time = int(d /MWBase::Environment::get().getWorld()->getStore().get().find("fTravelTimeMult")->getFloat()); for(int i = 0;i < time;i++) { MWBase::Environment::get().getMechanicsManager ()->restoreDynamicStats (); diff --git a/apps/openmw/mwgui/waitdialog.cpp b/apps/openmw/mwgui/waitdialog.cpp index 71fd108dcf..31b5cce358 100644 --- a/apps/openmw/mwgui/waitdialog.cpp +++ b/apps/openmw/mwgui/waitdialog.cpp @@ -120,6 +120,7 @@ namespace MWGui int hour = MWBase::Environment::get().getWorld ()->getTimeStamp ().getHour (); bool pm = hour >= 12; if (hour >= 13) hour -= 12; + if (hour == 0) hour = 12; std::string dateTimeText = boost::lexical_cast(MWBase::Environment::get().getWorld ()->getDay ()) + " " diff --git a/apps/openmw/mwgui/widgets.cpp b/apps/openmw/mwgui/widgets.cpp index ed09b98058..82e1128263 100644 --- a/apps/openmw/mwgui/widgets.cpp +++ b/apps/openmw/mwgui/widgets.cpp @@ -2,12 +2,12 @@ #include -#include "components/esm_store/store.hpp" - #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" #include "../mwbase/windowmanager.hpp" +#include "../mwworld/esmstore.hpp" + #undef min #undef max @@ -228,8 +228,10 @@ void MWSpell::setSpellId(const std::string &spellId) void MWSpell::createEffectWidgets(std::vector &effects, MyGUI::WidgetPtr creator, MyGUI::IntCoord &coord, int flags) { - const ESMS::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); - const ESM::Spell *spell = store.spells.search(mId); + const MWWorld::ESMStore &store = + MWBase::Environment::get().getWorld()->getStore(); + + const ESM::Spell *spell = store.get().search(mId); MYGUI_ASSERT(spell, "spell with id '" << mId << "' not found"); MWSpellEffectPtr effect = nullptr; @@ -259,8 +261,10 @@ void MWSpell::updateWidgets() { if (mSpellNameWidget && mWindowManager) { - const ESMS::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); - const ESM::Spell *spell = store.spells.search(mId); + const MWWorld::ESMStore &store = + MWBase::Environment::get().getWorld()->getStore(); + + const ESM::Spell *spell = store.get().search(mId); if (spell) static_cast(mSpellNameWidget)->setCaption(spell->mName); else @@ -386,8 +390,14 @@ void MWSpellEffect::setSpellEffect(const SpellEffectParams& params) void MWSpellEffect::updateWidgets() { - const ESMS::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); - const ESM::MagicEffect *magicEffect = store.magicEffects.search(mEffectParams.mEffectID); + if (!mWindowManager) + return; + + const MWWorld::ESMStore &store = + MWBase::Environment::get().getWorld()->getStore(); + + const ESM::MagicEffect *magicEffect = + store.get().search(mEffectParams.mEffectID); assert(magicEffect); assert(mWindowManager); diff --git a/apps/openmw/mwgui/widgets.hpp b/apps/openmw/mwgui/widgets.hpp index a41e1f1238..4ac5383f7a 100644 --- a/apps/openmw/mwgui/widgets.hpp +++ b/apps/openmw/mwgui/widgets.hpp @@ -1,7 +1,7 @@ #ifndef MWGUI_WIDGETS_H #define MWGUI_WIDGETS_H -#include +#include "../mwworld/esmstore.hpp" #include diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 0350581e45..376eca88d3 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -83,7 +83,6 @@ WindowManager::WindowManager( , mSpellCreationDialog(NULL) , mEnchantingDialog(NULL) , mTrainingWindow(NULL) - , mPlayerClass() , mPlayerName() , mPlayerRaceId() , mPlayerAttributes() @@ -499,8 +498,7 @@ void WindowManager::setValue (const std::string& id, int value) void WindowManager::setPlayerClass (const ESM::Class &class_) { - mPlayerClass = class_; - mStatsWindow->setValue("class", mPlayerClass.mName); + mStatsWindow->setValue("class", class_.mName); } void WindowManager::configureSkills (const SkillList& major, const SkillList& minor) @@ -554,7 +552,9 @@ int WindowManager::readPressedButton () std::string WindowManager::getGameSettingString(const std::string &id, const std::string &default_) { - const ESM::GameSetting *setting = MWBase::Environment::get().getWorld()->getStore().gameSettings.search(id); + const ESM::GameSetting *setting = + MWBase::Environment::get().getWorld()->getStore().get().search(id); + if (setting && setting->mType == ESM::VT_String) return setting->getString(); return default_; @@ -582,6 +582,8 @@ void WindowManager::onFrame (float frameDuration) mDragAndDrop->mDraggedWidget->setPosition(MyGUI::InputManager::getInstance().getMousePosition()); } + mDialogueWindow->onFrame(); + mInventoryWindow->onFrame(); mStatsWindow->onFrame(); @@ -604,37 +606,40 @@ void WindowManager::onFrame (float frameDuration) void WindowManager::changeCell(MWWorld::Ptr::CellStore* cell) { - if (!(cell->cell->mData.mFlags & ESM::Cell::Interior)) + if (cell->mCell->isExterior()) { std::string name; - if (cell->cell->mName != "") + if (cell->mCell->mName != "") { - name = cell->cell->mName; - mMap->addVisitedLocation (name, cell->cell->getGridX (), cell->cell->getGridY ()); + name = cell->mCell->mName; + mMap->addVisitedLocation (name, cell->mCell->getGridX (), cell->mCell->getGridY ()); } else { - const ESM::Region* region = MWBase::Environment::get().getWorld()->getStore().regions.search(cell->cell->mRegion); + const ESM::Region* region = + MWBase::Environment::get().getWorld()->getStore().get().search(cell->mCell->mRegion); if (region) name = region->mName; else name = getGameSettingString("sDefaultCellname", "Wilderness"); } + mMap->cellExplored(cell->mCell->getGridX(), cell->mCell->getGridY()); + mMap->setCellName( name ); mHud->setCellName( name ); mMap->setCellPrefix("Cell"); mHud->setCellPrefix("Cell"); - mMap->setActiveCell( cell->cell->mData.mX, cell->cell->mData.mY ); - mHud->setActiveCell( cell->cell->mData.mX, cell->cell->mData.mY ); + mMap->setActiveCell( cell->mCell->getGridX(), cell->mCell->getGridY() ); + mHud->setActiveCell( cell->mCell->getGridX(), cell->mCell->getGridY() ); } else { - mMap->setCellName( cell->cell->mName ); - mHud->setCellName( cell->cell->mName ); - mMap->setCellPrefix( cell->cell->mName ); - mHud->setCellPrefix( cell->cell->mName ); + mMap->setCellName( cell->mCell->mName ); + mHud->setCellName( cell->mCell->mName ); + mMap->setCellPrefix( cell->mCell->mName ); + mHud->setCellPrefix( cell->mCell->mName ); } } @@ -717,7 +722,9 @@ void WindowManager::setDragDrop(bool dragDrop) void WindowManager::onRetrieveTag(const MyGUI::UString& _tag, MyGUI::UString& _result) { - const ESM::GameSetting *setting = MWBase::Environment::get().getWorld()->getStore().gameSettings.find(_tag); + const ESM::GameSetting *setting = + MWBase::Environment::get().getWorld()->getStore().get().find(_tag); + if (setting && setting->mType == ESM::VT_String) _result = setting->getString(); else @@ -769,6 +776,13 @@ void WindowManager::pushGuiMode(GuiMode mode) if (mode==GM_Inventory && mAllowed==GW_None) return; + + // If this mode already exists somewhere in the stack, just bring it to the front. + if (std::find(mGuiModes.begin(), mGuiModes.end(), mode) != mGuiModes.end()) + { + mGuiModes.erase(std::find(mGuiModes.begin(), mGuiModes.end(), mode)); + } + mGuiModes.push_back(mode); bool gameMode = !isGuiMode(); @@ -808,7 +822,10 @@ void WindowManager::removeGuiMode(GuiMode mode) void WindowManager::setSelectedSpell(const std::string& spellId, int successChancePercent) { mHud->setSelectedSpell(spellId, successChancePercent); - const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(spellId); + + const ESM::Spell* spell = + MWBase::Environment::get().getWorld()->getStore().get().find(spellId); + mSpellWindow->setTitle(spell->mName); } diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index aa796343e9..2e684b5da2 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -261,7 +261,6 @@ namespace MWGui /// \todo get rid of this stuff. Move it to the respective UI element classes, if needed. // Various stats about player as needed by window manager - ESM::Class mPlayerClass; std::string mPlayerName; std::string mPlayerRaceId; std::map > mPlayerAttributes; diff --git a/apps/openmw/mwmechanics/activespells.cpp b/apps/openmw/mwmechanics/activespells.cpp index df5ea7c3ff..989bdedd71 100644 --- a/apps/openmw/mwmechanics/activespells.cpp +++ b/apps/openmw/mwmechanics/activespells.cpp @@ -9,7 +9,7 @@ #include #include -#include +#include "../mwworld/esmstore.hpp" #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" @@ -86,7 +86,7 @@ namespace MWMechanics if (effects.second) { const ESM::MagicEffect *magicEffect = - MWBase::Environment::get().getWorld()->getStore().magicEffects.find ( + MWBase::Environment::get().getWorld()->getStore().get().find ( iter->mEffectID); if (iter->mDuration==0) @@ -114,18 +114,18 @@ namespace MWMechanics std::pair ActiveSpells::getEffectList (const std::string& id) const { if (const ESM::Spell *spell = - MWBase::Environment::get().getWorld()->getStore().spells.search (id)) + MWBase::Environment::get().getWorld()->getStore().get().search (id)) return std::make_pair (spell->mEffects, false); if (const ESM::Potion *potion = - MWBase::Environment::get().getWorld()->getStore().potions.search (id)) + MWBase::Environment::get().getWorld()->getStore().get().search (id)) return std::make_pair (potion->mEffects, false); if (const ESM::Ingredient *ingredient = - MWBase::Environment::get().getWorld()->getStore().ingreds.search (id)) + MWBase::Environment::get().getWorld()->getStore().get().search (id)) { const ESM::MagicEffect *magicEffect = - MWBase::Environment::get().getWorld()->getStore().magicEffects.find ( + MWBase::Environment::get().getWorld()->getStore().get().find ( ingredient->mData.mEffectID[0]); ESM::ENAMstruct effect; diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index f3b6b16162..d541baea99 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -7,7 +7,7 @@ #include -#include +#include "../mwworld/esmstore.hpp" #include "../mwworld/class.hpp" #include "../mwworld/inventorystore.hpp" @@ -101,11 +101,11 @@ namespace MWMechanics health.setCurrent (health.getCurrent() + 0.1 * endurance); stats.setHealth (health); - const ESMS::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); + const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); - float fFatigueReturnBase = store.gameSettings.find("fFatigueReturnBase")->getFloat (); - float fFatigueReturnMult = store.gameSettings.find("fFatigueReturnMult")->getFloat (); - float fEndFatigueMult = store.gameSettings.find("fEndFatigueMult")->getFloat (); + float fFatigueReturnBase = store.get().find("fFatigueReturnBase")->getFloat (); + float fFatigueReturnMult = store.get().find("fFatigueReturnMult")->getFloat (); + float fEndFatigueMult = store.get().find("fEndFatigueMult")->getFloat (); float capacity = MWWorld::Class::get(ptr).getCapacity(ptr); float encumbrance = MWWorld::Class::get(ptr).getEncumbrance(ptr); @@ -122,7 +122,7 @@ namespace MWMechanics if (!stunted) { - float fRestMagicMult = store.gameSettings.find("fRestMagicMult")->getFloat (); + float fRestMagicMult = store.get().find("fRestMagicMult")->getFloat (); DynamicStat magicka = stats.getMagicka(); magicka.setCurrent (magicka.getCurrent() diff --git a/apps/openmw/mwmechanics/aiactivate.cpp b/apps/openmw/mwmechanics/aiactivate.cpp new file mode 100644 index 0000000000..b94c8c2599 --- /dev/null +++ b/apps/openmw/mwmechanics/aiactivate.cpp @@ -0,0 +1,21 @@ +#include "aiactivate.hpp" +#include + +MWMechanics::AiActivate::AiActivate(const std::string &objectId) +: mObjectId(objectId) +{ +} +MWMechanics::AiActivate *MWMechanics::AiActivate::clone() const +{ + return new AiActivate(*this); +} +bool MWMechanics::AiActivate::execute (const MWWorld::Ptr& actor) +{ + std::cout << "AiActivate completed.\n"; + return true; +} + +int MWMechanics::AiActivate::getTypeId() const +{ + return 4; +} diff --git a/apps/openmw/mwmechanics/aiactivate.hpp b/apps/openmw/mwmechanics/aiactivate.hpp new file mode 100644 index 0000000000..7f3d4016dc --- /dev/null +++ b/apps/openmw/mwmechanics/aiactivate.hpp @@ -0,0 +1,23 @@ +#ifndef GAME_MWMECHANICS_AIACTIVATE_H +#define GAME_MWMECHANICS_AIACTIVATE_H + +#include "aipackage.hpp" +#include + +namespace MWMechanics +{ + + class AiActivate : public AiPackage + { + public: + AiActivate(const std::string &objectId); + virtual AiActivate *clone() const; + virtual bool execute (const MWWorld::Ptr& actor); + ///< \return Package completed? + virtual int getTypeId() const; + + private: + std::string mObjectId; + }; +} +#endif // GAME_MWMECHANICS_AIACTIVATE_H diff --git a/apps/openmw/mwmechanics/aiescort.cpp b/apps/openmw/mwmechanics/aiescort.cpp new file mode 100644 index 0000000000..27cd9095dc --- /dev/null +++ b/apps/openmw/mwmechanics/aiescort.cpp @@ -0,0 +1,24 @@ +#include "aiescort.hpp" +#include + +MWMechanics::AiEscort::AiEscort(const std::string &actorId,int duration, float x, float y, float z) +: mActorId(actorId), mX(x), mY(y), mZ(z), mDuration(duration) +{ +} + +MWMechanics::AiEscort *MWMechanics::AiEscort::clone() const +{ + return new AiEscort(*this); +} + +bool MWMechanics::AiEscort::execute (const MWWorld::Ptr& actor) +{ + std::cout << "AiEscort completed. \n"; + return true; +} + +int MWMechanics::AiEscort::getTypeId() const +{ + return 2; +} + diff --git a/apps/openmw/mwmechanics/aiescort.hpp b/apps/openmw/mwmechanics/aiescort.hpp new file mode 100644 index 0000000000..fef70f508e --- /dev/null +++ b/apps/openmw/mwmechanics/aiescort.hpp @@ -0,0 +1,29 @@ +#ifndef GAME_MWMECHANICS_AIESCORT_H +#define GAME_MWMECHANICS_AIESCORT_H + +#include "aipackage.hpp" +#include + +namespace MWMechanics +{ + class AiEscort : public AiPackage + { + public: + AiEscort(const std::string &actorId,int duration, float x, float y, float z); + virtual AiEscort *clone() const; + + virtual bool execute (const MWWorld::Ptr& actor); + ///< \return Package completed? + + virtual int getTypeId() const; + + private: + std::string mActorId; + float mX; + float mY; + float mZ; + int mDuration; + + }; +} +#endif diff --git a/apps/openmw/mwmechanics/aifollow.cpp b/apps/openmw/mwmechanics/aifollow.cpp new file mode 100644 index 0000000000..3fee6d98c3 --- /dev/null +++ b/apps/openmw/mwmechanics/aifollow.cpp @@ -0,0 +1,22 @@ +#include "aifollow.hpp" +#include + +MWMechanics::AiFollow::AiFollow(const std::string &actorId,float duration, float x, float y, float z) +: mDuration(duration), mX(x), mY(y), mZ(z), mActorId(actorId) +{ +} +MWMechanics::AiFollow *MWMechanics::AiFollow::clone() const +{ + return new AiFollow(*this); +} + + bool MWMechanics::AiFollow::execute (const MWWorld::Ptr& actor) +{ + std::cout << "AiFollow completed.\n"; + return true; +} + + int MWMechanics::AiFollow::getTypeId() const +{ + return 3; +} diff --git a/apps/openmw/mwmechanics/aifollow.hpp b/apps/openmw/mwmechanics/aifollow.hpp new file mode 100644 index 0000000000..ded13d7800 --- /dev/null +++ b/apps/openmw/mwmechanics/aifollow.hpp @@ -0,0 +1,27 @@ +#ifndef GAME_MWMECHANICS_AIFALLOW_H +#define GAME_MWMECHANICS_AIFALLOW_H + +#include "aipackage.hpp" +#include + +namespace MWMechanics +{ + + class AiFollow : public AiPackage + { + public: + AiFollow(const std::string &ActorId,float duration, float X, float Y, float Z); + virtual AiFollow *clone() const; + virtual bool execute (const MWWorld::Ptr& actor); + ///< \return Package completed? + virtual int getTypeId() const; + + private: + float mDuration; + float mX; + float mY; + float mZ; + std::string mActorId; + }; +} +#endif diff --git a/apps/openmw/mwmechanics/aitravel.cpp b/apps/openmw/mwmechanics/aitravel.cpp new file mode 100644 index 0000000000..897dd17480 --- /dev/null +++ b/apps/openmw/mwmechanics/aitravel.cpp @@ -0,0 +1,25 @@ +#include "aitravel.hpp" +#include + +MWMechanics::AiTravel::AiTravel(float x, float y, float z) +: mX(x),mY(y),mZ(z) +{ +} + +MWMechanics::AiTravel * MWMechanics::AiTravel::clone() const +{ + return new AiTravel(*this); +} + +bool MWMechanics::AiTravel::execute (const MWWorld::Ptr& actor) +{ + std::cout << "AiTravel completed.\n"; + return true; +} + +int MWMechanics::AiTravel::getTypeId() const +{ + return 1; +} + + diff --git a/apps/openmw/mwmechanics/aitravel.hpp b/apps/openmw/mwmechanics/aitravel.hpp new file mode 100644 index 0000000000..1c6abbf279 --- /dev/null +++ b/apps/openmw/mwmechanics/aitravel.hpp @@ -0,0 +1,27 @@ +#ifndef GAME_MWMECHANICS_AITRAVEL_H +#define GAME_MWMECHANICS_AITRAVEL_H + +#include "aipackage.hpp" + +namespace MWMechanics +{ + class AiTravel : public AiPackage + { + public: + AiTravel(float x, float y, float z); + virtual AiTravel *clone() const; + + virtual bool execute (const MWWorld::Ptr& actor); + ///< \return Package completed? + + virtual int getTypeId() const; + + private: + float mX; + float mY; + float mZ; + + }; +} + +#endif diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp new file mode 100644 index 0000000000..e9db6d212a --- /dev/null +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -0,0 +1,23 @@ +#include "aiwander.hpp" +#include + +MWMechanics::AiWander::AiWander(int distance, int duration, int timeOfDay, const std::vector& idle): + mDistance(distance), mDuration(duration), mTimeOfDay(timeOfDay), mIdle(idle) +{ +} + +MWMechanics::AiPackage * MWMechanics::AiWander::clone() const +{ + return new AiWander(*this); +} + +bool MWMechanics::AiWander::execute (const MWWorld::Ptr& actor) +{ + std::cout << "AiWadner completed.\n"; + return true; +} + +int MWMechanics::AiWander::getTypeId() const +{ + return 0; +} diff --git a/apps/openmw/mwmechanics/aiwander.hpp b/apps/openmw/mwmechanics/aiwander.hpp new file mode 100644 index 0000000000..a71858febc --- /dev/null +++ b/apps/openmw/mwmechanics/aiwander.hpp @@ -0,0 +1,29 @@ +#ifndef GAME_MWMECHANICS_AIWANDER_H +#define GAME_MWMECHANICS_AIWANDER_H + +#include "aipackage.hpp" +#include + +namespace MWMechanics +{ + + class AiWander : public AiPackage + { + public: + + AiWander(int distance, int duration, int timeOfDay, const std::vector& idle); + virtual AiPackage *clone() const; + virtual bool execute (const MWWorld::Ptr& actor); + ///< \return Package completed? + virtual int getTypeId() const; + ///< 0: Wander + + private: + int mDistance; + int mDuration; + int mTimeOfDay; + std::vector mIdle; + }; + } + +#endif diff --git a/apps/openmw/mwmechanics/alchemy.cpp b/apps/openmw/mwmechanics/alchemy.cpp index 962350472e..c07c602096 100644 --- a/apps/openmw/mwmechanics/alchemy.cpp +++ b/apps/openmw/mwmechanics/alchemy.cpp @@ -13,11 +13,11 @@ #include #include -#include #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" +#include "../mwworld/esmstore.hpp" #include "../mwworld/containerstore.hpp" #include "../mwworld/class.hpp" #include "../mwworld/cellstore.hpp" @@ -38,11 +38,11 @@ std::set MWMechanics::Alchemy::listEffects() const const MWWorld::LiveCellRef *ingredient = iter->get(); for (int i=0; i<4; ++i) - if (ingredient->base->mData.mEffectID[i]!=-1) + if (ingredient->mBase->mData.mEffectID[i]!=-1) { EffectKey key ( - ingredient->base->mData.mEffectID[i], ingredient->base->mData.mSkills[i]!=-1 ? - ingredient->base->mData.mSkills[i] : ingredient->base->mData.mAttributes[i]); + ingredient->mBase->mData.mEffectID[i], ingredient->mBase->mData.mSkills[i]!=-1 ? + ingredient->mBase->mData.mSkills[i] : ingredient->mBase->mData.mAttributes[i]); ++effects[key]; } @@ -77,9 +77,9 @@ void MWMechanics::Alchemy::applyTools (int flags, float& value) const else return; - float toolQuality = setup==1 || setup==2 ? mTools[tool].get()->base->mData.mQuality : 0; + float toolQuality = setup==1 || setup==2 ? mTools[tool].get()->mBase->mData.mQuality : 0; float calcinatorQuality = setup==1 || setup==3 ? - mTools[ESM::Apparatus::Calcinator].get()->base->mData.mQuality : 0; + mTools[ESM::Apparatus::Calcinator].get()->mBase->mData.mQuality : 0; float quality = 1; @@ -130,30 +130,30 @@ void MWMechanics::Alchemy::updateEffects() // general alchemy factor float x = getChance(); - x *= mTools[ESM::Apparatus::MortarPestle].get()->base->mData.mQuality; - x *= MWBase::Environment::get().getWorld()->getStore().gameSettings.find ("fPotionStrengthMult")->getFloat(); + x *= mTools[ESM::Apparatus::MortarPestle].get()->mBase->mData.mQuality; + x *= MWBase::Environment::get().getWorld()->getStore().get().find ("fPotionStrengthMult")->getFloat(); // value mValue = static_cast ( - x * MWBase::Environment::get().getWorld()->getStore().gameSettings.find ("iAlchemyMod")->getFloat()); + x * MWBase::Environment::get().getWorld()->getStore().get().find ("iAlchemyMod")->getFloat()); // build quantified effect list for (std::set::const_iterator iter (effects.begin()); iter!=effects.end(); ++iter) { const ESM::MagicEffect *magicEffect = - MWBase::Environment::get().getWorld()->getStore().magicEffects.find (iter->mId); + MWBase::Environment::get().getWorld()->getStore().get().find (iter->mId); if (magicEffect->mData.mBaseCost<=0) throw std::runtime_error ("invalid base cost for magic effect " + iter->mId); float fPotionT1MagMul = - MWBase::Environment::get().getWorld()->getStore().gameSettings.find ("fPotionT1MagMult")->getFloat(); + MWBase::Environment::get().getWorld()->getStore().get().find ("fPotionT1MagMult")->getFloat(); if (fPotionT1MagMul<=0) throw std::runtime_error ("invalid gmst: fPotionT1MagMul"); float fPotionT1DurMult = - MWBase::Environment::get().getWorld()->getStore().gameSettings.find ("fPotionT1DurMult")->getFloat(); + MWBase::Environment::get().getWorld()->getStore().get().find ("fPotionT1DurMult")->getFloat(); if (fPotionT1DurMult<=0) throw std::runtime_error ("invalid gmst: fPotionT1DurMult"); @@ -192,18 +192,20 @@ void MWMechanics::Alchemy::updateEffects() const ESM::Potion *MWMechanics::Alchemy::getRecord() const { - for (ESMS::RecListWithIDT::MapType::const_iterator iter ( - MWBase::Environment::get().getWorld()->getStore().potions.list.begin()); - iter!=MWBase::Environment::get().getWorld()->getStore().potions.list.end(); ++iter) + const MWWorld::Store &potions = + MWBase::Environment::get().getWorld()->getStore().get(); + + MWWorld::Store::iterator iter = potions.begin(); + for (; iter != potions.end(); ++iter) { - if (iter->second.mEffects.mList.size()!=mEffects.size()) + if (iter->mEffects.mList.size() != mEffects.size()) continue; bool mismatch = false; - for (int i=0; i (iter->second.mEffects.mList.size()); ++iter) + for (int i=0; i (iter->mEffects.mList.size()); ++iter) { - const ESM::ENAMstruct& first = iter->second.mEffects.mList[i]; + const ESM::ENAMstruct& first = iter->mEffects.mList[i]; const ESM::ENAMstruct& second = mEffects[i]; if (first.mEffectID!=second.mEffectID || @@ -221,7 +223,7 @@ const ESM::Potion *MWMechanics::Alchemy::getRecord() const } if (!mismatch) - return &iter->second; + return &(*iter); } return 0; @@ -258,7 +260,7 @@ void MWMechanics::Alchemy::addPotion (const std::string& name) for (TIngredientsIterator iter (beginIngredients()); iter!=endIngredients(); ++iter) if (!iter->isEmpty()) - newRecord.mData.mWeight += iter->get()->base->mData.mWeight; + newRecord.mData.mWeight += iter->get()->mBase->mData.mWeight; newRecord.mData.mWeight /= countIngredients(); @@ -277,7 +279,7 @@ void MWMechanics::Alchemy::addPotion (const std::string& name) newRecord.mEffects.mList = mEffects; - record = MWBase::Environment::get().getWorld()->createRecord (newRecord).second; + record = MWBase::Environment::get().getWorld()->createRecord (newRecord); } MWWorld::ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), record->mId); @@ -332,13 +334,13 @@ void MWMechanics::Alchemy::setAlchemist (const MWWorld::Ptr& npc) { MWWorld::LiveCellRef* ref = iter->get(); - int type = ref->base->mData.mType; + int type = ref->mBase->mData.mType; if (type<0 || type>=static_cast (mTools.size())) throw std::runtime_error ("invalid apparatus type"); if (!mTools[type].isEmpty()) - if (ref->base->mData.mQuality<=mTools[type].get()->base->mData.mQuality) + if (ref->mBase->mData.mQuality<=mTools[type].get()->mBase->mData.mQuality) continue; mTools[type] = *iter; diff --git a/apps/openmw/mwmechanics/creaturestats.cpp b/apps/openmw/mwmechanics/creaturestats.cpp index 1e57ba3136..4be5d55b22 100644 --- a/apps/openmw/mwmechanics/creaturestats.cpp +++ b/apps/openmw/mwmechanics/creaturestats.cpp @@ -2,16 +2,19 @@ #include -#include +#include "../mwworld/esmstore.hpp" #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" namespace MWMechanics -{ +{ CreatureStats::CreatureStats() - : mLevel (0), mHello (0), mFight (0), mFlee (0), mAlarm (0), mLevelHealthBonus(0.f), mDead (false) + : mLevel (0), mLevelHealthBonus(0.f), mDead (false), mFriendlyHits (0), mTalkedTo (false), mAlarmed (false), + mAttacked (false), mHostile (false) { + for (int i=0; i<4; ++i) + mAiSettings[i] = 0; } void CreatureStats::increaseLevelHealthBonus (float value) @@ -28,25 +31,26 @@ namespace MWMechanics { return mAiSequence; } - + AiSequence& CreatureStats::getAiSequence() { - return mAiSequence; + return mAiSequence; } - - float CreatureStats::getFatigueTerm() const + + float CreatureStats::getFatigueTerm() const { int max = getFatigue().getModified(); int current = getFatigue().getCurrent(); - + float normalised = max==0 ? 1 : std::max (0.0f, static_cast (current)/max); - const ESMS::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); - - return store.gameSettings.find ("fFatigueBase")->getFloat() - - store.gameSettings.find ("fFatigueMult")->getFloat() * (1-normalised); + const MWWorld::Store &gmst = + MWBase::Environment::get().getWorld()->getStore().get(); + + return gmst.find ("fFatigueBase")->getFloat() + - gmst.find ("fFatigueMult")->getFloat() * (1-normalised); } - + const Stat &CreatureStats::getAttribute(int index) const { if (index < 0 || index > 7) { @@ -89,25 +93,11 @@ namespace MWMechanics { return mLevel; } - - int CreatureStats::getHello() const - { - return mHello; - } - int CreatureStats::getFight() const + int CreatureStats::getAiSetting (int index) const { - return mFight; - } - - int CreatureStats::getFlee() const - { - return mFlee; - } - - int CreatureStats::getAlarm() const - { - return mAlarm; + assert (index>=0 && index<4); + return mAiSettings[index]; } Stat &CreatureStats::getAttribute(int index) @@ -179,7 +169,7 @@ namespace MWMechanics if (index==0 && mDynamic[index].getCurrent()<1) mDead = true; } - + void CreatureStats::setLevel(int level) { mLevel = level; @@ -195,40 +185,91 @@ namespace MWMechanics mMagicEffects = effects; } - void CreatureStats::setHello(int value) + void CreatureStats::setAiSetting (int index, int value) { - mHello = value; + assert (index>=0 && index<4); + mAiSettings[index] = value; } - void CreatureStats::setFight(int value) - { - mFight = value; - } - - void CreatureStats::setFlee(int value) - { - mFlee = value; - } - - void CreatureStats::setAlarm(int value) - { - mAlarm = value; - } - bool CreatureStats::isDead() const { return mDead; } - + void CreatureStats::resurrect() { if (mDead) { if (mDynamic[0].getCurrent()<1) mDynamic[0].setCurrent (1); - + if (mDynamic[0].getCurrent()>=1) mDead = false; } } + + bool CreatureStats::hasCommonDisease() const + { + return mSpells.hasCommonDisease(); + } + + bool CreatureStats::hasBlightDisease() const + { + return mSpells.hasBlightDisease(); + } + + int CreatureStats::getFriendlyHits() const + { + return mFriendlyHits; + } + + void CreatureStats::friendlyHit() + { + ++mFriendlyHits; + } + + bool CreatureStats::hasTalkedToPlayer() const + { + return mTalkedTo; + } + + void CreatureStats::talkedToPlayer() + { + mTalkedTo = true; + } + + bool CreatureStats::isAlarmed() const + { + return mAlarmed; + } + + void CreatureStats::setAlarmed (bool alarmed) + { + mAlarmed = alarmed; + } + + bool CreatureStats::getAttacked() const + { + return mAttacked; + } + + void CreatureStats::setAttacked (bool attacked) + { + mAttacked = attacked; + } + + bool CreatureStats::isHostile() const + { + return mHostile; + } + + void CreatureStats::setHostile (bool hostile) + { + mHostile = hostile; + } + + bool CreatureStats::getCreatureTargetted() const + { + return false; + } } diff --git a/apps/openmw/mwmechanics/creaturestats.hpp b/apps/openmw/mwmechanics/creaturestats.hpp index 671dcd4396..3375c1af83 100644 --- a/apps/openmw/mwmechanics/creaturestats.hpp +++ b/apps/openmw/mwmechanics/creaturestats.hpp @@ -24,13 +24,15 @@ namespace MWMechanics Spells mSpells; ActiveSpells mActiveSpells; MagicEffects mMagicEffects; - int mHello; - int mFight; - int mFlee; - int mAlarm; + int mAiSettings[4]; AiSequence mAiSequence; float mLevelHealthBonus; - bool mDead; + bool mDead; + int mFriendlyHits; + bool mTalkedTo; + bool mAlarmed; + bool mAttacked; + bool mHostile; public: CreatureStats(); @@ -53,13 +55,8 @@ namespace MWMechanics int getLevel() const; - int getHello() const; - - int getFight() const; - - int getFlee() const; - - int getAlarm() const; + int getAiSetting (int index) const; + ///< 0: hello, 1 fight, 2 flee, 3 alarm Stat & getAttribute(int index); @@ -87,18 +84,13 @@ namespace MWMechanics void setLevel(int level); - void setHello(int value); + void setAiSetting (int index, int value); + ///< 0: hello, 1 fight, 2 flee, 3 alarm - void setFight(int value); - - void setFlee(int value); - - void setAlarm(int value); - const AiSequence& getAiSequence() const; - + AiSequence& getAiSequence(); - + float getFatigueTerm() const; ///< Return effective fatigue @@ -107,8 +99,37 @@ namespace MWMechanics float getLevelHealthBonus() const; bool isDead() const; - + void resurrect(); + + bool hasCommonDisease() const; + + bool hasBlightDisease() const; + + int getFriendlyHits() const; + ///< Number of friendly hits received. + + void friendlyHit(); + ///< Increase number of friendly hits by one. + + bool hasTalkedToPlayer() const; + ///< Has this creature talked with the player before? + + void talkedToPlayer(); + + bool isAlarmed() const; + + void setAlarmed (bool alarmed); + + bool getAttacked() const; + + void setAttacked (bool attacked); + + bool isHostile() const; + + void setHostile (bool hostile); + + bool getCreatureTargetted() const; }; } diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 873dd94988..1b6e4b9f3c 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -1,11 +1,12 @@ #include "mechanicsmanagerimp.hpp" -#include +#include "../mwworld/esmstore.hpp" #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" #include "../mwbase/windowmanager.hpp" +#include "../mwbase/dialoguemanager.hpp" #include "../mwworld/class.hpp" #include "../mwworld/player.hpp" @@ -19,7 +20,7 @@ namespace MWMechanics MWMechanics::CreatureStats& creatureStats = MWWorld::Class::get (ptr).getCreatureStats (ptr); MWMechanics::NpcStats& npcStats = MWWorld::Class::get (ptr).getNpcStats (ptr); - const ESM::NPC *player = ptr.get()->base; + const ESM::NPC *player = ptr.get()->mBase; // reset creatureStats.setLevel(player->mNpdt52.mLevel); @@ -37,15 +38,17 @@ namespace MWMechanics creatureStats.getAttribute(5).setBase (player->mNpdt52.mEndurance); creatureStats.getAttribute(6).setBase (player->mNpdt52.mPersonality); creatureStats.getAttribute(7).setBase (player->mNpdt52.mLuck); + + const MWWorld::ESMStore &esmStore = + MWBase::Environment::get().getWorld()->getStore(); // race if (mRaceSelected) { const ESM::Race *race = - MWBase::Environment::get().getWorld()->getStore().races.find ( - MWBase::Environment::get().getWorld()->getPlayer().getRace()); + esmStore.get().find(player->mRace); - bool male = MWBase::Environment::get().getWorld()->getPlayer().isMale(); + bool male = (player->mFlags & ESM::NPC::Female) == 0; for (int i=0; i<8; ++i) { @@ -88,11 +91,13 @@ namespace MWMechanics } // birthsign - if (!MWBase::Environment::get().getWorld()->getPlayer().getBirthsign().empty()) + const std::string &signId = + MWBase::Environment::get().getWorld()->getPlayer().getBirthSign(); + + if (!signId.empty()) { const ESM::BirthSign *sign = - MWBase::Environment::get().getWorld()->getStore().birthSigns.find ( - MWBase::Environment::get().getWorld()->getPlayer().getBirthsign()); + esmStore.get().find(signId); for (std::vector::const_iterator iter (sign->mPowers.mList.begin()); iter!=sign->mPowers.mList.end(); ++iter) @@ -104,11 +109,12 @@ namespace MWMechanics // class if (mClassSelected) { - const ESM::Class& class_ = MWBase::Environment::get().getWorld()->getPlayer().getClass(); + const ESM::Class *class_ = + esmStore.get().find(player->mClass); for (int i=0; i<2; ++i) { - int attribute = class_.mData.mAttribute[i]; + int attribute = class_->mData.mAttribute[i]; if (attribute>=0 && attribute<8) { creatureStats.getAttribute(attribute).setBase ( @@ -122,7 +128,7 @@ namespace MWMechanics for (int i2=0; i2<5; ++i2) { - int index = class_.mData.mSkills[i2][i]; + int index = class_->mData.mSkills[i2][i]; if (index>=0 && index<27) { @@ -132,14 +138,15 @@ namespace MWMechanics } } - typedef ESMS::IndexListT::MapType ContainerType; - const ContainerType& skills = MWBase::Environment::get().getWorld()->getStore().skills.list; + const MWWorld::Store &skills = + esmStore.get(); - for (ContainerType::const_iterator iter (skills.begin()); iter!=skills.end(); ++iter) + MWWorld::Store::iterator iter = skills.begin(); + for (; iter != skills.end(); ++iter) { - if (iter->second.mData.mSpecialization==class_.mData.mSpecialization) + if (iter->mData.mSpecialization==class_->mData.mSpecialization) { - int index = iter->first; + int index = iter->mIndex; if (index>=0 && index<27) { @@ -261,12 +268,22 @@ namespace MWMechanics if (mUpdatePlayer) { // basic player profile; should not change anymore after the creation phase is finished. - MWBase::Environment::get().getWindowManager()->setValue ("name", MWBase::Environment::get().getWorld()->getPlayer().getName()); - MWBase::Environment::get().getWindowManager()->setValue ("race", - MWBase::Environment::get().getWorld()->getStore().races.find (MWBase::Environment::get().getWorld()->getPlayer(). - getRace())->mName); - MWBase::Environment::get().getWindowManager()->setValue ("class", - MWBase::Environment::get().getWorld()->getPlayer().getClass().mName); + MWBase::WindowManager *winMgr = + MWBase::Environment::get().getWindowManager(); + + MWBase::World *world = MWBase::Environment::get().getWorld(); + const ESM::NPC *player = + world->getPlayer().getPlayer().get()->mBase; + + const ESM::Race *race = + world->getStore().get().find(player->mRace); + const ESM::Class *cls = + world->getStore().get().find(player->mClass); + + winMgr->setValue ("name", player->mName); + winMgr->setValue ("race", race->mName); + winMgr->setValue ("class", cls->mName); + mUpdatePlayer = false; MWBase::WindowManager::SkillList majorSkills (5); @@ -274,11 +291,11 @@ namespace MWMechanics for (int i=0; i<5; ++i) { - minorSkills[i] = MWBase::Environment::get().getWorld()->getPlayer().getClass().mData.mSkills[i][0]; - majorSkills[i] = MWBase::Environment::get().getWorld()->getPlayer().getClass().mData.mSkills[i][1]; + minorSkills[i] = cls->mData.mSkills[i][0]; + majorSkills[i] = cls->mData.mSkills[i][1]; } - MWBase::Environment::get().getWindowManager()->configureSkills (majorSkills, minorSkills); + winMgr->configureSkills (majorSkills, minorSkills); } mActors.update (movement, duration, paused); @@ -291,14 +308,31 @@ namespace MWMechanics void MechanicsManager::setPlayerName (const std::string& name) { - MWBase::Environment::get().getWorld()->getPlayer().setName (name); + MWBase::World *world = MWBase::Environment::get().getWorld(); + + ESM::NPC player = + *world->getPlayer().getPlayer().get()->mBase; + player.mName = name; + + world->createRecord(player); + mUpdatePlayer = true; } - void MechanicsManager::setPlayerRace (const std::string& race, bool male) + void MechanicsManager::setPlayerRace (const std::string& race, bool male, const std::string &head, const std::string &hair) { - MWBase::Environment::get().getWorld()->getPlayer().setGender (male); - MWBase::Environment::get().getWorld()->getPlayer().setRace (race); + MWBase::World *world = MWBase::Environment::get().getWorld(); + + ESM::NPC player = + *world->getPlayer().getPlayer().get()->mBase; + + player.mRace = race; + player.mHead = head; + player.mHair = hair; + player.setIsMale(male); + + world->createRecord(player); + mRaceSelected = true; buildPlayer(); mUpdatePlayer = true; @@ -306,29 +340,303 @@ namespace MWMechanics void MechanicsManager::setPlayerBirthsign (const std::string& id) { - MWBase::Environment::get().getWorld()->getPlayer().setBirthsign (id); + MWBase::Environment::get().getWorld()->getPlayer().setBirthSign(id); buildPlayer(); mUpdatePlayer = true; } void MechanicsManager::setPlayerClass (const std::string& id) { - MWBase::Environment::get().getWorld()->getPlayer().setClass (*MWBase::Environment::get().getWorld()->getStore().classes.find (id)); + MWBase::World *world = MWBase::Environment::get().getWorld(); + + ESM::NPC player = + *world->getPlayer().getPlayer().get()->mBase; + player.mClass = id; + + world->createRecord(player); + mClassSelected = true; buildPlayer(); mUpdatePlayer = true; } - void MechanicsManager::setPlayerClass (const ESM::Class& class_) + void MechanicsManager::setPlayerClass (const ESM::Class &cls) { - MWBase::Environment::get().getWorld()->getPlayer().setClass (class_); + MWBase::World *world = MWBase::Environment::get().getWorld(); + + const ESM::Class *ptr = world->createRecord(cls); + + ESM::NPC player = + *world->getPlayer().getPlayer().get()->mBase; + player.mClass = ptr->mId; + + world->createRecord(player); + mClassSelected = true; buildPlayer(); mUpdatePlayer = true; } - + + std::string toLower (const std::string& name) + { + std::string lowerCase; + + std::transform (name.begin(), name.end(), std::back_inserter (lowerCase), + (int(*)(int)) std::tolower); + + return lowerCase; + } + + int MechanicsManager::getDerivedDisposition(const MWWorld::Ptr& ptr) + { + MWMechanics::NpcStats npcSkill = MWWorld::Class::get(ptr).getNpcStats(ptr); + float x = npcSkill.getBaseDisposition(); + + MWWorld::LiveCellRef* npc = ptr.get(); + MWWorld::Ptr playerPtr = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + MWWorld::LiveCellRef* player = playerPtr.get(); + MWMechanics::CreatureStats playerStats = MWWorld::Class::get(playerPtr).getCreatureStats(playerPtr); + MWMechanics::NpcStats playerNpcStats = MWWorld::Class::get(playerPtr).getNpcStats(playerPtr); + + if (toLower(npc->mBase->mRace) == toLower(player->mBase->mRace)) x += MWBase::Environment::get().getWorld()->getStore().get().find("fDispRaceMod")->getFloat(); + + x += MWBase::Environment::get().getWorld()->getStore().get().find("fDispPersonalityMult")->getFloat() + * (playerStats.getAttribute(ESM::Attribute::Personality).getModified() - MWBase::Environment::get().getWorld()->getStore().get().find("fDispPersonalityBase")->getFloat()); + + float reaction = 0; + int rank = 0; + std::string npcFaction = ""; + if(!npcSkill.getFactionRanks().empty()) npcFaction = npcSkill.getFactionRanks().begin()->first; + + if (playerNpcStats.getFactionRanks().find(toLower(npcFaction)) != playerNpcStats.getFactionRanks().end()) + { + for(std::vector::const_iterator it = MWBase::Environment::get().getWorld()->getStore().get().find(toLower(npcFaction))->mReactions.begin(); + it != MWBase::Environment::get().getWorld()->getStore().get().find(toLower(npcFaction))->mReactions.end(); it++) + { + if(toLower(it->mFaction) == toLower(npcFaction)) reaction = it->mReaction; + } + rank = playerNpcStats.getFactionRanks().find(toLower(npcFaction))->second; + } + else if (npcFaction != "") + { + for(std::vector::const_iterator it = MWBase::Environment::get().getWorld()->getStore().get().find(toLower(npcFaction))->mReactions.begin(); + it != MWBase::Environment::get().getWorld()->getStore().get().find(toLower(npcFaction))->mReactions.end();it++) + { + if(playerNpcStats.getFactionRanks().find(toLower(it->mFaction)) != playerNpcStats.getFactionRanks().end() ) + { + if(it->mReactionmReaction; + } + } + rank = 0; + } + else + { + reaction = 0; + rank = 0; + } + x += (MWBase::Environment::get().getWorld()->getStore().get().find("fDispFactionRankMult")->getFloat() * rank + + MWBase::Environment::get().getWorld()->getStore().get().find("fDispFactionRankBase")->getFloat()) + * MWBase::Environment::get().getWorld()->getStore().get().find("fDispFactionMod")->getFloat() * reaction; + + x -= MWBase::Environment::get().getWorld()->getStore().get().find("fDispCrimeMod")->getFloat() * playerNpcStats.getBounty(); + if (playerStats.hasCommonDisease() || playerStats.hasBlightDisease()) + x += MWBase::Environment::get().getWorld()->getStore().get().find("fDispDiseaseMod")->getFloat(); + + if (playerNpcStats.getDrawState() == MWMechanics::DrawState_::DrawState_Weapon) + x += MWBase::Environment::get().getWorld()->getStore().get().find("fDispWeaponDrawn")->getFloat(); + + int effective_disposition = std::max(0,std::min(int(x),100));//, normally clamped to [0..100] when used + return effective_disposition; + } + + int MechanicsManager::getBarterOffer(const MWWorld::Ptr& ptr,int basePrice, bool buying) + { + if (ptr.getTypeName() == typeid(ESM::Creature).name()) + return basePrice; + + MWMechanics::NpcStats sellerSkill = MWWorld::Class::get(ptr).getNpcStats(ptr); + MWMechanics::CreatureStats sellerStats = MWWorld::Class::get(ptr).getCreatureStats(ptr); + + MWWorld::Ptr playerPtr = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + MWMechanics::NpcStats playerSkill = MWWorld::Class::get(playerPtr).getNpcStats(playerPtr); + MWMechanics::CreatureStats playerStats = MWWorld::Class::get(playerPtr).getCreatureStats(playerPtr); + + // I suppose the temporary disposition change _has_ to be considered here, + // otherwise one would get different prices when exiting and re-entering the dialogue window... + int clampedDisposition = std::max(0, std::min(getDerivedDisposition(ptr) + + MWBase::Environment::get().getDialogueManager()->getTemporaryDispositionChange(),100)); + float a = std::min(playerSkill.getSkill(ESM::Skill::Mercantile).getModified(), 100.f); + float b = std::min(0.1f * playerStats.getAttribute(ESM::Attribute::Luck).getModified(), 10.f); + float c = std::min(0.2f * playerStats.getAttribute(ESM::Attribute::Personality).getModified(), 10.f); + float d = std::min(sellerSkill.getSkill(ESM::Skill::Mercantile).getModified(), 100.f); + float e = std::min(0.1f * sellerStats.getAttribute(ESM::Attribute::Luck).getModified(), 10.f); + float f = std::min(0.2f * sellerStats.getAttribute(ESM::Attribute::Personality).getModified(), 10.f); + + float pcTerm = (clampedDisposition - 50 + a + b + c) * playerStats.getFatigueTerm(); + float npcTerm = (d + e + f) * sellerStats.getFatigueTerm(); + float buyTerm = 0.01 * (100 - 0.5 * (pcTerm - npcTerm)); + float sellTerm = 0.01 * (50 - 0.5 * (npcTerm - pcTerm)); + + float x; + if(buying) x = buyTerm; + else x = std::min(buyTerm, sellTerm); + int offerPrice; + if (x < 1) offerPrice = int(x * basePrice); + if (x >= 1) offerPrice = basePrice + int((x - 1) * basePrice); + offerPrice = std::max(1, offerPrice); + return offerPrice; + } + int MechanicsManager::countDeaths (const std::string& id) const { return mActors.countDeaths (id); } + + + void MechanicsManager::getPersuasionDispositionChange (const MWWorld::Ptr& npc, PersuasionType type, + float currentTemporaryDispositionDelta, bool& success, float& tempChange, float& permChange) + { + const MWWorld::Store &gmst = + MWBase::Environment::get().getWorld()->getStore().get(); + + MWWorld::Ptr playerPtr = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + MWMechanics::NpcStats playerSkill = MWWorld::Class::get(playerPtr).getNpcStats(playerPtr); + MWMechanics::CreatureStats playerStats = MWWorld::Class::get(playerPtr).getCreatureStats(playerPtr); + + MWMechanics::NpcStats npcSkill = MWWorld::Class::get(npc).getNpcStats(npc); + MWMechanics::CreatureStats npcStats = MWWorld::Class::get(npc).getCreatureStats(npc); + + + float persTerm = playerStats.getAttribute(ESM::Attribute::Personality).getModified() + / gmst.find("fPersonalityMod")->getFloat(); + + float luckTerm = playerStats.getAttribute(ESM::Attribute::Luck).getModified() + / gmst.find("fLuckMod")->getFloat(); + + float repTerm = playerSkill.getReputation() * gmst.find("fReputationMod")->getFloat(); + + float levelTerm = playerStats.getLevel() * gmst.find("fLevelMod")->getFloat(); + + float fatigueTerm = playerStats.getFatigueTerm(); + + float playerRating1 = (repTerm + luckTerm + persTerm + playerSkill.getSkill(ESM::Skill::Speechcraft).getModified()) * fatigueTerm; + float playerRating2 = playerRating1 + levelTerm; + float playerRating3 = (playerSkill.getSkill(ESM::Skill::Mercantile).getModified() + luckTerm + persTerm) * fatigueTerm; + + float npcRating1 = (repTerm + luckTerm + persTerm + playerSkill.getSkill(ESM::Skill::Speechcraft).getModified()) * fatigueTerm; + float npcRating2 = (levelTerm + repTerm + luckTerm + persTerm + npcSkill.getSkill(ESM::Skill::Speechcraft).getModified()) * fatigueTerm; + float npcRating3 = (playerSkill.getSkill(ESM::Skill::Mercantile).getModified() + repTerm + luckTerm + persTerm) * fatigueTerm; + + int currentDisposition = std::min(100, std::max(0, int(getDerivedDisposition(npc) + currentTemporaryDispositionDelta))); + + float d = 1 - 0.02 * abs(currentDisposition - 50); + float target1 = d * (playerRating1 - npcRating1 + 50); + float target2 = d * (playerRating2 - npcRating2 + 50); + + float bribeMod; + if (type == PT_Bribe10) bribeMod = gmst.find("fBribe10Mod")->getFloat(); + if (type == PT_Bribe100) bribeMod = gmst.find("fBribe100Mod")->getFloat(); + else bribeMod = gmst.find("fBribe1000Mod")->getFloat(); + + float target3 = d * (playerRating3 - npcRating3 + 50) + bribeMod; + + float iPerMinChance = gmst.find("iPerMinChance")->getInt(); + float iPerMinChange = gmst.find("iPerMinChange")->getInt(); + float fPerDieRollMult = gmst.find("fPerDieRollMult")->getFloat(); + float fPerTempMult = gmst.find("fPerTempMult")->getFloat(); + + float x,y; + + float roll = static_cast (std::rand()) / RAND_MAX * 100; + + if (type == PT_Admire) + { + target1 = std::max(iPerMinChance, target1); + success = (roll <= target1); + float c = int(fPerDieRollMult * (target1 - roll)); + x = success ? std::max(iPerMinChange, c) : c; + } + else if (type == PT_Intimidate) + { + target2 = std::max(iPerMinChance, target2); + + success = (roll <= target2); + + float r; + if (roll != target2) + r = int(target2 - roll); + else + r = 1; + + if (roll <= target2) + { + float s = int(r * fPerDieRollMult * fPerTempMult); + + npcStats.setAiSetting (2, std::max(0, std::min(100, npcStats.getAiSetting (2) + int(std::max(iPerMinChange, s))))); + npcStats.setAiSetting (1, std::max(0, std::min(100, npcStats.getAiSetting (1) + int(std::min(-iPerMinChange, -s))))); + } + + float c = -std::abs(int(r * fPerDieRollMult)); + if (success) + { + if (std::abs(c) < iPerMinChange) + { + x = 0; + y = -iPerMinChange; + } + else + { + x = -int(c * fPerTempMult); + y = c; + } + } + else + { + x = int(c * fPerTempMult); + y = c; + } + } + else if (type == PT_Taunt) + { + target1 = std::max(iPerMinChance, target1); + success = (roll <= target1); + + float c = std::abs(int(target1 - roll)); + + if (roll <= target1) + { + float s = c * fPerDieRollMult * fPerTempMult; + + npcStats.setAiSetting (2, std::max(0, std::min(100, npcStats.getAiSetting (2) + std::min(-int(iPerMinChange), int(-s))))); + npcStats.setAiSetting (1, std::max(0, std::min(100, npcStats.getAiSetting (1) + std::max(int(iPerMinChange), int(s))))); + } + x = int(-c * fPerDieRollMult); + + if (success && std::abs(x) < iPerMinChange) + x = -iPerMinChange; + } + else // Bribe + { + target3 = std::max(iPerMinChance, target3); + success = (roll <= target3); + float c = int((target3 - roll) * fPerDieRollMult); + + x = success ? std::max(iPerMinChange, c) : c; + } + + tempChange = type == PT_Intimidate ? x : int(x * fPerTempMult); + + + float cappedDispositionChange = tempChange; + if (currentDisposition + tempChange > 100.f) + cappedDispositionChange = 100 - currentDisposition; + if (currentDisposition + tempChange < 0.f) + cappedDispositionChange = -currentDisposition; + + permChange = int(cappedDispositionChange / fPerTempMult); + if (type == PT_Intimidate) + { + permChange = success ? -int(cappedDispositionChange/ fPerTempMult) : y; + } + } } diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp index 38536d3bd7..f8d470a4e8 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp @@ -64,7 +64,7 @@ namespace MWMechanics virtual void setPlayerName (const std::string& name); ///< Set player name. - virtual void setPlayerRace (const std::string& id, bool male); + virtual void setPlayerRace (const std::string& id, bool male, const std::string &head, const std::string &hair); ///< Set player race. virtual void setPlayerBirthsign (const std::string& id); @@ -79,9 +79,18 @@ namespace MWMechanics virtual void restoreDynamicStats(); ///< If the player is sleeping, this should be called every hour. + virtual int getBarterOffer(const MWWorld::Ptr& ptr,int basePrice, bool buying); + ///< This is used by every service to determine the price of objects given the trading skills of the player and NPC. + + virtual int getDerivedDisposition(const MWWorld::Ptr& ptr); + ///< Calculate the diposition of an NPC toward the player. + virtual int countDeaths (const std::string& id) const; ///< Return the number of deaths for actors with the given ID. + virtual void getPersuasionDispositionChange (const MWWorld::Ptr& npc, PersuasionType type, + float currentTemporaryDispositionDelta, bool& success, float& tempChange, float& permChange); + ///< Perform a persuasion action on NPC }; } diff --git a/apps/openmw/mwmechanics/npcstats.cpp b/apps/openmw/mwmechanics/npcstats.cpp index bbd42c1471..20a0360e77 100644 --- a/apps/openmw/mwmechanics/npcstats.cpp +++ b/apps/openmw/mwmechanics/npcstats.cpp @@ -3,14 +3,17 @@ #include #include +#include +#include #include #include #include #include +#include -#include +#include "../mwworld/esmstore.hpp" #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" @@ -18,8 +21,8 @@ #include "../mwbase/soundmanager.hpp" MWMechanics::NpcStats::NpcStats() -: mMovementFlags (0), mDrawState (DrawState_Nothing) -, mLevelProgress(0) +: mMovementFlags (0), mDrawState (DrawState_Nothing), mBounty (0) +, mLevelProgress(0), mDisposition(0), mVampire (0), mReputation(0), mWerewolf (false), mWerewolfKills (0) { mSkillIncreases.resize (ESM::Attribute::Length); for (int i=0; i& MWMechanics::NpcStats::getFactionRanks() return mFactionRank; } +std::set& MWMechanics::NpcStats::getExpelled() +{ + return mExpelled; +} + const std::map& MWMechanics::NpcStats::getFactionRanks() const { return mFactionRank; } +bool MWMechanics::NpcStats::isSameFaction (const NpcStats& npcStats) const +{ + for (std::map::const_iterator iter (mFactionRank.begin()); iter!=mFactionRank.end(); + ++iter) + if (npcStats.mFactionRank.find (iter->first)!=npcStats.mFactionRank.end()) + return true; + + return false; +} + float MWMechanics::NpcStats::getSkillGain (int skillIndex, const ESM::Class& class_, int usageType, int level) const { if (level<0) level = static_cast (getSkill (skillIndex).getBase()); - const ESM::Skill *skill = MWBase::Environment::get().getWorld()->getStore().skills.find (skillIndex); + const ESM::Skill *skill = + MWBase::Environment::get().getWorld()->getStore().get().find (skillIndex); float skillFactor = 1; @@ -96,14 +125,15 @@ float MWMechanics::NpcStats::getSkillGain (int skillIndex, const ESM::Class& cla throw std::runtime_error ("invalid skill gain factor"); } - float typeFactor = - MWBase::Environment::get().getWorld()->getStore().gameSettings.find ("fMiscSkillBonus")->getFloat(); + const MWWorld::Store &gmst = + MWBase::Environment::get().getWorld()->getStore().get(); + + float typeFactor = gmst.find ("fMiscSkillBonus")->getFloat(); for (int i=0; i<5; ++i) if (class_.mData.mSkills[i][0]==skillIndex) { - typeFactor = - MWBase::Environment::get().getWorld()->getStore().gameSettings.find ("fMinorSkillBonus")->getFloat(); + typeFactor = gmst.find ("fMinorSkillBonus")->getFloat(); break; } @@ -111,8 +141,7 @@ float MWMechanics::NpcStats::getSkillGain (int skillIndex, const ESM::Class& cla for (int i=0; i<5; ++i) if (class_.mData.mSkills[i][1]==skillIndex) { - typeFactor = - MWBase::Environment::get().getWorld()->getStore().gameSettings.find ("fMajorSkillBonus")->getFloat(); + typeFactor = gmst.find ("fMajorSkillBonus")->getFloat(); break; } @@ -124,8 +153,7 @@ float MWMechanics::NpcStats::getSkillGain (int skillIndex, const ESM::Class& cla if (skill->mData.mSpecialization==class_.mData.mSpecialization) { - specialisationFactor = - MWBase::Environment::get().getWorld()->getStore().gameSettings.find ("fSpecialSkillBonus")->getFloat(); + specialisationFactor = gmst.find ("fSpecialSkillBonus")->getFloat(); if (specialisationFactor<=0) throw std::runtime_error ("invalid skill specialisation factor"); @@ -178,7 +206,8 @@ void MWMechanics::NpcStats::increaseSkill(int skillIndex, const ESM::Class &clas mLevelProgress += levelProgress; // check the attribute this skill belongs to - const ESM::Skill* skill = MWBase::Environment::get().getWorld ()->getStore ().skills.find(skillIndex); + const ESM::Skill* skill = + MWBase::Environment::get().getWorld ()->getStore ().get().find(skillIndex); ++mSkillIncreases[skill->mData.mAttribute]; // Play sound & skill progress notification @@ -237,3 +266,88 @@ bool MWMechanics::NpcStats::hasBeenUsed (const std::string& id) const { return mUsedIds.find (id)!=mUsedIds.end(); } + +int MWMechanics::NpcStats::getBounty() const +{ + return mBounty; +} + +void MWMechanics::NpcStats::setBounty (int bounty) +{ + mBounty = bounty; +} + +int MWMechanics::NpcStats::getFactionReputation (const std::string& faction) const +{ + std::map::const_iterator iter = mFactionReputation.find (faction); + + if (iter==mFactionReputation.end()) + return 0; + + return iter->second; +} + +void MWMechanics::NpcStats::setFactionReputation (const std::string& faction, int value) +{ + mFactionReputation[faction] = value; +} + +bool MWMechanics::NpcStats::isVampire() const +{ + return mVampire; +} + +void MWMechanics::NpcStats::setVampire (bool set) +{ + mVampire = set; +} + +int MWMechanics::NpcStats::getReputation() const +{ + return mReputation; +} + +void MWMechanics::NpcStats::setReputation(int reputation) +{ + mReputation = reputation; +} + +bool MWMechanics::NpcStats::hasSkillsForRank (const std::string& factionId, int rank) const +{ + if (rank<0 || rank>=10) + throw std::runtime_error ("rank index out of range"); + + const ESM::Faction& faction = + *MWBase::Environment::get().getWorld()->getStore().get().find (factionId); + + std::vector skills; + + for (int i=0; i<6; ++i) + skills.push_back (static_cast (getSkill (faction.mData.mSkillID[i]).getModified())); + + std::sort (skills.begin(), skills.end()); + + std::vector::const_reverse_iterator iter = skills.rbegin(); + + const ESM::RankData& rankData = faction.mData.mRankData[rank]; + + if (*iter=rankData.mSkill2; +} + +bool MWMechanics::NpcStats::isWerewolf() const +{ + return mWerewolf; +} + +void MWMechanics::NpcStats::setWerewolf (bool set) +{ + mWerewolf = set; +} + +int MWMechanics::NpcStats::getWerewolfKills() const +{ + return mWerewolfKills; +} \ No newline at end of file diff --git a/apps/openmw/mwmechanics/npcstats.hpp b/apps/openmw/mwmechanics/npcstats.hpp index 48e63d7b6e..af32bd294a 100644 --- a/apps/openmw/mwmechanics/npcstats.hpp +++ b/apps/openmw/mwmechanics/npcstats.hpp @@ -43,8 +43,16 @@ namespace MWMechanics std::map mFactionRank; DrawState_ mDrawState; + int mDisposition; unsigned int mMovementFlags; Stat mSkill[27]; + int mBounty; + std::set mExpelled; + std::map mFactionReputation; + bool mVampire; + int mReputation; + bool mWerewolf; + int mWerewolfKills; int mLevelProgress; // 0-10 @@ -60,6 +68,14 @@ namespace MWMechanics void setDrawState (DrawState_ state); + int getBaseDisposition() const; + + void setBaseDisposition(int disposition); + + int getReputation() const; + + void setReputation(int reputation); + bool getMovementFlag (Flag flag) const; void setMovementFlag (Flag flag, bool state); @@ -70,6 +86,11 @@ namespace MWMechanics std::map& getFactionRanks(); + std::set& getExpelled(); + + bool isSameFaction (const NpcStats& npcStats) const; + ///< Do *this and \a npcStats share a faction? + const std::map& getFactionRanks() const; float getSkillGain (int skillIndex, const ESM::Class& class_, int usageType = -1, @@ -88,10 +109,30 @@ namespace MWMechanics int getLevelupAttributeMultiplier(int attribute) const; void levelUp(); - + void flagAsUsed (const std::string& id); - + bool hasBeenUsed (const std::string& id) const; + + int getBounty() const; + + void setBounty (int bounty); + + int getFactionReputation (const std::string& faction) const; + + void setFactionReputation (const std::string& faction, int value); + + bool isVampire() const; + + void setVampire (bool set); + + bool hasSkillsForRank (const std::string& factionId, int rank) const; + + bool isWerewolf() const; + + void setWerewolf (bool set); + + int getWerewolfKills() const; }; } diff --git a/apps/openmw/mwmechanics/spells.cpp b/apps/openmw/mwmechanics/spells.cpp index adfb35cd96..ef084f4795 100644 --- a/apps/openmw/mwmechanics/spells.cpp +++ b/apps/openmw/mwmechanics/spells.cpp @@ -1,7 +1,7 @@ #include "spells.hpp" -#include +#include "../mwworld/esmstore.hpp" #include @@ -50,7 +50,8 @@ namespace MWMechanics for (TIterator iter = mSpells.begin(); iter!=mSpells.end(); ++iter) { - const ESM::Spell *spell = MWBase::Environment::get().getWorld()->getStore().spells.find (*iter); + const ESM::Spell *spell = + MWBase::Environment::get().getWorld()->getStore().get().find (*iter); if (spell->mData.mType==ESM::Spell::ST_Ability || spell->mData.mType==ESM::Spell::ST_Blight || spell->mData.mType==ESM::Spell::ST_Disease || spell->mData.mType==ESM::Spell::ST_Curse) @@ -74,4 +75,32 @@ namespace MWMechanics { return mSelectedSpell; } + + bool Spells::hasCommonDisease() const + { + for (TIterator iter = mSpells.begin(); iter!=mSpells.end(); ++iter) + { + const ESM::Spell *spell = + MWBase::Environment::get().getWorld()->getStore().get().find (*iter); + + if (spell->mData.mFlags & ESM::Spell::ST_Disease) + return true; + } + + return false; + } + + bool Spells::hasBlightDisease() const + { + for (TIterator iter = mSpells.begin(); iter!=mSpells.end(); ++iter) + { + const ESM::Spell *spell = + MWBase::Environment::get().getWorld()->getStore().get().find (*iter); + + if (spell->mData.mFlags & ESM::Spell::ST_Blight) + return true; + } + + return false; + } } diff --git a/apps/openmw/mwmechanics/spells.hpp b/apps/openmw/mwmechanics/spells.hpp index d90f5b502d..12308661ba 100644 --- a/apps/openmw/mwmechanics/spells.hpp +++ b/apps/openmw/mwmechanics/spells.hpp @@ -55,6 +55,10 @@ namespace MWMechanics const std::string getSelectedSpell() const; ///< May return an empty string. + + bool hasCommonDisease() const; + + bool hasBlightDisease() const; }; } diff --git a/apps/openmw/mwmechanics/spellsuccess.hpp b/apps/openmw/mwmechanics/spellsuccess.hpp index a46667cdc4..57c600df50 100644 --- a/apps/openmw/mwmechanics/spellsuccess.hpp +++ b/apps/openmw/mwmechanics/spellsuccess.hpp @@ -8,7 +8,7 @@ #include "../mwworld/class.hpp" #include "../mwmechanics/creaturestats.hpp" -#include +#include "../mwworld/esmstore.hpp" #include "npcstats.hpp" @@ -40,7 +40,8 @@ namespace MWMechanics for (std::vector::const_iterator it = effects.begin(); it != effects.end(); ++it) { - const ESM::MagicEffect* effect = MWBase::Environment::get().getWorld()->getStore().magicEffects.find(it->mEffectID); + const ESM::MagicEffect* effect = + MWBase::Environment::get().getWorld()->getStore().get().find(it->mEffectID); int _school = effect->mData.mSchool; int _skillLevel = stats.getSkill (spellSchoolToSkill(_school)).getModified(); @@ -61,7 +62,8 @@ namespace MWMechanics inline int getSpellSchool(const std::string& spellId, const MWWorld::Ptr& actor) { - const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(spellId); + const ESM::Spell* spell = + MWBase::Environment::get().getWorld()->getStore().get().find(spellId); return getSpellSchool(spell, actor); } @@ -107,7 +109,8 @@ namespace MWMechanics inline float getSpellSuccessChance (const std::string& spellId, const MWWorld::Ptr& actor) { - const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(spellId); + const ESM::Spell* spell = + MWBase::Environment::get().getWorld()->getStore().get().find(spellId); return getSpellSuccessChance(spell, actor); } } diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index ef92497e55..2a3b8cf437 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -7,7 +7,6 @@ #include #include - namespace MWRender { diff --git a/apps/openmw/mwrender/characterpreview.cpp b/apps/openmw/mwrender/characterpreview.cpp index 017062baa2..0a11dc2814 100644 --- a/apps/openmw/mwrender/characterpreview.cpp +++ b/apps/openmw/mwrender/characterpreview.cpp @@ -48,8 +48,9 @@ namespace MWRender mNode->setVisible (false); - mCamera->setPosition(mPosition); - mCamera->lookAt(mLookAt); + Ogre::Vector3 scale = mNode->getScale(); + mCamera->setPosition(mPosition * scale); + mCamera->lookAt(mLookAt * scale); mCamera->setNearClipDistance (0.01); mCamera->setFarClipDistance (1000); @@ -80,6 +81,22 @@ namespace MWRender delete mAnimation; } + void CharacterPreview::rebuild() + { + assert(mAnimation); + delete mAnimation; + + mAnimation = new NpcAnimation(mCharacter, mNode, + MWWorld::Class::get(mCharacter).getInventoryStore (mCharacter), RV_PlayerPreview); + + mNode->setVisible (false); + + Ogre::Vector3 scale = mNode->getScale(); + mCamera->setPosition(mPosition * scale); + mCamera->lookAt(mLookAt * scale); + + onSetup(); + } // -------------------------------------------------------------------------------------------------- @@ -128,8 +145,10 @@ namespace MWRender RaceSelectionPreview::RaceSelectionPreview() : CharacterPreview(MWBase::Environment::get().getWorld()->getPlayer().getPlayer(), 512, 512, "CharacterHeadPreview", Ogre::Vector3(0, 120, -35), Ogre::Vector3(0,125,0)) + , mRef(&mBase) { - + mBase = *mCharacter.get()->mBase; + mCharacter = MWWorld::Ptr(&mRef, mCharacter.getCell()); } void RaceSelectionPreview::update(float angle) @@ -141,4 +160,11 @@ namespace MWRender mNode->setVisible (false); } + void RaceSelectionPreview::setPrototype(const ESM::NPC &proto) + { + mBase = proto; + mBase.mId = "player"; + rebuild(); + update(0); + } } diff --git a/apps/openmw/mwrender/characterpreview.hpp b/apps/openmw/mwrender/characterpreview.hpp index 2a6b12b9ec..18362d1db6 100644 --- a/apps/openmw/mwrender/characterpreview.hpp +++ b/apps/openmw/mwrender/characterpreview.hpp @@ -4,6 +4,7 @@ #include #include +#include #include "externalrendering.hpp" @@ -32,6 +33,7 @@ namespace MWRender virtual void setup (Ogre::SceneManager *sceneManager); virtual void onSetup(); + virtual void rebuild(); protected: Ogre::TexturePtr mTexture; @@ -77,10 +79,19 @@ namespace MWRender class RaceSelectionPreview : public CharacterPreview { + ESM::NPC mBase; + MWWorld::LiveCellRef mRef; + public: RaceSelectionPreview(); void update(float angle); + + const ESM::NPC &getPrototype() const { + return mBase; + } + + void setPrototype(const ESM::NPC &proto); }; } diff --git a/apps/openmw/mwrender/creatureanimation.cpp b/apps/openmw/mwrender/creatureanimation.cpp index afd1149723..7ee361a6f6 100644 --- a/apps/openmw/mwrender/creatureanimation.cpp +++ b/apps/openmw/mwrender/creatureanimation.cpp @@ -21,10 +21,10 @@ CreatureAnimation::CreatureAnimation(const MWWorld::Ptr& ptr): Animation() mInsert = ptr.getRefData().getBaseNode(); MWWorld::LiveCellRef *ref = ptr.get(); - assert (ref->base != NULL); - if(!ref->base->mModel.empty()) + assert (ref->mBase != NULL); + if(!ref->mBase->mModel.empty()) { - std::string mesh = "meshes\\" + ref->base->mModel; + std::string mesh = "meshes\\" + ref->mBase->mModel; mEntityList = NifOgre::NIFLoader::createEntities(mInsert, &mTextKeys, mesh); for(size_t i = 0;i < mEntityList.mEntities.size();i++) diff --git a/apps/openmw/mwrender/debugging.cpp b/apps/openmw/mwrender/debugging.cpp index 4f71507545..1548cc1b0f 100644 --- a/apps/openmw/mwrender/debugging.cpp +++ b/apps/openmw/mwrender/debugging.cpp @@ -11,7 +11,7 @@ #include #include -#include +#include "../mwworld/esmstore.hpp" #include "../mwbase/world.hpp" // these includes can be removed once the static-hack is gone #include "../mwbase/environment.hpp" @@ -228,22 +228,23 @@ void Debugging::togglePathgrid() void Debugging::enableCellPathgrid(MWWorld::Ptr::CellStore *store) { - ESM::Pathgrid *pathgrid = MWBase::Environment::get().getWorld()->getStore().pathgrids.search(*store->cell); + const ESM::Pathgrid *pathgrid = + MWBase::Environment::get().getWorld()->getStore().get().search(*store->mCell); if (!pathgrid) return; Vector3 cellPathGridPos(0, 0, 0); - if (store->cell->isExterior()) + if (store->mCell->isExterior()) { - cellPathGridPos.x = store->cell->mData.mX * ESM::Land::REAL_SIZE; - cellPathGridPos.y = store->cell->mData.mY * ESM::Land::REAL_SIZE; + cellPathGridPos.x = store->mCell->mData.mX * ESM::Land::REAL_SIZE; + cellPathGridPos.y = store->mCell->mData.mY * ESM::Land::REAL_SIZE; } SceneNode *cellPathGrid = mPathGridRoot->createChildSceneNode(cellPathGridPos); cellPathGrid->attachObject(createPathgridLines(pathgrid)); cellPathGrid->attachObject(createPathgridPoints(pathgrid)); - if (store->cell->isExterior()) + if (store->mCell->isExterior()) { - mExteriorPathgridNodes[std::make_pair(store->cell->mData.mX, store->cell->mData.mY)] = cellPathGrid; + mExteriorPathgridNodes[std::make_pair(store->mCell->getGridX(), store->mCell->getGridY())] = cellPathGrid; } else { @@ -254,10 +255,10 @@ void Debugging::enableCellPathgrid(MWWorld::Ptr::CellStore *store) void Debugging::disableCellPathgrid(MWWorld::Ptr::CellStore *store) { - if (store->cell->isExterior()) + if (store->mCell->isExterior()) { ExteriorPathgridNodes::iterator it = - mExteriorPathgridNodes.find(std::make_pair(store->cell->mData.mX, store->cell->mData.mY)); + mExteriorPathgridNodes.find(std::make_pair(store->mCell->getGridX(), store->mCell->getGridY())); if (it != mExteriorPathgridNodes.end()) { destroyCellPathgridNode(it->second); diff --git a/apps/openmw/mwrender/globalmap.cpp b/apps/openmw/mwrender/globalmap.cpp index 7a799a2e43..072015f9a8 100644 --- a/apps/openmw/mwrender/globalmap.cpp +++ b/apps/openmw/mwrender/globalmap.cpp @@ -1,18 +1,19 @@ #include "globalmap.hpp" #include +#include #include #include #include #include #include +#include #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" -#include -#include +#include "../mwworld/esmstore.hpp" namespace MWRender { @@ -29,24 +30,28 @@ namespace MWRender { Ogre::TexturePtr tex; + const MWWorld::ESMStore &esmStore = + MWBase::Environment::get().getWorld()->getStore(); + // get the size of the world - const ESMS::CellList::ExtCells& extCells = MWBase::Environment::get().getWorld ()->getStore ().cells.extCells; - for (ESMS::CellList::ExtCells::const_iterator it = extCells.begin(); it != extCells.end(); ++it) + MWWorld::Store::iterator it = esmStore.get().extBegin(); + for (; it != esmStore.get().extEnd(); ++it) { - if (it->first.first < mMinX) - mMinX = it->first.first; - if (it->first.first > mMaxX) - mMaxX = it->first.first; - if (it->first.second < mMinY) - mMinY = it->first.second; - if (it->first.second > mMaxY) - mMaxY = it->first.second; + if (it->getGridX() < mMinX) + mMinX = it->getGridX(); + if (it->getGridX() > mMaxX) + mMaxX = it->getGridX(); + if (it->getGridY() < mMinY) + mMinY = it->getGridY(); + if (it->getGridY() > mMaxY) + mMaxY = it->getGridY(); } int cellSize = 24; mWidth = cellSize*(mMaxX-mMinX+1); mHeight = cellSize*(mMaxY-mMinY+1); + mExploredBuffer.resize((mMaxX-mMinX+1) * (mMaxY-mMinY+1) * 4); //if (!boost::filesystem::exists(mCacheDir + "/GlobalMap.png")) if (1) @@ -59,7 +64,7 @@ namespace MWRender { for (int y = mMinY; y <= mMaxY; ++y) { - ESM::Land* land = MWBase::Environment::get().getWorld ()->getStore ().lands.search (x,y); + ESM::Land* land = esmStore.get().search (x,y); if (land) { @@ -155,13 +160,30 @@ namespace MWRender //image.save (mCacheDir + "/GlobalMap.png"); tex = Ogre::TextureManager::getSingleton ().createManual ("GlobalMap.png", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - Ogre::TEX_TYPE_2D, mWidth, mHeight, 0, Ogre::PF_B8G8R8, Ogre::TU_DEFAULT); + Ogre::TEX_TYPE_2D, mWidth, mHeight, 0, Ogre::PF_B8G8R8, Ogre::TU_STATIC); tex->loadImage(image); } else tex = Ogre::TextureManager::getSingleton ().getByName ("GlobalMap.png"); tex->load(); + + + + + mOverlayTexture = Ogre::TextureManager::getSingleton().createManual("GlobalMapOverlay", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, + Ogre::TEX_TYPE_2D, mWidth, mHeight, 0, Ogre::PF_A8B8G8R8, Ogre::TU_DYNAMIC_WRITE_ONLY); + + + std::vector buffer; + buffer.resize(mWidth * mHeight); + + // initialize to (0, 0, 0, 0) + for (int p=0; pgetBuffer()->lock(Ogre::HardwareBuffer::HBL_DISCARD), &buffer[0], mWidth*mHeight*4); + mOverlayTexture->getBuffer()->unlock(); } void GlobalMap::worldPosToImageSpace(float x, float z, float& imageX, float& imageY) @@ -179,5 +201,32 @@ namespace MWRender imageY = 1.f-float(y - mMinY + 1) / (mMaxY - mMinY + 1); } + void GlobalMap::exploreCell(int cellX, int cellY) + { + float originX = (cellX - mMinX) * 24; + // NB y + 1, because we want the top left corner, not bottom left where the origin of the cell is + float originY = mHeight - (cellY+1 - mMinY) * 24; + if (cellX > mMaxX || cellX < mMinX || cellY > mMaxY || cellY < mMinY) + return; + + Ogre::TexturePtr localMapTexture = Ogre::TextureManager::getSingleton().getByName("Cell_" + + boost::lexical_cast(cellX) + "_" + boost::lexical_cast(cellY)); + + // mipmap version - can't get ogre to generate automips.. + /*if (!localMapTexture.isNull()) + { + assert(localMapTexture->getBuffer(0, 4)->getWidth() == 64); // 1024 / 2^4 + + mOverlayTexture->getBuffer()->blit(localMapTexture->getBuffer(0, 4), Ogre::Image::Box(0,0,64, 64), + Ogre::Image::Box(originX,originY,originX+24,originY+24)); + }*/ + + if (!localMapTexture.isNull()) + { + + mOverlayTexture->getBuffer()->blit(localMapTexture->getBuffer(), Ogre::Image::Box(0,0,512,512), + Ogre::Image::Box(originX,originY,originX+24,originY+24)); + } + } } diff --git a/apps/openmw/mwrender/globalmap.hpp b/apps/openmw/mwrender/globalmap.hpp index 01f5fdb9e8..c01182c5b5 100644 --- a/apps/openmw/mwrender/globalmap.hpp +++ b/apps/openmw/mwrender/globalmap.hpp @@ -3,6 +3,8 @@ #include +#include + namespace MWRender { @@ -22,9 +24,16 @@ namespace MWRender void cellTopLeftCornerToImageSpace(int x, int y, float& imageX, float& imageY); + void exploreCell (int cellX, int cellY); + private: std::string mCacheDir; + std::vector< std::pair > mExploredCells; + + Ogre::TexturePtr mOverlayTexture; + std::vector mExploredBuffer; + int mWidth; int mHeight; diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index 1bdbce6d97..d878cb86ed 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -4,7 +4,7 @@ #include #include -#include +#include "../mwworld/esmstore.hpp" #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" @@ -108,10 +108,10 @@ void LocalMap::requestMap(MWWorld::Ptr::CellStore* cell) mCameraRotNode->setOrientation(Quaternion::IDENTITY); - std::string name = "Cell_"+coordStr(cell->cell->mData.mX, cell->cell->mData.mY); + int x = cell->mCell->getGridX(); + int y = cell->mCell->getGridY(); - int x = cell->cell->mData.mX; - int y = cell->cell->mData.mY; + std::string name = "Cell_"+coordStr(x, y); mCameraPosNode->setPosition(Vector3(0,0,0)); @@ -163,7 +163,7 @@ void LocalMap::requestMap(MWWorld::Ptr::CellStore* cell, const int segsX = std::ceil( length.x / sSize ); const int segsY = std::ceil( length.y / sSize ); - mInteriorName = cell->cell->mName; + mInteriorName = cell->mCell->mName; for (int x=0; xcell->mName + "_" + coordStr(x,y)); + cell->mCell->mName + "_" + coordStr(x,y)); } } } diff --git a/apps/openmw/mwrender/localmap.hpp b/apps/openmw/mwrender/localmap.hpp index 056d2498a3..1aedf13255 100644 --- a/apps/openmw/mwrender/localmap.hpp +++ b/apps/openmw/mwrender/localmap.hpp @@ -58,7 +58,6 @@ namespace MWRender */ void saveFogOfWar(MWWorld::CellStore* cell); - /** * Get the interior map texture index and normalized position * on this texture, given a world position (in ogre coordinates) @@ -75,7 +74,7 @@ namespace MWRender MWRender::RenderingManager* mRenderingManager; // 1024*1024 pixels for a cell - static const int sMapResolution = 1024; + static const int sMapResolution = 512; // the dynamic texture is a bottleneck, so don't set this too high static const int sFogOfWarResolution = 32; diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 5c2b05acab..e6a8006e24 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -4,7 +4,7 @@ #include #include -#include +#include "../mwworld/esmstore.hpp" #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" @@ -17,44 +17,54 @@ using namespace NifOgre; namespace MWRender{ NpcAnimation::~NpcAnimation() { - removeEntities(head); - removeEntities(hair); - removeEntities(neck); - removeEntities(chest); - removeEntities(groin); - removeEntities(skirt); - removeEntities(rHand); - removeEntities(lHand); - removeEntities(rWrist); - removeEntities(lWrist); - removeEntities(rForearm); - removeEntities(lForearm); - removeEntities(rupperArm); - removeEntities(lupperArm); - removeEntities(rfoot); - removeEntities(lfoot); - removeEntities(rAnkle); - removeEntities(lAnkle); - removeEntities(rKnee); - removeEntities(lKnee); - removeEntities(rUpperLeg); - removeEntities(lUpperLeg); - removeEntities(rclavicle); - removeEntities(lclavicle); - removeEntities(tail); + removeEntities(mHead); + removeEntities(mHair); + removeEntities(mNeck); + removeEntities(mChest); + removeEntities(mGroin); + removeEntities(mSkirt); + removeEntities(mHandL); + removeEntities(mHandR); + removeEntities(mWristL); + removeEntities(mWristR); + removeEntities(mForearmL); + removeEntities(mForearmR); + removeEntities(mUpperArmL); + removeEntities(mUpperArmR); + removeEntities(mFootL); + removeEntities(mFootR); + removeEntities(mAnkleL); + removeEntities(mAnkleR); + removeEntities(mKneeL); + removeEntities(mKneeR); + removeEntities(mUpperLegL); + removeEntities(mUpperLegR); + removeEntities(mClavicleL); + removeEntities(mClavicleR); + removeEntities(mTail); } -NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, MWWorld::InventoryStore& _inv, int visibilityFlags) - : Animation(), mStateID(-1), mInv(_inv), timeToChange(0), mVisibilityFlags(visibilityFlags), - robe(mInv.end()), helmet(mInv.end()), shirt(mInv.end()), - cuirass(mInv.end()), greaves(mInv.end()), - leftpauldron(mInv.end()), rightpauldron(mInv.end()), - boots(mInv.end()), - leftglove(mInv.end()), rightglove(mInv.end()), skirtiter(mInv.end()), - pants(mInv.end()) +NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, MWWorld::InventoryStore& inv, int visibilityFlags) + : Animation(), + mStateID(-1), + mInv(inv), + mTimeToChange(0), + mVisibilityFlags(visibilityFlags), + mRobe(mInv.end()), + mHelmet(mInv.end()), + mShirt(mInv.end()), + mCuirass(mInv.end()), + mGreaves(mInv.end()), + mPauldronL(mInv.end()), + mPauldronR(mInv.end()), + mBoots(mInv.end()), + mPants(mInv.end()), + mGloveL(mInv.end()), + mGloveR(mInv.end()), + mSkirtIter(mInv.end()) { - MWWorld::LiveCellRef *ref = ptr.get(); + mNpc = ptr.get()->mBase; for (int init = 0; init < 27; init++) { @@ -62,25 +72,20 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, MWWor mPartPriorities[init] = 0; } - const ESMS::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); - const ESM::Race *race = store.races.find(ref->base->mRace); + const MWWorld::ESMStore &store = + MWBase::Environment::get().getWorld()->getStore(); + const ESM::Race *race = store.get().find(mNpc->mRace); - std::string hairID = ref->base->mHair; - std::string headID = ref->base->mHead; - headModel = "meshes\\" + store.bodyParts.find(headID)->mModel; - hairModel = "meshes\\" + store.bodyParts.find(hairID)->mModel; - npcName = ref->base->mName; - - isFemale = !!(ref->base->mFlags&ESM::NPC::Female); - isBeast = !!(race->mData.mFlags&ESM::Race::Beast); - - bodyRaceID = "b_n_"+ref->base->mRace; - std::transform(bodyRaceID.begin(), bodyRaceID.end(), bodyRaceID.begin(), ::tolower); + mHeadModel = "meshes\\" + store.get().find(mNpc->mHead)->mModel; + mHairModel = "meshes\\" + store.get().find(mNpc->mHair)->mModel; + mBodyPrefix = "b_n_" + mNpc->mRace; + std::transform(mBodyPrefix.begin(), mBodyPrefix.end(), mBodyPrefix.begin(), ::tolower); mInsert = node; assert(mInsert); + bool isBeast = (race->mData.mFlags & ESM::Race::Beast) != 0; std::string smodel = (!isBeast ? "meshes\\base_anim.nif" : "meshes\\base_animkna.nif"); mEntityList = NifOgre::NIFLoader::createEntities(mInsert, &mTextKeys, smodel); @@ -124,7 +129,7 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, MWWor } float scale = race->mData.mHeight.mMale; - if (isFemale) { + if (!mNpc->isMale()) { scale = race->mData.mHeight.mFemale; } mInsert->scale(scale, scale, scale); @@ -140,18 +145,18 @@ void NpcAnimation::updateParts() MWWorld::ContainerStoreIterator *iter; int slot; } slotlist[] = { - { &robe, MWWorld::InventoryStore::Slot_Robe }, - { &skirtiter, MWWorld::InventoryStore::Slot_Skirt }, - { &helmet, MWWorld::InventoryStore::Slot_Helmet }, - { &cuirass, MWWorld::InventoryStore::Slot_Cuirass }, - { &greaves, MWWorld::InventoryStore::Slot_Greaves }, - { &leftpauldron, MWWorld::InventoryStore::Slot_LeftPauldron }, - { &rightpauldron, MWWorld::InventoryStore::Slot_RightPauldron }, - { &boots, MWWorld::InventoryStore::Slot_Boots }, - { &leftglove, MWWorld::InventoryStore::Slot_LeftGauntlet }, - { &rightglove, MWWorld::InventoryStore::Slot_RightGauntlet }, - { &shirt, MWWorld::InventoryStore::Slot_Shirt }, - { &pants, MWWorld::InventoryStore::Slot_Pants }, + { &mRobe, MWWorld::InventoryStore::Slot_Robe }, + { &mSkirtIter, MWWorld::InventoryStore::Slot_Skirt }, + { &mHelmet, MWWorld::InventoryStore::Slot_Helmet }, + { &mCuirass, MWWorld::InventoryStore::Slot_Cuirass }, + { &mGreaves, MWWorld::InventoryStore::Slot_Greaves }, + { &mPauldronL, MWWorld::InventoryStore::Slot_LeftPauldron }, + { &mPauldronR, MWWorld::InventoryStore::Slot_RightPauldron }, + { &mBoots, MWWorld::InventoryStore::Slot_Boots }, + { &mGloveL, MWWorld::InventoryStore::Slot_LeftGauntlet }, + { &mGloveR, MWWorld::InventoryStore::Slot_RightGauntlet }, + { &mShirt, MWWorld::InventoryStore::Slot_Shirt }, + { &mPants, MWWorld::InventoryStore::Slot_Pants }, }; for(size_t i = 0;i < sizeof(slotlist)/sizeof(slotlist[0]);i++) { @@ -166,11 +171,11 @@ void NpcAnimation::updateParts() if(apparelChanged) { - if(robe != mInv.end()) + if(mRobe != mInv.end()) { - MWWorld::Ptr ptr = *robe; + MWWorld::Ptr ptr = *mRobe; - const ESM::Clothing *clothes = (ptr.get())->base; + const ESM::Clothing *clothes = (ptr.get())->mBase; std::vector parts = clothes->mParts.mParts; addPartGroup(MWWorld::InventoryStore::Slot_Robe, 5, parts); reserveIndividualPart(ESM::PRT_Groin, MWWorld::InventoryStore::Slot_Robe, 5); @@ -186,11 +191,11 @@ void NpcAnimation::updateParts() reserveIndividualPart(ESM::PRT_RPauldron, MWWorld::InventoryStore::Slot_Robe, 5); reserveIndividualPart(ESM::PRT_LPauldron, MWWorld::InventoryStore::Slot_Robe, 5); } - if(skirtiter != mInv.end()) + if(mSkirtIter != mInv.end()) { - MWWorld::Ptr ptr = *skirtiter; + MWWorld::Ptr ptr = *mSkirtIter; - const ESM::Clothing *clothes = (ptr.get())->base; + const ESM::Clothing *clothes = (ptr.get())->mBase; std::vector parts = clothes->mParts.mParts; addPartGroup(MWWorld::InventoryStore::Slot_Skirt, 4, parts); reserveIndividualPart(ESM::PRT_Groin, MWWorld::InventoryStore::Slot_Skirt, 4); @@ -198,103 +203,103 @@ void NpcAnimation::updateParts() reserveIndividualPart(ESM::PRT_LLeg, MWWorld::InventoryStore::Slot_Skirt, 4); } - if(helmet != mInv.end()) + if(mHelmet != mInv.end()) { removeIndividualPart(ESM::PRT_Hair); - const ESM::Armor *armor = (helmet->get())->base; + const ESM::Armor *armor = (mHelmet->get())->mBase; std::vector parts = armor->mParts.mParts; addPartGroup(MWWorld::InventoryStore::Slot_Helmet, 3, parts); } - if(cuirass != mInv.end()) + if(mCuirass != mInv.end()) { - const ESM::Armor *armor = (cuirass->get())->base; + const ESM::Armor *armor = (mCuirass->get())->mBase; std::vector parts = armor->mParts.mParts; addPartGroup(MWWorld::InventoryStore::Slot_Cuirass, 3, parts); } - if(greaves != mInv.end()) + if(mGreaves != mInv.end()) { - const ESM::Armor *armor = (greaves->get())->base; + const ESM::Armor *armor = (mGreaves->get())->mBase; std::vector parts = armor->mParts.mParts; addPartGroup(MWWorld::InventoryStore::Slot_Greaves, 3, parts); } - if(leftpauldron != mInv.end()) + if(mPauldronL != mInv.end()) { - const ESM::Armor *armor = (leftpauldron->get())->base; + const ESM::Armor *armor = (mPauldronL->get())->mBase; std::vector parts = armor->mParts.mParts; addPartGroup(MWWorld::InventoryStore::Slot_LeftPauldron, 3, parts); } - if(rightpauldron != mInv.end()) + if(mPauldronR != mInv.end()) { - const ESM::Armor *armor = (rightpauldron->get())->base; + const ESM::Armor *armor = (mPauldronR->get())->mBase; std::vector parts = armor->mParts.mParts; addPartGroup(MWWorld::InventoryStore::Slot_RightPauldron, 3, parts); } - if(boots != mInv.end()) + if(mBoots != mInv.end()) { - if(boots->getTypeName() == typeid(ESM::Clothing).name()) + if(mBoots->getTypeName() == typeid(ESM::Clothing).name()) { - const ESM::Clothing *clothes = (boots->get())->base; + const ESM::Clothing *clothes = (mBoots->get())->mBase; std::vector parts = clothes->mParts.mParts; addPartGroup(MWWorld::InventoryStore::Slot_Boots, 2, parts); } - else if(boots->getTypeName() == typeid(ESM::Armor).name()) + else if(mBoots->getTypeName() == typeid(ESM::Armor).name()) { - const ESM::Armor *armor = (boots->get())->base; + const ESM::Armor *armor = (mBoots->get())->mBase; std::vector parts = armor->mParts.mParts; addPartGroup(MWWorld::InventoryStore::Slot_Boots, 3, parts); } } - if(leftglove != mInv.end()) + if(mGloveL != mInv.end()) { - if(leftglove->getTypeName() == typeid(ESM::Clothing).name()) + if(mGloveL->getTypeName() == typeid(ESM::Clothing).name()) { - const ESM::Clothing *clothes = (leftglove->get())->base; + const ESM::Clothing *clothes = (mGloveL->get())->mBase; std::vector parts = clothes->mParts.mParts; addPartGroup(MWWorld::InventoryStore::Slot_LeftGauntlet, 2, parts); } else { - const ESM::Armor *armor = (leftglove->get())->base; + const ESM::Armor *armor = (mGloveL->get())->mBase; std::vector parts = armor->mParts.mParts; addPartGroup(MWWorld::InventoryStore::Slot_LeftGauntlet, 3, parts); } } - if(rightglove != mInv.end()) + if(mGloveR != mInv.end()) { - if(rightglove->getTypeName() == typeid(ESM::Clothing).name()) + if(mGloveR->getTypeName() == typeid(ESM::Clothing).name()) { - const ESM::Clothing *clothes = (rightglove->get())->base; + const ESM::Clothing *clothes = (mGloveR->get())->mBase; std::vector parts = clothes->mParts.mParts; addPartGroup(MWWorld::InventoryStore::Slot_RightGauntlet, 2, parts); } else { - const ESM::Armor *armor = (rightglove->get())->base; + const ESM::Armor *armor = (mGloveR->get())->mBase; std::vector parts = armor->mParts.mParts; addPartGroup(MWWorld::InventoryStore::Slot_RightGauntlet, 3, parts); } } - if(shirt != mInv.end()) + if(mShirt != mInv.end()) { - const ESM::Clothing *clothes = (shirt->get())->base; + const ESM::Clothing *clothes = (mShirt->get())->mBase; std::vector parts = clothes->mParts.mParts; addPartGroup(MWWorld::InventoryStore::Slot_Shirt, 2, parts); } - if(pants != mInv.end()) + if(mPants != mInv.end()) { - const ESM::Clothing *clothes = (pants->get())->base; + const ESM::Clothing *clothes = (mPants->get())->mBase; std::vector parts = clothes->mParts.mParts; addPartGroup(MWWorld::InventoryStore::Slot_Pants, 2, parts); } } if(mPartPriorities[ESM::PRT_Head] < 1) - addOrReplaceIndividualPart(ESM::PRT_Head, -1,1, headModel); + addOrReplaceIndividualPart(ESM::PRT_Head, -1,1, mHeadModel); if(mPartPriorities[ESM::PRT_Hair] < 1 && mPartPriorities[ESM::PRT_Head] <= 1) - addOrReplaceIndividualPart(ESM::PRT_Hair, -1,1, hairModel); + addOrReplaceIndividualPart(ESM::PRT_Hair, -1,1, mHairModel); static const struct { ESM::PartReferenceType type; @@ -322,26 +327,27 @@ void NpcAnimation::updateParts() { ESM::PRT_Tail, { "tail", "" } } }; - const ESMS::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); + const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); for(size_t i = 0;i < sizeof(PartTypeList)/sizeof(PartTypeList[0]);i++) { if(mPartPriorities[PartTypeList[i].type] < 1) { const ESM::BodyPart *part = NULL; - bool tryfemale = isFemale; - int ni = 0; - do { - part = store.bodyParts.search(bodyRaceID+(tryfemale?"_f_":"_m_")+PartTypeList[i].name[ni]); - if(part) break; + const MWWorld::Store &partStore = + store.get(); - ni ^= 1; - if(ni == 0) - { - if(!tryfemale) - break; - tryfemale = false; + if (!mNpc->isMale()) { + part = partStore.search(mBodyPrefix + "_f_" + PartTypeList[i].name[0]); + if (part == 0) { + part = partStore.search(mBodyPrefix + "_f_" + PartTypeList[i].name[1]); } - } while(1); + } + if (part == 0) { + part = partStore.search(mBodyPrefix + "_m_" + PartTypeList[i].name[0]); + } + if (part == 0) { + part = partStore.search(mBodyPrefix + "_m_" + PartTypeList[i].name[1]); + } if(part) addOrReplaceIndividualPart(PartTypeList[i].type, -1,1, "meshes\\"+part->mModel); @@ -364,12 +370,12 @@ NifOgre::EntityList NpcAnimation::insertBoundedPart(const std::string &mesh, int void NpcAnimation::runAnimation(float timepassed) { - if(timeToChange > .2) + if(mTimeToChange > .2) { - timeToChange = 0; + mTimeToChange = 0; updateParts(); } - timeToChange += timepassed; + mTimeToChange += timepassed; Animation::runAnimation(timepassed); } @@ -394,61 +400,61 @@ void NpcAnimation::removeIndividualPart(int type) mPartslots[type] = -1; if(type == ESM::PRT_Head) //0 - removeEntities(head); + removeEntities(mHead); else if(type == ESM::PRT_Hair) //1 - removeEntities(hair); + removeEntities(mHair); else if(type == ESM::PRT_Neck) //2 - removeEntities(neck); + removeEntities(mNeck); else if(type == ESM::PRT_Cuirass)//3 - removeEntities(chest); + removeEntities(mChest); else if(type == ESM::PRT_Groin)//4 - removeEntities(groin); + removeEntities(mGroin); else if(type == ESM::PRT_Skirt)//5 - removeEntities(skirt); + removeEntities(mSkirt); else if(type == ESM::PRT_RHand)//6 - removeEntities(rHand); + removeEntities(mHandR); else if(type == ESM::PRT_LHand)//7 - removeEntities(lHand); + removeEntities(mHandL); else if(type == ESM::PRT_RWrist)//8 - removeEntities(rWrist); + removeEntities(mWristR); else if(type == ESM::PRT_LWrist) //9 - removeEntities(lWrist); + removeEntities(mWristL); else if(type == ESM::PRT_Shield) //10 { } else if(type == ESM::PRT_RForearm) //11 - removeEntities(rForearm); + removeEntities(mForearmR); else if(type == ESM::PRT_LForearm) //12 - removeEntities(lForearm); + removeEntities(mForearmL); else if(type == ESM::PRT_RUpperarm) //13 - removeEntities(rupperArm); + removeEntities(mUpperArmR); else if(type == ESM::PRT_LUpperarm) //14 - removeEntities(lupperArm); + removeEntities(mUpperArmL); else if(type == ESM::PRT_RFoot) //15 - removeEntities(rfoot); + removeEntities(mFootR); else if(type == ESM::PRT_LFoot) //16 - removeEntities(lfoot); + removeEntities(mFootL); else if(type == ESM::PRT_RAnkle) //17 - removeEntities(rAnkle); + removeEntities(mAnkleR); else if(type == ESM::PRT_LAnkle) //18 - removeEntities(lAnkle); + removeEntities(mAnkleL); else if(type == ESM::PRT_RKnee) //19 - removeEntities(rKnee); + removeEntities(mKneeR); else if(type == ESM::PRT_LKnee) //20 - removeEntities(lKnee); + removeEntities(mKneeL); else if(type == ESM::PRT_RLeg) //21 - removeEntities(rUpperLeg); + removeEntities(mUpperLegR); else if(type == ESM::PRT_LLeg) //22 - removeEntities(lUpperLeg); + removeEntities(mUpperLegL); else if(type == ESM::PRT_RPauldron) //23 - removeEntities(rclavicle); + removeEntities(mClavicleR); else if(type == ESM::PRT_LPauldron) //24 - removeEntities(lclavicle); + removeEntities(mClavicleL); else if(type == ESM::PRT_Weapon) //25 { } else if(type == ESM::PRT_Tail) //26 - removeEntities(tail); + removeEntities(mTail); } void NpcAnimation::reserveIndividualPart(int type, int group, int priority) @@ -481,83 +487,83 @@ bool NpcAnimation::addOrReplaceIndividualPart(int type, int group, int priority, switch(type) { case ESM::PRT_Head: //0 - head = insertBoundedPart(mesh, group, "Head"); + mHead = insertBoundedPart(mesh, group, "Head"); break; case ESM::PRT_Hair: //1 - hair = insertBoundedPart(mesh, group, "Head"); + mHair = insertBoundedPart(mesh, group, "Head"); break; case ESM::PRT_Neck: //2 - neck = insertBoundedPart(mesh, group, "Neck"); + mNeck = insertBoundedPart(mesh, group, "Neck"); break; case ESM::PRT_Cuirass: //3 - chest = insertBoundedPart(mesh, group, "Chest"); + mChest = insertBoundedPart(mesh, group, "Chest"); break; case ESM::PRT_Groin: //4 - groin = insertBoundedPart(mesh, group, "Groin"); + mGroin = insertBoundedPart(mesh, group, "Groin"); break; case ESM::PRT_Skirt: //5 - skirt = insertBoundedPart(mesh, group, "Groin"); + mSkirt = insertBoundedPart(mesh, group, "Groin"); break; case ESM::PRT_RHand: //6 - rHand = insertBoundedPart(mesh, group, "Right Hand"); + mHandR = insertBoundedPart(mesh, group, "Right Hand"); break; case ESM::PRT_LHand: //7 - lHand = insertBoundedPart(mesh, group, "Left Hand"); + mHandL = insertBoundedPart(mesh, group, "Left Hand"); break; case ESM::PRT_RWrist: //8 - rWrist = insertBoundedPart(mesh, group, "Right Wrist"); + mWristR = insertBoundedPart(mesh, group, "Right Wrist"); break; case ESM::PRT_LWrist: //9 - lWrist = insertBoundedPart(mesh, group, "Left Wrist"); + mWristL = insertBoundedPart(mesh, group, "Left Wrist"); break; case ESM::PRT_Shield: //10 break; case ESM::PRT_RForearm: //11 - rForearm = insertBoundedPart(mesh, group, "Right Forearm"); + mForearmR = insertBoundedPart(mesh, group, "Right Forearm"); break; case ESM::PRT_LForearm: //12 - lForearm = insertBoundedPart(mesh, group, "Left Forearm"); + mForearmL = insertBoundedPart(mesh, group, "Left Forearm"); break; case ESM::PRT_RUpperarm: //13 - rupperArm = insertBoundedPart(mesh, group, "Right Upper Arm"); + mUpperArmR = insertBoundedPart(mesh, group, "Right Upper Arm"); break; case ESM::PRT_LUpperarm: //14 - lupperArm = insertBoundedPart(mesh, group, "Left Upper Arm"); + mUpperArmL = insertBoundedPart(mesh, group, "Left Upper Arm"); break; case ESM::PRT_RFoot: //15 - rfoot = insertBoundedPart(mesh, group, "Right Foot"); + mFootR = insertBoundedPart(mesh, group, "Right Foot"); break; case ESM::PRT_LFoot: //16 - lfoot = insertBoundedPart(mesh, group, "Left Foot"); + mFootL = insertBoundedPart(mesh, group, "Left Foot"); break; case ESM::PRT_RAnkle: //17 - rAnkle = insertBoundedPart(mesh, group, "Right Ankle"); + mAnkleR = insertBoundedPart(mesh, group, "Right Ankle"); break; case ESM::PRT_LAnkle: //18 - lAnkle = insertBoundedPart(mesh, group, "Left Ankle"); + mAnkleL = insertBoundedPart(mesh, group, "Left Ankle"); break; case ESM::PRT_RKnee: //19 - rKnee = insertBoundedPart(mesh, group, "Right Knee"); + mKneeR = insertBoundedPart(mesh, group, "Right Knee"); break; case ESM::PRT_LKnee: //20 - lKnee = insertBoundedPart(mesh, group, "Left Knee"); + mKneeL = insertBoundedPart(mesh, group, "Left Knee"); break; case ESM::PRT_RLeg: //21 - rUpperLeg = insertBoundedPart(mesh, group, "Right Upper Leg"); + mUpperLegR = insertBoundedPart(mesh, group, "Right Upper Leg"); break; case ESM::PRT_LLeg: //22 - lUpperLeg = insertBoundedPart(mesh, group, "Left Upper Leg"); + mUpperLegL = insertBoundedPart(mesh, group, "Left Upper Leg"); break; case ESM::PRT_RPauldron: //23 - rclavicle = insertBoundedPart(mesh , group, "Right Clavicle"); + mClavicleR = insertBoundedPart(mesh , group, "Right Clavicle"); break; case ESM::PRT_LPauldron: //24 - lclavicle = insertBoundedPart(mesh, group, "Left Clavicle"); + mClavicleL = insertBoundedPart(mesh, group, "Left Clavicle"); break; case ESM::PRT_Weapon: //25 break; case ESM::PRT_Tail: //26 - tail = insertBoundedPart(mesh, group, "Tail"); + mTail = insertBoundedPart(mesh, group, "Tail"); break; } return true; @@ -569,11 +575,14 @@ void NpcAnimation::addPartGroup(int group, int priority, std::vector &partStore = + MWBase::Environment::get().getWorld()->getStore().get(); + const ESM::BodyPart *bodypart = 0; - if(isFemale) - bodypart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search(part.mFemale); + if(!mNpc->isMale()) + bodypart = partStore.search(part.mFemale); if(!bodypart) - bodypart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search(part.mMale); + bodypart = partStore.search(part.mMale); if(bodypart) addOrReplaceIndividualPart(part.mPart, group, priority,"meshes\\" + bodypart->mModel); diff --git a/apps/openmw/mwrender/npcanimation.hpp b/apps/openmw/mwrender/npcanimation.hpp index 21edb3be4f..ca76dcc222 100644 --- a/apps/openmw/mwrender/npcanimation.hpp +++ b/apps/openmw/mwrender/npcanimation.hpp @@ -8,6 +8,11 @@ #include "../mwclass/npc.hpp" #include "../mwworld/containerstore.hpp" +namespace ESM +{ + struct NPC; +} + namespace MWRender{ class NpcAnimation: public Animation{ @@ -19,57 +24,57 @@ private: int mPartPriorities[27]; //Bounded Parts - NifOgre::EntityList lclavicle; - NifOgre::EntityList rclavicle; - NifOgre::EntityList rupperArm; - NifOgre::EntityList lupperArm; - NifOgre::EntityList rUpperLeg; - NifOgre::EntityList lUpperLeg; - NifOgre::EntityList lForearm; - NifOgre::EntityList rForearm; - NifOgre::EntityList lWrist; - NifOgre::EntityList rWrist; - NifOgre::EntityList rKnee; - NifOgre::EntityList lKnee; - NifOgre::EntityList neck; - NifOgre::EntityList rAnkle; - NifOgre::EntityList lAnkle; - NifOgre::EntityList groin; - NifOgre::EntityList skirt; - NifOgre::EntityList lfoot; - NifOgre::EntityList rfoot; - NifOgre::EntityList hair; - NifOgre::EntityList rHand; - NifOgre::EntityList lHand; - NifOgre::EntityList head; - NifOgre::EntityList chest; - NifOgre::EntityList tail; + NifOgre::EntityList mClavicleL; + NifOgre::EntityList mClavicleR; + NifOgre::EntityList mUpperArmL; + NifOgre::EntityList mUpperArmR; + NifOgre::EntityList mUpperLegL; + NifOgre::EntityList mUpperLegR; + NifOgre::EntityList mForearmL; + NifOgre::EntityList mForearmR; + NifOgre::EntityList mWristL; + NifOgre::EntityList mWristR; + NifOgre::EntityList mKneeR; + NifOgre::EntityList mKneeL; + NifOgre::EntityList mNeck; + NifOgre::EntityList mAnkleL; + NifOgre::EntityList mAnkleR; + NifOgre::EntityList mGroin; + NifOgre::EntityList mSkirt; + NifOgre::EntityList mFootL; + NifOgre::EntityList mFootR; + NifOgre::EntityList mHair; + NifOgre::EntityList mHandL; + NifOgre::EntityList mHandR; + NifOgre::EntityList mHead; + NifOgre::EntityList mChest; + NifOgre::EntityList mTail; - bool isBeast; - bool isFemale; - std::string headModel; - std::string hairModel; - std::string npcName; - std::string bodyRaceID; - float timeToChange; - MWWorld::ContainerStoreIterator robe; - MWWorld::ContainerStoreIterator helmet; - MWWorld::ContainerStoreIterator shirt; - MWWorld::ContainerStoreIterator cuirass; - MWWorld::ContainerStoreIterator greaves; - MWWorld::ContainerStoreIterator leftpauldron; - MWWorld::ContainerStoreIterator rightpauldron; - MWWorld::ContainerStoreIterator boots; - MWWorld::ContainerStoreIterator pants; - MWWorld::ContainerStoreIterator leftglove; - MWWorld::ContainerStoreIterator rightglove; - MWWorld::ContainerStoreIterator skirtiter; + const ESM::NPC *mNpc; + std::string mHeadModel; + std::string mHairModel; + std::string mBodyPrefix; + + + float mTimeToChange; + MWWorld::ContainerStoreIterator mRobe; + MWWorld::ContainerStoreIterator mHelmet; + MWWorld::ContainerStoreIterator mShirt; + MWWorld::ContainerStoreIterator mCuirass; + MWWorld::ContainerStoreIterator mGreaves; + MWWorld::ContainerStoreIterator mPauldronL; + MWWorld::ContainerStoreIterator mPauldronR; + MWWorld::ContainerStoreIterator mBoots; + MWWorld::ContainerStoreIterator mPants; + MWWorld::ContainerStoreIterator mGloveL; + MWWorld::ContainerStoreIterator mGloveR; + MWWorld::ContainerStoreIterator mSkirtIter; int mVisibilityFlags; public: NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, - MWWorld::InventoryStore& _inv, int visibilityFlags); + MWWorld::InventoryStore& inv, int visibilityFlags); virtual ~NpcAnimation(); NifOgre::EntityList insertBoundedPart(const std::string &mesh, int group, const std::string &bonename); virtual void runAnimation(float timepassed); diff --git a/apps/openmw/mwrender/objects.cpp b/apps/openmw/mwrender/objects.cpp index 69c853d86b..36f09e6d96 100644 --- a/apps/openmw/mwrender/objects.cpp +++ b/apps/openmw/mwrender/objects.cpp @@ -219,18 +219,18 @@ void Objects::insertLight (const MWWorld::Ptr& ptr, float r, float g, float b, f info.radius = radius; info.colour = Ogre::ColourValue(r, g, b); - if (ref->base->mData.mFlags & ESM::Light::Negative) + if (ref->mBase->mData.mFlags & ESM::Light::Negative) info.colour *= -1; - info.interior = (ptr.getCell()->cell->mData.mFlags & ESM::Cell::Interior); + info.interior = !ptr.getCell()->mCell->isExterior(); - if (ref->base->mData.mFlags & ESM::Light::Flicker) + if (ref->mBase->mData.mFlags & ESM::Light::Flicker) info.type = LT_Flicker; - else if (ref->base->mData.mFlags & ESM::Light::FlickerSlow) + else if (ref->mBase->mData.mFlags & ESM::Light::FlickerSlow) info.type = LT_FlickerSlow; - else if (ref->base->mData.mFlags & ESM::Light::Pulse) + else if (ref->mBase->mData.mFlags & ESM::Light::Pulse) info.type = LT_Pulse; - else if (ref->base->mData.mFlags & ESM::Light::PulseSlow) + else if (ref->mBase->mData.mFlags & ESM::Light::PulseSlow) info.type = LT_PulseSlow; else info.type = LT_Normal; diff --git a/apps/openmw/mwrender/player.cpp b/apps/openmw/mwrender/player.cpp index bbc75cade1..0e4c76b0ed 100644 --- a/apps/openmw/mwrender/player.cpp +++ b/apps/openmw/mwrender/player.cpp @@ -23,7 +23,8 @@ namespace MWRender mFreeLook(true), mHeight(128.f), mCameraDistance(300.f), - mDistanceAdjusted(false) + mDistanceAdjusted(false), + mAnimation(NULL) { mVanity.enabled = false; mVanity.allowed = true; @@ -309,7 +310,13 @@ namespace MWRender void Player::setAnimation(NpcAnimation *anim) { + delete mAnimation; mAnimation = anim; + + mPlayerNode->setVisible( + mVanity.enabled || mPreviewMode || !mFirstPersonView, + false + ); } void Player::setHeight(float height) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 426cc47903..5f1f1ad433 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -19,7 +19,7 @@ #include #include -#include +#include "../mwworld/esmstore.hpp" #include #include "../mwbase/world.hpp" // these includes can be removed once the static-hack is gone @@ -207,7 +207,7 @@ void RenderingManager::removeCell (MWWorld::Ptr::CellStore *store) mObjects.removeCell(store); mActors.removeCell(store); mDebugging->cellRemoved(store); - if (store->cell->isExterior()) + if (store->mCell->isExterior()) mTerrainManager->cellRemoved(store); } @@ -228,7 +228,7 @@ void RenderingManager::cellAdded (MWWorld::Ptr::CellStore *store) { mObjects.buildStaticGeometry (*store); mDebugging->cellAdded(store); - if (store->cell->isExterior()) + if (store->mCell->isExterior()) mTerrainManager->cellAdded(store); waterAdded(store); } @@ -377,22 +377,26 @@ void RenderingManager::update (float duration, bool paused) mWater->updateUnderwater( world->isUnderwater( - *world->getPlayer().getPlayer().getCell()->cell, + *world->getPlayer().getPlayer().getCell()->mCell, Ogre::Vector3(cam.x, -cam.z, cam.y)) ); mWater->update(duration); } } -void RenderingManager::waterAdded (MWWorld::Ptr::CellStore *store){ - if(store->cell->mData.mFlags & store->cell->HasWater - || ((!(store->cell->mData.mFlags & ESM::Cell::Interior)) - && !MWBase::Environment::get().getWorld()->getStore().lands.search(store->cell->mData.mX,store->cell->mData.mY) )) // always use water, if the cell does not have land. +void RenderingManager::waterAdded (MWWorld::Ptr::CellStore *store) +{ + const MWWorld::Store &lands = + MWBase::Environment::get().getWorld()->getStore().get(); + + if(store->mCell->mData.mFlags & ESM::Cell::HasWater + || ((store->mCell->isExterior()) + && !lands.search(store->mCell->getGridX(),store->mCell->getGridY()) )) // always use water, if the cell does not have land. { if(mWater == 0) - mWater = new MWRender::Water(mRendering.getCamera(), this, store->cell); + mWater = new MWRender::Water(mRendering.getCamera(), this, store->mCell); else - mWater->changeCell(store->cell); + mWater->changeCell(store->mCell); mWater->setActive(true); } else @@ -469,7 +473,13 @@ bool RenderingManager::toggleRenderMode(int mode) return false; } } - else //if (mode == MWWorld::World::Render_Compositors) + else if (mode == MWBase::World::Render_BoundingBoxes) + { + bool show = !mRendering.getScene()->getShowBoundingBoxes(); + mRendering.getScene()->showBoundingBoxes(show); + return show; + } + else //if (mode == MWBase::World::Render_Compositors) { return mCompositors->toggle(); } @@ -478,9 +488,9 @@ bool RenderingManager::toggleRenderMode(int mode) void RenderingManager::configureFog(MWWorld::Ptr::CellStore &mCell) { Ogre::ColourValue color; - color.setAsABGR (mCell.cell->mAmbi.mFog); + color.setAsABGR (mCell.mCell->mAmbi.mFog); - configureFog(mCell.cell->mAmbi.mFogDensity, color); + configureFog(mCell.mCell->mAmbi.mFogDensity, color); if (mWater) mWater->setViewportBackground (Ogre::ColourValue(0.8f, 0.9f, 1.0f)); @@ -530,7 +540,7 @@ void RenderingManager::setAmbientMode() void RenderingManager::configureAmbient(MWWorld::Ptr::CellStore &mCell) { - mAmbientColor.setAsABGR (mCell.cell->mAmbi.mAmbient); + mAmbientColor.setAsABGR (mCell.mCell->mAmbi.mAmbient); setAmbientMode(); // Create a "sun" that shines light downwards. It doesn't look @@ -540,7 +550,7 @@ void RenderingManager::configureAmbient(MWWorld::Ptr::CellStore &mCell) mSun = mRendering.getScene()->createLight(); } Ogre::ColourValue colour; - colour.setAsABGR (mCell.cell->mAmbi.mSunlight); + colour.setAsABGR (mCell.mCell->mAmbi.mSunlight); mSun->setDiffuseColour (colour); mSun->setType(Ogre::Light::LT_DIRECTIONAL); mSun->setDirection(0,-1,0); @@ -624,7 +634,7 @@ void RenderingManager::setGlare(bool glare) void RenderingManager::requestMap(MWWorld::Ptr::CellStore* cell) { - if (!(cell->cell->mData.mFlags & ESM::Cell::Interior)) + if (cell->mCell->isExterior()) mLocalMap->requestMap(cell); else mLocalMap->requestMap(cell, mObjects.getDimensions(cell)); diff --git a/apps/openmw/mwrender/terrain.cpp b/apps/openmw/mwrender/terrain.cpp index b00e52b520..d46c2521f0 100644 --- a/apps/openmw/mwrender/terrain.cpp +++ b/apps/openmw/mwrender/terrain.cpp @@ -4,7 +4,7 @@ #include #include -#include +#include "../mwworld/esmstore.hpp" #include @@ -92,10 +92,11 @@ namespace MWRender void TerrainManager::cellAdded(MWWorld::Ptr::CellStore *store) { - const int cellX = store->cell->getGridX(); - const int cellY = store->cell->getGridY(); + const int cellX = store->mCell->getGridX(); + const int cellY = store->mCell->getGridY(); - ESM::Land* land = MWBase::Environment::get().getWorld()->getStore().lands.search(cellX, cellY); + ESM::Land* land = + MWBase::Environment::get().getWorld()->getStore().get().search(cellX, cellY); if (land == NULL) // no land data means we're not going to create any terrain. return; @@ -188,8 +189,8 @@ namespace MWRender { for ( int y = 0; y < 2; y++ ) { - int terrainX = store->cell->getGridX() * 2 + x; - int terrainY = store->cell->getGridY() * 2 + y; + int terrainX = store->mCell->getGridX() * 2 + x; + int terrainY = store->mCell->getGridY() * 2 + y; if (mTerrainGroup.getTerrain(terrainX, terrainY) != NULL) mTerrainGroup.unloadTerrain(terrainX, terrainY); } @@ -258,11 +259,13 @@ namespace MWRender { //NB: All vtex ids are +1 compared to the ltex ids + const MWWorld::Store <exStore = + MWBase::Environment::get().getWorld()->getStore().get(); + // NOTE: using the quick hack above, we should no longer end up with textures indices // that are out of bounds. However, I haven't updated the test to a multi-palette // system yet. We probably need more work here, so we skip it for now. - - //assert( (int)MWBase::Environment::get().getWorld()->getStore().landTexts.getSize() >= (int)ltexIndex - 1 && + //assert( (int)ltexStore.getSize() >= (int)ltexIndex - 1 && //"LAND.VTEX must be within the bounds of the LTEX array"); std::string texture; @@ -272,7 +275,7 @@ namespace MWRender } else { - texture = MWBase::Environment::get().getWorld()->getStore().landTexts.search(ltexIndex-1, plugin)->mTexture; + texture = ltexStore.search(ltexIndex-1, plugin)->mTexture; //TODO this is needed due to MWs messed up texture handling texture = texture.substr(0, texture.rfind(".")) + ".dds"; } @@ -428,7 +431,8 @@ namespace MWRender } - ESM::Land* land = MWBase::Environment::get().getWorld()->getStore().lands.search(cellX, cellY); + ESM::Land* land = + MWBase::Environment::get().getWorld()->getStore().get().search(cellX, cellY); if ( land != NULL ) { if (!land->isDataLoaded(ESM::Land::DATA_VTEX)) diff --git a/apps/openmw/mwscript/aiextensions.cpp b/apps/openmw/mwscript/aiextensions.cpp index 9d70c28bd7..787962ad1e 100644 --- a/apps/openmw/mwscript/aiextensions.cpp +++ b/apps/openmw/mwscript/aiextensions.cpp @@ -130,7 +130,7 @@ namespace MWScript Interpreter::Type_Integer value = runtime[0].mInteger; runtime.pop(); - MWWorld::Class::get (ptr).getCreatureStats (ptr).setHello(value); + MWWorld::Class::get (ptr).getCreatureStats (ptr).setAiSetting (0, value); } }; @@ -146,7 +146,7 @@ namespace MWScript Interpreter::Type_Integer value = runtime[0].mInteger; runtime.pop(); - MWWorld::Class::get (ptr).getCreatureStats (ptr).setFight(value); + MWWorld::Class::get (ptr).getCreatureStats (ptr).setAiSetting (1, value); } }; @@ -162,7 +162,7 @@ namespace MWScript Interpreter::Type_Integer value = runtime[0].mInteger; runtime.pop(); - MWWorld::Class::get (ptr).getCreatureStats (ptr).setFlee(value); + MWWorld::Class::get (ptr).getCreatureStats (ptr).setAiSetting (2, value); } }; @@ -178,7 +178,7 @@ namespace MWScript Interpreter::Type_Integer value = runtime[0].mInteger; runtime.pop(); - MWWorld::Class::get (ptr).getCreatureStats (ptr).setAlarm(value); + MWWorld::Class::get (ptr).getCreatureStats (ptr).setAiSetting (3, value); } }; diff --git a/apps/openmw/mwscript/cellextensions.cpp b/apps/openmw/mwscript/cellextensions.cpp index 57dd7962b2..a4a738ca76 100644 --- a/apps/openmw/mwscript/cellextensions.cpp +++ b/apps/openmw/mwscript/cellextensions.cpp @@ -1,7 +1,7 @@ #include "cellextensions.hpp" -#include +#include "../mwworld/esmstore.hpp" #include @@ -87,8 +87,7 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime) { bool interior = - MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getCell()->cell->mData.mFlags & - ESM::Cell::Interior; + !MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getCell()->mCell->isExterior(); runtime.push (interior ? 1 : 0); } @@ -103,14 +102,14 @@ namespace MWScript std::string name = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); - const ESM::Cell *cell = MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getCell()->cell; + const ESM::Cell *cell = MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getCell()->mCell; std::string current = cell->mName; if (!(cell->mData.mFlags & ESM::Cell::Interior) && current.empty()) { const ESM::Region *region = - MWBase::Environment::get().getWorld()->getStore().regions.find (cell->mRegion); + MWBase::Environment::get().getWorld()->getStore().get().find (cell->mRegion); current = region->mName; } @@ -143,7 +142,7 @@ namespace MWScript MWWorld::Ptr::CellStore *cell = MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getCell(); - if (!(cell->cell->mData.mFlags & ESM::Cell::Interior)) + if (cell->mCell->isExterior()) throw std::runtime_error("Can't set water level in exterior cell"); cell->mWaterLevel = level; @@ -161,7 +160,7 @@ namespace MWScript MWWorld::Ptr::CellStore *cell = MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getCell(); - if (!(cell->cell->mData.mFlags & ESM::Cell::Interior)) + if (cell->mCell->isExterior()) throw std::runtime_error("Can't set water level in exterior cell"); cell->mWaterLevel +=level; diff --git a/apps/openmw/mwscript/compilercontext.cpp b/apps/openmw/mwscript/compilercontext.cpp index 139a5cc6cf..57d93512f4 100644 --- a/apps/openmw/mwscript/compilercontext.cpp +++ b/apps/openmw/mwscript/compilercontext.cpp @@ -1,7 +1,7 @@ #include "compilercontext.hpp" -#include +#include "../mwworld/esmstore.hpp" #include @@ -42,26 +42,29 @@ namespace MWScript bool CompilerContext::isId (const std::string& name) const { + const MWWorld::ESMStore &store = + MWBase::Environment::get().getWorld()->getStore(); + return - MWBase::Environment::get().getWorld()->getStore().activators.search (name) || - MWBase::Environment::get().getWorld()->getStore().potions.search (name) || - MWBase::Environment::get().getWorld()->getStore().appas.search (name) || - MWBase::Environment::get().getWorld()->getStore().armors.search (name) || - MWBase::Environment::get().getWorld()->getStore().books.search (name) || - MWBase::Environment::get().getWorld()->getStore().clothes.search (name) || - MWBase::Environment::get().getWorld()->getStore().containers.search (name) || - MWBase::Environment::get().getWorld()->getStore().creatures.search (name) || - MWBase::Environment::get().getWorld()->getStore().doors.search (name) || - MWBase::Environment::get().getWorld()->getStore().ingreds.search (name) || - MWBase::Environment::get().getWorld()->getStore().creatureLists.search (name) || - MWBase::Environment::get().getWorld()->getStore().itemLists.search (name) || - MWBase::Environment::get().getWorld()->getStore().lights.search (name) || - MWBase::Environment::get().getWorld()->getStore().lockpicks.search (name) || - MWBase::Environment::get().getWorld()->getStore().miscItems.search (name) || - MWBase::Environment::get().getWorld()->getStore().npcs.search (name) || - MWBase::Environment::get().getWorld()->getStore().probes.search (name) || - MWBase::Environment::get().getWorld()->getStore().repairs.search (name) || - MWBase::Environment::get().getWorld()->getStore().statics.search (name) || - MWBase::Environment::get().getWorld()->getStore().weapons.search (name); + store.get().search (name) || + store.get().search (name) || + store.get().search (name) || + store.get().search (name) || + store.get().search (name) || + store.get().search (name) || + store.get().search (name) || + store.get().search (name) || + store.get().search (name) || + store.get().search (name) || + store.get().search (name) || + store.get().search (name) || + store.get().search (name) || + store.get().search (name) || + store.get().search (name) || + store.get().search (name) || + store.get().search (name) || + store.get().search (name) || + store.get().search (name) || + store.get().search (name); } } diff --git a/apps/openmw/mwscript/dialogueextensions.cpp b/apps/openmw/mwscript/dialogueextensions.cpp index 21c21acf00..72ae257241 100644 --- a/apps/openmw/mwscript/dialogueextensions.cpp +++ b/apps/openmw/mwscript/dialogueextensions.cpp @@ -11,6 +11,9 @@ #include "../mwbase/dialoguemanager.hpp" #include "../mwbase/journal.hpp" +#include "../mwworld/class.hpp" +#include "../mwmechanics/npcstats.hpp" + #include "interpretercontext.hpp" #include "ref.hpp" @@ -126,6 +129,37 @@ namespace MWScript } }; + template + class OpModReputation : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWWorld::Ptr ptr = R()(runtime); + Interpreter::Type_Integer value = runtime[0].mInteger; + runtime.pop(); + + MWWorld::Class::get(ptr).getNpcStats (ptr).setReputation (MWWorld::Class::get(ptr).getNpcStats (ptr).getReputation () + value); + } + }; + + template + class OpSetReputation : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWWorld::Ptr ptr = R()(runtime); + Interpreter::Type_Integer value = runtime[0].mInteger; + runtime.pop(); + + MWWorld::Class::get(ptr).getNpcStats (ptr).setReputation (value); + } + }; + + const int opcodeJournal = 0x2000133; const int opcodeSetJournalIndex = 0x2000134; const int opcodeGetJournalIndex = 0x2000135; @@ -134,6 +168,10 @@ namespace MWScript const int opcodeForceGreeting = 0x200014f; const int opcodeForceGreetingExplicit = 0x2000150; const int opcodeGoodbye = 0x2000152; + const int opcodeSetReputation = 0x20001ad; + const int opcodeModReputation = 0x20001ae; + const int opcodeSetReputationExplicit = 0x20001af; + const int opcodeModReputationExplicit = 0x20001b0; void registerExtensions (Compiler::Extensions& extensions) { @@ -146,6 +184,10 @@ namespace MWScript extensions.registerInstruction("forcegreeting","",opcodeForceGreeting, opcodeForceGreetingExplicit); extensions.registerInstruction("goodbye", "", opcodeGoodbye); + extensions.registerInstruction("setreputation", "l", opcodeSetReputation, + opcodeSetReputationExplicit); + extensions.registerInstruction("modreputation", "l", opcodeModReputation, + opcodeModReputationExplicit); } void installOpcodes (Interpreter::Interpreter& interpreter) @@ -158,6 +200,10 @@ namespace MWScript interpreter.installSegment5 (opcodeForceGreeting, new OpForceGreeting); interpreter.installSegment5 (opcodeForceGreetingExplicit, new OpForceGreeting); interpreter.installSegment5 (opcodeGoodbye, new OpGoodbye); + interpreter.installSegment5 (opcodeSetReputation, new OpSetReputation); + interpreter.installSegment5 (opcodeModReputation, new OpModReputation); + interpreter.installSegment5 (opcodeSetReputationExplicit, new OpSetReputation); + interpreter.installSegment5 (opcodeModReputationExplicit, new OpModReputation); } } diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index cb984e257c..b130aa9547 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -31,7 +31,13 @@ op 0x2000e: PCGetRank implicit op 0x2000f: PCGetRank explicit op 0x20010: AiWander op 0x20011: AiWander, explicit reference -op s 0x20012-0x3ffff unused +op 0x20012: GetPCFacRep +op 0x20013: GetPCFacRep, explicit reference +op 0x20014: SetPCFacRep +op 0x20015: SetPCFacRep, explicit reference +op 0x20016: ModPCFacRep +op 0x20017: ModPCFacRep, explicit reference +op s 0x20018-0x3ffff unused Segment 4: (not implemented yet) @@ -198,14 +204,27 @@ op 0x2000197: Position Explicit op 0x2000198: PositionCell op 0x2000199: PositionCell Explicit op 0x200019a: PlaceItemCell -op 0x200019b: PlaceItem +op 0x200019b: PlaceItem op 0x200019c: PlaceAtPc -op 0x200019d: PlaceAtMe +op 0x200019d: PlaceAtMe op 0x200019e: PlaceAtMe Explicit op 0x200019f: GetPcSleep op 0x20001a0: ShowMap op 0x20001a1: FillMap op 0x20001a2: WakeUpPc op 0x20001a3: GetDeadCount -opcodes 0x20001a4-0x3ffffff unused +op 0x20001a4: SetDisposition +op 0x20001a5: SetDisposition, Explicit +op 0x20001a6: GetDisposition +op 0x20001a7: GetDisposition, Explicit +op 0x20001a8: CommonDisease +op 0x20001a9: CommonDisease, explicit reference +op 0x20001aa: BlightDisease +op 0x20001ab: BlightDisease, explicit reference +op 0x20001ac: ToggleCollisionBoxes +op 0x20001ad: SetReputation +op 0x20001ae: ModReputation +op 0x20001af: SetReputation, explicit +op 0x20001b0: ModReputation, explicit +opcodes 0x20001b1-0x3ffffff unused diff --git a/apps/openmw/mwscript/globalscripts.cpp b/apps/openmw/mwscript/globalscripts.cpp index 37cf341271..3ef138432d 100644 --- a/apps/openmw/mwscript/globalscripts.cpp +++ b/apps/openmw/mwscript/globalscripts.cpp @@ -3,8 +3,7 @@ #include -#include -#include +#include "../mwworld/esmstore.hpp" #include "../mwbase/environment.hpp" #include "../mwbase/scriptmanager.hpp" @@ -13,21 +12,23 @@ namespace MWScript { - GlobalScripts::GlobalScripts (const ESMS::ESMStore& store) + GlobalScripts::GlobalScripts (const MWWorld::ESMStore& store) : mStore (store) { addScript ("Main"); - for (ESMS::RecListT::MapType::const_iterator iter - (store.startScripts.list.begin()); - iter != store.startScripts.list.end(); ++iter) - addScript (iter->second.mScript); + MWWorld::Store::iterator iter = + store.get().begin(); + + for (; iter != store.get().end(); ++iter) { + addScript (iter->mScript); + } } void GlobalScripts::addScript (const std::string& name) { if (mScripts.find (name)==mScripts.end()) - if (const ESM::Script *script = mStore.scripts.find (name)) + if (const ESM::Script *script = mStore.get().find (name)) { Locals locals; diff --git a/apps/openmw/mwscript/globalscripts.hpp b/apps/openmw/mwscript/globalscripts.hpp index cc2f7ffdd4..f9f9b7ae3a 100644 --- a/apps/openmw/mwscript/globalscripts.hpp +++ b/apps/openmw/mwscript/globalscripts.hpp @@ -6,7 +6,7 @@ #include "locals.hpp" -namespace ESMS +namespace MWWorld { struct ESMStore; } @@ -15,12 +15,12 @@ namespace MWScript { class GlobalScripts { - const ESMS::ESMStore& mStore; + const MWWorld::ESMStore& mStore; std::map > mScripts; // running, local variables public: - GlobalScripts (const ESMS::ESMStore& store); + GlobalScripts (const MWWorld::ESMStore& store); void addScript (const std::string& name); diff --git a/apps/openmw/mwscript/guiextensions.cpp b/apps/openmw/mwscript/guiextensions.cpp index 66bb4e0432..72c2db164f 100644 --- a/apps/openmw/mwscript/guiextensions.cpp +++ b/apps/openmw/mwscript/guiextensions.cpp @@ -9,8 +9,7 @@ #include #include -#include -#include +#include "../mwworld/esmstore.hpp" #include "../mwbase/environment.hpp" #include "../mwbase/windowmanager.hpp" @@ -109,13 +108,20 @@ namespace MWScript // "Will match complete or partial cells, so ShowMap, "Vivec" will show cells Vivec and Vivec, Fred's House as well." // http://www.uesp.net/wiki/Tes3Mod:ShowMap - const ESMS::CellList::ExtCells& extCells = MWBase::Environment::get().getWorld ()->getStore ().cells.extCells; - for (ESMS::CellList::ExtCells::const_iterator it = extCells.begin(); it != extCells.end(); ++it) + const MWWorld::Store &cells = + MWBase::Environment::get().getWorld()->getStore().get(); + + MWWorld::Store::iterator it = cells.extBegin(); + for (; it != cells.extEnd(); ++it) { - std::string name = it->second->mName; + std::string name = it->mName; boost::algorithm::to_lower(name); if (name.find(cell) != std::string::npos) - MWBase::Environment::get().getWindowManager()->addVisitedLocation (it->second->mName, it->first.first, it->first.second); + MWBase::Environment::get().getWindowManager()->addVisitedLocation ( + it->mName, + it->getGridX(), + it->getGridY() + ); } } }; @@ -126,12 +132,19 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime) { - const ESMS::CellList::ExtCells& extCells = MWBase::Environment::get().getWorld ()->getStore ().cells.extCells; - for (ESMS::CellList::ExtCells::const_iterator it = extCells.begin(); it != extCells.end(); ++it) + const MWWorld::Store &cells = + MWBase::Environment::get().getWorld ()->getStore().get(); + + MWWorld::Store::iterator it = cells.extBegin(); + for (; it != cells.extEnd(); ++it) { - std::string name = it->second->mName; + std::string name = it->mName; if (name != "") - MWBase::Environment::get().getWindowManager()->addVisitedLocation (name, it->first.first, it->first.second); + MWBase::Environment::get().getWindowManager()->addVisitedLocation ( + name, + it->getGridX(), + it->getGridY() + ); } } }; diff --git a/apps/openmw/mwscript/interpretercontext.cpp b/apps/openmw/mwscript/interpretercontext.cpp index 075ac56462..577ad008f5 100644 --- a/apps/openmw/mwscript/interpretercontext.cpp +++ b/apps/openmw/mwscript/interpretercontext.cpp @@ -5,7 +5,7 @@ #include #include -#include +#include "../mwworld/esmstore.hpp" #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" @@ -278,7 +278,7 @@ namespace MWScript int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 's'); ptr.getRefData().setLocals ( - *MWBase::Environment::get().getWorld()->getStore().scripts.find (scriptId)); + *MWBase::Environment::get().getWorld()->getStore().get().find (scriptId)); return ptr.getRefData().getLocals().mShorts[index]; } @@ -291,7 +291,7 @@ namespace MWScript int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 'l'); ptr.getRefData().setLocals ( - *MWBase::Environment::get().getWorld()->getStore().scripts.find (scriptId)); + *MWBase::Environment::get().getWorld()->getStore().get().find (scriptId)); return ptr.getRefData().getLocals().mLongs[index]; } @@ -304,7 +304,7 @@ namespace MWScript int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 'f'); ptr.getRefData().setLocals ( - *MWBase::Environment::get().getWorld()->getStore().scripts.find (scriptId)); + *MWBase::Environment::get().getWorld()->getStore().get().find (scriptId)); return ptr.getRefData().getLocals().mFloats[index]; } @@ -317,7 +317,7 @@ namespace MWScript int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 's'); ptr.getRefData().setLocals ( - *MWBase::Environment::get().getWorld()->getStore().scripts.find (scriptId)); + *MWBase::Environment::get().getWorld()->getStore().get().find (scriptId)); ptr.getRefData().getLocals().mShorts[index] = value; } @@ -330,7 +330,7 @@ namespace MWScript int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 'l'); ptr.getRefData().setLocals ( - *MWBase::Environment::get().getWorld()->getStore().scripts.find (scriptId)); + *MWBase::Environment::get().getWorld()->getStore().get().find (scriptId)); ptr.getRefData().getLocals().mLongs[index] = value; } @@ -343,7 +343,7 @@ namespace MWScript int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 'f'); ptr.getRefData().setLocals ( - *MWBase::Environment::get().getWorld()->getStore().scripts.find (scriptId)); + *MWBase::Environment::get().getWorld()->getStore().get().find (scriptId)); ptr.getRefData().getLocals().mFloats[index] = value; } diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index 674548cd68..c09f0c860f 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -132,6 +132,24 @@ namespace MWScript } }; + + class OpToggleCollisionBoxes : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + InterpreterContext& context = + static_cast (runtime.getContext()); + + bool enabled = + MWBase::Environment::get().getWorld()->toggleRenderMode (MWBase::World::Render_BoundingBoxes); + + context.report (enabled ? + "Bounding Box Rendering -> On" : "Bounding Box Rendering -> Off"); + } + }; + class OpToggleWireframe : public Interpreter::Opcode0 { public: @@ -262,6 +280,7 @@ namespace MWScript const int opcodeUnlock = 0x200008c; const int opcodeUnlockExplicit = 0x200008d; const int opcodeToggleCollisionDebug = 0x2000132; + const int opcodeToggleCollisionBoxes = 0x20001ac; const int opcodeToggleWireframe = 0x200013b; const int opcodeFadeIn = 0x200013c; const int opcodeFadeOut = 0x200013d; @@ -280,9 +299,9 @@ namespace MWScript extensions.registerInstruction ("activate", "", opcodeActivate); extensions.registerInstruction ("lock", "/l", opcodeLock, opcodeLockExplicit); extensions.registerInstruction ("unlock", "", opcodeUnlock, opcodeUnlockExplicit); - extensions.registerInstruction ("togglecollisionboxes", "", opcodeToggleCollisionDebug); + extensions.registerInstruction ("togglecollisionboxes", "", opcodeToggleCollisionBoxes); extensions.registerInstruction ("togglecollisiongrid", "", opcodeToggleCollisionDebug); - extensions.registerInstruction ("tcb", "", opcodeToggleCollisionDebug); + extensions.registerInstruction ("tcb", "", opcodeToggleCollisionBoxes); extensions.registerInstruction ("tcg", "", opcodeToggleCollisionDebug); extensions.registerInstruction ("twf", "", opcodeToggleWireframe); extensions.registerInstruction ("togglewireframe", "", opcodeToggleWireframe); @@ -310,6 +329,7 @@ namespace MWScript interpreter.installSegment5 (opcodeUnlock, new OpUnlock); interpreter.installSegment5 (opcodeUnlockExplicit, new OpUnlock); interpreter.installSegment5 (opcodeToggleCollisionDebug, new OpToggleCollisionDebug); + interpreter.installSegment5 (opcodeToggleCollisionBoxes, new OpToggleCollisionBoxes); interpreter.installSegment5 (opcodeToggleWireframe, new OpToggleWireframe); interpreter.installSegment5 (opcodeFadeIn, new OpFadeIn); interpreter.installSegment5 (opcodeFadeOut, new OpFadeOut); diff --git a/apps/openmw/mwscript/scriptmanagerimp.cpp b/apps/openmw/mwscript/scriptmanagerimp.cpp index 883d3dfd38..1f338edbd3 100644 --- a/apps/openmw/mwscript/scriptmanagerimp.cpp +++ b/apps/openmw/mwscript/scriptmanagerimp.cpp @@ -7,7 +7,7 @@ #include #include -#include +#include "../mwworld/esmstore.hpp" #include #include @@ -17,7 +17,7 @@ namespace MWScript { - ScriptManager::ScriptManager (const ESMS::ESMStore& store, bool verbose, + ScriptManager::ScriptManager (const MWWorld::ESMStore& store, bool verbose, Compiler::Context& compilerContext) : mErrorHandler (std::cerr), mStore (store), mVerbose (verbose), mCompilerContext (compilerContext), mParser (mErrorHandler, mCompilerContext), @@ -31,7 +31,7 @@ namespace MWScript bool Success = true; - if (const ESM::Script *script = mStore.scripts.find (name)) + if (const ESM::Script *script = mStore.get().find (name)) { if (mVerbose) std::cout << "compiling script: " << name << std::endl; @@ -125,15 +125,14 @@ namespace MWScript std::pair ScriptManager::compileAll() { - typedef ESMS::ScriptListT::MapType Container; - - const Container& scripts = mStore.scripts.list; - int count = 0; int success = 0; - for (Container::const_iterator iter (scripts.begin()); iter!=scripts.end(); ++iter, ++count) - if (compile (iter->first)) + const MWWorld::Store& scripts = mStore.get(); + MWWorld::Store::iterator it = scripts.begin(); + + for (; it != scripts.end(); ++it, ++count) + if (compile (it->mId)) ++success; return std::make_pair (count, success); @@ -170,7 +169,7 @@ namespace MWScript int ScriptManager::getLocalIndex (const std::string& scriptId, const std::string& variable, char type) { - const ESM::Script *script = mStore.scripts.find (scriptId); + const ESM::Script *script = mStore.get().find (scriptId); int offset = 0; int size = 0; diff --git a/apps/openmw/mwscript/scriptmanagerimp.hpp b/apps/openmw/mwscript/scriptmanagerimp.hpp index a97310ae5c..c4a016eb79 100644 --- a/apps/openmw/mwscript/scriptmanagerimp.hpp +++ b/apps/openmw/mwscript/scriptmanagerimp.hpp @@ -14,7 +14,7 @@ #include "globalscripts.hpp" -namespace ESMS +namespace MWWorld { struct ESMStore; } @@ -35,7 +35,7 @@ namespace MWScript class ScriptManager : public MWBase::ScriptManager { Compiler::StreamErrorHandler mErrorHandler; - const ESMS::ESMStore& mStore; + const MWWorld::ESMStore& mStore; bool mVerbose; Compiler::Context& mCompilerContext; Compiler::FileParser mParser; @@ -50,7 +50,7 @@ namespace MWScript public: - ScriptManager (const ESMS::ESMStore& store, bool verbose, + ScriptManager (const MWWorld::ESMStore& store, bool verbose, Compiler::Context& compilerContext); virtual void run (const std::string& name, Interpreter::Context& interpreterContext); diff --git a/apps/openmw/mwscript/statsextensions.cpp b/apps/openmw/mwscript/statsextensions.cpp index 0d69608e1c..f6a31dd7f7 100644 --- a/apps/openmw/mwscript/statsextensions.cpp +++ b/apps/openmw/mwscript/statsextensions.cpp @@ -7,7 +7,7 @@ #include -#include +#include "../mwworld/esmstore.hpp" #include @@ -28,6 +28,21 @@ #include "interpretercontext.hpp" #include "ref.hpp" +namespace +{ + std::string getDialogueActorFaction() + { + MWWorld::Ptr actor = MWBase::Environment::get().getDialogueManager()->getActor(); + + MWMechanics::NpcStats stats = MWWorld::Class::get (actor).getNpcStats (actor); + + if (stats.getFactionRanks().empty()) + throw std::runtime_error ( + "failed to determine dialogue actors faction (because actor is factionless)"); + + return stats.getFactionRanks().begin()->first; + } +} namespace MWScript { @@ -193,7 +208,7 @@ namespace MWScript .getDynamic (mIndex)); stat.setModified (value, 0); - + MWWorld::Class::get (ptr).getCreatureStats (ptr).setDynamic (mIndex, stat); } }; @@ -328,7 +343,7 @@ namespace MWScript assert (ref); const ESM::Class& class_ = - *MWBase::Environment::get().getWorld()->getStore().classes.find (ref->base->mClass); + *MWBase::Environment::get().getWorld()->getStore().get().find (ref->mBase->mClass); float level = 0; float progress = std::modf (stats.getSkill (mIndex).getBase(), &level); @@ -390,7 +405,7 @@ namespace MWScript runtime.pop(); // make sure a spell with this ID actually exists. - MWBase::Environment::get().getWorld()->getStore().spells.find (id); + MWBase::Environment::get().getWorld()->getStore().get().find (id); MWWorld::Class::get (ptr).getCreatureStats (ptr).getSpells().add (id); } @@ -450,7 +465,7 @@ namespace MWScript if(arg0==0) { - factionID = MWBase::Environment::get().getDialogueManager()->getFaction(); + factionID = getDialogueActorFaction(); } else { @@ -479,7 +494,7 @@ namespace MWScript if(arg0==0) { - factionID = MWBase::Environment::get().getDialogueManager()->getFaction(); + factionID = getDialogueActorFaction(); } else { @@ -512,7 +527,7 @@ namespace MWScript if(arg0==0) { - factionID = MWBase::Environment::get().getDialogueManager()->getFaction(); + factionID = getDialogueActorFaction(); } else { @@ -550,7 +565,7 @@ namespace MWScript { if(MWWorld::Class::get(ptr).getNpcStats(ptr).getFactionRanks().empty()) { - //throw exception? + factionID = ""; } else { @@ -586,13 +601,43 @@ namespace MWScript { MWWorld::Ptr ptr = R()(runtime); -// Interpreter::Type_Integer value = runtime[0].mInteger; + Interpreter::Type_Integer value = runtime[0].mInteger; runtime.pop(); - /// \todo modify disposition towards the player + MWWorld::Class::get (ptr).getNpcStats (ptr).setBaseDisposition + (MWWorld::Class::get (ptr).getNpcStats (ptr).getBaseDisposition() + value); } }; - + + template + class OpSetDisposition : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWWorld::Ptr ptr = R()(runtime); + + Interpreter::Type_Integer value = runtime[0].mInteger; + runtime.pop(); + + MWWorld::Class::get (ptr).getNpcStats (ptr).setBaseDisposition (value); + } + }; + + template + class OpGetDisposition : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWWorld::Ptr ptr = R()(runtime); + + runtime.push (MWWorld::Class::get (ptr).getNpcStats (ptr).getBaseDisposition()); + } + }; + class OpGetDeadCount : public Interpreter::Opcode0 { public: @@ -602,7 +647,138 @@ namespace MWScript std::string id = runtime.getStringLiteral (runtime[0].mInteger); runtime[0].mInteger = MWBase::Environment::get().getMechanicsManager()->countDeaths (id); } - }; + }; + + template + class OpGetPCFacRep : public Interpreter::Opcode1 + { + public: + + virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) + { + std::string factionId; + + if (arg0==1) + { + factionId = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + } + else + { + MWWorld::Ptr ptr = R()(runtime); + + if (!MWWorld::Class::get (ptr).getNpcStats (ptr).getFactionRanks().empty()) + factionId = MWWorld::Class::get (ptr).getNpcStats (ptr).getFactionRanks().begin()->first; + } + + if (factionId.empty()) + throw std::runtime_error ("failed to determine faction"); + + boost::algorithm::to_lower (factionId); + + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + runtime.push ( + MWWorld::Class::get (player).getNpcStats (player).getFactionReputation (factionId)); + } + }; + + template + class OpSetPCFacRep : public Interpreter::Opcode1 + { + public: + + virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) + { + Interpreter::Type_Integer value = runtime[0].mInteger; + runtime.pop(); + + std::string factionId; + + if (arg0==1) + { + factionId = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + } + else + { + MWWorld::Ptr ptr = R()(runtime); + + if (!MWWorld::Class::get (ptr).getNpcStats (ptr).getFactionRanks().empty()) + factionId = MWWorld::Class::get (ptr).getNpcStats (ptr).getFactionRanks().begin()->first; + } + + if (factionId.empty()) + throw std::runtime_error ("failed to determine faction"); + + boost::algorithm::to_lower (factionId); + + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + MWWorld::Class::get (player).getNpcStats (player).setFactionReputation (factionId, value); + } + }; + + template + class OpModPCFacRep : public Interpreter::Opcode1 + { + public: + + virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) + { + Interpreter::Type_Integer value = runtime[0].mInteger; + runtime.pop(); + + std::string factionId; + + if (arg0==1) + { + factionId = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + } + else + { + MWWorld::Ptr ptr = R()(runtime); + + if (!MWWorld::Class::get (ptr).getNpcStats (ptr).getFactionRanks().empty()) + factionId = MWWorld::Class::get (ptr).getNpcStats (ptr).getFactionRanks().begin()->first; + } + + if (factionId.empty()) + throw std::runtime_error ("failed to determine faction"); + + boost::algorithm::to_lower (factionId); + + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + MWWorld::Class::get (player).getNpcStats (player).setFactionReputation (factionId, + MWWorld::Class::get (player).getNpcStats (player).getFactionReputation (factionId)+ + value); + } + }; + + template + class OpGetCommonDisease : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWWorld::Ptr ptr = R()(runtime); + + runtime.push (MWWorld::Class::get (ptr).getCreatureStats (ptr).hasCommonDisease()); + } + }; + + template + class OpGetBlightDisease : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWWorld::Ptr ptr = R()(runtime); + + runtime.push (MWWorld::Class::get (ptr).getCreatureStats (ptr).hasBlightDisease()); + } + }; const int numberOfAttributes = 8; @@ -650,14 +826,30 @@ namespace MWScript const int opcodeGetPCRankExplicit = 0x2000f; const int opcodeModDisposition = 0x200014d; const int opcodeModDispositionExplicit = 0x200014e; + const int opcodeSetDisposition = 0x20001a4; + const int opcodeSetDispositionExplicit = 0x20001a5; + const int opcodeGetDisposition = 0x20001a6; + const int opcodeGetDispositionExplicit = 0x20001a7; const int opcodeGetLevel = 0x200018c; const int opcodeGetLevelExplicit = 0x200018d; const int opcodeSetLevel = 0x200018e; const int opcodeSetLevelExplicit = 0x200018f; - + const int opcodeGetDeadCount = 0x20001a3; + const int opcodeGetPCFacRep = 0x20012; + const int opcodeGetPCFacRepExplicit = 0x20013; + const int opcodeSetPCFacRep = 0x20014; + const int opcodeSetPCFacRepExplicit = 0x20015; + const int opcodeModPCFacRep = 0x20016; + const int opcodeModPCFacRepExplicit = 0x20017; + + const int opcodeGetCommonDisease = 0x20001a8; + const int opcodeGetCommonDiseaseExplicit = 0x20001a9; + const int opcodeGetBlightDisease = 0x20001aa; + const int opcodeGetBlightDiseaseExplicit = 0x20001ab; + void registerExtensions (Compiler::Extensions& extensions) { static const char *attributes[numberOfAttributes] = @@ -737,14 +929,27 @@ namespace MWScript extensions.registerInstruction("pcraiserank","/S",opcodePCRaiseRank); extensions.registerInstruction("pclowerrank","/S",opcodePCLowerRank); extensions.registerInstruction("pcjoinfaction","/S",opcodePCJoinFaction); - extensions.registerInstruction("moddisposition","l",opcodeModDisposition, + extensions.registerInstruction ("moddisposition","l",opcodeModDisposition, opcodeModDispositionExplicit); + extensions.registerInstruction ("setdisposition","l",opcodeSetDisposition, + opcodeSetDispositionExplicit); + extensions.registerFunction ("getdisposition",'l', "",opcodeGetDisposition, + opcodeGetDispositionExplicit); extensions.registerFunction("getpcrank",'l',"/S",opcodeGetPCRank,opcodeGetPCRankExplicit); extensions.registerInstruction("setlevel", "l", opcodeSetLevel, opcodeSetLevelExplicit); extensions.registerFunction("getlevel", 'l', "", opcodeGetLevel, opcodeGetLevelExplicit); - extensions.registerFunction("getdeadcount", 'l', "c", opcodeGetDeadCount); + extensions.registerFunction ("getdeadcount", 'l', "c", opcodeGetDeadCount); + + extensions.registerFunction ("getpcfacrep", 'l', "/c", opcodeGetPCFacRep, opcodeGetPCFacRepExplicit); + extensions.registerInstruction ("setpcfacrep", "l/c", opcodeSetPCFacRep, opcodeSetPCFacRepExplicit); + extensions.registerInstruction ("modpcfacrep", "l/c", opcodeModPCFacRep, opcodeModPCFacRepExplicit); + + extensions.registerFunction ("getcommondisease", 'l', "", opcodeGetCommonDisease, + opcodeGetCommonDiseaseExplicit); + extensions.registerFunction ("getblightdisease", 'l', "", opcodeGetBlightDisease, + opcodeGetBlightDiseaseExplicit); } void installOpcodes (Interpreter::Interpreter& interpreter) @@ -812,17 +1017,34 @@ namespace MWScript interpreter.installSegment3(opcodePCRaiseRank,new OpPCRaiseRank); interpreter.installSegment3(opcodePCLowerRank,new OpPCLowerRank); interpreter.installSegment3(opcodePCJoinFaction,new OpPCJoinFaction); - interpreter.installSegment5(opcodeModDisposition,new OpModDisposition); - interpreter.installSegment5(opcodeModDispositionExplicit,new OpModDisposition); interpreter.installSegment3(opcodeGetPCRank,new OpGetPCRank); interpreter.installSegment3(opcodeGetPCRankExplicit,new OpGetPCRank); + interpreter.installSegment5(opcodeModDisposition,new OpModDisposition); + interpreter.installSegment5(opcodeModDispositionExplicit,new OpModDisposition); + interpreter.installSegment5(opcodeSetDisposition,new OpSetDisposition); + interpreter.installSegment5(opcodeSetDispositionExplicit,new OpSetDisposition); + interpreter.installSegment5(opcodeGetDisposition,new OpGetDisposition); + interpreter.installSegment5(opcodeGetDispositionExplicit,new OpGetDisposition); + interpreter.installSegment5 (opcodeGetLevel, new OpGetLevel); interpreter.installSegment5 (opcodeGetLevelExplicit, new OpGetLevel); interpreter.installSegment5 (opcodeSetLevel, new OpSetLevel); interpreter.installSegment5 (opcodeSetLevelExplicit, new OpSetLevel); interpreter.installSegment5 (opcodeGetDeadCount, new OpGetDeadCount); + + interpreter.installSegment3 (opcodeGetPCFacRep, new OpGetPCFacRep); + interpreter.installSegment3 (opcodeGetPCFacRepExplicit, new OpGetPCFacRep); + interpreter.installSegment3 (opcodeSetPCFacRep, new OpSetPCFacRep); + interpreter.installSegment3 (opcodeSetPCFacRepExplicit, new OpSetPCFacRep); + interpreter.installSegment3 (opcodeModPCFacRep, new OpModPCFacRep); + interpreter.installSegment3 (opcodeModPCFacRepExplicit, new OpModPCFacRep); + + interpreter.installSegment5 (opcodeGetCommonDisease, new OpGetCommonDisease); + interpreter.installSegment5 (opcodeGetCommonDiseaseExplicit, new OpGetCommonDisease); + interpreter.installSegment5 (opcodeGetBlightDisease, new OpGetBlightDisease); + interpreter.installSegment5 (opcodeGetBlightDiseaseExplicit, new OpGetBlightDisease); } } } diff --git a/apps/openmw/mwscript/transformationextensions.cpp b/apps/openmw/mwscript/transformationextensions.cpp index 6e70f588e0..a64651a977 100644 --- a/apps/openmw/mwscript/transformationextensions.cpp +++ b/apps/openmw/mwscript/transformationextensions.cpp @@ -3,7 +3,7 @@ #include #include -#include +#include "../mwworld/esmstore.hpp" #include #include diff --git a/apps/openmw/mwsound/ffmpeg_decoder.cpp b/apps/openmw/mwsound/ffmpeg_decoder.cpp index 9298bf8488..a2cccfd13b 100644 --- a/apps/openmw/mwsound/ffmpeg_decoder.cpp +++ b/apps/openmw/mwsound/ffmpeg_decoder.cpp @@ -1,7 +1,12 @@ #ifdef OPENMW_USE_FFMPEG + #include "ffmpeg_decoder.hpp" +// auto_ptr +#include + +#include namespace MWSound { diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index 5d5ef3d1d0..8c4798c9d7 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -4,7 +4,7 @@ #include #include -#include +#include "../mwworld/esmstore.hpp" #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" @@ -116,9 +116,8 @@ namespace MWSound std::string SoundManager::lookup(const std::string &soundId, float &volume, float &min, float &max) { - const ESM::Sound *snd = MWBase::Environment::get().getWorld()->getStore().sounds.search(soundId); - if(snd == NULL) - throw std::runtime_error(std::string("Failed to lookup sound ")+soundId); + const ESM::Sound *snd = + MWBase::Environment::get().getWorld()->getStore().get().find(soundId); volume *= pow(10.0, (snd->mData.mVolume/255.0*3348.0 - 3348.0) / 2000.0); @@ -414,17 +413,19 @@ namespace MWSound //If the region has changed timePassed += duration; - if((current->cell->mData.mFlags & current->cell->Interior) || timePassed < 10) + if(!current->mCell->isExterior() || timePassed < 10) return; timePassed = 0; - if(regionName != current->cell->mRegion) + if(regionName != current->mCell->mRegion) { - regionName = current->cell->mRegion; + regionName = current->mCell->mRegion; total = 0; } - const ESM::Region *regn = MWBase::Environment::get().getWorld()->getStore().regions.search(regionName); + const ESM::Region *regn = + MWBase::Environment::get().getWorld()->getStore().get().search(regionName); + if (regn == NULL) return; @@ -477,7 +478,7 @@ namespace MWSound MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); - const ESM::Cell *cell = player.getCell()->cell; + const ESM::Cell *cell = player.getCell()->mCell; Environment env = Env_Normal; if((cell->mData.mFlags&cell->HasWater) && mListenerPos.z < cell->mWater) diff --git a/apps/openmw/mwworld/actioneat.cpp b/apps/openmw/mwworld/actioneat.cpp index abd1ac4b97..63efff738e 100644 --- a/apps/openmw/mwworld/actioneat.cpp +++ b/apps/openmw/mwworld/actioneat.cpp @@ -5,14 +5,13 @@ #include -#include - #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" #include "../mwmechanics/creaturestats.hpp" #include "../mwmechanics/npcstats.hpp" +#include "esmstore.hpp" #include "class.hpp" namespace MWWorld diff --git a/apps/openmw/mwworld/actionread.cpp b/apps/openmw/mwworld/actionread.cpp index 4ac613df7f..6d5d9d8fde 100644 --- a/apps/openmw/mwworld/actionread.cpp +++ b/apps/openmw/mwworld/actionread.cpp @@ -4,15 +4,14 @@ #include "../mwbase/windowmanager.hpp" #include "../mwbase/world.hpp" -#include "../mwworld/player.hpp" -#include "../mwworld/class.hpp" - #include "../mwmechanics/npcstats.hpp" #include "../mwgui/bookwindow.hpp" #include "../mwgui/scrollwindow.hpp" -#include +#include "player.hpp" +#include "class.hpp" +#include "esmstore.hpp" namespace MWWorld { @@ -24,7 +23,7 @@ namespace MWWorld { LiveCellRef *ref = getTarget().get(); - if (ref->base->mData.mIsScroll) + if (ref->mBase->mData.mIsScroll) { MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Scroll); MWBase::Environment::get().getWindowManager()->getScrollWindow()->open(getTarget()); @@ -39,16 +38,19 @@ namespace MWWorld MWMechanics::NpcStats& npcStats = MWWorld::Class::get(player).getNpcStats (player); // Skill gain from books - if (ref->base->mData.mSkillID >= 0 && ref->base->mData.mSkillID < ESM::Skill::Length - && !npcStats.hasBeenUsed (ref->base->mId)) + if (ref->mBase->mData.mSkillID >= 0 && ref->mBase->mData.mSkillID < ESM::Skill::Length + && !npcStats.hasBeenUsed (ref->mBase->mId)) { MWWorld::LiveCellRef *playerRef = player.get(); - const ESM::Class *class_ = MWBase::Environment::get().getWorld()->getStore().classes.find ( - playerRef->base->mClass); - npcStats.increaseSkill (ref->base->mData.mSkillID, *class_, true); + const ESM::Class *class_ = + MWBase::Environment::get().getWorld()->getStore().get().find ( + playerRef->mBase->mClass + ); - npcStats.flagAsUsed (ref->base->mId); + npcStats.increaseSkill (ref->mBase->mData.mSkillID, *class_, true); + + npcStats.flagAsUsed (ref->mBase->mId); } } diff --git a/apps/openmw/mwworld/cells.cpp b/apps/openmw/mwworld/cells.cpp index 667f2d4ca5..c595b0587c 100644 --- a/apps/openmw/mwworld/cells.cpp +++ b/apps/openmw/mwworld/cells.cpp @@ -1,11 +1,10 @@ #include "cells.hpp" -#include - #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" #include "class.hpp" +#include "esmstore.hpp" #include "containerstore.hpp" MWWorld::Ptr::CellStore *MWWorld::Cells::getCellStore (const ESM::Cell *cell) @@ -24,12 +23,12 @@ MWWorld::Ptr::CellStore *MWWorld::Cells::getCellStore (const ESM::Cell *cell) else { std::map, Ptr::CellStore>::iterator result = - mExteriors.find (std::make_pair (cell->mData.mX, cell->mData.mY)); + mExteriors.find (std::make_pair (cell->getGridX(), cell->getGridY())); if (result==mExteriors.end()) { result = mExteriors.insert (std::make_pair ( - std::make_pair (cell->mData.mX, cell->mData.mY), Ptr::CellStore (cell))).first; + std::make_pair (cell->getGridX(), cell->getGridY()), Ptr::CellStore (cell))).first; } @@ -40,33 +39,33 @@ MWWorld::Ptr::CellStore *MWWorld::Cells::getCellStore (const ESM::Cell *cell) void MWWorld::Cells::fillContainers (Ptr::CellStore& cellStore) { for (CellRefList::List::iterator iter ( - cellStore.containers.list.begin()); - iter!=cellStore.containers.list.end(); ++iter) + cellStore.mContainers.mList.begin()); + iter!=cellStore.mContainers.mList.end(); ++iter) { Ptr container (&iter->second, &cellStore); Class::get (container).getContainerStore (container).fill ( - iter->second.base->mInventory, mStore); + iter->second.mBase->mInventory, mStore); } for (CellRefList::List::iterator iter ( - cellStore.creatures.list.begin()); - iter!=cellStore.creatures.list.end(); ++iter) + cellStore.mCreatures.mList.begin()); + iter!=cellStore.mCreatures.mList.end(); ++iter) { Ptr container (&iter->second, &cellStore); Class::get (container).getContainerStore (container).fill ( - iter->second.base->mInventory, mStore); + iter->second.mBase->mInventory, mStore); } for (CellRefList::List::iterator iter ( - cellStore.npcs.list.begin()); - iter!=cellStore.npcs.list.end(); ++iter) + cellStore.mNpcs.mList.begin()); + iter!=cellStore.mNpcs.mList.end(); ++iter) { Ptr container (&iter->second, &cellStore); Class::get (container).getContainerStore (container).fill ( - iter->second.base->mInventory, mStore); + iter->second.mBase->mInventory, mStore); } } @@ -85,7 +84,7 @@ MWWorld::Ptr MWWorld::Cells::getPtrAndCache (const std::string& name, Ptr::CellS return ptr; } -MWWorld::Cells::Cells (const ESMS::ESMStore& store, std::vector& reader) +MWWorld::Cells::Cells (const MWWorld::ESMStore& store, std::vector& reader) : mStore (store), mReader (reader), mIdCache (20, std::pair ("", (Ptr::CellStore*)0)), /// \todo make cache size configurable mIdCacheIndex (0) @@ -98,7 +97,7 @@ MWWorld::Ptr::CellStore *MWWorld::Cells::getExterior (int x, int y) if (result==mExteriors.end()) { - const ESM::Cell *cell = mStore.cells.searchExt (x, y); + const ESM::Cell *cell = mStore.get().search(x, y); if (!cell) { @@ -134,7 +133,7 @@ MWWorld::Ptr::CellStore *MWWorld::Cells::getInterior (const std::string& name) if (result==mInteriors.end()) { - const ESM::Cell *cell = mStore.cells.findInt (name); + const ESM::Cell *cell = mStore.get().find(name); result = mInteriors.insert (std::make_pair (name, Ptr::CellStore (cell))).first; } @@ -170,64 +169,64 @@ MWWorld::Ptr MWWorld::Cells::getPtr (const std::string& name, Ptr::CellStore& ce } MWWorld::Ptr ptr; - if (MWWorld::LiveCellRef *ref = cell.activators.find (name)) + if (MWWorld::LiveCellRef *ref = cell.mActivators.find (name)) ptr = Ptr (ref, &cell); - if (MWWorld::LiveCellRef *ref = cell.potions.find (name)) + if (MWWorld::LiveCellRef *ref = cell.mPotions.find (name)) ptr = Ptr (ref, &cell); - if (MWWorld::LiveCellRef *ref = cell.appas.find (name)) + if (MWWorld::LiveCellRef *ref = cell.mAppas.find (name)) ptr = Ptr (ref, &cell); - if (MWWorld::LiveCellRef *ref = cell.armors.find (name)) + if (MWWorld::LiveCellRef *ref = cell.mArmors.find (name)) ptr = Ptr (ref, &cell); - if (MWWorld::LiveCellRef *ref = cell.books.find (name)) + if (MWWorld::LiveCellRef *ref = cell.mBooks.find (name)) ptr = Ptr (ref, &cell); - if (MWWorld::LiveCellRef *ref = cell.clothes.find (name)) + if (MWWorld::LiveCellRef *ref = cell.mClothes.find (name)) ptr = Ptr (ref, &cell); - if (MWWorld::LiveCellRef *ref = cell.containers.find (name)) + if (MWWorld::LiveCellRef *ref = cell.mContainers.find (name)) ptr = Ptr (ref, &cell); - if (MWWorld::LiveCellRef *ref = cell.creatures.find (name)) + if (MWWorld::LiveCellRef *ref = cell.mCreatures.find (name)) ptr = Ptr (ref, &cell); - if (MWWorld::LiveCellRef *ref = cell.doors.find (name)) + if (MWWorld::LiveCellRef *ref = cell.mDoors.find (name)) ptr = Ptr (ref, &cell); - if (MWWorld::LiveCellRef *ref = cell.ingreds.find (name)) + if (MWWorld::LiveCellRef *ref = cell.mIngreds.find (name)) ptr = Ptr (ref, &cell); - if (MWWorld::LiveCellRef *ref = cell.creatureLists.find (name)) + if (MWWorld::LiveCellRef *ref = cell.mCreatureLists.find (name)) ptr = Ptr (ref, &cell); - if (MWWorld::LiveCellRef *ref = cell.itemLists.find (name)) + if (MWWorld::LiveCellRef *ref = cell.mItemLists.find (name)) ptr = Ptr (ref, &cell); - if (MWWorld::LiveCellRef *ref = cell.lights.find (name)) + if (MWWorld::LiveCellRef *ref = cell.mLights.find (name)) ptr = Ptr (ref, &cell); - if (MWWorld::LiveCellRef *ref = cell.lockpicks.find (name)) + if (MWWorld::LiveCellRef *ref = cell.mLockpicks.find (name)) ptr = Ptr (ref, &cell); - if (MWWorld::LiveCellRef *ref = cell.miscItems.find (name)) + if (MWWorld::LiveCellRef *ref = cell.mMiscItems.find (name)) ptr = Ptr (ref, &cell); - if (MWWorld::LiveCellRef *ref = cell.npcs.find (name)) + if (MWWorld::LiveCellRef *ref = cell.mNpcs.find (name)) ptr = Ptr (ref, &cell); - if (MWWorld::LiveCellRef *ref = cell.probes.find (name)) + if (MWWorld::LiveCellRef *ref = cell.mProbes.find (name)) ptr = Ptr (ref, &cell); - if (MWWorld::LiveCellRef *ref = cell.repairs.find (name)) + if (MWWorld::LiveCellRef *ref = cell.mRepairs.find (name)) ptr = Ptr (ref, &cell); - if (MWWorld::LiveCellRef *ref = cell.statics.find (name)) + if (MWWorld::LiveCellRef *ref = cell.mStatics.find (name)) ptr = Ptr (ref, &cell); - if (MWWorld::LiveCellRef *ref = cell.weapons.find (name)) + if (MWWorld::LiveCellRef *ref = cell.mWeapons.find (name)) ptr = Ptr (ref, &cell); if (!ptr.isEmpty() && ptr.getRefData().getCount() > 0) { @@ -266,10 +265,12 @@ MWWorld::Ptr MWWorld::Cells::getPtr (const std::string& name) } // Now try the other cells - for (ESMS::CellList::IntCells::const_iterator iter = mStore.cells.intCells.begin(); - iter!=mStore.cells.intCells.end(); ++iter) + const MWWorld::Store &cells = mStore.get(); + MWWorld::Store::iterator iter; + + for (iter = cells.intBegin(); iter != cells.intEnd(); ++iter) { - Ptr::CellStore *cellStore = getCellStore (iter->second); + Ptr::CellStore *cellStore = getCellStore (&(*iter)); Ptr ptr = getPtrAndCache (name, *cellStore); @@ -277,10 +278,9 @@ MWWorld::Ptr MWWorld::Cells::getPtr (const std::string& name) return ptr; } - for (ESMS::CellList::ExtCells::const_iterator iter = mStore.cells.extCells.begin(); - iter!=mStore.cells.extCells.end(); ++iter) + for (iter = cells.extBegin(); iter != cells.extEnd(); ++iter) { - Ptr::CellStore *cellStore = getCellStore (iter->second); + Ptr::CellStore *cellStore = getCellStore (&(*iter)); Ptr ptr = getPtrAndCache (name, *cellStore); diff --git a/apps/openmw/mwworld/cells.hpp b/apps/openmw/mwworld/cells.hpp index 3941399f89..f999fedde2 100644 --- a/apps/openmw/mwworld/cells.hpp +++ b/apps/openmw/mwworld/cells.hpp @@ -12,17 +12,14 @@ namespace ESM class ESMReader; } -namespace ESM -{ - class ESMStore; -} - namespace MWWorld { + class ESMStore; + /// \brief Cell container class Cells { - const ESMS::ESMStore& mStore; + const MWWorld::ESMStore& mStore; std::vector& mReader; std::map mInteriors; std::map, CellStore> mExteriors; @@ -40,7 +37,7 @@ namespace MWWorld public: - Cells (const ESMS::ESMStore& store, std::vector& reader); + Cells (const MWWorld::ESMStore& store, std::vector& reader); ///< \todo pass the dynamic part of the ESMStore isntead (once it is written) of the whole /// world diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index 0af8861243..74856c9ed9 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -2,28 +2,28 @@ #include -#include - #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" #include "ptr.hpp" +#include "esmstore.hpp" namespace MWWorld { - CellStore::CellStore (const ESM::Cell *cell_) : cell (cell_), mState (State_Unloaded) + CellStore::CellStore (const ESM::Cell *cell) + : mCell (cell), mState (State_Unloaded) { mWaterLevel = cell->mWater; } - void CellStore::load (const ESMS::ESMStore &store, std::vector &esm) + void CellStore::load (const MWWorld::ESMStore &store, std::vector &esm) { if (mState!=State_Loaded) { if (mState==State_Preloaded) mIds.clear(); - std::cout << "loading cell " << cell->getDescription() << std::endl; + std::cout << "loading cell " << mCell->getDescription() << std::endl; loadRefs (store, esm); @@ -31,7 +31,7 @@ namespace MWWorld } } - void CellStore::preload (const ESMS::ESMStore &store, std::vector &esm) + void CellStore::preload (const MWWorld::ESMStore &store, std::vector &esm) { if (mState==State_Unloaded) { @@ -41,11 +41,11 @@ namespace MWWorld } } - void CellStore::listRefs(const ESMS::ESMStore &store, std::vector &esm) + void CellStore::listRefs(const MWWorld::ESMStore &store, std::vector &esm) { - assert (cell); + assert (mCell); - if (cell->mContextList.size() == 0) + if (mCell->mContextList.size() == 0) return; // this is a dynamically generated cell -> skipping. // Load references from all plugins that do something with this cell. @@ -53,12 +53,12 @@ namespace MWWorld { // Reopen the ESM reader and seek to the right position. int index = cell->mContextList.at(i).index; - cell->restore (esm[index], i); + mCell->restore (esm[index], i); ESM::CellRef ref; // Get each reference in turn - while (cell->getNextRef (esm[index], ref)) + while (mCell->getNextRef (esm[index], ref)) { std::string lowerCase; @@ -73,11 +73,11 @@ namespace MWWorld std::sort (mIds.begin(), mIds.end()); } - void CellStore::loadRefs(const ESMS::ESMStore &store, std::vector &esm) + void CellStore::loadRefs(const MWWorld::ESMStore &store, std::vector &esm) { - assert (cell); + assert (mCell); - if (cell->mContextList.size() == 0) + if (mCell->mContextList.size() == 0) return; // this is a dynamically generated cell -> skipping. // Load references from all plugins that do something with this cell. @@ -85,12 +85,12 @@ namespace MWWorld { // Reopen the ESM reader and seek to the right position. int index = cell->mContextList.at(i).index; - cell->restore (esm[index], i); + mCell->restore (esm[index], i); ESM::CellRef ref; // Get each reference in turn - while(cell->getNextRef(esm[index], ref)) + while(mCell->getNextRef(esm[index], ref)) { std::string lowerCase; @@ -109,26 +109,26 @@ namespace MWWorld */ switch(rec) { - case ESM::REC_ACTI: activators.find(ref, store.activators); break; - case ESM::REC_ALCH: potions.find(ref, store.potions); break; - case ESM::REC_APPA: appas.find(ref, store.appas); break; - case ESM::REC_ARMO: armors.find(ref, store.armors); break; - case ESM::REC_BOOK: books.find(ref, store.books); break; - case ESM::REC_CLOT: clothes.find(ref, store.clothes); break; - case ESM::REC_CONT: containers.find(ref, store.containers); break; - case ESM::REC_CREA: creatures.find(ref, store.creatures); break; - case ESM::REC_DOOR: doors.find(ref, store.doors); break; - case ESM::REC_INGR: ingreds.find(ref, store.ingreds); break; - case ESM::REC_LEVC: creatureLists.find(ref, store.creatureLists); break; - case ESM::REC_LEVI: itemLists.find(ref, store.itemLists); break; - case ESM::REC_LIGH: lights.find(ref, store.lights); break; - case ESM::REC_LOCK: lockpicks.find(ref, store.lockpicks); break; - case ESM::REC_MISC: miscItems.find(ref, store.miscItems); break; - case ESM::REC_NPC_: npcs.find(ref, store.npcs); break; - case ESM::REC_PROB: probes.find(ref, store.probes); break; - case ESM::REC_REPA: repairs.find(ref, store.repairs); break; - case ESM::REC_STAT: statics.find(ref, store.statics); break; - case ESM::REC_WEAP: weapons.find(ref, store.weapons); break; + case ESM::REC_ACTI: mActivators.load(ref, store); break; + case ESM::REC_ALCH: mPotions.load(ref, store); break; + case ESM::REC_APPA: mAppas.load(ref, store); break; + case ESM::REC_ARMO: mArmors.load(ref, store); break; + case ESM::REC_BOOK: mBooks.load(ref, store); break; + case ESM::REC_CLOT: mClothes.load(ref, store); break; + case ESM::REC_CONT: mContainers.load(ref, store); break; + case ESM::REC_CREA: mCreatures.load(ref, store); break; + case ESM::REC_DOOR: mDoors.load(ref, store); break; + case ESM::REC_INGR: mIngreds.load(ref, store); break; + case ESM::REC_LEVC: mCreatureLists.load(ref, store); break; + case ESM::REC_LEVI: mItemLists.load(ref, store); break; + case ESM::REC_LIGH: mLights.load(ref, store); break; + case ESM::REC_LOCK: mLockpicks.load(ref, store); break; + case ESM::REC_MISC: mMiscItems.load(ref, store); break; + case ESM::REC_NPC_: mNpcs.load(ref, store); break; + case ESM::REC_PROB: mProbes.load(ref, store); break; + case ESM::REC_REPA: mRepairs.load(ref, store); break; + case ESM::REC_STAT: mStatics.load(ref, store); break; + case ESM::REC_WEAP: mWeapons.load(ref, store); break; case 0: std::cout << "Cell reference " + ref.mRefID + " not found!\n"; break; default: diff --git a/apps/openmw/mwworld/cellstore.hpp b/apps/openmw/mwworld/cellstore.hpp index 236f672311..b66137cc6b 100644 --- a/apps/openmw/mwworld/cellstore.hpp +++ b/apps/openmw/mwworld/cellstore.hpp @@ -7,15 +7,12 @@ #include #include "refdata.hpp" - -namespace ESMS -{ - struct ESMStore; -} +#include "esmstore.hpp" namespace MWWorld { class Ptr; + class ESMStore; /// A reference to one object (of any type) in a cell. /// @@ -26,19 +23,21 @@ namespace MWWorld template struct LiveCellRef { - LiveCellRef(const ESM::CellRef& cref, const X* b = NULL) : base(b), ref(cref), - mData(ref) {} + LiveCellRef(const ESM::CellRef& cref, const X* b = NULL) + : mBase(b), mRef(cref), mData(mRef) + {} - - LiveCellRef(const X* b = NULL) : base(b), mData(ref) {} + LiveCellRef(const X* b = NULL) + : mBase(b), mData(mRef) + {} // The object that this instance is based on. - const X* base; + const X* mBase; /* Information about this instance, such as 3D location and rotation and individual type-dependent data. */ - ESM::CellRef ref; + ESM::CellRef mRef; /// runtime-data RefData mData; @@ -91,26 +90,29 @@ namespace MWWorld { typedef LiveCellRef LiveRef; typedef std::list List; - List list; + List mList; - // Search for the given reference in the given reclist from - // ESMStore. Insert the reference into the list if a match is - // found. If not, throw an exception. - template - void find(ESM::CellRef &ref, const Y& recList) + /// Searches for reference of appropriate type in given ESMStore. + /// If reference exists, loads it into container, throws an exception + /// on miss + void load(ESM::CellRef &ref, const MWWorld::ESMStore &esmStore) { - const X* obj = recList.find(ref.mRefID); - if(obj == NULL) - throw std::runtime_error("Error resolving cell reference " + ref.mRefID); + // for throwing exception on unhandled record type + const MWWorld::Store &store = esmStore.get(); + const X *ptr = store.find(ref.mRefID); - list.push_back(LiveRef(ref, obj)); + /// \note redundant because Store::find() throws exception on miss + if (ptr == NULL) { + throw std::runtime_error("Error resolving cell reference " + ref.mRefID); + } + mList.push_back(LiveRef(ref, ptr)); } LiveRef *find (const std::string& name) { - for (typename std::list::iterator iter (list.begin()); iter!=list.end(); ++iter) + for (typename std::list::iterator iter (mList.begin()); iter!=mList.end(); ++iter) { - if (iter->mData.getCount() > 0 && iter->ref.mRefID == name) + if (iter->mData.getCount() > 0 && iter->mRef.mRefID == name) return &*iter; } @@ -118,8 +120,8 @@ namespace MWWorld } LiveRef &insert(const LiveRef &item) { - list.push_back(item); - return list.back(); + mList.push_back(item); + return mList.back(); } }; @@ -135,37 +137,37 @@ namespace MWWorld CellStore (const ESM::Cell *cell_); - const ESM::Cell *cell; + const ESM::Cell *mCell; State mState; std::vector mIds; float mWaterLevel; // Lists for each individual object type - CellRefList activators; - CellRefList potions; - CellRefList appas; - CellRefList armors; - CellRefList books; - CellRefList clothes; - CellRefList containers; - CellRefList creatures; - CellRefList doors; - CellRefList ingreds; - CellRefList creatureLists; - CellRefList itemLists; - CellRefList lights; - CellRefList lockpicks; - CellRefList miscItems; - CellRefList npcs; - CellRefList probes; - CellRefList repairs; - CellRefList statics; - CellRefList weapons; + CellRefList mActivators; + CellRefList mPotions; + CellRefList mAppas; + CellRefList mArmors; + CellRefList mBooks; + CellRefList mClothes; + CellRefList mContainers; + CellRefList mCreatures; + CellRefList mDoors; + CellRefList mIngreds; + CellRefList mCreatureLists; + CellRefList mItemLists; + CellRefList mLights; + CellRefList mLockpicks; + CellRefList mMiscItems; + CellRefList mNpcs; + CellRefList mProbes; + CellRefList mRepairs; + CellRefList mStatics; + CellRefList mWeapons; - void load (const ESMS::ESMStore &store, std::vector &esm); + void load (const MWWorld::ESMStore &store, std::vector &esm); - void preload (const ESMS::ESMStore &store, std::vector &esm); + void preload (const MWWorld::ESMStore &store, std::vector &esm); /// Call functor (ref) for each reference. functor must return a bool. Returning /// false will abort the iteration. @@ -174,32 +176,32 @@ namespace MWWorld bool forEach (Functor& functor) { return - forEachImp (functor, activators) && - forEachImp (functor, potions) && - forEachImp (functor, appas) && - forEachImp (functor, armors) && - forEachImp (functor, books) && - forEachImp (functor, clothes) && - forEachImp (functor, containers) && - forEachImp (functor, creatures) && - forEachImp (functor, doors) && - forEachImp (functor, ingreds) && - forEachImp (functor, creatureLists) && - forEachImp (functor, itemLists) && - forEachImp (functor, lights) && - forEachImp (functor, lockpicks) && - forEachImp (functor, miscItems) && - forEachImp (functor, npcs) && - forEachImp (functor, probes) && - forEachImp (functor, repairs) && - forEachImp (functor, statics) && - forEachImp (functor, weapons); + forEachImp (functor, mActivators) && + forEachImp (functor, mPotions) && + forEachImp (functor, mAppas) && + forEachImp (functor, mArmors) && + forEachImp (functor, mBooks) && + forEachImp (functor, mClothes) && + forEachImp (functor, mContainers) && + forEachImp (functor, mCreatures) && + forEachImp (functor, mDoors) && + forEachImp (functor, mIngreds) && + forEachImp (functor, mCreatureLists) && + forEachImp (functor, mItemLists) && + forEachImp (functor, mLights) && + forEachImp (functor, mLockpicks) && + forEachImp (functor, mMiscItems) && + forEachImp (functor, mNpcs) && + forEachImp (functor, mProbes) && + forEachImp (functor, mRepairs) && + forEachImp (functor, mStatics) && + forEachImp (functor, mWeapons); } bool operator==(const CellStore &cell) { - return this->cell->mName == cell.cell->mName && - this->cell->mData.mX == cell.cell->mData.mX && - this->cell->mData.mY == cell.cell->mData.mY; + return mCell->mName == cell.mCell->mName && + mCell->mData.mX == cell.mCell->mData.mX && + mCell->mData.mY == cell.mCell->mData.mY; } bool operator!=(const CellStore &cell) { @@ -207,7 +209,7 @@ namespace MWWorld } bool isExterior() const { - return cell->isExterior(); + return mCell->isExterior(); } private: @@ -215,18 +217,18 @@ namespace MWWorld template bool forEachImp (Functor& functor, List& list) { - for (typename List::List::iterator iter (list.list.begin()); iter!=list.list.end(); + for (typename List::List::iterator iter (list.mList.begin()); iter!=list.mList.end(); ++iter) - if (!functor (iter->second.ref, iter->second.mData)) + if (!functor (iter->second.mRef, iter->second.mData)) return false; return true; } /// Run through references and store IDs - void listRefs(const ESMS::ESMStore &store, std::vector &esm); + void listRefs(const MWWorld::ESMStore &store, std::vector &esm); - void loadRefs(const ESMS::ESMStore &store, std::vector &esm); + void loadRefs(const MWWorld::ESMStore &store, std::vector &esm); }; } diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index 8c639a874c..c760191496 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -162,6 +162,11 @@ namespace MWWorld return false; } + bool Class::hasDetected (const MWWorld::Ptr& ptr, const MWWorld::Ptr& ptr2) const + { + return false; + } + const Class& Class::get (const std::string& key) { std::map >::const_iterator iter = sClasses.find (key); diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index 4662cbab63..07dcb8fe03 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -191,6 +191,11 @@ namespace MWWorld /// /// (default implementation: return false) + virtual bool hasDetected (const MWWorld::Ptr& ptr, const MWWorld::Ptr& ptr2) const; + ///< Has \æ ptr detected \a ptr2? + /// + /// (default implementation: return false) + static const Class& get (const std::string& key); ///< If there is no class for this \a key, an exception is thrown. diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index 035f79310f..76d474c29c 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -24,12 +24,12 @@ namespace float sum = 0; for (typename MWWorld::ContainerRefList::List::const_iterator iter ( - cellRefList.list.begin()); - iter!=cellRefList.list.end(); + cellRefList.mList.begin()); + iter!=cellRefList.mList.end(); ++iter) { if (iter->mData.getCount()>0) - sum += iter->mData.getCount()*iter->base->mData.mWeight; + sum += iter->mData.getCount()*iter->mBase->mData.mWeight; } return sum; @@ -74,26 +74,29 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add (const Ptr& ptr) { int type = getType(ptr); + const MWWorld::ESMStore &esmStore = + MWBase::Environment::get().getWorld()->getStore(); + // gold needs special handling: when it is inserted into a container, the base object automatically becomes Gold_001 // this ensures that gold piles of different sizes stack with each other (also, several scripts rely on Gold_001 for detecting player gold) - if (MWWorld::Class::get(ptr).getName(ptr) == MWBase::Environment::get().getWorld()->getStore().gameSettings.find("sGold")->getString()) + if (MWWorld::Class::get(ptr).getName(ptr) == esmStore.get().find("sGold")->getString()) { MWWorld::LiveCellRef *gold = ptr.get(); - if (compare_string_ci(gold->ref.mRefID, "gold_001") - || compare_string_ci(gold->ref.mRefID, "gold_005") - || compare_string_ci(gold->ref.mRefID, "gold_010") - || compare_string_ci(gold->ref.mRefID, "gold_025") - || compare_string_ci(gold->ref.mRefID, "gold_100")) + if (compare_string_ci(gold->mRef.mRefID, "gold_001") + || compare_string_ci(gold->mRef.mRefID, "gold_005") + || compare_string_ci(gold->mRef.mRefID, "gold_010") + || compare_string_ci(gold->mRef.mRefID, "gold_025") + || compare_string_ci(gold->mRef.mRefID, "gold_100")) { - MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), "Gold_001"); + MWWorld::ManualRef ref(esmStore, "Gold_001"); - int count = (ptr.getRefData().getCount() == 1) ? gold->base->mData.mValue : ptr.getRefData().getCount(); + int count = (ptr.getRefData().getCount() == 1) ? gold->mBase->mData.mValue : ptr.getRefData().getCount(); ref.getPtr().getRefData().setCount(count); for (MWWorld::ContainerStoreIterator iter (begin(type)); iter!=end(); ++iter) { - if (compare_string_ci((*iter).get()->ref.mRefID, "gold_001")) + if (compare_string_ci((*iter).get()->mRef.mRefID, "gold_001")) { (*iter).getRefData().setCount( (*iter).getRefData().getCount() + count); flagAsModified(); @@ -127,25 +130,25 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::addImpl (const Ptr& ptr switch (getType(ptr)) { - case Type_Potion: potions.list.push_back (*ptr.get()); it = ContainerStoreIterator(this, --potions.list.end()); break; - case Type_Apparatus: appas.list.push_back (*ptr.get()); it = ContainerStoreIterator(this, --appas.list.end()); break; - case Type_Armor: armors.list.push_back (*ptr.get()); it = ContainerStoreIterator(this, --armors.list.end()); break; - case Type_Book: books.list.push_back (*ptr.get()); it = ContainerStoreIterator(this, --books.list.end()); break; - case Type_Clothing: clothes.list.push_back (*ptr.get()); it = ContainerStoreIterator(this, --clothes.list.end()); break; - case Type_Ingredient: ingreds.list.push_back (*ptr.get()); it = ContainerStoreIterator(this, --ingreds.list.end()); break; - case Type_Light: lights.list.push_back (*ptr.get()); it = ContainerStoreIterator(this, --lights.list.end()); break; - case Type_Lockpick: lockpicks.list.push_back (*ptr.get()); it = ContainerStoreIterator(this, --lockpicks.list.end()); break; - case Type_Miscellaneous: miscItems.list.push_back (*ptr.get()); it = ContainerStoreIterator(this, --miscItems.list.end()); break; - case Type_Probe: probes.list.push_back (*ptr.get()); it = ContainerStoreIterator(this, --probes.list.end()); break; - case Type_Repair: repairs.list.push_back (*ptr.get()); it = ContainerStoreIterator(this, --repairs.list.end()); break; - case Type_Weapon: weapons.list.push_back (*ptr.get()); it = ContainerStoreIterator(this, --weapons.list.end()); break; + case Type_Potion: potions.mList.push_back (*ptr.get()); it = ContainerStoreIterator(this, --potions.mList.end()); break; + case Type_Apparatus: appas.mList.push_back (*ptr.get()); it = ContainerStoreIterator(this, --appas.mList.end()); break; + case Type_Armor: armors.mList.push_back (*ptr.get()); it = ContainerStoreIterator(this, --armors.mList.end()); break; + case Type_Book: books.mList.push_back (*ptr.get()); it = ContainerStoreIterator(this, --books.mList.end()); break; + case Type_Clothing: clothes.mList.push_back (*ptr.get()); it = ContainerStoreIterator(this, --clothes.mList.end()); break; + case Type_Ingredient: ingreds.mList.push_back (*ptr.get()); it = ContainerStoreIterator(this, --ingreds.mList.end()); break; + case Type_Light: lights.mList.push_back (*ptr.get()); it = ContainerStoreIterator(this, --lights.mList.end()); break; + case Type_Lockpick: lockpicks.mList.push_back (*ptr.get()); it = ContainerStoreIterator(this, --lockpicks.mList.end()); break; + case Type_Miscellaneous: miscItems.mList.push_back (*ptr.get()); it = ContainerStoreIterator(this, --miscItems.mList.end()); break; + case Type_Probe: probes.mList.push_back (*ptr.get()); it = ContainerStoreIterator(this, --probes.mList.end()); break; + case Type_Repair: repairs.mList.push_back (*ptr.get()); it = ContainerStoreIterator(this, --repairs.mList.end()); break; + case Type_Weapon: weapons.mList.push_back (*ptr.get()); it = ContainerStoreIterator(this, --weapons.mList.end()); break; } flagAsModified(); return it; } -void MWWorld::ContainerStore::fill (const ESM::InventoryList& items, const ESMS::ESMStore& store) +void MWWorld::ContainerStore::fill (const ESM::InventoryList& items, const MWWorld::ESMStore& store) { for (std::vector::const_iterator iter (items.mList.begin()); iter!=items.mList.end(); ++iter) @@ -326,63 +329,63 @@ bool MWWorld::ContainerStoreIterator::resetIterator() { case ContainerStore::Type_Potion: - mPotion = mContainer->potions.list.begin(); - return mPotion!=mContainer->potions.list.end(); + mPotion = mContainer->potions.mList.begin(); + return mPotion!=mContainer->potions.mList.end(); case ContainerStore::Type_Apparatus: - mApparatus = mContainer->appas.list.begin(); - return mApparatus!=mContainer->appas.list.end(); + mApparatus = mContainer->appas.mList.begin(); + return mApparatus!=mContainer->appas.mList.end(); case ContainerStore::Type_Armor: - mArmor = mContainer->armors.list.begin(); - return mArmor!=mContainer->armors.list.end(); + mArmor = mContainer->armors.mList.begin(); + return mArmor!=mContainer->armors.mList.end(); case ContainerStore::Type_Book: - mBook = mContainer->books.list.begin(); - return mBook!=mContainer->books.list.end(); + mBook = mContainer->books.mList.begin(); + return mBook!=mContainer->books.mList.end(); case ContainerStore::Type_Clothing: - mClothing = mContainer->clothes.list.begin(); - return mClothing!=mContainer->clothes.list.end(); + mClothing = mContainer->clothes.mList.begin(); + return mClothing!=mContainer->clothes.mList.end(); case ContainerStore::Type_Ingredient: - mIngredient = mContainer->ingreds.list.begin(); - return mIngredient!=mContainer->ingreds.list.end(); + mIngredient = mContainer->ingreds.mList.begin(); + return mIngredient!=mContainer->ingreds.mList.end(); case ContainerStore::Type_Light: - mLight = mContainer->lights.list.begin(); - return mLight!=mContainer->lights.list.end(); + mLight = mContainer->lights.mList.begin(); + return mLight!=mContainer->lights.mList.end(); case ContainerStore::Type_Lockpick: - mLockpick = mContainer->lockpicks.list.begin(); - return mLockpick!=mContainer->lockpicks.list.end(); + mLockpick = mContainer->lockpicks.mList.begin(); + return mLockpick!=mContainer->lockpicks.mList.end(); case ContainerStore::Type_Miscellaneous: - mMiscellaneous = mContainer->miscItems.list.begin(); - return mMiscellaneous!=mContainer->miscItems.list.end(); + mMiscellaneous = mContainer->miscItems.mList.begin(); + return mMiscellaneous!=mContainer->miscItems.mList.end(); case ContainerStore::Type_Probe: - mProbe = mContainer->probes.list.begin(); - return mProbe!=mContainer->probes.list.end(); + mProbe = mContainer->probes.mList.begin(); + return mProbe!=mContainer->probes.mList.end(); case ContainerStore::Type_Repair: - mRepair = mContainer->repairs.list.begin(); - return mRepair!=mContainer->repairs.list.end(); + mRepair = mContainer->repairs.mList.begin(); + return mRepair!=mContainer->repairs.mList.end(); case ContainerStore::Type_Weapon: - mWeapon = mContainer->weapons.list.begin(); - return mWeapon!=mContainer->weapons.list.end(); + mWeapon = mContainer->weapons.mList.begin(); + return mWeapon!=mContainer->weapons.mList.end(); } return false; @@ -395,62 +398,62 @@ bool MWWorld::ContainerStoreIterator::incIterator() case ContainerStore::Type_Potion: ++mPotion; - return mPotion==mContainer->potions.list.end(); + return mPotion==mContainer->potions.mList.end(); case ContainerStore::Type_Apparatus: ++mApparatus; - return mApparatus==mContainer->appas.list.end(); + return mApparatus==mContainer->appas.mList.end(); case ContainerStore::Type_Armor: ++mArmor; - return mArmor==mContainer->armors.list.end(); + return mArmor==mContainer->armors.mList.end(); case ContainerStore::Type_Book: ++mBook; - return mBook==mContainer->books.list.end(); + return mBook==mContainer->books.mList.end(); case ContainerStore::Type_Clothing: ++mClothing; - return mClothing==mContainer->clothes.list.end(); + return mClothing==mContainer->clothes.mList.end(); case ContainerStore::Type_Ingredient: ++mIngredient; - return mIngredient==mContainer->ingreds.list.end(); + return mIngredient==mContainer->ingreds.mList.end(); case ContainerStore::Type_Light: ++mLight; - return mLight==mContainer->lights.list.end(); + return mLight==mContainer->lights.mList.end(); case ContainerStore::Type_Lockpick: ++mLockpick; - return mLockpick==mContainer->lockpicks.list.end(); + return mLockpick==mContainer->lockpicks.mList.end(); case ContainerStore::Type_Miscellaneous: ++mMiscellaneous; - return mMiscellaneous==mContainer->miscItems.list.end(); + return mMiscellaneous==mContainer->miscItems.mList.end(); case ContainerStore::Type_Probe: ++mProbe; - return mProbe==mContainer->probes.list.end(); + return mProbe==mContainer->probes.mList.end(); case ContainerStore::Type_Repair: ++mRepair; - return mRepair==mContainer->repairs.list.end(); + return mRepair==mContainer->repairs.mList.end(); case ContainerStore::Type_Weapon: ++mWeapon; - return mWeapon==mContainer->weapons.list.end(); + return mWeapon==mContainer->weapons.mList.end(); } return true; diff --git a/apps/openmw/mwworld/containerstore.hpp b/apps/openmw/mwworld/containerstore.hpp index 9611b9c219..36e22bb404 100644 --- a/apps/openmw/mwworld/containerstore.hpp +++ b/apps/openmw/mwworld/containerstore.hpp @@ -83,7 +83,7 @@ namespace MWWorld public: - void fill (const ESM::InventoryList& items, const ESMS::ESMStore& store); + void fill (const ESM::InventoryList& items, const MWWorld::ESMStore& store); ///< Insert items into *this. void clear(); diff --git a/apps/openmw/mwworld/esmstore.cpp b/apps/openmw/mwworld/esmstore.cpp new file mode 100644 index 0000000000..73f5185c98 --- /dev/null +++ b/apps/openmw/mwworld/esmstore.cpp @@ -0,0 +1,111 @@ +#include "esmstore.hpp" + +#include +#include + +namespace MWWorld +{ + +static bool isCacheableRecord(int id) +{ + if (id == ESM::REC_ACTI || id == ESM::REC_ALCH || id == ESM::REC_APPA || id == ESM::REC_ARMO || + id == ESM::REC_BOOK || id == ESM::REC_CLOT || id == ESM::REC_CONT || id == ESM::REC_CREA || + id == ESM::REC_DOOR || id == ESM::REC_INGR || id == ESM::REC_LEVC || id == ESM::REC_LEVI || + id == ESM::REC_LIGH || id == ESM::REC_LOCK || id == ESM::REC_MISC || id == ESM::REC_NPC_ || + id == ESM::REC_PROB || id == ESM::REC_REPA || id == ESM::REC_STAT || id == ESM::REC_WEAP) + { + return true; + } + return false; +} + +void ESMStore::load(ESM::ESMReader &esm) +{ + std::set missing; + + ESM::Dialogue *dialogue = 0; + + // Loop through all records + while(esm.hasMoreRecs()) + { + ESM::NAME n = esm.getRecName(); + esm.getRecHeader(); + + // Look up the record type. + std::map::iterator it = mStores.find(n.val); + + if (it == mStores.end()) { + if (n.val == ESM::REC_INFO) { + if (dialogue) { + dialogue->mInfo.push_back(ESM::DialInfo()); + dialogue->mInfo.back().load(esm); + } else { + std::cerr << "error: info record without dialog" << std::endl; + esm.skipRecord(); + } + } else if (n.val == ESM::REC_MGEF) { + mMagicEffects.load (esm); + } else if (n.val == ESM::REC_SKIL) { + mSkills.load (esm); + } else { + // Not found (this would be an error later) + esm.skipRecord(); + missing.insert(n.toString()); + } + } else { + // Load it + std::string id = esm.getHNOString("NAME"); + it->second->load(esm, id); + + if (n.val==ESM::REC_DIAL) { + // dirty hack, but it is better than non-const search() + // or friends + dialogue = &mDialogs.mStatic.back(); + assert (dialogue->mId == id); + } else { + dialogue = 0; + } + // Insert the reference into the global lookup + if (!id.empty() && isCacheableRecord(n.val)) { + mIds[id] = n.val; + } + } + } + + /* This information isn't needed on screen. But keep the code around + for debugging purposes later. + + cout << "\n" << mStores.size() << " record types:\n"; + for(RecListList::iterator it = mStores.begin(); it != mStores.end(); it++) + cout << " " << toStr(it->first) << ": " << it->second->getSize() << endl; + cout << "\nNot implemented yet: "; + for(set::iterator it = missing.begin(); + it != missing.end(); it++ ) + cout << *it << " "; + cout << endl; + */ + setUp(); +} + +void ESMStore::setUp() +{ + std::map::iterator it = mStores.begin(); + for (; it != mStores.end(); ++it) { + it->second->setUp(); + } + mSkills.setUp(); + mMagicEffects.setUp(); + mAttributes.setUp(); + + ESM::NPC item; + item.mId = "player"; + + std::vector::iterator pIt = + std::lower_bound(mNpcs.mStatic.begin(), mNpcs.mStatic.end(), item, RecordCmp()); + assert(pIt != mNpcs.mStatic.end() && pIt->mId == "player"); + + mNpcs.insert(*pIt); + mNpcs.mStatic.erase(pIt); +} + +} // end namespace diff --git a/apps/openmw/mwworld/esmstore.hpp b/apps/openmw/mwworld/esmstore.hpp new file mode 100644 index 0000000000..9917254ee7 --- /dev/null +++ b/apps/openmw/mwworld/esmstore.hpp @@ -0,0 +1,426 @@ +#ifndef OPENMW_MWWORLD_ESMSTORE_H +#define OPENMW_MWWORLD_ESMSTORE_H + +#include + +#include +#include "store.hpp" + +namespace MWWorld +{ + class ESMStore + { + Store mActivators; + Store mPotions; + Store mAppas; + Store mArmors; + Store mBodyParts; + Store mBooks; + Store mBirthSigns; + Store mClasses; + Store mClothes; + Store mContChange; + Store mContainers; + Store mCreatures; + Store mCreaChange; + Store mDialogs; + Store mDoors; + Store mEnchants; + Store mFactions; + Store mGlobals; + Store mIngreds; + Store mCreatureLists; + Store mItemLists; + Store mLights; + Store mLockpicks; + Store mMiscItems; + Store mNpcs; + Store mNpcChange; + Store mProbes; + Store mRaces; + Store mRegions; + Store mRepairs; + Store mSoundGens; + Store mSounds; + Store mSpells; + Store mStartScripts; + Store mStatics; + Store mWeapons; + + Store mGameSettings; + Store mScripts; + + // Lists that need special rules + Store mCells; + Store mLands; + Store mLandTextures; + Store mPathgrids; + + Store mMagicEffects; + Store mSkills; + + // Special entry which is hardcoded and not loaded from an ESM + Store mAttributes; + + // Lookup of all IDs. Makes looking up references faster. Just + // maps the id name to the record type. + std::map mIds; + std::map mStores; + + unsigned int mDynamicCount; + + public: + /// \todo replace with SharedIterator + typedef std::map::const_iterator iterator; + + iterator begin() const { + return mStores.begin(); + } + + iterator end() const { + return mStores.end(); + } + + // Look up the given ID in 'all'. Returns 0 if not found. + int find(const std::string &id) const + { + std::map::const_iterator it = mIds.find(id); + if (it == mIds.end()) { + return 0; + } + return it->second; + } + + ESMStore() + : mDynamicCount(0) + { + mStores[ESM::REC_ACTI] = &mActivators; + mStores[ESM::REC_ALCH] = &mPotions; + mStores[ESM::REC_APPA] = &mAppas; + mStores[ESM::REC_ARMO] = &mArmors; + mStores[ESM::REC_BODY] = &mBodyParts; + mStores[ESM::REC_BOOK] = &mBooks; + mStores[ESM::REC_BSGN] = &mBirthSigns; + mStores[ESM::REC_CELL] = &mCells; + mStores[ESM::REC_CLAS] = &mClasses; + mStores[ESM::REC_CLOT] = &mClothes; + mStores[ESM::REC_CNTC] = &mContChange; + mStores[ESM::REC_CONT] = &mContainers; + mStores[ESM::REC_CREA] = &mCreatures; + mStores[ESM::REC_CREC] = &mCreaChange; + mStores[ESM::REC_DIAL] = &mDialogs; + mStores[ESM::REC_DOOR] = &mDoors; + mStores[ESM::REC_ENCH] = &mEnchants; + mStores[ESM::REC_FACT] = &mFactions; + mStores[ESM::REC_GLOB] = &mGlobals; + mStores[ESM::REC_GMST] = &mGameSettings; + mStores[ESM::REC_INGR] = &mIngreds; + mStores[ESM::REC_LAND] = &mLands; + mStores[ESM::REC_LEVC] = &mCreatureLists; + mStores[ESM::REC_LEVI] = &mItemLists; + mStores[ESM::REC_LIGH] = &mLights; + mStores[ESM::REC_LOCK] = &mLockpicks; + mStores[ESM::REC_LTEX] = &mLandTextures; + mStores[ESM::REC_MISC] = &mMiscItems; + mStores[ESM::REC_NPC_] = &mNpcs; + mStores[ESM::REC_NPCC] = &mNpcChange; + mStores[ESM::REC_PGRD] = &mPathgrids; + mStores[ESM::REC_PROB] = &mProbes; + mStores[ESM::REC_RACE] = &mRaces; + mStores[ESM::REC_REGN] = &mRegions; + mStores[ESM::REC_REPA] = &mRepairs; + mStores[ESM::REC_SCPT] = &mScripts; + mStores[ESM::REC_SNDG] = &mSoundGens; + mStores[ESM::REC_SOUN] = &mSounds; + mStores[ESM::REC_SPEL] = &mSpells; + mStores[ESM::REC_SSCR] = &mStartScripts; + mStores[ESM::REC_STAT] = &mStatics; + mStores[ESM::REC_WEAP] = &mWeapons; + } + + void load(ESM::ESMReader &esm); + + template + const Store &get() const { + throw std::runtime_error("Storage for this type not exist"); + } + + template + const T *insert(const T &x) { + Store &store = const_cast &>(get()); + if (store.search(x.mId) != 0) { + std::ostringstream msg; + msg << "Try to override existing record '" << x.mId << "'"; + throw std::runtime_error(msg.str()); + } + T record = x; + + std::ostringstream id; + id << "$dynamic" << mDynamicCount++; + record.mId = id.str(); + + T *ptr = store.insert(record); + for (iterator it = mStores.begin(); it != mStores.end(); ++it) { + if (it->second == &store) { + mIds[ptr->mId] = it->first; + } + } + return ptr; + } + + private: + void setUp(); + }; + + template <> + inline const ESM::Cell *ESMStore::insert(const ESM::Cell &cell) { + return mCells.insert(cell); + } + + template <> + inline const ESM::NPC *ESMStore::insert(const ESM::NPC &npc) { + if (StringUtils::ciEqual(npc.mId, "player")) { + return mNpcs.insert(npc); + } else if (mNpcs.search(npc.mId) != 0) { + std::ostringstream msg; + msg << "Try to override existing record '" << npc.mId << "'"; + throw std::runtime_error(msg.str()); + } + ESM::NPC record = npc; + + std::ostringstream id; + id << "$dynamic" << mDynamicCount++; + record.mId = id.str(); + + ESM::NPC *ptr = mNpcs.insert(record); + mIds[ptr->mId] = ESM::REC_NPC_; + return ptr; + } + + template <> + inline const Store &ESMStore::get() const { + return mActivators; + } + + template <> + inline const Store &ESMStore::get() const { + return mPotions; + } + + template <> + inline const Store &ESMStore::get() const { + return mAppas; + } + + template <> + inline const Store &ESMStore::get() const { + return mArmors; + } + + template <> + inline const Store &ESMStore::get() const { + return mBodyParts; + } + + template <> + inline const Store &ESMStore::get() const { + return mBooks; + } + + template <> + inline const Store &ESMStore::get() const { + return mBirthSigns; + } + + template <> + inline const Store &ESMStore::get() const { + return mClasses; + } + + template <> + inline const Store &ESMStore::get() const { + return mClothes; + } + + template <> + inline const Store &ESMStore::get() const { + return mContChange; + } + + template <> + inline const Store &ESMStore::get() const { + return mContainers; + } + + template <> + inline const Store &ESMStore::get() const { + return mCreatures; + } + + template <> + inline const Store &ESMStore::get() const { + return mCreaChange; + } + + template <> + inline const Store &ESMStore::get() const { + return mDialogs; + } + + template <> + inline const Store &ESMStore::get() const { + return mDoors; + } + + template <> + inline const Store &ESMStore::get() const { + return mEnchants; + } + + template <> + inline const Store &ESMStore::get() const { + return mFactions; + } + + template <> + inline const Store &ESMStore::get() const { + return mGlobals; + } + + template <> + inline const Store &ESMStore::get() const { + return mIngreds; + } + + template <> + inline const Store &ESMStore::get() const { + return mCreatureLists; + } + + template <> + inline const Store &ESMStore::get() const { + return mItemLists; + } + + template <> + inline const Store &ESMStore::get() const { + return mLights; + } + + template <> + inline const Store &ESMStore::get() const { + return mLockpicks; + } + + template <> + inline const Store &ESMStore::get() const { + return mMiscItems; + } + + template <> + inline const Store &ESMStore::get() const { + return mNpcs; + } + + template <> + inline const Store &ESMStore::get() const { + return mNpcChange; + } + + template <> + inline const Store &ESMStore::get() const { + return mProbes; + } + + template <> + inline const Store &ESMStore::get() const { + return mRaces; + } + + template <> + inline const Store &ESMStore::get() const { + return mRegions; + } + + template <> + inline const Store &ESMStore::get() const { + return mRepairs; + } + + template <> + inline const Store &ESMStore::get() const { + return mSoundGens; + } + + template <> + inline const Store &ESMStore::get() const { + return mSounds; + } + + template <> + inline const Store &ESMStore::get() const { + return mSpells; + } + + template <> + inline const Store &ESMStore::get() const { + return mStartScripts; + } + + template <> + inline const Store &ESMStore::get() const { + return mStatics; + } + + template <> + inline const Store &ESMStore::get() const { + return mWeapons; + } + + template <> + inline const Store &ESMStore::get() const { + return mGameSettings; + } + + template <> + inline const Store &ESMStore::get() const { + return mScripts; + } + + template <> + inline const Store &ESMStore::get() const { + return mCells; + } + + template <> + inline const Store &ESMStore::get() const { + return mLands; + } + + template <> + inline const Store &ESMStore::get() const { + return mLandTextures; + } + + template <> + inline const Store &ESMStore::get() const { + return mPathgrids; + } + + template <> + inline const Store &ESMStore::get() const { + return mMagicEffects; + } + + template <> + inline const Store &ESMStore::get() const { + return mSkills; + } + + template <> + inline const Store &ESMStore::get() const { + return mAttributes; + } +} + +#endif diff --git a/apps/openmw/mwworld/failedaction.cpp b/apps/openmw/mwworld/failedaction.cpp new file mode 100644 index 0000000000..ec763dba01 --- /dev/null +++ b/apps/openmw/mwworld/failedaction.cpp @@ -0,0 +1,21 @@ +#include "failedaction.hpp" +#include "../mwbase/world.hpp" + +#include "../mwbase/environment.hpp" +#include "../mwbase/windowmanager.hpp" + + +namespace MWWorld +{ + FailedAction::FailedAction (const std::string& msg) : Action (false), message(msg) + { } + + + void FailedAction::executeImp (const Ptr& actor) + { + if ( actor.getRefData().getHandle()=="player" && !(message.empty())) + { + MWBase::Environment::get().getWindowManager() ->messageBox(message, std::vector()); + } + } +} diff --git a/apps/openmw/mwworld/failedaction.hpp b/apps/openmw/mwworld/failedaction.hpp new file mode 100644 index 0000000000..e736bfb63b --- /dev/null +++ b/apps/openmw/mwworld/failedaction.hpp @@ -0,0 +1,20 @@ +#ifndef GAME_MWWORLD_FAILEDACTION_H +#define GAME_MWWORLD_FAILEDACTION_H + +#include "action.hpp" +#include "ptr.hpp" + +namespace MWWorld +{ + class FailedAction : public Action + { + std::string message; + + virtual void executeImp (const Ptr& actor); + + public: + FailedAction (const std::string& message = std::string()); + }; +} + +#endif \ No newline at end of file diff --git a/apps/openmw/mwworld/globals.cpp b/apps/openmw/mwworld/globals.cpp index 1430219d91..76dede5a34 100644 --- a/apps/openmw/mwworld/globals.cpp +++ b/apps/openmw/mwworld/globals.cpp @@ -3,7 +3,7 @@ #include -#include +#include "esmstore.hpp" namespace MWWorld { @@ -27,35 +27,36 @@ namespace MWWorld return iter; } - Globals::Globals (const ESMS::ESMStore& store) + Globals::Globals (const MWWorld::ESMStore& store) { - for (ESMS::RecListT::MapType::const_iterator iter - (store.globals.list.begin()); iter != store.globals.list.end(); ++iter) + const MWWorld::Store &globals = store.get(); + MWWorld::Store::iterator iter = globals.begin(); + for (; iter != globals.end(); ++iter) { char type = ' '; Data value; - switch (iter->second.mType) + switch (iter->mType) { case ESM::VT_Short: type = 's'; value.mShort = *reinterpret_cast ( - &iter->second.mValue); + &iter->mValue); break; case ESM::VT_Int: type = 'l'; value.mLong = *reinterpret_cast ( - &iter->second.mValue); + &iter->mValue); break; case ESM::VT_Float: type = 'f'; value.mFloat = *reinterpret_cast ( - &iter->second.mValue); + &iter->mValue); break; default: @@ -63,7 +64,7 @@ namespace MWWorld throw std::runtime_error ("unsupported global variable type"); } - mVariables.insert (std::make_pair (iter->first, std::make_pair (type, value))); + mVariables.insert (std::make_pair (iter->mId, std::make_pair (type, value))); } if (mVariables.find ("dayspassed")==mVariables.end()) diff --git a/apps/openmw/mwworld/globals.hpp b/apps/openmw/mwworld/globals.hpp index 6aa54ade29..c7aee5f939 100644 --- a/apps/openmw/mwworld/globals.hpp +++ b/apps/openmw/mwworld/globals.hpp @@ -6,13 +6,10 @@ #include -namespace ESMS -{ - struct ESMStore; -} - namespace MWWorld { + class ESMStore; + class Globals { public: @@ -36,7 +33,7 @@ namespace MWWorld public: - Globals (const ESMS::ESMStore& store); + Globals (const MWWorld::ESMStore& store); const Data& operator[] (const std::string& name) const; diff --git a/apps/openmw/mwworld/inventorystore.cpp b/apps/openmw/mwworld/inventorystore.cpp index 179a484e9b..dd518ff6a4 100644 --- a/apps/openmw/mwworld/inventorystore.cpp +++ b/apps/openmw/mwworld/inventorystore.cpp @@ -6,13 +6,12 @@ #include -#include - #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" #include "../mwmechanics/npcstats.hpp" +#include "esmstore.hpp" #include "class.hpp" void MWWorld::InventoryStore::copySlots (const InventoryStore& store) @@ -231,7 +230,7 @@ const MWMechanics::MagicEffects& MWWorld::InventoryStore::getMagicEffects() if (!enchantmentId.empty()) { const ESM::Enchantment& enchantment = - *MWBase::Environment::get().getWorld()->getStore().enchants.find (enchantmentId); + *MWBase::Environment::get().getWorld()->getStore().get().find (enchantmentId); if (enchantment.mData.mType==ESM::Enchantment::ConstantEffect) mMagicEffects.add (enchantment.mEffects); diff --git a/apps/openmw/mwworld/localscripts.cpp b/apps/openmw/mwworld/localscripts.cpp index 1ef1cdeaf1..be83a191ab 100644 --- a/apps/openmw/mwworld/localscripts.cpp +++ b/apps/openmw/mwworld/localscripts.cpp @@ -1,8 +1,6 @@ - #include "localscripts.hpp" -#include - +#include "esmstore.hpp" #include "cellstore.hpp" namespace @@ -12,18 +10,18 @@ namespace MWWorld::CellRefList& cellRefList, MWWorld::Ptr::CellStore *cell) { for (typename MWWorld::CellRefList::List::iterator iter ( - cellRefList.list.begin()); - iter!=cellRefList.list.end(); ++iter) + cellRefList.mList.begin()); + iter!=cellRefList.mList.end(); ++iter) { - if (!iter->second.base->mScript.empty() && iter->second.mData.getCount()) + if (!iter->second.mBase->mScript.empty() && iter->second.mData.getCount()) { - localScripts.add (iter->second.base->mScript, MWWorld::Ptr (&iter->second, cell)); + localScripts.add (iter->second.mBase->mScript, MWWorld::Ptr (&iter->second, cell)); } } } } -MWWorld::LocalScripts::LocalScripts (const ESMS::ESMStore& store) : mStore (store) {} +MWWorld::LocalScripts::LocalScripts (const MWWorld::ESMStore& store) : mStore (store) {} void MWWorld::LocalScripts::setIgnore (const Ptr& ptr) { @@ -63,7 +61,7 @@ std::pair MWWorld::LocalScripts::getNext() void MWWorld::LocalScripts::add (const std::string& scriptName, const Ptr& ptr) { - if (const ESM::Script *script = mStore.scripts.find (scriptName)) + if (const ESM::Script *script = mStore.get().find (scriptName)) { ptr.getRefData().setLocals (*script); @@ -73,23 +71,23 @@ void MWWorld::LocalScripts::add (const std::string& scriptName, const Ptr& ptr) void MWWorld::LocalScripts::addCell (Ptr::CellStore *cell) { - listCellScripts (*this, cell->activators, cell); - listCellScripts (*this, cell->potions, cell); - listCellScripts (*this, cell->appas, cell); - listCellScripts (*this, cell->armors, cell); - listCellScripts (*this, cell->books, cell); - listCellScripts (*this, cell->clothes, cell); - listCellScripts (*this, cell->containers, cell); - listCellScripts (*this, cell->creatures, cell); - listCellScripts (*this, cell->doors, cell); - listCellScripts (*this, cell->ingreds, cell); - listCellScripts (*this, cell->lights, cell); - listCellScripts (*this, cell->lockpicks, cell); - listCellScripts (*this, cell->miscItems, cell); - listCellScripts (*this, cell->npcs, cell); - listCellScripts (*this, cell->probes, cell); - listCellScripts (*this, cell->repairs, cell); - listCellScripts (*this, cell->weapons, cell); + listCellScripts (*this, cell->mActivators, cell); + listCellScripts (*this, cell->mPotions, cell); + listCellScripts (*this, cell->mAppas, cell); + listCellScripts (*this, cell->mArmors, cell); + listCellScripts (*this, cell->mBooks, cell); + listCellScripts (*this, cell->mClothes, cell); + listCellScripts (*this, cell->mContainers, cell); + listCellScripts (*this, cell->mCreatures, cell); + listCellScripts (*this, cell->mDoors, cell); + listCellScripts (*this, cell->mIngreds, cell); + listCellScripts (*this, cell->mLights, cell); + listCellScripts (*this, cell->mLockpicks, cell); + listCellScripts (*this, cell->mMiscItems, cell); + listCellScripts (*this, cell->mNpcs, cell); + listCellScripts (*this, cell->mProbes, cell); + listCellScripts (*this, cell->mRepairs, cell); + listCellScripts (*this, cell->mWeapons, cell); } void MWWorld::LocalScripts::clear() diff --git a/apps/openmw/mwworld/localscripts.hpp b/apps/openmw/mwworld/localscripts.hpp index 78f65e356e..028dcdedad 100644 --- a/apps/openmw/mwworld/localscripts.hpp +++ b/apps/openmw/mwworld/localscripts.hpp @@ -6,13 +6,9 @@ #include "ptr.hpp" -namespace ESMS -{ - struct ESMStore; -} - namespace MWWorld { + struct ESMStore; class CellStore; /// \brief List of active local scripts @@ -21,11 +17,11 @@ namespace MWWorld std::list > mScripts; std::list >::iterator mIter; MWWorld::Ptr mIgnore; - const ESMS::ESMStore& mStore; + const MWWorld::ESMStore& mStore; public: - LocalScripts (const ESMS::ESMStore& store); + LocalScripts (const MWWorld::ESMStore& store); void setIgnore (const Ptr& ptr); ///< Mark a single reference for ignoring during iteration over local scripts (will revoke diff --git a/apps/openmw/mwworld/manualref.hpp b/apps/openmw/mwworld/manualref.hpp index 6570761ab7..91b8cf8cd4 100644 --- a/apps/openmw/mwworld/manualref.hpp +++ b/apps/openmw/mwworld/manualref.hpp @@ -3,8 +3,7 @@ #include -#include - +#include "esmstore.hpp" #include "ptr.hpp" #include "cellstore.hpp" @@ -20,29 +19,12 @@ namespace MWWorld ManualRef& operator= (const ManualRef&); template - bool create (const ESMS::RecListT& list, const std::string& name) + bool create (const MWWorld::Store& list, const std::string& name) { if (const T *instance = list.search (name)) { LiveCellRef ref; - ref.base = instance; - - mRef = ref; - mPtr = Ptr (&boost::any_cast&> (mRef), 0); - - return true; - } - - return false; - } - - template - bool create (const ESMS::RecListWithIDT& list, const std::string& name) - { - if (const T *instance = list.search (name)) - { - LiveCellRef ref; - ref.base = instance; + ref.mBase = instance; mRef = ref; mPtr = Ptr (&boost::any_cast&> (mRef), 0); @@ -55,29 +37,29 @@ namespace MWWorld public: - ManualRef (const ESMS::ESMStore& store, const std::string& name) + ManualRef (const MWWorld::ESMStore& store, const std::string& name) { // create - if (!create (store.activators, name) && - !create (store.potions, name) && - !create (store.appas, name) && - !create (store.armors, name) && - !create (store.books, name) && - !create (store.clothes, name) && - !create (store.containers, name) && - !create (store.creatures, name) && - !create (store.doors, name) && - !create (store.ingreds, name) && - !create (store.creatureLists, name) && - !create (store.itemLists, name) && - !create (store.lights, name) && - !create (store.lockpicks, name) && - !create (store.miscItems, name) && - !create (store.npcs, name) && - !create (store.probes, name) && - !create (store.repairs, name) && - !create (store.statics, name) && - !create (store.weapons, name)) + if (!create (store.get(), name) && + !create (store.get(), name) && + !create (store.get(), name) && + !create (store.get(), name) && + !create (store.get(), name) && + !create (store.get(), name) && + !create (store.get(), name) && + !create (store.get(), name) && + !create (store.get(), name) && + !create (store.get(), name) && + !create (store.get(), name) && + !create (store.get(), name) && + !create (store.get(), name) && + !create (store.get(), name) && + !create (store.get(), name) && + !create (store.get(), name) && + !create (store.get(), name) && + !create (store.get(), name) && + !create (store.get(), name) && + !create (store.get(), name)) throw std::logic_error ("failed to create manual cell ref for " + name); // initialise diff --git a/apps/openmw/mwworld/player.cpp b/apps/openmw/mwworld/player.cpp index e1eb02c32b..3414ba4489 100644 --- a/apps/openmw/mwworld/player.cpp +++ b/apps/openmw/mwworld/player.cpp @@ -1,7 +1,6 @@ #include "player.hpp" -#include #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" @@ -9,37 +8,21 @@ #include "../mwmechanics/movement.hpp" #include "../mwmechanics/npcstats.hpp" +#include "esmstore.hpp" #include "class.hpp" namespace MWWorld { - Player::Player (const ESM::NPC *player, const MWBase::World& world) : - mCellStore (0), mClass (0), - mAutoMove (false), mForwardBackward (0) + Player::Player (const ESM::NPC *player, const MWBase::World& world) + : mCellStore(0), + mAutoMove(false), + mForwardBackward (0) { - mPlayer.base = player; - mPlayer.ref.mRefID = "player"; - mName = player->mName; - mMale = !(player->mFlags & ESM::NPC::Female); - mRace = player->mRace; + mPlayer.mBase = player; + mPlayer.mRef.mRefID = "player"; float* playerPos = mPlayer.mData.getPosition().pos; playerPos[0] = playerPos[1] = playerPos[2] = 0; - - /// \todo Do not make a copy of classes defined in esm/p records. - mClass = new ESM::Class (*world.getStore().classes.find (player->mClass)); - } - - Player::~Player() - { - delete mClass; - } - - void Player::setClass (const ESM::Class& class_) - { - ESM::Class *new_class = new ESM::Class (class_); - delete mClass; - mClass = new_class; } void Player::setDrawState (MWMechanics::DrawState_ state) @@ -102,5 +85,4 @@ namespace MWWorld MWWorld::Ptr ptr = getPlayer(); return MWWorld::Class::get(ptr).getNpcStats(ptr).getDrawState(); } - } diff --git a/apps/openmw/mwworld/player.hpp b/apps/openmw/mwworld/player.hpp index 68df2ec6df..1c1ef76cf0 100644 --- a/apps/openmw/mwworld/player.hpp +++ b/apps/openmw/mwworld/player.hpp @@ -1,8 +1,6 @@ #ifndef GAME_MWWORLD_PLAYER_H #define GAME_MWWORLD_PLAYER_H -#include "OgreCamera.h" - #include "../mwworld/cellstore.hpp" #include "../mwworld/refdata.hpp" #include "../mwworld/ptr.hpp" @@ -21,21 +19,17 @@ namespace MWWorld /// \brief NPC object representing the player and additional player data class Player { - LiveCellRef mPlayer; - MWWorld::CellStore *mCellStore; - std::string mName; - bool mMale; - std::string mRace; - std::string mBirthsign; - ESM::Class *mClass; - bool mAutoMove; - int mForwardBackward; + LiveCellRef mPlayer; + MWWorld::CellStore *mCellStore; + std::string mSign; + + bool mAutoMove; + int mForwardBackward; + public: Player(const ESM::NPC *player, const MWBase::World& world); - ~Player(); - void setCell (MWWorld::CellStore *cellStore) { mCellStore = cellStore; @@ -47,55 +41,16 @@ namespace MWWorld return ptr; } - void setName (const std::string& name) - { - mName = name; + void setBirthSign(const std::string &sign) { + mSign = sign; } - void setGender (bool male) - { - mMale = male; + const std::string &getBirthSign() const { + return mSign; } - void setRace (const std::string& race) - { - mRace = race; - } - - void setBirthsign (const std::string& birthsign) - { - mBirthsign = birthsign; - } - - void setClass (const ESM::Class& class_); - void setDrawState (MWMechanics::DrawState_ state); - std::string getName() const - { - return mName; - } - - bool isMale() const - { - return mMale; - } - - std::string getRace() const - { - return mRace; - } - - std::string getBirthsign() const - { - return mBirthsign; - } - - const ESM::Class& getClass() const - { - return *mClass; - } - bool getAutoMove() const { return mAutoMove; diff --git a/apps/openmw/mwworld/ptr.hpp b/apps/openmw/mwworld/ptr.hpp index f74fdd3ef7..594ddef2d5 100644 --- a/apps/openmw/mwworld/ptr.hpp +++ b/apps/openmw/mwworld/ptr.hpp @@ -50,7 +50,7 @@ namespace MWWorld : mContainerStore (0) { mPtr = liveCellRef; - mCellRef = &liveCellRef->ref; + mCellRef = &liveCellRef->mRef; mRefData = &liveCellRef->mData; mCell = cell; mTypeName = typeid (T).name(); diff --git a/apps/openmw/mwworld/recordcmp.hpp b/apps/openmw/mwworld/recordcmp.hpp new file mode 100644 index 0000000000..0b16551005 --- /dev/null +++ b/apps/openmw/mwworld/recordcmp.hpp @@ -0,0 +1,84 @@ +#ifndef OPENMW_MWWORLD_RECORDCMP_H +#define OPENMW_MWWORLD_RECORDCMP_H + +#include +#include +#include + +#include + +namespace MWWorld +{ + /// \todo move this to another location + class StringUtils + { + struct ci + { + bool operator()(int x, int y) const { + return std::tolower(x) < std::tolower(y); + } + }; + + public: + static bool ciLess(const std::string &x, const std::string &y) { + return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end(), ci()); + } + + static bool ciEqual(const std::string &x, const std::string &y) { + if (x.size() != y.size()) { + return false; + } + std::string::const_iterator xit = x.begin(); + std::string::const_iterator yit = y.begin(); + for (; xit != x.end(); ++xit, ++yit) { + if (std::tolower(*xit) != std::tolower(*yit)) { + return false; + } + } + return true; + } + + /// Transforms input string to lower case w/o copy + static std::string &toLower(std::string &inout) { + std::transform( + inout.begin(), + inout.end(), + inout.begin(), + (int (*)(int)) std::tolower + ); + return inout; + } + + /// Returns lower case copy of input string + static std::string lowerCase(const std::string &in) + { + std::string out = in; + return toLower(out); + } + }; + + struct RecordCmp + { + template + bool operator()(const T &x, const T& y) const { + return x.mId < y.mId; + } + }; + + template <> + inline bool RecordCmp::operator()(const ESM::Dialogue &x, const ESM::Dialogue &y) const { + return StringUtils::ciLess(x.mId, y.mId); + } + + template <> + inline bool RecordCmp::operator()(const ESM::Cell &x, const ESM::Cell &y) const { + return StringUtils::ciLess(x.mName, y.mName); + } + + template <> + inline bool RecordCmp::operator()(const ESM::Pathgrid &x, const ESM::Pathgrid &y) const { + return StringUtils::ciLess(x.mCell, y.mCell); + } + +} // end namespace +#endif diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index b6add7fbfc..eacd4e6bd1 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -1,6 +1,5 @@ #include "scene.hpp" -#include #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" /// FIXME @@ -10,6 +9,7 @@ #include "player.hpp" #include "localscripts.hpp" +#include "esmstore.hpp" #include "cellfunctors.hpp" @@ -20,15 +20,15 @@ namespace void insertCellRefList(MWRender::RenderingManager& rendering, T& cellRefList, MWWorld::CellStore &cell, MWWorld::PhysicsSystem& physics) { - if (!cellRefList.list.empty()) + if (!cellRefList.mList.empty()) { const MWWorld::Class& class_ = - MWWorld::Class::get (MWWorld::Ptr (&cellRefList.list.begin()->second, &cell)); + MWWorld::Class::get (MWWorld::Ptr (&cellRefList.mList.begin()->second, &cell)); - int numRefs = cellRefList.list.size(); + int numRefs = cellRefList.mList.size(); int current = 0; - for (typename T::List::iterator it = cellRefList.list.begin(); - it != cellRefList.list.end(); it++) + for (typename T::List::iterator it = cellRefList.mList.begin(); + it != cellRefList.mList.end(); it++) { MWBase::Environment::get().getWindowManager ()->setLoadingProgress ("Loading cells", 1, current, numRefs); ++current; @@ -82,11 +82,15 @@ namespace MWWorld mPhysics->removeObject (node->getName()); } - if (!((*iter)->cell->mData.mFlags & ESM::Cell::Interior)) + if ((*iter)->mCell->isExterior()) { - ESM::Land* land = MWBase::Environment::get().getWorld()->getStore().lands.search((*iter)->cell->mData.mX,(*iter)->cell->mData.mY); + ESM::Land* land = + MWBase::Environment::get().getWorld()->getStore().get().search( + (*iter)->mCell->getGridX(), + (*iter)->mCell->getGridY() + ); if (land) - mPhysics->removeHeightField( (*iter)->cell->mData.mX, (*iter)->cell->mData.mY ); + mPhysics->removeHeightField( (*iter)->mCell->getGridX(), (*iter)->mCell->getGridY() ); } } @@ -113,13 +117,23 @@ namespace MWWorld float verts = ESM::Land::LAND_SIZE; float worldsize = ESM::Land::REAL_SIZE; - if (!(cell->cell->mData.mFlags & ESM::Cell::Interior)) + if (cell->mCell->isExterior()) { - ESM::Land* land = MWBase::Environment::get().getWorld()->getStore().lands.search(cell->cell->mData.mX,cell->cell->mData.mY); - if (land) - mPhysics->addHeightField (land->mLandData->mHeights, - cell->cell->mData.mX, cell->cell->mData.mY, - 0, ( worldsize/(verts-1) ), verts); + ESM::Land* land = + MWBase::Environment::get().getWorld()->getStore().get().search( + cell->mCell->getGridX(), + cell->mCell->getGridY() + ); + if (land) { + mPhysics->addHeightField ( + land->mLandData->mHeights, + cell->mCell->getGridX(), + cell->mCell->getGridY(), + 0, + worldsize / (verts-1), + verts) + ; + } } mRendering.configureAmbient(*cell); @@ -130,8 +144,8 @@ namespace MWWorld void Scene::playerCellChange(MWWorld::CellStore *cell, const ESM::Position& pos, bool adjustPlayerPos) { - bool hasWater = cell->cell->mData.mFlags & cell->cell->HasWater; - mPhysics->setCurrentWater(hasWater, cell->cell->mWater); + bool hasWater = cell->mCell->mData.mFlags & ESM::Cell::HasWater; + mPhysics->setCurrentWater(hasWater, cell->mCell->mWater); MWBase::World *world = MWBase::Environment::get().getWorld(); world->getPlayer().setCell(cell); @@ -169,10 +183,10 @@ namespace MWWorld int numUnload = 0; while (active!=mActiveCells.end()) { - if (!((*active)->cell->mData.mFlags & ESM::Cell::Interior)) + if ((*active)->mCell->isExterior()) { - if (std::abs (X-(*active)->cell->mData.mX)<=1 && - std::abs (Y-(*active)->cell->mData.mY)<=1) + if (std::abs (X-(*active)->mCell->getGridX())<=1 && + std::abs (Y-(*active)->mCell->getGridY())<=1) { // keep cells within the new 3x3 grid ++active; @@ -187,10 +201,10 @@ namespace MWWorld active = mActiveCells.begin(); while (active!=mActiveCells.end()) { - if (!((*active)->cell->mData.mFlags & ESM::Cell::Interior)) + if ((*active)->mCell->isExterior()) { - if (std::abs (X-(*active)->cell->mData.mX)<=1 && - std::abs (Y-(*active)->cell->mData.mY)<=1) + if (std::abs (X-(*active)->mCell->getGridX())<=1 && + std::abs (Y-(*active)->mCell->getGridY())<=1) { // keep cells within the new 3x3 grid ++active; @@ -212,10 +226,10 @@ namespace MWWorld while (iter!=mActiveCells.end()) { - assert (!((*iter)->cell->mData.mFlags & ESM::Cell::Interior)); + assert ((*iter)->mCell->isExterior()); - if (x==(*iter)->cell->mData.mX && - y==(*iter)->cell->mData.mY) + if (x==(*iter)->mCell->getGridX() && + y==(*iter)->mCell->getGridY()) break; ++iter; @@ -234,10 +248,10 @@ namespace MWWorld while (iter!=mActiveCells.end()) { - assert (!((*iter)->cell->mData.mFlags & ESM::Cell::Interior)); + assert ((*iter)->mCell->isExterior()); - if (x==(*iter)->cell->mData.mX && - y==(*iter)->cell->mData.mY) + if (x==(*iter)->mCell->getGridX() && + y==(*iter)->mCell->getGridY()) break; ++iter; @@ -258,10 +272,10 @@ namespace MWWorld while (iter!=mActiveCells.end()) { - assert (!((*iter)->cell->mData.mFlags & ESM::Cell::Interior)); + assert ((*iter)->mCell->isExterior()); - if (X==(*iter)->cell->mData.mX && - Y==(*iter)->cell->mData.mY) + if (X==(*iter)->mCell->getGridX() && + Y==(*iter)->mCell->getGridY()) break; ++iter; @@ -348,7 +362,7 @@ namespace MWWorld } // Load cell. - std::cout << "cellName: " << cell->cell->mName << std::endl; + std::cout << "cellName: " << cell->mCell->mName << std::endl; MWBase::Environment::get().getWindowManager ()->setLoadingProgress ("Loading cells", 0, 0, 1); loadCell (cell); @@ -393,26 +407,26 @@ namespace MWWorld void Scene::insertCell (Ptr::CellStore &cell) { // Loop through all references in the cell - insertCellRefList(mRendering, cell.activators, cell, *mPhysics); - insertCellRefList(mRendering, cell.potions, cell, *mPhysics); - insertCellRefList(mRendering, cell.appas, cell, *mPhysics); - insertCellRefList(mRendering, cell.armors, cell, *mPhysics); - insertCellRefList(mRendering, cell.books, cell, *mPhysics); - insertCellRefList(mRendering, cell.clothes, cell, *mPhysics); - insertCellRefList(mRendering, cell.containers, cell, *mPhysics); - insertCellRefList(mRendering, cell.creatures, cell, *mPhysics); - insertCellRefList(mRendering, cell.doors, cell, *mPhysics); - insertCellRefList(mRendering, cell.ingreds, cell, *mPhysics); - insertCellRefList(mRendering, cell.creatureLists, cell, *mPhysics); - insertCellRefList(mRendering, cell.itemLists, cell, *mPhysics); - insertCellRefList(mRendering, cell.lights, cell, *mPhysics); - insertCellRefList(mRendering, cell.lockpicks, cell, *mPhysics); - insertCellRefList(mRendering, cell.miscItems, cell, *mPhysics); - insertCellRefList(mRendering, cell.npcs, cell, *mPhysics); - insertCellRefList(mRendering, cell.probes, cell, *mPhysics); - insertCellRefList(mRendering, cell.repairs, cell, *mPhysics); - insertCellRefList(mRendering, cell.statics, cell, *mPhysics); - insertCellRefList(mRendering, cell.weapons, cell, *mPhysics); + insertCellRefList(mRendering, cell.mActivators, cell, *mPhysics); + insertCellRefList(mRendering, cell.mPotions, cell, *mPhysics); + insertCellRefList(mRendering, cell.mAppas, cell, *mPhysics); + insertCellRefList(mRendering, cell.mArmors, cell, *mPhysics); + insertCellRefList(mRendering, cell.mBooks, cell, *mPhysics); + insertCellRefList(mRendering, cell.mClothes, cell, *mPhysics); + insertCellRefList(mRendering, cell.mContainers, cell, *mPhysics); + insertCellRefList(mRendering, cell.mCreatures, cell, *mPhysics); + insertCellRefList(mRendering, cell.mDoors, cell, *mPhysics); + insertCellRefList(mRendering, cell.mIngreds, cell, *mPhysics); + insertCellRefList(mRendering, cell.mCreatureLists, cell, *mPhysics); + insertCellRefList(mRendering, cell.mItemLists, cell, *mPhysics); + insertCellRefList(mRendering, cell.mLights, cell, *mPhysics); + insertCellRefList(mRendering, cell.mLockpicks, cell, *mPhysics); + insertCellRefList(mRendering, cell.mMiscItems, cell, *mPhysics); + insertCellRefList(mRendering, cell.mNpcs, cell, *mPhysics); + insertCellRefList(mRendering, cell.mProbes, cell, *mPhysics); + insertCellRefList(mRendering, cell.mRepairs, cell, *mPhysics); + insertCellRefList(mRendering, cell.mStatics, cell, *mPhysics); + insertCellRefList(mRendering, cell.mWeapons, cell, *mPhysics); } void Scene::addObjectToScene (const Ptr& ptr) diff --git a/apps/openmw/mwworld/store.hpp b/apps/openmw/mwworld/store.hpp new file mode 100644 index 0000000000..fd93f39f1e --- /dev/null +++ b/apps/openmw/mwworld/store.hpp @@ -0,0 +1,879 @@ +#ifndef OPENMW_MWWORLD_STORE_H +#define OPENMW_MWWORLD_STORE_H + +#include +#include +#include +#include + +#include "recordcmp.hpp" + +namespace MWWorld +{ + struct StoreBase + { + virtual ~StoreBase() {} + + virtual void setUp() {} + virtual void listIdentifier(std::vector &list) const {} + + virtual int getSize() const = 0; + virtual void load(ESM::ESMReader &esm, const std::string &id) = 0; + }; + + template + class SharedIterator + { + typedef typename std::vector::const_iterator Iter; + + Iter mIter; + + public: + SharedIterator() {} + + SharedIterator(const SharedIterator &orig) + : mIter(orig.mIter) + {} + + SharedIterator(const Iter &iter) + : mIter(iter) + {} + + SharedIterator &operator++() { + ++mIter; + return *this; + } + + SharedIterator operator++(int) { + SharedIterator iter = *this; + mIter++; + + return iter; + } + + SharedIterator &operator--() { + --mIter; + return *this; + } + + SharedIterator operator--(int) { + SharedIterator iter = *this; + mIter--; + + return iter; + } + + bool operator==(const SharedIterator &x) const { + return mIter == x.mIter; + } + + bool operator!=(const SharedIterator &x) const { + return !(*this == x); + } + + const T &operator*() const { + return **mIter; + } + + const T *operator->() const { + return &(**mIter); + } + }; + + class ESMStore; + + template + class Store : public StoreBase + { + std::vector mStatic; + std::vector mShared; + std::map mDynamic; + + typedef std::map Dynamic; + + friend class ESMStore; + + public: + Store() + {} + + Store(const Store &orig) + : mStatic(orig.mData) + {} + + typedef SharedIterator iterator; + + const T *search(const std::string &id) const { + T item; + item.mId = StringUtils::lowerCase(id); + + typename std::vector::const_iterator it = + std::lower_bound(mStatic.begin(), mStatic.end(), item, RecordCmp()); + + if (it != mStatic.end() && StringUtils::ciEqual(it->mId, id)) { + return &(*it); + } + + typename Dynamic::const_iterator dit = mDynamic.find(item.mId); + if (dit != mDynamic.end()) { + return &dit->second; + } + + return 0; + } + + const T *find(const std::string &id) const { + const T *ptr = search(id); + if (ptr == 0) { + std::ostringstream msg; + msg << "Object '" << id << "' not found (const)"; + throw std::runtime_error(msg.str()); + } + return ptr; + } + + void load(ESM::ESMReader &esm, const std::string &id) { + mStatic.push_back(T()); + mStatic.back().mId = StringUtils::lowerCase(id); + mStatic.back().load(esm); + } + + void setUp() { + std::sort(mStatic.begin(), mStatic.end(), RecordCmp()); + + mShared.reserve(mStatic.size()); + typename std::vector::iterator it = mStatic.begin(); + for (; it != mStatic.end(); ++it) { + mShared.push_back(&(*it)); + } + } + + iterator begin() const { + return mShared.begin(); + } + + iterator end() const { + return mShared.end(); + } + + int getSize() const { + return mShared.size(); + } + + void listIdentifier(std::vector &list) const { + list.reserve(list.size() + getSize()); + typename std::vector::const_iterator it = mShared.begin(); + for (; it != mShared.end(); ++it) { + list.push_back((*it)->mId); + } + } + + T *insert(const T &item) { + std::string id = StringUtils::lowerCase(item.mId); + std::pair result = + mDynamic.insert(std::pair(id, item)); + T *ptr = &result.first->second; + if (result.second) { + mShared.push_back(ptr); + } else { + *ptr = item; + } + return ptr; + } + + bool erase(const std::string &id) { + std::string key = StringUtils::lowerCase(id); + typename Dynamic::iterator it = mDynamic.find(key); + if (it == mDynamic.end()) { + return false; + } + mDynamic.erase(it); + + // have to reinit the whole shared part + mShared.erase(mShared.begin() + mStatic.size(), mShared.end()); + for (it = mDynamic.begin(); it != mDynamic.end(); ++it) { + mShared.push_back(&it->second); + } + return true; + } + + bool erase(const T &item) { + return erase(item.mId); + } + }; + + template <> + inline void Store::load(ESM::ESMReader &esm, const std::string &id) { + mStatic.push_back(ESM::Dialogue()); + mStatic.back().mId = id; + mStatic.back().load(esm); + } + + template <> + inline void Store::load(ESM::ESMReader &esm, const std::string &id) { + mStatic.push_back(ESM::Script()); + mStatic.back().load(esm); + StringUtils::toLower(mStatic.back().mId); + } + + template <> + class Store : public StoreBase + { + std::vector mStatic; + + public: + Store() { + mStatic.reserve(128); + } + + typedef std::vector::const_iterator iterator; + + const ESM::LandTexture *search(size_t index) const { + if (index < mStatic.size()) { + return &mStatic.at(index); + } + return 0; + } + + const ESM::LandTexture *find(size_t index) const { + const ESM::LandTexture *ptr = search(index); + if (ptr == 0) { + std::ostringstream msg; + msg << "Land texture with index " << index << " not found"; + throw std::runtime_error(msg.str()); + } + return ptr; + } + + int getSize() const { + return mStatic.size(); + } + + void load(ESM::ESMReader &esm, const std::string &id) { + ESM::LandTexture ltex; + ltex.load(esm); + + if (ltex.mIndex >= (int) mStatic.size()) { + mStatic.resize(ltex.mIndex + 1); + } + mStatic[ltex.mIndex] = ltex; + mStatic[ltex.mIndex].mId = id; + } + + iterator begin() const { + return mStatic.begin(); + } + + iterator end() const { + return mStatic.end(); + } + }; + + template <> + class Store : public StoreBase + { + std::vector mStatic; + + struct Compare + { + bool operator()(const ESM::Land *x, const ESM::Land *y) { + if (x->mX == y->mX) { + return x->mY < y->mY; + } + return x->mX < y->mX; + } + }; + + public: + typedef SharedIterator iterator; + + int getSize() const { + return mStatic.size(); + } + + iterator begin() const { + return iterator(mStatic.begin()); + } + + iterator end() const { + return iterator(mStatic.end()); + } + + ESM::Land *search(int x, int y) const { + ESM::Land land; + land.mX = x, land.mY = y; + + std::vector::const_iterator it = + std::lower_bound(mStatic.begin(), mStatic.end(), &land, Compare()); + + if (it != mStatic.end() && (*it)->mX == x && (*it)->mY == y) { + return const_cast(*it); + } + return 0; + } + + ESM::Land *find(int x, int y) const{ + ESM::Land *ptr = search(x, y); + if (ptr == 0) { + std::ostringstream msg; + msg << "Land at (" << x << ", " << y << ") not found"; + throw std::runtime_error(msg.str()); + } + return ptr; + } + + void load(ESM::ESMReader &esm, const std::string &id) { + ESM::Land *ptr = new ESM::Land(); + ptr->load(esm); + + mStatic.push_back(ptr); + } + + void setUp() { + std::sort(mStatic.begin(), mStatic.end(), Compare()); + } + }; + + template <> + class Store : public StoreBase + { + struct ExtCmp + { + bool operator()(const ESM::Cell &x, const ESM::Cell &y) { + if (x.mData.mX == y.mData.mX) { + return x.mData.mY < y.mData.mY; + } + return x.mData.mX < y.mData.mX; + } + }; + + std::vector mInt; + std::vector mExt; + + std::vector mSharedInt; + std::vector mSharedExt; + + typedef std::map DynamicInt; + typedef std::map, ESM::Cell> DynamicExt; + + DynamicInt mDynamicInt; + DynamicExt mDynamicExt; + + + const ESM::Cell *search(const ESM::Cell &cell) const { + if (cell.isExterior()) { + return search(cell.getGridX(), cell.getGridY()); + } + return search(cell.mName); + } + + public: + typedef SharedIterator iterator; + + Store() + {} + + const ESM::Cell *search(const std::string &id) const { + ESM::Cell cell; + cell.mName = StringUtils::lowerCase(id); + + std::vector::const_iterator it = + std::lower_bound(mInt.begin(), mInt.end(), cell, RecordCmp()); + + if (it != mInt.end() && StringUtils::ciEqual(it->mName, id)) { + return &(*it); + } + + DynamicInt::const_iterator dit = mDynamicInt.find(cell.mName); + if (dit != mDynamicInt.end()) { + return &dit->second; + } + + return 0; + } + + const ESM::Cell *search(int x, int y) const { + ESM::Cell cell; + cell.mData.mX = x, cell.mData.mY = y; + + std::vector::const_iterator it = + std::lower_bound(mExt.begin(), mExt.end(), cell, ExtCmp()); + + if (it != mExt.end() && it->mData.mX == x && it->mData.mY == y) { + return &(*it); + } + + std::pair key(x, y); + DynamicExt::const_iterator dit = mDynamicExt.find(key); + if (dit != mDynamicExt.end()) { + return &dit->second; + } + + return 0; + } + + const ESM::Cell *find(const std::string &id) const { + const ESM::Cell *ptr = search(id); + if (ptr == 0) { + std::ostringstream msg; + msg << "Interior cell '" << id << "' not found"; + throw std::runtime_error(msg.str()); + } + return ptr; + } + + const ESM::Cell *find(int x, int y) const { + const ESM::Cell *ptr = search(x, y); + if (ptr == 0) { + std::ostringstream msg; + msg << "Exterior at (" << x << ", " << y << ") not found"; + throw std::runtime_error(msg.str()); + } + return ptr; + } + + void setUp() { + typedef std::vector::iterator Iterator; + + std::sort(mInt.begin(), mInt.end(), RecordCmp()); + mSharedInt.reserve(mInt.size()); + for (Iterator it = mInt.begin(); it != mInt.end(); ++it) { + mSharedInt.push_back(&(*it)); + } + + std::sort(mExt.begin(), mExt.end(), ExtCmp()); + mSharedExt.reserve(mExt.size()); + for (Iterator it = mExt.begin(); it != mExt.end(); ++it) { + mSharedExt.push_back(&(*it)); + } + } + + void load(ESM::ESMReader &esm, const std::string &id) { + ESM::Cell cell; + cell.mName = id; + cell.load(esm); + + if (cell.isExterior()) { + mExt.push_back(cell); + } else { + mInt.push_back(cell); + } + } + + iterator intBegin() const { + return iterator(mSharedInt.begin()); + } + + iterator intEnd() const { + return iterator(mSharedInt.end()); + } + + iterator extBegin() const { + return iterator(mSharedExt.begin()); + } + + iterator extEnd() const { + return iterator(mSharedExt.end()); + } + + /// \todo implement appropriate index + const ESM::Cell *searchExtByName(const std::string &id) const { + std::vector::const_iterator it = mSharedExt.begin(); + for (; it != mSharedExt.end(); ++it) { + if (StringUtils::ciEqual((*it)->mName, id)) { + return *it; + } + } + return 0; + } + + /// \todo implement appropriate index + const ESM::Cell *searchExtByRegion(const std::string &id) const { + std::vector::const_iterator it = mSharedExt.begin(); + for (; it != mSharedExt.end(); ++it) { + if (StringUtils::ciEqual((*it)->mRegion, id)) { + return *it; + } + } + return 0; + } + + int getSize() const { + return mSharedInt.size() + mSharedExt.size(); + } + + void listIdentifier(std::vector &list) const { + list.reserve(list.size() + mSharedInt.size()); + + std::vector::const_iterator it = mSharedInt.begin(); + for (; it != mSharedInt.end(); ++it) { + list.push_back((*it)->mName); + } + } + + ESM::Cell *insert(const ESM::Cell &cell) { + if (search(cell) != 0) { + std::ostringstream msg; + msg << "Failed to create "; + msg << ((cell.isExterior()) ? "exterior" : "interior"); + msg << " cell"; + + throw std::runtime_error(msg.str()); + } + ESM::Cell *ptr; + if (cell.isExterior()) { + std::pair key(cell.getGridX(), cell.getGridY()); + + // duplicate insertions are avoided by search(ESM::Cell &) + std::pair result = + mDynamicExt.insert(std::make_pair(key, cell)); + + ptr = &result.first->second; + mSharedExt.push_back(ptr); + } else { + std::string key = StringUtils::lowerCase(cell.mName); + + // duplicate insertions are avoided by search(ESM::Cell &) + std::pair result = + mDynamicInt.insert(std::make_pair(key, cell)); + + ptr = &result.first->second; + mSharedInt.push_back(ptr); + } + return ptr; + } + + bool erase(const ESM::Cell &cell) { + if (cell.isExterior()) { + return erase(cell.getGridX(), cell.getGridY()); + } + return erase(cell.mName); + } + + bool erase(const std::string &id) { + std::string key = StringUtils::lowerCase(id); + DynamicInt::iterator it = mDynamicInt.find(key); + + if (it == mDynamicInt.end()) { + return false; + } + mDynamicInt.erase(it); + mSharedInt.erase( + mSharedInt.begin() + mSharedInt.size(), + mSharedInt.end() + ); + + for (it = mDynamicInt.begin(); it != mDynamicInt.end(); ++it) { + mSharedInt.push_back(&it->second); + } + + return true; + } + + bool erase(int x, int y) { + std::pair key(x, y); + DynamicExt::iterator it = mDynamicExt.find(key); + + if (it == mDynamicExt.end()) { + return false; + } + mDynamicExt.erase(it); + mSharedExt.erase( + mSharedExt.begin() + mSharedExt.size(), + mSharedExt.end() + ); + + for (it = mDynamicExt.begin(); it != mDynamicExt.end(); ++it) { + mSharedExt.push_back(&it->second); + } + + return true; + } + }; + + template <> + class Store : public StoreBase + { + public: + typedef std::vector::const_iterator iterator; + + private: + std::vector mStatic; + + std::vector::iterator mIntBegin, mIntEnd, mExtBegin, mExtEnd; + + struct IntExtOrdering + { + bool operator()(const ESM::Pathgrid &x, const ESM::Pathgrid &y) const { + // interior pathgrids precedes exterior ones (x < y) + if ((x.mData.mX == 0 && x.mData.mY == 0) && + (y.mData.mX != 0 || y.mData.mY != 0)) + { + return true; + } + return false; + } + }; + + struct ExtCompare + { + bool operator()(const ESM::Pathgrid &x, const ESM::Pathgrid &y) const { + if (x.mData.mX == y.mData.mX) { + return x.mData.mY < y.mData.mY; + } + return x.mData.mX < y.mData.mX; + } + }; + + public: + + void load(ESM::ESMReader &esm, const std::string &id) { + mStatic.push_back(ESM::Pathgrid()); + mStatic.back().load(esm); + } + + int getSize() const { + return mStatic.size(); + } + + void setUp() { + IntExtOrdering cmp; + std::sort(mStatic.begin(), mStatic.end(), cmp); + + ESM::Pathgrid pg; + pg.mData.mX = pg.mData.mY = 1; + mExtBegin = + std::lower_bound(mStatic.begin(), mStatic.end(), pg, cmp); + mExtEnd = mStatic.end(); + + mIntBegin = mStatic.begin(); + mIntEnd = mExtBegin; + + std::sort(mIntBegin, mIntEnd, RecordCmp()); + std::sort(mExtBegin, mExtEnd, ExtCompare()); + } + + const ESM::Pathgrid *search(int x, int y) const { + ESM::Pathgrid pg; + pg.mData.mX = x; + pg.mData.mY = y; + + iterator it = + std::lower_bound(mExtBegin, mExtEnd, pg, ExtCompare()); + if (it != mExtEnd && it->mData.mX == x && it->mData.mY == y) { + return &(*it); + } + return 0; + } + + const ESM::Pathgrid *find(int x, int y) const { + const ESM::Pathgrid *ptr = search(x, y); + if (ptr == 0) { + std::ostringstream msg; + msg << "Pathgrid at (" << x << ", " << y << ") not found"; + throw std::runtime_error(msg.str()); + } + return ptr; + } + + const ESM::Pathgrid *search(const std::string &name) const { + ESM::Pathgrid pg; + pg.mCell = name; + + iterator it = std::lower_bound(mIntBegin, mIntEnd, pg, RecordCmp()); + if (it != mIntEnd && StringUtils::ciEqual(it->mCell, name)) { + return &(*it); + } + return 0; + } + + const ESM::Pathgrid *find(const std::string &name) const { + const ESM::Pathgrid *ptr = search(name); + if (ptr == 0) { + std::ostringstream msg; + msg << "Pathgrid in cell '" << name << "' not found"; + throw std::runtime_error(msg.str()); + } + return ptr; + } + + const ESM::Pathgrid *search(const ESM::Cell &cell) const { + if (cell.mData.mFlags & ESM::Cell::Interior) { + return search(cell.mName); + } + return search(cell.mData.mX, cell.mData.mY); + } + + const ESM::Pathgrid *find(const ESM::Cell &cell) const { + if (cell.mData.mFlags & ESM::Cell::Interior) { + return find(cell.mName); + } + return find(cell.mData.mX, cell.mData.mY); + } + + iterator begin() const { + return mStatic.begin(); + } + + iterator end() const { + return mStatic.end(); + } + + iterator interiorPathsBegin() const { + return mIntBegin; + } + + iterator interiorPathsEnd() const { + return mIntEnd; + } + + iterator exteriorPathsBegin() const { + return mExtBegin; + } + + iterator exteriorPathsEnd() const { + return mExtEnd; + } + }; + + template + class IndexedStore + { + struct Compare + { + bool operator()(const T &x, const T &y) const { + return x.mIndex < y.mIndex; + } + }; + protected: + std::vector mStatic; + + public: + typedef typename std::vector::const_iterator iterator; + + IndexedStore() {} + + IndexedStore(unsigned int size) { + mStatic.reserve(size); + } + + iterator begin() const { + return mStatic.begin(); + } + + iterator end() const { + return mStatic.end(); + } + + /// \todo refine loading order + void load(ESM::ESMReader &esm) { + mStatic.push_back(T()); + mStatic.back().load(esm); + } + + int getSize() const { + return mStatic.size(); + } + + void setUp() { + std::sort(mStatic.begin(), mStatic.end(), Compare()); + } + + const T *search(int index) const { + T item; + item.mIndex = index; + + iterator it = + std::lower_bound(mStatic.begin(), mStatic.end(), item, Compare()); + if (it != mStatic.end() && it->mIndex == index) { + return &(*it); + } + return 0; + } + + const T *find(int index) const { + const T *ptr = search(index); + if (ptr == 0) { + std::ostringstream msg; + msg << "Object with index " << index << " not found"; + throw std::runtime_error(msg.str()); + } + return ptr; + } + }; + + template <> + struct Store : public IndexedStore + { + Store() {} + Store(unsigned int size) + : IndexedStore(size) + {} + }; + + template <> + struct Store : public IndexedStore + { + Store() {} + Store(unsigned int size) + : IndexedStore(size) + {} + }; + + template <> + class Store : public IndexedStore + { + std::vector mStatic; + + public: + typedef std::vector::const_iterator iterator; + + Store() { + mStatic.reserve(ESM::Attribute::Length); + } + + const ESM::Attribute *search(size_t index) const { + if (index >= mStatic.size()) { + return 0; + } + return &mStatic.at(index); + } + + const ESM::Attribute *find(size_t index) const { + const ESM::Attribute *ptr = search(index); + if (ptr == 0) { + std::ostringstream msg; + msg << "Attribute with index " << index << " not found"; + throw std::runtime_error(msg.str()); + } + return ptr; + } + + void setUp() { + for (int i = 0; i < ESM::Attribute::Length; ++i) { + mStatic.push_back( + ESM::Attribute( + ESM::Attribute::sAttributeIds[i], + ESM::Attribute::sGmstAttributeIds[i], + ESM::Attribute::sGmstAttributeDescIds[i] + ) + ); + } + } + + int getSize() const { + return mStatic.size(); + } + + iterator begin() const { + return mStatic.begin(); + } + + iterator end() const { + return mStatic.end(); + } + }; + +} //end namespace + +#endif diff --git a/apps/openmw/mwworld/weather.cpp b/apps/openmw/mwworld/weather.cpp index 391b34a840..009b325c06 100644 --- a/apps/openmw/mwworld/weather.cpp +++ b/apps/openmw/mwworld/weather.cpp @@ -5,8 +5,6 @@ #include -#include - #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" #include "../mwbase/soundmanager.hpp" @@ -14,6 +12,7 @@ #include "../mwrender/renderingmanager.hpp" #include "player.hpp" +#include "esmstore.hpp" using namespace Ogre; using namespace MWWorld; @@ -497,7 +496,7 @@ void WeatherManager::update(float duration) if (exterior) { - std::string regionstr = MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getCell()->cell->mRegion; + std::string regionstr = MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getCell()->mCell->mRegion; boost::algorithm::to_lower(regionstr); if (mWeatherUpdateTime <= 0 || regionstr != mCurrentRegion) @@ -512,7 +511,8 @@ void WeatherManager::update(float duration) else { // get weather probabilities for the current region - const ESM::Region *region = MWBase::Environment::get().getWorld()->getStore().regions.search (regionstr); + const ESM::Region *region = + MWBase::Environment::get().getWorld()->getStore().get().search (regionstr); if (region != 0) { diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index e999100f0e..9f2d419f16 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -19,34 +19,37 @@ using namespace Ogre; namespace { +/* // NOTE this code is never instantiated (proper copy in localscripts.cpp), + // so this commented out to not produce syntactic errors + template - void listCellScripts (const ESMS::ESMStore& store, + void listCellScripts (const MWWorld::ESMStore& store, MWWorld::CellRefList& cellRefList, MWWorld::LocalScripts& localScripts, MWWorld::Ptr::CellStore *cell) { for (typename MWWorld::CellRefList::List::iterator iter ( - cellRefList.list.begin()); - iter!=cellRefList.list.end(); ++iter) + cellRefList.mList.begin()); + iter!=cellRefList.mList.end(); ++iter) { - if (!iter->second->base->script.empty() && iter->second->mData.getCount()) + if (!iter->second.mBase->mScript.empty() && iter->second.mData.getCount()) { - if (const ESM::Script *script = store.scripts.find (iter->second->base->script)) + if (const ESM::Script *script = store.get().find (iter->second.mBase->mScript)) { iter->mData.setLocals (*script); - localScripts.add (iter->base->script, MWWorld::Ptr (&iter->second, cell)); + localScripts.add (iter->second.mBase->mScript, MWWorld::Ptr (&iter->second, cell)); } } } } - +*/ template MWWorld::LiveCellRef *searchViaHandle (const std::string& handle, MWWorld::CellRefList& refList) { typedef typename MWWorld::CellRefList::List::iterator iterator; - for (iterator iter (refList.list.begin()); iter!=refList.list.end(); ++iter) + for (iterator iter (refList.mList.begin()); iter!=refList.mList.end(); ++iter) { if (iter->second.mData.getCount() > 0 && iter->second.mData.getBaseNode()){ if (iter->second.mData.getHandle()==handle) @@ -64,44 +67,44 @@ namespace MWWorld Ptr World::getPtrViaHandle (const std::string& handle, Ptr::CellStore& cell) { if (MWWorld::LiveCellRef *ref = - searchViaHandle (handle, cell.activators)) + searchViaHandle (handle, cell.mActivators)) return Ptr (ref, &cell); - if (MWWorld::LiveCellRef *ref = searchViaHandle (handle, cell.potions)) + if (MWWorld::LiveCellRef *ref = searchViaHandle (handle, cell.mPotions)) return Ptr (ref, &cell); - if (MWWorld::LiveCellRef *ref = searchViaHandle (handle, cell.appas)) + if (MWWorld::LiveCellRef *ref = searchViaHandle (handle, cell.mAppas)) return Ptr (ref, &cell); - if (MWWorld::LiveCellRef *ref = searchViaHandle (handle, cell.armors)) + if (MWWorld::LiveCellRef *ref = searchViaHandle (handle, cell.mArmors)) return Ptr (ref, &cell); - if (MWWorld::LiveCellRef *ref = searchViaHandle (handle, cell.books)) + if (MWWorld::LiveCellRef *ref = searchViaHandle (handle, cell.mBooks)) return Ptr (ref, &cell); - if (MWWorld::LiveCellRef *ref = searchViaHandle (handle, cell.clothes)) + if (MWWorld::LiveCellRef *ref = searchViaHandle (handle, cell.mClothes)) return Ptr (ref, &cell); if (MWWorld::LiveCellRef *ref = - searchViaHandle (handle, cell.containers)) + searchViaHandle (handle, cell.mContainers)) return Ptr (ref, &cell); if (MWWorld::LiveCellRef *ref = - searchViaHandle (handle, cell.creatures)) + searchViaHandle (handle, cell.mCreatures)) return Ptr (ref, &cell); - if (MWWorld::LiveCellRef *ref = searchViaHandle (handle, cell.doors)) + if (MWWorld::LiveCellRef *ref = searchViaHandle (handle, cell.mDoors)) return Ptr (ref, &cell); if (MWWorld::LiveCellRef *ref = - searchViaHandle (handle, cell.ingreds)) + searchViaHandle (handle, cell.mIngreds)) return Ptr (ref, &cell); - if (MWWorld::LiveCellRef *ref = searchViaHandle (handle, cell.lights)) + if (MWWorld::LiveCellRef *ref = searchViaHandle (handle, cell.mLights)) return Ptr (ref, &cell); - if (MWWorld::LiveCellRef *ref = searchViaHandle (handle, cell.lockpicks)) + if (MWWorld::LiveCellRef *ref = searchViaHandle (handle, cell.mLockpicks)) return Ptr (ref, &cell); - if (MWWorld::LiveCellRef *ref = searchViaHandle (handle, cell.miscItems)) + if (MWWorld::LiveCellRef *ref = searchViaHandle (handle, cell.mMiscItems)) return Ptr (ref, &cell); - if (MWWorld::LiveCellRef *ref = searchViaHandle (handle, cell.npcs)) + if (MWWorld::LiveCellRef *ref = searchViaHandle (handle, cell.mNpcs)) return Ptr (ref, &cell); - if (MWWorld::LiveCellRef *ref = searchViaHandle (handle, cell.probes)) + if (MWWorld::LiveCellRef *ref = searchViaHandle (handle, cell.mProbes)) return Ptr (ref, &cell); - if (MWWorld::LiveCellRef *ref = searchViaHandle (handle, cell.repairs)) + if (MWWorld::LiveCellRef *ref = searchViaHandle (handle, cell.mRepairs)) return Ptr (ref, &cell); - if (MWWorld::LiveCellRef *ref = searchViaHandle (handle, cell.statics)) + if (MWWorld::LiveCellRef *ref = searchViaHandle (handle, cell.mStatics)) return Ptr (ref, &cell); - if (MWWorld::LiveCellRef *ref = searchViaHandle (handle, cell.weapons)) + if (MWWorld::LiveCellRef *ref = searchViaHandle (handle, cell.mWeapons)) return Ptr (ref, &cell); return Ptr(); } @@ -168,7 +171,7 @@ namespace MWWorld const boost::filesystem::path& resDir, const boost::filesystem::path& cacheDir, bool newGame, const std::string& encoding, std::map fallbackMap) : mPlayer (0), mLocalScripts (mStore), mGlobalVariables (0), - mSky (true), mNextDynamicRecord (0), mCells (mStore, mEsm), + mSky (true), mCells (mStore, mEsm), mNumFacing(0) { mPhysics = new PhysicsSystem(renderer); @@ -213,7 +216,7 @@ namespace MWWorld mStore.load (mEsm[idx]); } - mPlayer = new MWWorld::Player (mStore.npcs.find ("player"), *this); + mPlayer = new MWWorld::Player (mStore.get().find ("player"), *this); mRendering->attachCameraTo(mPlayer->getPlayer()); mPhysics->addActor(mPlayer->getPlayer()); @@ -249,21 +252,19 @@ namespace MWWorld const ESM::Cell *World::getExterior (const std::string& cellName) const { // first try named cells - if (const ESM::Cell *cell = mStore.cells.searchExtByName (cellName)) + const ESM::Cell *cell = mStore.get().searchExtByName (cellName); + if (cell != 0) { return cell; + } // didn't work -> now check for regions - std::string cellName2 = ESMS::RecListT::toLower (cellName); - - for (ESMS::RecListT::MapType::const_iterator iter (mStore.regions.list.begin()); - iter!=mStore.regions.list.end(); ++iter) + const MWWorld::Store ®ions = mStore.get(); + MWWorld::Store::iterator it = regions.begin(); + for (; it != regions.end(); ++it) { - if (ESMS::RecListT::toLower (iter->second.mName)==cellName2) + if (MWWorld::StringUtils::ciEqual(cellName, it->mName)) { - if (const ESM::Cell *cell = mStore.cells.searchExtByRegion (iter->first)) - return cell; - - break; + return mStore.get().searchExtByRegion(it->mId); } } @@ -285,7 +286,7 @@ namespace MWWorld return *mPlayer; } - const ESMS::ESMStore& World::getStore() const + const MWWorld::ESMStore& World::getStore() const { return mStore; } @@ -559,7 +560,7 @@ namespace MWWorld std::pair result = mPhysics->getFacedHandle (*this); if (result.first.empty() || - result.second>getStore().gameSettings.find ("iMaxActivateDist")->getInt()) + result.second>getStore().get().find ("iMaxActivateDist")->getInt()) return ""; return result.first; @@ -605,15 +606,16 @@ namespace MWWorld CellStore *currCell = ptr.getCell(); bool isPlayer = ptr == mPlayer->getPlayer(); bool haveToMove = mWorldScene->isCellActive(*currCell) || isPlayer; + if (*currCell != newCell) { if (isPlayer) if (!newCell.isExterior()) - changeToInteriorCell(toLower(newCell.cell->mName), pos); + changeToInteriorCell(toLower(newCell.mCell->mName), pos); else { - int cellX = newCell.cell->mData.mX; - int cellY = newCell.cell->mData.mY; + int cellX = newCell.mCell->getGridX(); + int cellY = newCell.mCell->getGridY(); mWorldScene->changeCell(cellX, cellY, pos, false); } else { @@ -804,76 +806,43 @@ namespace MWWorld return mRendering->toggleRenderMode (mode); } - std::pair World::createRecord (const ESM::Potion& record) + const ESM::Potion *World::createRecord (const ESM::Potion& record) { - /// \todo Rewrite the ESMStore so that a dynamic 2nd ESMStore can be attached to it. - /// This function should then insert the record into the 2nd store (the code for this - /// should also be moved to the ESMStore class). It might be a good idea to review - /// the STL-container usage of the ESMStore before the rewrite. - - std::ostringstream stream; - stream << "$dynamic" << mNextDynamicRecord++; - - ESM::Potion record2 (record); - record2.mId = stream.str(); - - const ESM::Potion *created = - &mStore.potions.list.insert (std::make_pair (stream.str(), record2)).first->second; - - mStore.all.insert (std::make_pair (stream.str(), ESM::REC_ALCH)); - - return std::make_pair (stream.str(), created); + return mStore.insert(record); } - std::pair World::createRecord (const ESM::Class& record) + const ESM::Class *World::createRecord (const ESM::Class& record) { - /// \todo See function above. - std::ostringstream stream; - stream << "$dynamic" << mNextDynamicRecord++; - - const ESM::Class *created = - &mStore.classes.list.insert (std::make_pair (stream.str(), record)).first->second; - - mStore.all.insert (std::make_pair (stream.str(), ESM::REC_CLAS)); - - return std::make_pair (stream.str(), created); + return mStore.insert(record); } - std::pair World::createRecord (const ESM::Spell& record) + const ESM::Spell *World::createRecord (const ESM::Spell& record) { - /// \todo See function above. - std::ostringstream stream; - stream << "$dynamic" << mNextDynamicRecord++; - - const ESM::Spell *created = - &mStore.spells.list.insert (std::make_pair (stream.str(), record)).first->second; - - mStore.all.insert (std::make_pair (stream.str(), ESM::REC_SPEL)); - - return std::make_pair (stream.str(), created); + return mStore.insert(record); } const ESM::Cell *World::createRecord (const ESM::Cell& record) { - if (record.mData.mFlags & ESM::Cell::Interior) - { - if (mStore.cells.searchInt (record.mName)) - throw std::runtime_error ("failed creating interior cell"); + return mStore.insert(record); + } - ESM::Cell *cell = new ESM::Cell (record); - mStore.cells.intCells.insert (std::make_pair (record.mName, cell)); - return cell; - } - else - { - if (mStore.cells.searchExt (record.mData.mX, record.mData.mY)) - throw std::runtime_error ("failed creating exterior cell"); + const ESM::NPC *World::createRecord(const ESM::NPC &record) + { + bool update = false; + if (StringUtils::ciEqual(record.mId, "player")) { + const ESM::NPC *player = + mPlayer->getPlayer().get()->mBase; - ESM::Cell *cell = new ESM::Cell (record); - mStore.cells.extCells.insert ( - std::make_pair (std::make_pair (record.mData.mX, record.mData.mY), cell)); - return cell; + update = record.isMale() != player->isMale() || + !StringUtils::ciEqual(record.mRace, player->mRace) || + !StringUtils::ciEqual(record.mHead, player->mHead) || + !StringUtils::ciEqual(record.mHair, player->mHair); } + const ESM::NPC *ret = mStore.insert(record); + if (update) { + mRendering->renderPlayer(mPlayer->getPlayer()); + } + return ret; } void World::playAnimationGroup (const MWWorld::Ptr& ptr, const std::string& groupName, int mode, @@ -1062,10 +1031,7 @@ namespace MWWorld Ptr::CellStore *currentCell = mWorldScene->getCurrentCell(); if (currentCell) { - if (!(currentCell->cell->mData.mFlags & ESM::Cell::Interior)) - return true; - else - return false; + return currentCell->mCell->isExterior(); } return false; } @@ -1075,7 +1041,7 @@ namespace MWWorld Ptr::CellStore *currentCell = mWorldScene->getCurrentCell(); if (currentCell) { - if (!(currentCell->cell->mData.mFlags & ESM::Cell::QuasiEx)) + if (!(currentCell->mCell->mData.mFlags & ESM::Cell::QuasiEx)) return false; else return true; @@ -1100,7 +1066,7 @@ namespace MWWorld Ogre::Vector2 World::getNorthVector (CellStore* cell) { - MWWorld::CellRefList& statics = cell->statics; + MWWorld::CellRefList& statics = cell->mStatics; MWWorld::LiveCellRef* ref = statics.find("northmarker"); if (!ref) return Vector2(0, 1); @@ -1114,34 +1080,33 @@ namespace MWWorld { std::vector result; - MWWorld::CellRefList& doors = cell->doors; - std::map >& refList = doors.list; + MWWorld::CellRefList& doors = cell->mDoors; + std::map< MWWorld::LiveCellRef >& refList = doors.mList; for (std::map >::iterator it = refList.begin(); it != refList.end(); ++it) { MWWorld::LiveCellRef& ref = it->second; - if (ref.ref.mTeleport) + if (ref.mRef.mTeleport) { World::DoorMarker newMarker; std::string dest; - if (ref.ref.mDestCell != "") + if (ref.mRef.mDestCell != "") { // door leads to an interior, use interior name - dest = ref.ref.mDestCell; + dest = ref.mRef.mDestCell; } else { // door leads to exterior, use cell name (if any), otherwise translated region name int x,y; - positionToIndex (ref.ref.mDoorDest.pos[0], ref.ref.mDoorDest.pos[1], x, y); - const ESM::Cell* cell = mStore.cells.findExt(x,y); + positionToIndex (ref.mRef.mDoorDest.pos[0], ref.mRef.mDoorDest.pos[1], x, y); + const ESM::Cell* cell = mStore.get().find(x,y); if (cell->mName != "") dest = cell->mName; else { - const ESM::Region* region = mStore.regions.search(cell->mRegion); - dest = region->mName; + dest = mStore.get().find(cell->mRegion)->mName; } } @@ -1285,7 +1250,7 @@ namespace MWWorld /// \fixme should rely on object height pos.z += 30; - return isUnderwater(*object.getCell()->cell, pos); + return isUnderwater(*object.getCell()->mCell, pos); } bool @@ -1321,10 +1286,10 @@ namespace MWWorld mPhysics->castRay(playerPos, Ogre::Vector3(0,0,-1), 50); bool isOnGround = (hit.first ? (hit.second.distance (playerPos) < 25) : false); - if (!isOnGround || isUnderwater (*currentCell->cell, playerPos)) + if (!isOnGround || isUnderwater (*currentCell->mCell, playerPos)) return 2; - if (currentCell->cell->mData.mFlags & ESM::Cell::NoSleep) + if (currentCell->mCell->mData.mFlags & ESM::Cell::NoSleep) return 1; return 0; diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index ffb2137c7b..f904ea2757 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -1,12 +1,11 @@ #ifndef GAME_MWWORLD_WORLDIMP_H #define GAME_MWWORLD_WORLDIMP_H -#include - #include "../mwrender/debugging.hpp" #include "ptr.hpp" #include "scene.hpp" +#include "esmstore.hpp" #include "physicssystem.hpp" #include "cells.hpp" #include "localscripts.hpp" @@ -56,12 +55,11 @@ namespace MWWorld MWWorld::Scene *mWorldScene; MWWorld::Player *mPlayer; std::vector mEsm; - ESMS::ESMStore mStore; + MWWorld::ESMStore mStore; LocalScripts mLocalScripts; MWWorld::Globals *mGlobalVariables; MWWorld::PhysicsSystem *mPhysics; bool mSky; - int mNextDynamicRecord; Cells mCells; @@ -125,7 +123,7 @@ namespace MWWorld virtual Player& getPlayer(); - virtual const ESMS::ESMStore& getStore() const; + virtual const MWWorld::ESMStore& getStore() const; virtual std::vector& getEsmReader(); @@ -253,21 +251,26 @@ namespace MWWorld ///< Toggle a render mode. ///< \return Resulting mode - virtual std::pair createRecord (const ESM::Potion& record); + virtual const ESM::Potion *createRecord (const ESM::Potion& record); ///< Create a new recrod (of type potion) in the ESM store. - /// \return ID, pointer to created record + /// \return pointer to created record - virtual std::pair createRecord (const ESM::Spell& record); + virtual const ESM::Spell *createRecord (const ESM::Spell& record); ///< Create a new recrod (of type spell) in the ESM store. - /// \return ID, pointer to created record + /// \return pointer to created record - virtual std::pair createRecord (const ESM::Class& record); + virtual const ESM::Class *createRecord (const ESM::Class& record); ///< Create a new recrod (of type class) in the ESM store. - /// \return ID, pointer to created record + /// \return pointer to created record virtual const ESM::Cell *createRecord (const ESM::Cell& record); ///< Create a new recrod (of type cell) in the ESM store. - /// \return ID, pointer to created record + /// \return pointer to created record + + virtual const ESM::NPC *createRecord(const ESM::NPC &record); + ///< Create a new recrod (of type npc) in the ESM store. + /// \return pointer to created record + virtual void playAnimationGroup (const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number = 1); diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index c714693c3a..29d6f46cdb 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -34,10 +34,6 @@ add_component_dir (file_finder file_finder filename_less search ) -add_component_dir (esm_store - reclists store - ) - add_component_dir (esm attr defs esmcommon esmreader esmwriter loadacti loadalch loadappa loadarmo loadbody loadbook loadbsgn loadcell loadclas loadclot loadcont loadcrea loadcrec loaddial loaddoor loadench loadfact loadglob loadgmst diff --git a/components/esm/loadacti.hpp b/components/esm/loadacti.hpp index 86c2f44c4d..8cb335feb2 100644 --- a/components/esm/loadacti.hpp +++ b/components/esm/loadacti.hpp @@ -11,7 +11,7 @@ class ESMWriter; struct Activator { - std::string mName, mScript, mModel; + std::string mId, mName, mScript, mModel; void load(ESMReader &esm); void save(ESMWriter &esm); diff --git a/components/esm/loadappa.hpp b/components/esm/loadappa.hpp index 101c39f414..486a559f89 100644 --- a/components/esm/loadappa.hpp +++ b/components/esm/loadappa.hpp @@ -32,7 +32,7 @@ struct Apparatus }; AADTstruct mData; - std::string mModel, mIcon, mScript, mName; + std::string mId, mModel, mIcon, mScript, mName; void load(ESMReader &esm); void save(ESMWriter &esm); diff --git a/components/esm/loadarmo.hpp b/components/esm/loadarmo.hpp index 57c9ccf125..a94ae67353 100644 --- a/components/esm/loadarmo.hpp +++ b/components/esm/loadarmo.hpp @@ -84,7 +84,7 @@ struct Armor AODTstruct mData; PartReferenceList mParts; - std::string mName, mModel, mIcon, mScript, mEnchant; + std::string mId, mName, mModel, mIcon, mScript, mEnchant; void load(ESMReader &esm); void save(ESMWriter &esm); diff --git a/components/esm/loadbody.hpp b/components/esm/loadbody.hpp index 8a05d9924d..c91bb40bf2 100644 --- a/components/esm/loadbody.hpp +++ b/components/esm/loadbody.hpp @@ -52,7 +52,7 @@ struct BodyPart }; BYDTstruct mData; - std::string mModel, mName; + std::string mId, mModel, mName; void load(ESMReader &esm); void save(ESMWriter &esm); diff --git a/components/esm/loadbsgn.hpp b/components/esm/loadbsgn.hpp index ac4050878f..b0bc28be48 100644 --- a/components/esm/loadbsgn.hpp +++ b/components/esm/loadbsgn.hpp @@ -13,7 +13,7 @@ class ESMWriter; struct BirthSign { - std::string mName, mDescription, mTexture; + std::string mId, mName, mDescription, mTexture; // List of powers and abilities that come with this birth sign. SpellList mPowers; diff --git a/components/esm/loadclas.hpp b/components/esm/loadclas.hpp index 0311002b86..264e342e63 100644 --- a/components/esm/loadclas.hpp +++ b/components/esm/loadclas.hpp @@ -60,7 +60,7 @@ struct Class int mCalc; }; // 60 bytes - std::string mName, mDescription; + std::string mId, mName, mDescription; CLDTstruct mData; void load(ESMReader &esm); diff --git a/components/esm/loadclot.hpp b/components/esm/loadclot.hpp index df64c87d32..623983ccfa 100644 --- a/components/esm/loadclot.hpp +++ b/components/esm/loadclot.hpp @@ -42,7 +42,7 @@ struct Clothing PartReferenceList mParts; - std::string mName, mModel, mIcon, mEnchant, mScript; + std::string mId, mName, mModel, mIcon, mEnchant, mScript; void load(ESMReader &esm); void save(ESMWriter &esm); diff --git a/components/esm/loadcont.hpp b/components/esm/loadcont.hpp index eb1f64d6f2..b66ca086d9 100644 --- a/components/esm/loadcont.hpp +++ b/components/esm/loadcont.hpp @@ -39,7 +39,7 @@ struct Container Unknown = 8 }; - std::string mName, mModel, mScript; + std::string mId, mName, mModel, mScript; float mWeight; // Not sure, might be max total weight allowed? int mFlags; diff --git a/components/esm/loadcrec.hpp b/components/esm/loadcrec.hpp index a95656f63f..6904df15a4 100644 --- a/components/esm/loadcrec.hpp +++ b/components/esm/loadcrec.hpp @@ -1,6 +1,8 @@ #ifndef OPENMW_ESM_CREC_H #define OPENMW_ESM_CREC_H +#include + // TODO create implementation files and remove this one #include "esmreader.hpp" @@ -15,6 +17,8 @@ class ESMWriter; /// Changes a creature struct LoadCREC { + std::string mId; + void load(ESMReader &esm) { esm.skipRecord(); @@ -28,6 +32,8 @@ struct LoadCREC /// Changes an item list / container struct LoadCNTC { + std::string mId; + void load(ESMReader &esm) { esm.skipRecord(); diff --git a/components/esm/loaddoor.hpp b/components/esm/loaddoor.hpp index 5c0af52e42..e992a592f6 100644 --- a/components/esm/loaddoor.hpp +++ b/components/esm/loaddoor.hpp @@ -11,7 +11,7 @@ class ESMWriter; struct Door { - std::string mName, mModel, mScript, mOpenSound, mCloseSound; + std::string mId, mName, mModel, mScript, mOpenSound, mCloseSound; void load(ESMReader &esm); void save(ESMWriter &esm); diff --git a/components/esm/loadench.hpp b/components/esm/loadench.hpp index d895493227..999f93ad97 100644 --- a/components/esm/loadench.hpp +++ b/components/esm/loadench.hpp @@ -1,6 +1,8 @@ #ifndef OPENMW_ESM_ENCH_H #define OPENMW_ESM_ENCH_H +#include + #include "effectlist.hpp" namespace ESM @@ -32,6 +34,7 @@ struct Enchantment // calculate }; + std::string mId; ENDTstruct mData; EffectList mEffects; diff --git a/components/esm/loadglob.hpp b/components/esm/loadglob.hpp index b85af74bce..302729d2e6 100644 --- a/components/esm/loadglob.hpp +++ b/components/esm/loadglob.hpp @@ -1,6 +1,8 @@ #ifndef OPENMW_ESM_GLOB_H #define OPENMW_ESM_GLOB_H +#include + #include "defs.hpp" namespace ESM @@ -15,6 +17,7 @@ class ESMWriter; struct Global { + std::string mId; unsigned mValue; VarType mType; diff --git a/components/esm/loadgmst.cpp b/components/esm/loadgmst.cpp index dcc5001254..14e29f4ae8 100644 --- a/components/esm/loadgmst.cpp +++ b/components/esm/loadgmst.cpp @@ -2,6 +2,8 @@ #include +#include + #include "esmreader.hpp" #include "esmwriter.hpp" @@ -12,9 +14,9 @@ namespace ESM /// working properly in its current state and I doubt it can be fixed without breaking other stuff. // Some handy macros -#define cI(s,x) { if(mId == (s)) return (mI == (x)); } -#define cF(s,x) { if(mId == (s)) return (mF == (x)); } -#define cS(s,x) { if(mId == (s)) return (mStr == (x)); } +#define cI(s,x) { label = (s); boost::algorithm::to_lower(label); if (mId == label) return (mI == (x)); } +#define cF(s,x) { label = (s); boost::algorithm::to_lower(label); if (mId == label) return (mF == (x)); } +#define cS(s,x) { label = (s); boost::algorithm::to_lower(label); if (mId == label) return (mStr == (x)); } bool GameSetting::isDirtyTribunal() { @@ -28,6 +30,7 @@ bool GameSetting::isDirtyTribunal() from other mods. */ + std::string label; // Strings cS("sProfitValue", "Profit Value"); // 'Profit:' cS("sEditNote", "Edit Note"); // same @@ -51,13 +54,14 @@ bool GameSetting::isDirtyTribunal() // [The difference here is "Profit Value" -> "Profit"] // Strings that matches the mId - cS("sEffectSummonFabricant", mId);// 'Summon Fabricant' + cS("sEffectSummonFabricant", "sEffectSummonFabricant");// 'Summon Fabricant' return false; } // Bloodmoon variant bool GameSetting::isDirtyBloodmoon() { + std::string label; // Strings cS("sWerewolfPopup", "Werewolf"); // same cS("sWerewolfRestMessage", @@ -69,16 +73,16 @@ bool GameSetting::isDirtyBloodmoon() // 'You have been detected as a known werewolf.' // Strings that matches the mId - cS("sMagicCreature01ID", mId); // 'BM_wolf_grey_summon' - cS("sMagicCreature02ID", mId); // 'BM_bear_black_summon' - cS("sMagicCreature03ID", mId); // 'BM_wolf_bone_summon' - cS("sMagicCreature04ID", mId); // same - cS("sMagicCreature05ID", mId); // same - cS("sEffectSummonCreature01", mId); // 'Calf Wolf' - cS("sEffectSummonCreature02", mId); // 'Calf Bear' - cS("sEffectSummonCreature03", mId); // 'Summon Bonewolf' - cS("sEffectSummonCreature04", mId); // same - cS("sEffectSummonCreature05", mId); // same + cS("sMagicCreature01ID", "sMagicCreature01ID"); // 'BM_wolf_grey_summon' + cS("sMagicCreature02ID", "sMagicCreature02ID"); // 'BM_bear_black_summon' + cS("sMagicCreature03ID", "sMagicCreature03ID"); // 'BM_wolf_bone_summon' + cS("sMagicCreature04ID", "sMagicCreature04ID"); // same + cS("sMagicCreature05ID", "sMagicCreature05ID"); // same + cS("sEffectSummonCreature01", "sEffectSummonCreature01"); // 'Calf Wolf' + cS("sEffectSummonCreature02", "sEffectSummonCreature02"); // 'Calf Bear' + cS("sEffectSummonCreature03", "sEffectSummonCreature03"); // 'Summon Bonewolf' + cS("sEffectSummonCreature04", "sEffectSummonCreature04"); // same + cS("sEffectSummonCreature05", "sEffectSummonCreature05"); // same // Integers cI("iWereWolfBounty", 10000); // 1000 diff --git a/components/esm/loadinfo.hpp b/components/esm/loadinfo.hpp index f04fe862e2..f1decb9c63 100644 --- a/components/esm/loadinfo.hpp +++ b/components/esm/loadinfo.hpp @@ -32,10 +32,10 @@ struct DialInfo { int mUnknown1; int mDisposition; - char mRank; // Rank of NPC - char mGender; // See Gender enum - char mPCrank; // Player rank - char mUnknown2; + signed char mRank; // Rank of NPC + signed char mGender; // See Gender enum + signed char mPCrank; // Player rank + signed char mUnknown2; }; // 12 bytes DATAstruct mData; diff --git a/components/esm/loadlevlist.hpp b/components/esm/loadlevlist.hpp index 72b4af92f0..b7db5db360 100644 --- a/components/esm/loadlevlist.hpp +++ b/components/esm/loadlevlist.hpp @@ -33,6 +33,7 @@ struct LeveledListBase // list.) int mFlags; unsigned char mChanceNone; // Chance that none are selected (0-255?) + std::string mId; // Record name used to read references. Must be set before load() is // called. diff --git a/components/esm/loadligh.hpp b/components/esm/loadligh.hpp index c425af6b3b..b3d703cc26 100644 --- a/components/esm/loadligh.hpp +++ b/components/esm/loadligh.hpp @@ -41,7 +41,7 @@ struct Light LHDTstruct mData; - std::string mSound, mScript, mModel, mIcon, mName; + std::string mSound, mScript, mModel, mIcon, mName, mId; void load(ESMReader &esm); void save(ESMWriter &esm); diff --git a/components/esm/loadlocks.hpp b/components/esm/loadlocks.hpp index 72d375cbb7..8e88c548e7 100644 --- a/components/esm/loadlocks.hpp +++ b/components/esm/loadlocks.hpp @@ -36,7 +36,7 @@ struct Tool Data mData; Type mType; - std::string mName, mModel, mIcon, mScript; + std::string mId, mName, mModel, mIcon, mScript; void load(ESMReader &esm); void save(ESMWriter &esm); diff --git a/components/esm/loadmgef.cpp b/components/esm/loadmgef.cpp index d0230e3b6a..4aef97838a 100644 --- a/components/esm/loadmgef.cpp +++ b/components/esm/loadmgef.cpp @@ -1,5 +1,7 @@ #include "loadmgef.hpp" +#include + #include #include "esmreader.hpp" diff --git a/components/esm/loadmisc.hpp b/components/esm/loadmisc.hpp index 1a34e65041..26d25139cb 100644 --- a/components/esm/loadmisc.hpp +++ b/components/esm/loadmisc.hpp @@ -26,7 +26,7 @@ struct Miscellaneous }; MCDTstruct mData; - std::string mName, mModel, mIcon, mScript; + std::string mId, mName, mModel, mIcon, mScript; void load(ESMReader &esm); void save(ESMWriter &esm); diff --git a/components/esm/loadnpc.hpp b/components/esm/loadnpc.hpp index ee9ef6b0bc..46be29961d 100644 --- a/components/esm/loadnpc.hpp +++ b/components/esm/loadnpc.hpp @@ -117,6 +117,17 @@ struct NPC // Implementation moved to load_impl.cpp void load(ESMReader &esm); void save(ESMWriter &esm); + + bool isMale() const { + return (mFlags & Female) == 0; + } + + void setIsMale(bool value) { + mFlags |= Female; + if (value) { + mFlags ^= Female; + } + } }; } #endif diff --git a/components/esm/loadnpcc.hpp b/components/esm/loadnpcc.hpp index 3da14655f8..79d92397f8 100644 --- a/components/esm/loadnpcc.hpp +++ b/components/esm/loadnpcc.hpp @@ -1,6 +1,8 @@ #ifndef OPENMW_ESM_NPCC_H #define OPENMW_ESM_NPCC_H +#include + // TODO: create implementation files to remove this #include "esmreader.hpp" @@ -76,6 +78,8 @@ class ESMWriter; struct LoadNPCC { + std::string mId; + void load(ESMReader &esm) { esm.skipRecord(); diff --git a/components/esm/loadrace.hpp b/components/esm/loadrace.hpp index 42b2c91a72..91a424c10b 100644 --- a/components/esm/loadrace.hpp +++ b/components/esm/loadrace.hpp @@ -64,7 +64,7 @@ struct Race RADTstruct mData; - std::string mName, mDescription; + std::string mId, mName, mDescription; SpellList mPowers; void load(ESMReader &esm); diff --git a/components/esm/loadregn.hpp b/components/esm/loadregn.hpp index fd0863b5bb..0496ef5af2 100644 --- a/components/esm/loadregn.hpp +++ b/components/esm/loadregn.hpp @@ -42,7 +42,7 @@ struct Region // sleepList refers to a eveled list of creatures you can meet if // you sleep outside in this region. - std::string mName, mSleepList; + std::string mId, mName, mSleepList; std::vector mSoundList; diff --git a/components/esm/loadscpt.cpp b/components/esm/loadscpt.cpp index dc28166d44..d9b6497d98 100644 --- a/components/esm/loadscpt.cpp +++ b/components/esm/loadscpt.cpp @@ -6,9 +6,18 @@ namespace ESM { +struct SCHD +{ + NAME32 mName; + Script::SCHDstruct mData; +}; + void Script::load(ESMReader &esm) { - esm.getHNT(mData, "SCHD", 52); + SCHD data; + esm.getHNT(data, "SCHD", 52); + mData = data.mData; + mId = data.mName.toString(); // List of local variables if (esm.isNextSub("SCVR")) @@ -48,7 +57,13 @@ void Script::save(ESMWriter &esm) for (std::vector::iterator it = mVarNames.begin(); it != mVarNames.end(); ++it) varNameString.append(*it); - esm.writeHNT("SCHD", mData, 52); + SCHD data; + memset(&data, 0, sizeof(data)); + + data.mData = mData; + memcpy(data.mName.name, mId.c_str(), mId.size()); + + esm.writeHNT("SCHD", data, 52); if (!mVarNames.empty()) { diff --git a/components/esm/loadscpt.hpp b/components/esm/loadscpt.hpp index db8f850572..10a6d24b10 100644 --- a/components/esm/loadscpt.hpp +++ b/components/esm/loadscpt.hpp @@ -42,13 +42,13 @@ public: approach though. */ - NAME32 mName; - // These describe the sizes we need to allocate for the script // data. int mNumShorts, mNumLongs, mNumFloats, mScriptDataSize, mStringTableSize; }; // 52 bytes + std::string mId; + SCHDstruct mData; std::vector mVarNames; // Variable names diff --git a/components/esm/loadsndg.hpp b/components/esm/loadsndg.hpp index dadfbd2393..a6226c1545 100644 --- a/components/esm/loadsndg.hpp +++ b/components/esm/loadsndg.hpp @@ -30,7 +30,7 @@ struct SoundGenerator // Type int mType; - std::string mCreature, mSound; + std::string mId, mCreature, mSound; void load(ESMReader &esm); void save(ESMWriter &esm); diff --git a/components/esm/loadsoun.hpp b/components/esm/loadsoun.hpp index 5443c6cb9d..8f59f690a1 100644 --- a/components/esm/loadsoun.hpp +++ b/components/esm/loadsoun.hpp @@ -17,7 +17,7 @@ struct SOUNstruct struct Sound { SOUNstruct mData; - std::string mSound; + std::string mId, mSound; void load(ESMReader &esm); void save(ESMWriter &esm); diff --git a/components/esm/loadspel.hpp b/components/esm/loadspel.hpp index 5ad1841265..0d5e0be522 100644 --- a/components/esm/loadspel.hpp +++ b/components/esm/loadspel.hpp @@ -38,7 +38,7 @@ struct Spell }; SPDTstruct mData; - std::string mName; + std::string mId, mName; EffectList mEffects; void load(ESMReader &esm); diff --git a/components/esm/loadsscr.hpp b/components/esm/loadsscr.hpp index d180bfcffd..713fe96b52 100644 --- a/components/esm/loadsscr.hpp +++ b/components/esm/loadsscr.hpp @@ -20,7 +20,7 @@ class ESMWriter; struct StartScript { std::string mData; - std::string mScript; + std::string mId, mScript; // Load a record and add it to the list void load(ESMReader &esm); diff --git a/components/esm/loadstat.hpp b/components/esm/loadstat.hpp index ba35fa7183..790a71147c 100644 --- a/components/esm/loadstat.hpp +++ b/components/esm/loadstat.hpp @@ -22,7 +22,7 @@ class ESMWriter; struct Static { - std::string mModel; + std::string mId, mModel; void load(ESMReader &esm); void save(ESMWriter &esm); diff --git a/components/esm/loadweap.hpp b/components/esm/loadweap.hpp index 341a2c86e5..e482d3b109 100644 --- a/components/esm/loadweap.hpp +++ b/components/esm/loadweap.hpp @@ -56,7 +56,7 @@ struct Weapon WPDTstruct mData; - std::string mName, mModel, mIcon, mEnchant, mScript; + std::string mId, mName, mModel, mIcon, mEnchant, mScript; void load(ESMReader &esm); void save(ESMWriter &esm); diff --git a/components/esm_store/store.hpp b/components/esm_store/store.hpp deleted file mode 100644 index 7329386d4a..0000000000 --- a/components/esm_store/store.hpp +++ /dev/null @@ -1,146 +0,0 @@ -#ifndef _GAME_ESM_STORE_H -#define _GAME_ESM_STORE_H - -/* - The ESM storage module. - - This is separate from the ESM loader module, located in esm/. It is - also unaware of the cell loading and storage module. - - The advantage of this, as with all other modularizations, is that - you can replace the storage method later without touching the - loading code. Cutting down dependencies also help on the general - maintainability. - */ - -#include "components/esm/records.hpp" -#include "reclists.hpp" - -namespace ESMS -{ - using namespace ESM; - - struct ESMStore - { - /* Lists all the list types. Mostly used for quick lookup on - loading. The key is the record name (4 chars) parsed as a 32 - bit int. See esm/records.hpp for the complete list. - */ - RecListList recLists; - - // Each individual list - RecListT activators; - RecListWithIDT potions; - RecListT appas; - RecListT armors; - RecListT bodyParts; - RecListWithIDT books; - RecListT birthSigns; - RecListT classes; - RecListT clothes; - RecListT contChange; - RecListT containers; - RecListWithIDT creatures; - RecListT creaChange; - RecListCaseT dialogs; - RecListT doors; - RecListT enchants; - RecListT factions; - RecListT globals; - RecListWithIDT ingreds; - RecListT creatureLists; - RecListT itemLists; - RecListT lights; - RecListT lockpicks; - RecListT miscItems; - RecListWithIDT npcs; - RecListT npcChange; - RecListT probes; - RecListT races; - RecListT regions; - RecListT repairs; - RecListT soundGens; - RecListT sounds; - RecListT spells; - RecListT startScripts; - RecListT statics; - RecListT weapons; - - // Lists that need special rules - CellList cells; - RecIDListT gameSettings; - LandList lands; - LTexList landTexts; - ScriptListT