diff --git a/.gitignore b/.gitignore
index 26ba80e1a..9734ac35c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,3 +14,4 @@ Makefile
 makefile
 data
 *.kdev4
+CMakeLists.txt.user
diff --git a/apps/openmw/mwbase/mechanicsmanager.hpp b/apps/openmw/mwbase/mechanicsmanager.hpp
index 750fc2fff..9f9b5af70 100644
--- a/apps/openmw/mwbase/mechanicsmanager.hpp
+++ b/apps/openmw/mwbase/mechanicsmanager.hpp
@@ -76,6 +76,12 @@ 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.
diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp
index 3a7cb0874..5416945e7 100644
--- a/apps/openmw/mwbase/world.hpp
+++ b/apps/openmw/mwbase/world.hpp
@@ -29,6 +29,7 @@ namespace ESM
     struct Class;
     struct Potion;
     struct Spell;
+    struct NPC;
 }
 
 namespace MWRender
@@ -230,24 +231,28 @@ namespace MWBase
             ///< Toggle a render mode.
             ///< \return Resulting mode
 
-            virtual std::pair<std::string, const ESM::Potion *> 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<std::string, const ESM::Spell *> 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<std::string, const ESM::Class *> 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/npc.cpp b/apps/openmw/mwclass/npc.cpp
index e58de6079..6a516bcc8 100644
--- a/apps/openmw/mwclass/npc.cpp
+++ b/apps/openmw/mwclass/npc.cpp
@@ -95,6 +95,7 @@ namespace MWClass
                 data->mCreatureStats.setFatigue (ref->mBase->mNpdt52.mFatigue);
 
                 data->mCreatureStats.setLevel(ref->mBase->mNpdt52.mLevel);
+                data->mNpcStats.setDisposition(ref->mBase->mNpdt52.mDisposition);
             }
             else
             {
diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp
index e12a22247..15852198f 100644
--- a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp
+++ b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp
@@ -464,7 +464,7 @@ namespace MWDialogue
             || services & ESM::NPC::Misc)
             windowServices |= MWGui::DialogueWindow::Service_Trade;
 
-        if( !mActor.get<ESM::NPC>()->mBase->mTransport.empty())
+        if(mActor.getTypeName() == typeid(ESM::NPC).name() && !mActor.get<ESM::NPC>()->mBase->mTransport.empty())
             windowServices |= MWGui::DialogueWindow::Service_Travel;
 
         if (services & ESM::NPC::Spells)
diff --git a/apps/openmw/mwgui/charactercreation.cpp b/apps/openmw/mwgui/charactercreation.cpp
index 253e0779c..a054f34dd 100644
--- a/apps/openmw/mwgui/charactercreation.cpp
+++ b/apps/openmw/mwgui/charactercreation.cpp
@@ -559,6 +559,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);
diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp
index b8022f629..e1baaf8e0 100644
--- a/apps/openmw/mwgui/dialogue.cpp
+++ b/apps/openmw/mwgui/dialogue.cpp
@@ -12,6 +12,7 @@
 #include "../mwbase/dialoguemanager.hpp"
 #include "../mwbase/world.hpp"
 #include "../mwbase/windowmanager.hpp"
+#include "../mwbase/mechanicsmanager.hpp"
 
 #include "dialogue_history.hpp"
 #include "widgets.hpp"
@@ -50,7 +51,7 @@ std::string::size_type find_str_ci(const std::string& str, const std::string& su
 
 DialogueWindow::DialogueWindow(MWBase::WindowManager& parWindowManager)
     : WindowBase("openmw_dialogue_window.layout", parWindowManager)
-    , mEnabled(true)
+    , mEnabled(false)
     , mServices(0)
 {
     // Centre dialog
@@ -299,10 +300,13 @@ 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<std::string>(MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(mPtr))+std::string("/100")+"#B29154");
+    }
 }
 
 void DialogueWindow::goodbye()
@@ -316,3 +320,14 @@ void DialogueWindow::onReferenceUnavailable()
 {
     mWindowManager.removeGuiMode(GM_Dialogue);
 }
+
+void DialogueWindow::onFrame()
+{
+    if(mEnabled && 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<std::string>(MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(mPtr))+std::string("/100")+"#B29154");
+    }
+}
diff --git a/apps/openmw/mwgui/dialogue.hpp b/apps/openmw/mwgui/dialogue.hpp
index 3a89409ca..bb9acf5db 100644
--- a/apps/openmw/mwgui/dialogue.hpp
+++ b/apps/openmw/mwgui/dialogue.hpp
@@ -47,6 +47,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; }
diff --git a/apps/openmw/mwgui/levelupdialog.cpp b/apps/openmw/mwgui/levelupdialog.cpp
index 399ff74a3..45890b89f 100644
--- a/apps/openmw/mwgui/levelupdialog.cpp
+++ b/apps/openmw/mwgui/levelupdialog.cpp
@@ -108,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);
 
@@ -119,20 +120,13 @@ namespace MWGui
 
         setAttributeValues();
 
-        // set class image
-        const ESM::Class& playerClass = MWBase::Environment::get().getWorld ()->getPlayer ().getClass ();
-        // retrieve the ID to this class
-        std::string classId;
-        const MWWorld::Store<ESM::Class> &classes =
-            MWBase::Environment::get().getWorld()->getStore().get<ESM::Class>();
+        const ESM::NPC *playerData = player.get<ESM::NPC>()->mBase;
 
-        MWWorld::Store<ESM::Class>::iterator it = classes.begin();
-        for (; it != classes.end(); ++it)
-        {
-            if (playerClass.mName == it->mName)
-                classId = it->mId;
-        }
-        mClassImage->setImageTexture ("textures\\levelup\\" + classId + ".dds");
+        // set class image
+        const ESM::Class *cls =
+            world->getStore().get<ESM::Class>().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/spellbuyingwindow.cpp b/apps/openmw/mwgui/spellbuyingwindow.cpp
index 813a21b12..a41f401a5 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"
@@ -52,9 +53,9 @@ namespace MWGui
         const MWWorld::ESMStore &store =
             MWBase::Environment::get().getWorld()->getStore();
 
-        const ESM::Spell* spell = store.get<ESM::Spell>().find(spellId);
-
+        const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().find(spellId);
         int price = spell->mData.mCost*store.get<ESM::GameSetting>().find("fSpellValueMult")->getFloat();
+        price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr,price,true);
 
         MyGUI::Button* toAdd =
             mSpellsView->createWidget<MyGUI::Button>(
@@ -67,7 +68,6 @@ namespace MWGui
             );
 
         mCurrentY += sLineHeight;
-        /// \todo price adjustment depending on merchantile skill
 
         toAdd->setUserData(price);
         toAdd->setCaptionWithReplacing(spell->mName+"   -   "+boost::lexical_cast<std::string>(price)+"#{sgp}");
diff --git a/apps/openmw/mwgui/spellcreationdialog.cpp b/apps/openmw/mwgui/spellcreationdialog.cpp
index 2ece05cb6..69d69519f 100644
--- a/apps/openmw/mwgui/spellcreationdialog.cpp
+++ b/apps/openmw/mwgui/spellcreationdialog.cpp
@@ -7,6 +7,7 @@
 #include "../mwbase/world.hpp"
 #include "../mwbase/environment.hpp"
 #include "../mwbase/soundmanager.hpp"
+#include "../mwbase/mechanicsmanager.hpp"
 
 #include "../mwworld/esmstore.hpp"
 #include "../mwworld/player.hpp"
@@ -336,12 +337,12 @@ namespace MWGui
 
         MWBase::Environment::get().getSoundManager()->playSound ("Item Gold Up", 1.0, 1.0);
 
-        std::pair<std::string, const ESM::Spell*> 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);
 
@@ -399,8 +400,7 @@ namespace MWGui
         float fSpellMakingValueMult =
             store.get<ESM::GameSetting>().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<std::string>(int(price)));
 
diff --git a/apps/openmw/mwgui/stats_window.cpp b/apps/openmw/mwgui/stats_window.cpp
index 9d6842068..4b47bb025 100644
--- a/apps/openmw/mwgui/stats_window.cpp
+++ b/apps/openmw/mwgui/stats_window.cpp
@@ -253,7 +253,10 @@ 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);
 
     if (mChanged)
         updateSkillArea();
@@ -426,11 +429,13 @@ void StatsWindow::updateSkillArea()
     if (!mMiscSkills.empty())
         addSkills(mMiscSkills, "sSkillClassMisc", "Misc Skills", coord1, coord2);
 
-    const MWWorld::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<ESM::NPC>()->mBase;
 
     // race tooltip
-    const ESM::Race* playerRace =
-        store.get<ESM::Race>().find (MWBase::Environment::get().getWorld()->getPlayer().getRace());
+    const ESM::Race* playerRace = store.get<ESM::Race>().find(player->mRace);
 
     MyGUI::Widget* raceWidget;
     getWidget(raceWidget, "RaceText");
@@ -440,11 +445,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<ESM::Class>().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())
     {
diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp
index 6498cd712..0707ad985 100644
--- a/apps/openmw/mwgui/tradewindow.cpp
+++ b/apps/openmw/mwgui/tradewindow.cpp
@@ -6,10 +6,16 @@
 #include "../mwbase/world.hpp"
 #include "../mwbase/soundmanager.hpp"
 #include "../mwbase/windowmanager.hpp"
+#include "../mwbase/mechanicsmanager.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 +58,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 +71,7 @@ namespace MWGui
         setTitle(MWWorld::Class::get(actor).getName(actor));
 
         mCurrentBalance = 0;
+        mCurrentMerchantOffer = 0;
 
         mWindowManager.getInventoryWindow()->startTrade();
 
@@ -135,6 +144,9 @@ namespace MWGui
 
     void TradeWindow::onOfferButtonClicked(MyGUI::Widget* _sender)
     {
+        const MWWorld::Store<ESM::GameSetting> &gmst =
+            MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
+
         // were there any items traded at all?
         MWWorld::ContainerStore& playerBought = mWindowManager.getInventoryWindow()->getBoughtItems();
         MWWorld::ContainerStore& merchantBought = getBoughtItems();
@@ -178,6 +190,56 @@ 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<std::string>());
+                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<int>(0,std::min<int>(int(MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(mPtr)),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<std::string>());
+                /// \todo adjust npc temporary disposition by iBarterSuccessDisposition or iBarterFailDisposition
+                return ;
+            }
+        }
+
+
+/// \todo adjust npc temporary disposition by iBarterSuccessDisposition or iBarterFailDisposition
+
         // success! make the item transfer.
         transferBoughtItems();
         mWindowManager.getInventoryWindow()->transferBoughtItems();
@@ -202,6 +264,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<std::string>(mWindowManager.getInventoryWindow()->getPlayerGold()));
@@ -320,19 +396,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 4ec55045c..db386d8b6 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 1e9841afb..ba39ee601 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"
 
@@ -78,8 +79,8 @@ namespace MWGui
 
         for (int i=0; i<3; ++i)
         {
-            /// \todo mercantile skill
-            int price = pcStats.getSkill (bestSkills[i].first).getBase() * gmst.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";
 
@@ -119,8 +120,8 @@ namespace MWGui
         const MWWorld::ESMStore &store =
             MWBase::Environment::get().getWorld()->getStore();
 
-        /// \todo mercantile skill
         int price = pcStats.getSkill (skillId).getBase() * store.get<ESM::GameSetting>().find("iTrainingMod")->getInt ();
+        price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr,price,true);
 
         if (mWindowManager.getInventoryWindow()->getPlayerGold()<price)
             return;
diff --git a/apps/openmw/mwgui/travelwindow.cpp b/apps/openmw/mwgui/travelwindow.cpp
index 0e7ebaaa3..abbc6172f 100644
--- a/apps/openmw/mwgui/travelwindow.cpp
+++ b/apps/openmw/mwgui/travelwindow.cpp
@@ -69,9 +69,10 @@ namespace MWGui
             price = d/gmst.find("fTravelMult")->getFloat();
         }
 
+        price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr,price,true);
+
         MyGUI::Button* toAdd = mDestinationsView->createWidget<MyGUI::Button>((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
diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp
index 8e4187f7f..963a1fe17 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)
@@ -584,6 +582,8 @@ void WindowManager::onFrame (float frameDuration)
         mDragAndDrop->mDraggedWidget->setPosition(MyGUI::InputManager::getInstance().getMousePosition());
     }
 
+    mDialogueWindow->onFrame();
+
     mInventoryWindow->onFrame();
 
     mStatsWindow->onFrame();
@@ -774,6 +774,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();
diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp
index aa796343e..2e684b5da 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<int, MWMechanics::Stat<int> > mPlayerAttributes;
diff --git a/apps/openmw/mwmechanics/alchemy.cpp b/apps/openmw/mwmechanics/alchemy.cpp
index 5ccdc5750..c07c60209 100644
--- a/apps/openmw/mwmechanics/alchemy.cpp
+++ b/apps/openmw/mwmechanics/alchemy.cpp
@@ -279,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);
diff --git a/apps/openmw/mwmechanics/creaturestats.cpp b/apps/openmw/mwmechanics/creaturestats.cpp
index 95e721c01..e94adf458 100644
--- a/apps/openmw/mwmechanics/creaturestats.cpp
+++ b/apps/openmw/mwmechanics/creaturestats.cpp
@@ -232,4 +232,14 @@ namespace MWMechanics
                 mDead = false;
         }
     }
+    
+    bool CreatureStats::hasCommonDisease() const
+    {
+        return mSpells.hasCommonDisease();
+    }
+
+    bool CreatureStats::hasBlightDisease() const
+    {
+        return mSpells.hasBlightDisease();
+    }
 }
diff --git a/apps/openmw/mwmechanics/creaturestats.hpp b/apps/openmw/mwmechanics/creaturestats.hpp
index 671dcd439..cdeee6853 100644
--- a/apps/openmw/mwmechanics/creaturestats.hpp
+++ b/apps/openmw/mwmechanics/creaturestats.hpp
@@ -109,6 +109,10 @@ namespace MWMechanics
         bool isDead() const;
         
         void resurrect();
+        
+        bool hasCommonDisease() const;
+
+        bool hasBlightDisease() const;         
     };
 }
 
diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp
index 94418c522..3b5a80ef3 100644
--- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp
+++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp
@@ -37,16 +37,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().get<ESM::Race>().find (
-                    MWBase::Environment::get().getWorld()->getPlayer().getRace()
-                );
+                esmStore.get<ESM::Race>().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)
             {
@@ -89,11 +90,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().get<ESM::BirthSign>().find (
-                MWBase::Environment::get().getWorld()->getPlayer().getBirthsign());
+                esmStore.get<ESM::BirthSign>().find(signId);
 
             for (std::vector<std::string>::const_iterator iter (sign->mPowers.mList.begin());
                 iter!=sign->mPowers.mList.end(); ++iter)
@@ -105,11 +108,12 @@ namespace MWMechanics
         // class
         if (mClassSelected)
         {
-            const ESM::Class& class_ = MWBase::Environment::get().getWorld()->getPlayer().getClass();
+            const ESM::Class *class_ =
+                esmStore.get<ESM::Class>().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 (
@@ -123,7 +127,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)
                     {
@@ -134,12 +138,12 @@ namespace MWMechanics
             }
 
             const MWWorld::Store<ESM::Skill> &skills =
-                MWBase::Environment::get().getWorld()->getStore().get<ESM::Skill>();
+                esmStore.get<ESM::Skill>();
 
             MWWorld::Store<ESM::Skill>::iterator iter = skills.begin();
             for (; iter != skills.end(); ++iter)
             {
-                if (iter->mData.mSpecialization==class_.mData.mSpecialization)
+                if (iter->mData.mSpecialization==class_->mData.mSpecialization)
                 {
                     int index = iter->mIndex;
 
@@ -265,13 +269,19 @@ namespace MWMechanics
             // basic player profile; should not change anymore after the creation phase is finished.
             MWBase::WindowManager *winMgr =
                 MWBase::Environment::get().getWindowManager();
-            
-            MWBase::World   *world = MWBase::Environment::get().getWorld();
-            MWWorld::Player &player = world->getPlayer();
+           
+            MWBase::World *world = MWBase::Environment::get().getWorld();
+            const ESM::NPC *player =
+                world->getPlayer().getPlayer().get<ESM::NPC>()->mBase;
 
-            winMgr->setValue ("name", player.getName());
-            winMgr->setValue ("race", world->getStore().get<ESM::Race>().find (player.getRace())->mName);
-            winMgr->setValue ("class", player.getClass().mName);
+            const ESM::Race *race =
+                world->getStore().get<ESM::Race>().find(player->mRace);
+            const ESM::Class *cls =
+                world->getStore().get<ESM::Class>().find(player->mClass);
+
+            winMgr->setValue ("name", player->mName);
+            winMgr->setValue ("race", race->mName);
+            winMgr->setValue ("class", cls->mName);
 
             mUpdatePlayer = false;
 
@@ -280,8 +290,8 @@ namespace MWMechanics
 
             for (int i=0; i<5; ++i)
             {
-                minorSkills[i] = player.getClass().mData.mSkills[i][0];
-                majorSkills[i] = player.getClass().mData.mSkills[i][1];
+                minorSkills[i] = cls->mData.mSkills[i][0];
+                majorSkills[i] = cls->mData.mSkills[i][1];
             }
 
             winMgr->configureSkills (majorSkills, minorSkills);
@@ -297,14 +307,33 @@ 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<ESM::NPC>()->mBase;
+        player.mName = name;
+
+        world->createRecord(player);
+
         mUpdatePlayer = true;
     }
 
     void MechanicsManager::setPlayerRace (const std::string& race, bool male)
     {
-        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<ESM::NPC>()->mBase;
+
+        player.mRace = race;
+
+        player.mFlags |= ESM::NPC::Female;
+        if (male) {
+            player.mFlags ^= ESM::NPC::Female;
+        }
+
+        world->createRecord(player);
+
         mRaceSelected = true;
         buildPlayer();
         mUpdatePlayer = true;
@@ -312,29 +341,148 @@ 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().get<ESM::Class>().find (id)
-        );
+        MWBase::World *world = MWBase::Environment::get().getWorld();
+
+        ESM::NPC player =
+            *world->getPlayer().getPlayer().get<ESM::NPC>()->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<ESM::NPC>()->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.getDisposition();
+
+        MWWorld::LiveCellRef<ESM::NPC>* npc = ptr.get<ESM::NPC>();
+        MWWorld::Ptr playerPtr = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
+        MWWorld::LiveCellRef<ESM::NPC>* player = playerPtr.get<ESM::NPC>();
+        MWMechanics::CreatureStats playerStats = MWWorld::Class::get(playerPtr).getCreatureStats(playerPtr);
+        MWMechanics::NpcStats playerSkill = MWWorld::Class::get(playerPtr).getNpcStats(playerPtr);
+
+        if (toLower(npc->mBase->mRace) == toLower(player->mBase->mRace)) x += MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fDispRaceMod")->getFloat();
+
+        x += MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fDispPersonalityMult")->getFloat()
+            * (playerStats.getAttribute(ESM::Attribute::Personality).getModified() - MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fDispPersonalityBase")->getFloat());
+
+        float reaction = 0;
+        int rank = 0;
+        std::string npcFaction = "";
+        if(!npcSkill.getFactionRanks().empty()) npcFaction = npcSkill.getFactionRanks().begin()->first;
+
+        if (playerSkill.getFactionRanks().find(toLower(npcFaction)) != playerSkill.getFactionRanks().end())
+        {
+            for(std::vector<ESM::Faction::Reaction>::const_iterator it = MWBase::Environment::get().getWorld()->getStore().get<ESM::Faction>().find(toLower(npcFaction))->mReactions.begin();
+                it != MWBase::Environment::get().getWorld()->getStore().get<ESM::Faction>().find(toLower(npcFaction))->mReactions.end(); it++)
+            {
+                if(toLower(it->mFaction) == toLower(npcFaction)) reaction = it->mReaction;
+            }
+            rank = playerSkill.getFactionRanks().find(toLower(npcFaction))->second;
+        }
+        else if (npcFaction != "")
+        {
+            for(std::vector<ESM::Faction::Reaction>::const_iterator it = MWBase::Environment::get().getWorld()->getStore().get<ESM::Faction>().find(toLower(npcFaction))->mReactions.begin();
+                it != MWBase::Environment::get().getWorld()->getStore().get<ESM::Faction>().find(toLower(npcFaction))->mReactions.end();it++)
+            {
+                if(playerSkill.getFactionRanks().find(toLower(it->mFaction)) != playerSkill.getFactionRanks().end() )
+                {
+                    if(it->mReaction<reaction) reaction = it->mReaction;
+                }
+            }
+            rank = 0;
+        }
+        else
+        {
+            reaction = 0;
+            rank = 0;
+        }
+        x += (MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fDispFactionRankMult")->getFloat() * rank
+            + MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fDispFactionRankBase")->getFloat())
+            * MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fDispFactionMod")->getFloat() * reaction;
+
+        /// \todo implement bounty and disease
+        //x -= MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fDispCrimeMod") * pcBounty;
+        //if (pc has a disease) x += MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fDispDiseaseMod");
+        if (playerSkill.getDrawState() == MWMechanics::DrawState_::DrawState_Weapon) x += MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().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);
+
+        int clampedDisposition = std::min(getDerivedDisposition(ptr),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);
diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp
index 38536d3bd..0344d951c 100644
--- a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp
+++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp
@@ -79,6 +79,12 @@ 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.
             
diff --git a/apps/openmw/mwmechanics/npcstats.cpp b/apps/openmw/mwmechanics/npcstats.cpp
index c0da99aaf..5b2ce739f 100644
--- a/apps/openmw/mwmechanics/npcstats.cpp
+++ b/apps/openmw/mwmechanics/npcstats.cpp
@@ -18,8 +18,9 @@
 #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)
+
 {
     mSkillIncreases.resize (ESM::Attribute::Length);
     for (int i=0; i<ESM::Attribute::Length; ++i)
@@ -36,6 +37,16 @@ void MWMechanics::NpcStats::setDrawState (DrawState_ state)
     mDrawState = state;
 }
 
+int MWMechanics::NpcStats::getDisposition() const
+{
+    return mDisposition;
+}
+
+void MWMechanics::NpcStats::setDisposition(int disposition)
+{
+    mDisposition = disposition;
+}
+
 bool MWMechanics::NpcStats::getMovementFlag (Flag flag) const
 {
     return mMovementFlags & flag;
@@ -238,3 +249,13 @@ 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;
+}
diff --git a/apps/openmw/mwmechanics/npcstats.hpp b/apps/openmw/mwmechanics/npcstats.hpp
index 48e63d7b6..35af4afa0 100644
--- a/apps/openmw/mwmechanics/npcstats.hpp
+++ b/apps/openmw/mwmechanics/npcstats.hpp
@@ -43,8 +43,10 @@ namespace MWMechanics
             std::map<std::string, int> mFactionRank;
 
             DrawState_ mDrawState;
+            int mDisposition;
             unsigned int mMovementFlags;
             Stat<float> mSkill[27];
+            int mBounty;
 
             int mLevelProgress; // 0-10
 
@@ -60,6 +62,10 @@ namespace MWMechanics
 
             void setDrawState (DrawState_ state);
 
+            int getDisposition() const;
+
+            void setDisposition(int disposition);
+
             bool getMovementFlag (Flag flag) const;
 
             void setMovementFlag (Flag flag, bool state);
@@ -92,6 +98,10 @@ namespace MWMechanics
             void flagAsUsed (const std::string& id);
             
             bool hasBeenUsed (const std::string& id) const;
+            
+            int getBounty() const;
+            
+            void setBounty (int bounty);
     };
 }
 
diff --git a/apps/openmw/mwmechanics/spells.cpp b/apps/openmw/mwmechanics/spells.cpp
index 3ff10cdb8..ef084f479 100644
--- a/apps/openmw/mwmechanics/spells.cpp
+++ b/apps/openmw/mwmechanics/spells.cpp
@@ -75,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<ESM::Spell>().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<ESM::Spell>().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 d90f5b502..12308661b 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/mwworld/esmstore.hpp b/apps/openmw/mwworld/esmstore.hpp
index 0a6ea01b3..9917254ee 100644
--- a/apps/openmw/mwworld/esmstore.hpp
+++ b/apps/openmw/mwworld/esmstore.hpp
@@ -146,8 +146,13 @@ namespace MWWorld
         }
 
         template <class T>
-        T *insert(const T &x) {
+        const T *insert(const T &x) {
             Store<T> &store = const_cast<Store<T> &>(get<T>());
+            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;
@@ -168,10 +173,30 @@ namespace MWWorld
     };
 
     template <>
-    inline ESM::Cell *ESMStore::insert<ESM::Cell>(const ESM::Cell &cell) {
+    inline const ESM::Cell *ESMStore::insert<ESM::Cell>(const ESM::Cell &cell) {
         return mCells.insert(cell);
     }
 
+    template <>
+    inline const ESM::NPC *ESMStore::insert<ESM::NPC>(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<ESM::Activator> &ESMStore::get<ESM::Activator>() const {
         return mActivators;
diff --git a/apps/openmw/mwworld/player.cpp b/apps/openmw/mwworld/player.cpp
index a1318f727..3414ba448 100644
--- a/apps/openmw/mwworld/player.cpp
+++ b/apps/openmw/mwworld/player.cpp
@@ -13,33 +13,16 @@
 
 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.mBase = player;
         mPlayer.mRef.mRefID = "player";
-        mName = player->mName;
-        mMale = !(player->mFlags & ESM::NPC::Female);
-        mRace = player->mRace;
 
         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().get<ESM::Class>().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 68df2ec6d..1c1ef76cf 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<ESM::NPC> mPlayer;
-        MWWorld::CellStore *mCellStore;
-        std::string mName;
-        bool mMale;
-        std::string mRace;
-        std::string mBirthsign;
-        ESM::Class *mClass;
-        bool mAutoMove;
-        int mForwardBackward;
+        LiveCellRef<ESM::NPC>   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/store.hpp b/apps/openmw/mwworld/store.hpp
index 97b61b528..a406a39de 100644
--- a/apps/openmw/mwworld/store.hpp
+++ b/apps/openmw/mwworld/store.hpp
@@ -168,26 +168,6 @@ namespace MWWorld
             }
         }
 
-        T *search(const std::string &id) {
-            std::string key = StringUtils::lowerCase(id);
-            typename Dynamic::iterator dit = mDynamic.find(key);
-
-            if (dit != mDynamic.end()) {
-                return &dit->second;
-            }
-            return 0;
-        }
-
-        T *find(const std::string &id) {
-            T *ptr = search(id);
-            if (ptr == 0) {
-                std::ostringstream msg;
-                msg << "Object '" << id << "' not found (non-const)";
-                throw std::runtime_error(msg.str());
-            }
-            return ptr;
-        }
-
         T *insert(const T &item) {
             std::string id = StringUtils::lowerCase(item.mId);
             std::pair<typename Dynamic::iterator, bool> result =
@@ -523,43 +503,6 @@ namespace MWWorld
             }
         }
 
-        ESM::Cell *search(const std::string &id) {
-            std::string key = StringUtils::lowerCase(id);
-            DynamicInt::iterator it = mDynamicInt.find(key);
-            if (it != mDynamicInt.end()) {
-                return &it->second;
-            }
-            return 0;
-        }
-
-        ESM::Cell *find(const std::string &id) {
-            ESM::Cell *ptr = search(id);
-            if (ptr == 0) {
-                std::ostringstream msg;
-                msg << "Interior '" << id << "' not found (non-const)";
-                throw std::runtime_error(msg.str());
-            }
-            return ptr;
-        }
-
-        ESM::Cell *search(int x, int y) {
-            DynamicExt::iterator it = mDynamicExt.find(std::make_pair(x, y));
-            if (it != mDynamicExt.end()) {
-                return &it->second;
-            }
-            return 0;
-        }
-
-        ESM::Cell *find(int x, int y) {
-            ESM::Cell *ptr = search(x, y);
-            if (ptr == 0) {
-                std::ostringstream msg;
-                msg << "Exterior at (" << x << ", " << y << ") not found (non-const";
-                throw std::runtime_error(msg.str());
-            }
-            return ptr;
-        }
-
         ESM::Cell *insert(const ESM::Cell &cell) {
             if (search(cell) != 0) {
                 std::ostringstream msg;
diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp
index 9f5b7520c..af5745744 100644
--- a/apps/openmw/mwworld/worldimp.cpp
+++ b/apps/openmw/mwworld/worldimp.cpp
@@ -779,22 +779,19 @@ namespace MWWorld
         return mRendering->toggleRenderMode (mode);
     }
 
-    std::pair<std::string, const ESM::Potion *> World::createRecord (const ESM::Potion& record)
+    const ESM::Potion *World::createRecord (const ESM::Potion& record)
     {
-        const ESM::Potion *ptr = mStore.insert(record);
-        return std::make_pair(ptr->mId, ptr);
+        return mStore.insert(record); 
     }
 
-    std::pair<std::string, const ESM::Class *> World::createRecord (const ESM::Class& record)
+    const ESM::Class *World::createRecord (const ESM::Class& record)
     {
-        const ESM::Class *ptr = mStore.insert(record);
-        return std::make_pair(ptr->mId, ptr);
+        return mStore.insert(record);
     }
 
-    std::pair<std::string, const ESM::Spell *> World::createRecord (const ESM::Spell& record)
+    const ESM::Spell *World::createRecord (const ESM::Spell& record)
     {
-        const ESM::Spell *ptr = mStore.insert(record);
-        return std::make_pair(ptr->mId, ptr);
+        return mStore.insert(record);
     }
 
     const ESM::Cell *World::createRecord (const ESM::Cell& record)
@@ -802,6 +799,11 @@ namespace MWWorld
         return mStore.insert(record);
     }
 
+    const ESM::NPC *World::createRecord(const ESM::NPC &record)
+    {
+        return mStore.insert(record);
+    }
+
     void World::playAnimationGroup (const MWWorld::Ptr& ptr, const std::string& groupName, int mode,
         int number)
     {
diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp
index 2b2ad7821..0962c292c 100644
--- a/apps/openmw/mwworld/worldimp.hpp
+++ b/apps/openmw/mwworld/worldimp.hpp
@@ -250,21 +250,26 @@ namespace MWWorld
             ///< Toggle a render mode.
             ///< \return Resulting mode
 
-            virtual std::pair<std::string, const ESM::Potion *> 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<std::string, const ESM::Spell *> 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<std::string, const ESM::Class *> 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/nifbullet/bullet_nif_loader.cpp b/components/nifbullet/bullet_nif_loader.cpp
index d2ec7ca82..42f6a8e68 100644
--- a/components/nifbullet/bullet_nif_loader.cpp
+++ b/components/nifbullet/bullet_nif_loader.cpp
@@ -69,7 +69,7 @@ btVector3 ManualBulletShapeLoader::getbtVector(Ogre::Vector3 &v)
 
 void ManualBulletShapeLoader::loadResource(Ogre::Resource *resource)
 {
-    cShape = static_cast<BulletShape *>(resource);
+    cShape = static_cast<OEngine::Physic::BulletShape *>(resource);
     resourceName = cShape->getName();
     cShape->mCollide = false;
     mBoundingBox = NULL;
@@ -314,8 +314,8 @@ void ManualBulletShapeLoader::handleNiTriShape(Nif::NiTriShape *shape, int flags
 void ManualBulletShapeLoader::load(const std::string &name,const std::string &group)
 {
     // Check if the resource already exists
-    Ogre::ResourcePtr ptr = BulletShapeManager::getSingleton().getByName(name, group);
+    Ogre::ResourcePtr ptr = OEngine::Physic::BulletShapeManager::getSingleton().getByName(name, group);
     if (!ptr.isNull())
         return;
-    BulletShapeManager::getSingleton().create(name,group,true,this);
+    OEngine::Physic::BulletShapeManager::getSingleton().create(name,group,true,this);
 }
diff --git a/components/nifbullet/bullet_nif_loader.hpp b/components/nifbullet/bullet_nif_loader.hpp
index 82ac227a0..2190fda1b 100644
--- a/components/nifbullet/bullet_nif_loader.hpp
+++ b/components/nifbullet/bullet_nif_loader.hpp
@@ -48,7 +48,7 @@ namespace NifBullet
 /**
 *Load bulletShape from NIF files.
 */
-class ManualBulletShapeLoader : public BulletShapeLoader
+class ManualBulletShapeLoader : public OEngine::Physic::BulletShapeLoader
 {
 public:
 
@@ -104,7 +104,7 @@ private:
 
     
 
-    BulletShape* cShape;//current shape
+    OEngine::Physic::BulletShape* cShape;//current shape
     btTriangleMesh *mTriMesh;
     btBoxShape *mBoundingBox;
     btBvhTriangleMeshShape* currentShape;//the shape curently under construction
diff --git a/libs/openengine/bullet/BulletShapeLoader.cpp b/libs/openengine/bullet/BulletShapeLoader.cpp
index dd3bca692..071a5ee8a 100644
--- a/libs/openengine/bullet/BulletShapeLoader.cpp
+++ b/libs/openengine/bullet/BulletShapeLoader.cpp
@@ -1,6 +1,8 @@
 #include "BulletShapeLoader.h"
 
-
+namespace OEngine {
+namespace Physic
+{
 
 BulletShape::BulletShape(Ogre::ResourceManager* creator, const Ogre::String &name,
     Ogre::ResourceHandle handle, const Ogre::String &group, bool isManual,
@@ -64,21 +66,24 @@ size_t BulletShape::calculateSize() const
 
 
 //=============================================================================================================
-template<> BulletShapeManager *Ogre::Singleton<BulletShapeManager>::msSingleton = 0;
+BulletShapeManager *BulletShapeManager::sThis = 0;
 
 BulletShapeManager *BulletShapeManager::getSingletonPtr()
 {
-    return msSingleton;
+    return sThis;
 }
 
 BulletShapeManager &BulletShapeManager::getSingleton()
 {
-    assert(msSingleton);
-    return(*msSingleton);
+    assert(sThis);
+    return(*sThis);
 }
 
 BulletShapeManager::BulletShapeManager()
 {
+    assert(!sThis);
+    sThis = this;
+
     mResourceType = "BulletShape";
 
     // low, because it will likely reference other resources
@@ -92,6 +97,8 @@ BulletShapeManager::~BulletShapeManager()
 {
     // and this is how we unregister it
     Ogre::ResourceGroupManager::getSingleton()._unregisterResourceManager(mResourceType);
+
+    sThis = 0;
 }
 
 BulletShapePtr BulletShapeManager::load(const Ogre::String &name, const Ogre::String &group)
@@ -124,3 +131,6 @@ void BulletShapeLoader::loadResource(Ogre::Resource *resource)
 
 void BulletShapeLoader::load(const std::string &name,const std::string &group)
 {}
+
+}
+}
diff --git a/libs/openengine/bullet/BulletShapeLoader.h b/libs/openengine/bullet/BulletShapeLoader.h
index 21d21777a..d9bd5879a 100644
--- a/libs/openengine/bullet/BulletShapeLoader.h
+++ b/libs/openengine/bullet/BulletShapeLoader.h
@@ -5,8 +5,10 @@
 #include <OgreResourceManager.h>
 #include <btBulletCollisionCommon.h>
 #include <OgreVector3.h>
-//For some reason, Ogre Singleton  cannot be used in another namespace, that's why there is no namespace here.
-//But the risk of name collision seems pretty low here.
+
+namespace OEngine {
+namespace Physic
+{
 
 /**
 *Define a new resource which describe a Shape usable by bullet.See BulletShapeManager for how to get/use them.
@@ -107,7 +109,7 @@ public:
 *Important Note: i have no idea of what happen if you try to load two time the same resource without unloading.
 *It won't crash, but it might lead to memory leaks(I don't know how Ogre handle this). So don't do it!
 */
-class BulletShapeManager : public Ogre::ResourceManager, public Ogre::Singleton<BulletShapeManager>
+class BulletShapeManager : public Ogre::ResourceManager
 {
 protected:
 
@@ -116,6 +118,16 @@ protected:
         const Ogre::String &group, bool isManual, Ogre::ManualResourceLoader *loader,
         const Ogre::NameValuePairList *createParams);
 
+    static BulletShapeManager *sThis;
+
+private:
+    /** \brief Explicit private copy constructor. This is a forbidden operation.*/
+    BulletShapeManager(const BulletShapeManager &);
+
+    /** \brief Private operator= . This is a forbidden operation. */
+    BulletShapeManager& operator=(const BulletShapeManager &);
+
+
 public:
 
     BulletShapeManager();
@@ -139,4 +151,7 @@ public:
     virtual void load(const std::string &name,const std::string &group);
 };
 
+}
+}
+
 #endif
diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp
index d78e25ce7..b39ba53a2 100644
--- a/libs/openengine/bullet/physic.cpp
+++ b/libs/openengine/bullet/physic.cpp
@@ -251,7 +251,6 @@ namespace Physic
 
     PhysicEngine::~PhysicEngine()
     {
-
         HeightFieldContainer::iterator hf_it = mHeightFieldMap.begin();
         for (; hf_it != mHeightFieldMap.end(); ++hf_it)
         {
@@ -293,6 +292,8 @@ namespace Physic
         delete broadphase;
         delete pairCache;
         delete mShapeLoader;
+
+        delete BulletShapeManager::getSingletonPtr();
     }
 
     void PhysicEngine::addHeightField(float* heights,