From c991f68a2dbf929a7a158593042e4dd08163fc18 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 15 Oct 2012 21:54:19 +0200 Subject: [PATCH 01/20] buying created spell --- apps/openmw/mwbase/world.hpp | 6 ++++ apps/openmw/mwgui/spellcreationdialog.cpp | 42 +++++++++++++++++++++++ apps/openmw/mwworld/worldimp.cpp | 14 ++++++++ apps/openmw/mwworld/worldimp.hpp | 4 +++ 4 files changed, 66 insertions(+) diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 521bbb988e..1cb120b5c3 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -28,6 +28,7 @@ namespace ESM struct Cell; struct Class; struct Potion; + struct Spell; } namespace ESMS @@ -235,6 +236,11 @@ namespace MWBase ///< Create a new recrod (of type potion) in the ESM store. /// \return ID, pointer to created record + virtual std::pair createRecord (const ESM::Spell& record) + = 0; + ///< Create a new recrod (of type spell) in the ESM store. + /// \return ID, pointer to created record + virtual std::pair createRecord (const ESM::Class& record) = 0; ///< Create a new recrod (of type class) in the ESM store. diff --git a/apps/openmw/mwgui/spellcreationdialog.cpp b/apps/openmw/mwgui/spellcreationdialog.cpp index 02ce763ea0..bb066e8ffe 100644 --- a/apps/openmw/mwgui/spellcreationdialog.cpp +++ b/apps/openmw/mwgui/spellcreationdialog.cpp @@ -8,6 +8,7 @@ #include "../mwbase/world.hpp" #include "../mwbase/environment.hpp" +#include "../mwbase/soundmanager.hpp" #include "../mwworld/player.hpp" #include "../mwworld/class.hpp" @@ -297,7 +298,35 @@ namespace MWGui void SpellCreationDialog::onBuyButtonClicked (MyGUI::Widget* sender) { + if (mEffects.size() <= 0) + { + mWindowManager.messageBox ("#{sNotifyMessage30}", std::vector()); + return; + } + if (mNameEdit->getCaption () == "") + { + mWindowManager.messageBox ("#{sNotifyMessage10}", std::vector()); + return; + } + + ESM::Spell newSpell; + ESM::EffectList effectList; + effectList.mList = mEffects; + newSpell.mEffects = effectList; + newSpell.mName = mNameEdit->getCaption(); + newSpell.mData.mType = ESM::Spell::ST_Spell; + + std::pair result = MWBase::Environment::get().getWorld()->createRecord(newSpell); + + 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); + + MWBase::Environment::get().getSoundManager()->playSound ("Item Gold Up", 1.0, 1.0); + + mWindowManager.removeGuiMode (GM_SpellCreation); } void SpellCreationDialog::open() @@ -372,6 +401,9 @@ namespace MWGui ToolTips::createMagicEffectToolTip (w, *it); } + + mEffects.clear(); + updateEffectsView (); } void EffectEditorBase::setWidgets (Widgets::MWList *availableEffectsList, MyGUI::ScrollView *usedEffectsView) @@ -413,6 +445,16 @@ namespace MWGui { short effectId = *sender->getUserData(); + + for (std::vector::const_iterator it = mEffects.begin(); it != mEffects.end(); ++it) + { + if (it->mEffectID == effectId) + { + MWBase::Environment::get().getWindowManager()->messageBox ("#{sOnetypeEffectMessage}", std::vector()); + return; + } + } + const ESM::MagicEffect* effect = MWBase::Environment::get().getWorld()->getStore().magicEffects.find(effectId); mAddEffectDialog.newEffect (effect); diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 6fc228f0b5..495deb1ad8 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -802,6 +802,20 @@ namespace MWWorld return std::make_pair (stream.str(), created); } + std::pair 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); + } + const ESM::Cell *World::createRecord (const ESM::Cell& record) { if (record.mData.mFlags & ESM::Cell::Interior) diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 90cd2151b6..830a299187 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -253,6 +253,10 @@ namespace MWWorld ///< Create a new recrod (of type potion) in the ESM store. /// \return ID, pointer to created record + virtual std::pair createRecord (const ESM::Spell& record); + ///< Create a new recrod (of type spell) in the ESM store. + /// \return ID, pointer to created record + virtual std::pair createRecord (const ESM::Class& record); ///< Create a new recrod (of type class) in the ESM store. /// \return ID, pointer to created record From bdca5aff879665aabe13ca923cab28b5791a60b3 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 19 Oct 2012 13:10:06 +0200 Subject: [PATCH 02/20] Issue #68: simplified the dynamic stats interface --- apps/openmw/mwclass/creature.cpp | 6 +-- apps/openmw/mwclass/npc.cpp | 6 +-- apps/openmw/mwmechanics/actors.cpp | 54 ++++++++++++------- apps/openmw/mwmechanics/creaturestats.cpp | 25 ++++----- apps/openmw/mwmechanics/creaturestats.hpp | 14 ++--- .../mwmechanics/mechanicsmanagerimp.cpp | 10 ++-- apps/openmw/mwscript/statsextensions.cpp | 27 +++++++--- 7 files changed, 78 insertions(+), 64 deletions(-) diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index 0cf348b14d..0fb9daf195 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -55,9 +55,9 @@ namespace MWClass 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.getHealth().set (ref->base->mData.mHealth); - data->mCreatureStats.getMagicka().set (ref->base->mData.mMana); - data->mCreatureStats.getFatigue().set (ref->base->mData.mFatigue); + data->mCreatureStats.setHealth (ref->base->mData.mHealth); + data->mCreatureStats.setMagicka (ref->base->mData.mMana); + data->mCreatureStats.setFatigue (ref->base->mData.mFatigue); data->mCreatureStats.setLevel(ref->base->mData.mLevel); diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 03b5e56aa4..7e7e4937bf 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -89,9 +89,9 @@ namespace MWClass 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.getHealth().set (ref->base->mNpdt52.mHealth); - data->mCreatureStats.getMagicka().set (ref->base->mNpdt52.mMana); - data->mCreatureStats.getFatigue().set (ref->base->mNpdt52.mFatigue); + data->mCreatureStats.setHealth (ref->base->mNpdt52.mHealth); + data->mCreatureStats.setMagicka (ref->base->mNpdt52.mMana); + data->mCreatureStats.setFatigue (ref->base->mNpdt52.mFatigue); data->mCreatureStats.setLevel(ref->base->mNpdt52.mLevel); } diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index ab332eb960..43d9e8a3b7 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -73,13 +73,17 @@ namespace MWMechanics double magickaFactor = creatureStats.getMagicEffects().get (EffectKey (84)).mMagnitude * 0.1 + 0.5; - creatureStats.getHealth().setBase( - static_cast (0.5 * (strength + endurance)) + creatureStats.getLevelHealthBonus ()); + DynamicStat health = creatureStats.getHealth(); + health.setBase (static_cast (0.5 * (strength + endurance)) + creatureStats.getLevelHealthBonus ()); + creatureStats.setHealth (health); - creatureStats.getMagicka().setBase( - static_cast (intelligence + magickaFactor * intelligence)); - - creatureStats.getFatigue().setBase(strength+willpower+agility+endurance); + DynamicStat magicka = creatureStats.getMagicka(); + magicka.setBase (static_cast (intelligence + magickaFactor * intelligence)); + creatureStats.setMagicka (magicka); + + DynamicStat fatigue = creatureStats.getFatigue(); + fatigue.setBase (strength+willpower+agility+endurance); + creatureStats.setFatigue (fatigue); } void Actors::calculateRestoration (const MWWorld::Ptr& ptr, float duration) @@ -92,8 +96,10 @@ namespace MWMechanics bool stunted = stats.getMagicEffects ().get(MWMechanics::EffectKey(136)).mMagnitude > 0; int endurance = stats.getAttribute (ESM::Attribute::Endurance).getModified (); - stats.getHealth().setCurrent(stats.getHealth ().getCurrent () - + 0.1 * endurance); + + DynamicStat health = stats.getHealth(); + health.setCurrent (health.getCurrent() + 0.1 * endurance); + stats.setHealth (health); const ESMS::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); @@ -109,13 +115,19 @@ namespace MWMechanics float x = fFatigueReturnBase + fFatigueReturnMult * (1 - normalizedEncumbrance); x *= fEndFatigueMult * endurance; - stats.getFatigue ().setCurrent (stats.getFatigue ().getCurrent () + 3600 * x); - + + DynamicStat fatigue = stats.getFatigue(); + fatigue.setCurrent (fatigue.getCurrent() + 3600 * x); + stats.setFatigue (fatigue); + if (!stunted) { float fRestMagicMult = store.gameSettings.find("fRestMagicMult")->getFloat (); - stats.getMagicka().setCurrent (stats.getMagicka ().getCurrent () - + fRestMagicMult * stats.getAttribute(ESM::Attribute::Intelligence).getModified ()); + + DynamicStat magicka = stats.getMagicka(); + magicka.setCurrent (magicka.getCurrent() + + fRestMagicMult * stats.getAttribute(ESM::Attribute::Intelligence).getModified()); + stats.setMagicka (magicka); } } } @@ -137,14 +149,16 @@ namespace MWMechanics // dynamic stats MagicEffects effects = creatureStats.getMagicEffects(); - creatureStats.getHealth().setModifier( - effects.get(EffectKey(80)).mMagnitude - effects.get(EffectKey(18)).mMagnitude); - - creatureStats.getMagicka().setModifier( - effects.get(EffectKey(81)).mMagnitude - effects.get(EffectKey(19)).mMagnitude); - - creatureStats.getFatigue().setModifier( - effects.get(EffectKey(82)).mMagnitude - effects.get(EffectKey(20)).mMagnitude); + + for (int i=0; i<3; ++i) + { + DynamicStat stat = creatureStats.getDynamic (i); + + stat.setModifier ( + effects.get (EffectKey(80+i)).mMagnitude - effects.get (EffectKey(18+i)).mMagnitude); + + creatureStats.setDynamic (i, stat); + } } Actors::Actors() : mDuration (0) {} diff --git a/apps/openmw/mwmechanics/creaturestats.cpp b/apps/openmw/mwmechanics/creaturestats.cpp index fc05231412..4f699bba0f 100644 --- a/apps/openmw/mwmechanics/creaturestats.cpp +++ b/apps/openmw/mwmechanics/creaturestats.cpp @@ -118,22 +118,7 @@ namespace MWMechanics return mAttributes[index]; } - DynamicStat &CreatureStats::getHealth() - { - return mDynamic[0]; - } - - DynamicStat &CreatureStats::getMagicka() - { - return mDynamic[1]; - } - - DynamicStat &CreatureStats::getFatigue() - { - return mDynamic[2]; - } - - DynamicStat &CreatureStats::getDynamic(int index) + const DynamicStat &CreatureStats::getDynamic(int index) const { if (index < 0 || index > 2) { throw std::runtime_error("dynamic stat index is out of range"); @@ -184,6 +169,14 @@ namespace MWMechanics mDynamic[2] = value; } + void CreatureStats::setDynamic (int index, const DynamicStat &value) + { + if (index < 0 || index > 2) + throw std::runtime_error("dynamic stat index is out of range"); + + mDynamic[index] = value; + } + void CreatureStats::setLevel(int level) { mLevel = level; diff --git a/apps/openmw/mwmechanics/creaturestats.hpp b/apps/openmw/mwmechanics/creaturestats.hpp index 7a1e46f56e..82988ce8b4 100644 --- a/apps/openmw/mwmechanics/creaturestats.hpp +++ b/apps/openmw/mwmechanics/creaturestats.hpp @@ -43,6 +43,8 @@ namespace MWMechanics const DynamicStat & getFatigue() const; + const DynamicStat & getDynamic (int index) const; + const Spells & getSpells() const; const ActiveSpells & getActiveSpells() const; @@ -59,24 +61,14 @@ namespace MWMechanics int getAlarm() const; - Stat & getAttribute(int index); - DynamicStat & getHealth(); - - DynamicStat & getMagicka(); - - DynamicStat & getFatigue(); - - DynamicStat & getDynamic(int index); - Spells & getSpells(); ActiveSpells & getActiveSpells(); MagicEffects & getMagicEffects(); - void setAttribute(int index, const Stat &value); void setHealth(const DynamicStat &value); @@ -85,6 +77,8 @@ namespace MWMechanics void setFatigue(const DynamicStat &value); + void setDynamic (int index, const DynamicStat &value); + void setSpells(const Spells &spells); void setActiveSpells(const ActiveSpells &active); diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 364e653217..6d8bdb3321 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -153,12 +153,14 @@ namespace MWMechanics // forced update and current value adjustments mActors.updateActor (ptr, 0); - creatureStats.getHealth().setCurrent(creatureStats.getHealth().getModified()); - creatureStats.getMagicka().setCurrent(creatureStats.getMagicka().getModified()); - creatureStats.getFatigue().setCurrent(creatureStats.getFatigue().getModified()); + for (int i=0; i<2; ++i) + { + DynamicStat stat = creatureStats.getDynamic (i); + stat.setCurrent (stat.getModified()); + creatureStats.setDynamic (i, stat); + } } - MechanicsManager::MechanicsManager() : mUpdatePlayer (true), mClassSelected (false), mRaceSelected (false) diff --git a/apps/openmw/mwscript/statsextensions.cpp b/apps/openmw/mwscript/statsextensions.cpp index 66a5acae0a..11548feab1 100644 --- a/apps/openmw/mwscript/statsextensions.cpp +++ b/apps/openmw/mwscript/statsextensions.cpp @@ -188,10 +188,12 @@ namespace MWScript Interpreter::Type_Integer value = runtime[0].mInteger; runtime.pop(); - MWWorld::Class::get(ptr) - .getCreatureStats(ptr) - .getDynamic(mIndex) - .setModified(value, 0); + MWMechanics::DynamicStat stat (MWWorld::Class::get (ptr).getCreatureStats (ptr) + .getDynamic (mIndex)); + + stat.setModified (value, 0); + + MWWorld::Class::get (ptr).getCreatureStats (ptr).setDynamic (mIndex, stat); } }; @@ -215,10 +217,14 @@ namespace MWScript Interpreter::Type_Integer current = stats.getDynamic(mIndex).getCurrent(); - stats.getDynamic(mIndex).setModified( - diff + stats.getDynamic(mIndex).getModified(), 0); + MWMechanics::DynamicStat stat (MWWorld::Class::get (ptr).getCreatureStats (ptr) + .getDynamic (mIndex)); - stats.getDynamic(mIndex).setCurrent(diff + current); + stat.setModified (diff + stat.getModified(), 0); + + stat.setCurrent (diff + current); + + MWWorld::Class::get (ptr).getCreatureStats (ptr).setDynamic (mIndex, stat); } }; @@ -242,7 +248,12 @@ namespace MWScript Interpreter::Type_Integer current = stats.getDynamic(mIndex).getCurrent(); - stats.getDynamic(mIndex).setCurrent (diff + current); + MWMechanics::DynamicStat stat (MWWorld::Class::get (ptr).getCreatureStats (ptr) + .getDynamic (mIndex)); + + stat.setCurrent (diff + current); + + MWWorld::Class::get (ptr).getCreatureStats (ptr).setDynamic (mIndex, stat); } }; From a8f294c9ae88efcc487f4a260cd0a056bcabb8e0 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 19 Oct 2012 18:01:45 +0200 Subject: [PATCH 03/20] fixed types of dynamic stats script instructions --- apps/openmw/mwscript/statsextensions.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/apps/openmw/mwscript/statsextensions.cpp b/apps/openmw/mwscript/statsextensions.cpp index 11548feab1..fc57bb6545 100644 --- a/apps/openmw/mwscript/statsextensions.cpp +++ b/apps/openmw/mwscript/statsextensions.cpp @@ -155,7 +155,7 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime) { MWWorld::Ptr ptr = R()(runtime); - Interpreter::Type_Integer value; + Interpreter::Type_Float value; if (mIndex==0 && MWWorld::Class::get (ptr).hasItemHealth (ptr)) { @@ -185,7 +185,7 @@ namespace MWScript { MWWorld::Ptr ptr = R()(runtime); - Interpreter::Type_Integer value = runtime[0].mInteger; + Interpreter::Type_Float value = runtime[0].mFloat; runtime.pop(); MWMechanics::DynamicStat stat (MWWorld::Class::get (ptr).getCreatureStats (ptr) @@ -210,12 +210,12 @@ namespace MWScript { MWWorld::Ptr ptr = R()(runtime); - Interpreter::Type_Integer diff = runtime[0].mInteger; + Interpreter::Type_Float diff = runtime[0].mFloat; runtime.pop(); MWMechanics::CreatureStats& stats = MWWorld::Class::get (ptr).getCreatureStats (ptr); - Interpreter::Type_Integer current = stats.getDynamic(mIndex).getCurrent(); + Interpreter::Type_Float current = stats.getDynamic(mIndex).getCurrent(); MWMechanics::DynamicStat stat (MWWorld::Class::get (ptr).getCreatureStats (ptr) .getDynamic (mIndex)); @@ -241,12 +241,12 @@ namespace MWScript { MWWorld::Ptr ptr = R()(runtime); - Interpreter::Type_Integer diff = runtime[0].mInteger; + Interpreter::Type_Float diff = runtime[0].mFloat; runtime.pop(); MWMechanics::CreatureStats& stats = MWWorld::Class::get (ptr).getCreatureStats (ptr); - Interpreter::Type_Integer current = stats.getDynamic(mIndex).getCurrent(); + Interpreter::Type_Float current = stats.getDynamic(mIndex).getCurrent(); MWMechanics::DynamicStat stat (MWWorld::Class::get (ptr).getCreatureStats (ptr) .getDynamic (mIndex)); @@ -687,16 +687,16 @@ namespace MWScript for (int i=0; i Date: Fri, 19 Oct 2012 18:56:22 +0200 Subject: [PATCH 04/20] Issue #68: added dead flag to CreatureStats --- apps/openmw/mwmechanics/creaturestats.cpp | 28 +++++++++++++++++++---- apps/openmw/mwmechanics/creaturestats.hpp | 6 ++++- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwmechanics/creaturestats.cpp b/apps/openmw/mwmechanics/creaturestats.cpp index 4f699bba0f..1ce7bdb93a 100644 --- a/apps/openmw/mwmechanics/creaturestats.cpp +++ b/apps/openmw/mwmechanics/creaturestats.cpp @@ -10,7 +10,7 @@ namespace MWMechanics { CreatureStats::CreatureStats() - : mLevelHealthBonus(0.f) + : mLevel (0), mHello (0), mFight (0), mFlee (0), mAlarm (0), mLevelHealthBonus(0.f), mDead (false) { } @@ -156,17 +156,17 @@ namespace MWMechanics void CreatureStats::setHealth(const DynamicStat &value) { - mDynamic[0] = value; + setDynamic (0, value); } void CreatureStats::setMagicka(const DynamicStat &value) { - mDynamic[1] = value; + setDynamic (1, value); } void CreatureStats::setFatigue(const DynamicStat &value) { - mDynamic[2] = value; + setDynamic (2, value); } void CreatureStats::setDynamic (int index, const DynamicStat &value) @@ -175,6 +175,9 @@ namespace MWMechanics throw std::runtime_error("dynamic stat index is out of range"); mDynamic[index] = value; + + if (index==2 && mDynamic[index].getCurrent()<1) + mDead = true; } void CreatureStats::setLevel(int level) @@ -211,4 +214,21 @@ namespace MWMechanics { 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; + } + } } diff --git a/apps/openmw/mwmechanics/creaturestats.hpp b/apps/openmw/mwmechanics/creaturestats.hpp index 82988ce8b4..671dcd4396 100644 --- a/apps/openmw/mwmechanics/creaturestats.hpp +++ b/apps/openmw/mwmechanics/creaturestats.hpp @@ -29,8 +29,8 @@ namespace MWMechanics int mFlee; int mAlarm; AiSequence mAiSequence; - float mLevelHealthBonus; + bool mDead; public: CreatureStats(); @@ -105,6 +105,10 @@ namespace MWMechanics // small hack to allow the fact that Health permanently increases by 10% of endurance on each level up void increaseLevelHealthBonus(float value); float getLevelHealthBonus() const; + + bool isDead() const; + + void resurrect(); }; } From f2e25b8a476a2fad5c35d29c7e894bd716a110f3 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 20 Oct 2012 10:49:48 +0200 Subject: [PATCH 05/20] Issue #68: Keep dead actors out of the actor list for the current scene --- apps/openmw/mwbase/mechanicsmanager.hpp | 2 ++ apps/openmw/mwmechanics/actors.cpp | 3 ++- apps/openmw/mwmechanics/actors.hpp | 2 ++ apps/openmw/mwmechanics/mechanicsmanagerimp.hpp | 2 ++ 4 files changed, 8 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwbase/mechanicsmanager.hpp b/apps/openmw/mwbase/mechanicsmanager.hpp index 39d7e6e1a4..c5d721e264 100644 --- a/apps/openmw/mwbase/mechanicsmanager.hpp +++ b/apps/openmw/mwbase/mechanicsmanager.hpp @@ -39,6 +39,8 @@ namespace MWBase virtual void addActor (const MWWorld::Ptr& ptr) = 0; ///< Register an actor for stats management + /// + /// \note Dead actors are ignored. virtual void removeActor (const MWWorld::Ptr& ptr) = 0; ///< Deregister an actor for stats management diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 43d9e8a3b7..63f890d65d 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -165,7 +165,8 @@ namespace MWMechanics void Actors::addActor (const MWWorld::Ptr& ptr) { - mActors.insert (ptr); + if (!MWWorld::Class::get (ptr).getCreatureStats (ptr).isDead()) + mActors.insert (ptr); } void Actors::removeActor (const MWWorld::Ptr& ptr) diff --git a/apps/openmw/mwmechanics/actors.hpp b/apps/openmw/mwmechanics/actors.hpp index 7e5a0ac861..f8a00f3492 100644 --- a/apps/openmw/mwmechanics/actors.hpp +++ b/apps/openmw/mwmechanics/actors.hpp @@ -40,6 +40,8 @@ namespace MWMechanics void addActor (const MWWorld::Ptr& ptr); ///< Register an actor for stats management + /// + /// \note Dead actors are ignored. void removeActor (const MWWorld::Ptr& ptr); ///< Deregister an actor for stats management diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp index 3a41e8fa60..205deaf714 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp @@ -41,6 +41,8 @@ namespace MWMechanics virtual void addActor (const MWWorld::Ptr& ptr); ///< Register an actor for stats management + /// + /// \note Dead actors are ignored. virtual void removeActor (const MWWorld::Ptr& ptr); ///< Deregister an actor for stats management From 0547f11564efec3fc719d64d0f859478eb0d9450 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 20 Oct 2012 10:54:51 +0200 Subject: [PATCH 06/20] Issue #68: Remove dead actors from actor list --- apps/openmw/mwmechanics/actors.cpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 63f890d65d..a33ef7240c 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -199,13 +199,23 @@ namespace MWMechanics { float totalDuration = mDuration; mDuration = 0; + + std::set::iterator iter (mActors.begin()); - for (std::set::iterator iter (mActors.begin()); iter!=mActors.end(); ++iter) + while (iter!=mActors.end()) { - updateActor (*iter, totalDuration); + if (!MWWorld::Class::get (*iter).getCreatureStats (*iter).isDead()) + { + updateActor (*iter, totalDuration); - if (iter->getTypeName()==typeid (ESM::NPC).name()) - updateNpc (*iter, totalDuration, paused); + if (iter->getTypeName()==typeid (ESM::NPC).name()) + updateNpc (*iter, totalDuration, paused); + } + + if (MWWorld::Class::get (*iter).getCreatureStats (*iter).isDead()) + mActors.erase (iter++); + else + ++iter; } } From 9f821e5df20370da3eb3c39f24a69e05c96cdc3b Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 22 Oct 2012 16:56:43 +0200 Subject: [PATCH 07/20] fix shaders --- files/materials/objects.shader | 15 ++++++++++++--- files/materials/terrain.shader | 12 ++++++++---- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/files/materials/objects.shader b/files/materials/objects.shader index 525e4ab636..5ea076342e 100644 --- a/files/materials/objects.shader +++ b/files/materials/objects.shader @@ -157,10 +157,15 @@ shUniform(float4, shadowFar_fadeStart) @shSharedParameter(shadowFar_fadeStart) #endif -#if UNDERWATER +#if (UNDERWATER) || (FOG) shUniform(float4x4, worldMatrix) @shAutoConstant(worldMatrix, world_matrix) - shUniform(float, waterLevel) @shSharedParameter(waterLevel) shUniform(float4, cameraPos) @shAutoConstant(cameraPos, camera_position) +#endif + +#if UNDERWATER + + shUniform(float, waterLevel) @shSharedParameter(waterLevel) + shUniform(float4, lightDirectionWS0) @shAutoConstant(lightDirectionWS0, light_position, 0) shSampler2D(causticMap) @@ -211,8 +216,12 @@ float3 caustics = float3(1,1,1); -#if UNDERWATER + +#if (UNDERWATER) || (FOG) float3 worldPos = shMatrixMult(worldMatrix, float4(objSpacePositionPassthrough,1)).xyz; +#endif + +#if UNDERWATER float3 waterEyePos = float3(1,1,1); // NOTE: this calculation would be wrong for non-uniform scaling float4 worldNormal = shMatrixMult(worldMatrix, float4(normal.xyz, 0)); diff --git a/files/materials/terrain.shader b/files/materials/terrain.shader index 35ce403307..dee7332630 100644 --- a/files/materials/terrain.shader +++ b/files/materials/terrain.shader @@ -187,11 +187,13 @@ shUniform(float4, shadowFar_fadeStart) @shSharedParameter(shadowFar_fadeStart) #endif +#if (UNDERWATER) || (FOG) + shUniform(float4x4, worldMatrix) @shAutoConstant(worldMatrix, world_matrix) + shUniform(float4, cameraPos) @shAutoConstant(cameraPos, camera_position) +#endif #if UNDERWATER - shUniform(float4x4, worldMatrix) @shAutoConstant(worldMatrix, world_matrix) shUniform(float, waterLevel) @shSharedParameter(waterLevel) - shUniform(float4, cameraPos) @shAutoConstant(cameraPos, camera_position) shUniform(float4, lightDirectionWS0) @shAutoConstant(lightDirectionWS0, light_position, 0) shSampler2D(causticMap) @@ -222,9 +224,12 @@ float3 caustics = float3(1,1,1); +#if (UNDERWATER) || (FOG) + float3 worldPos = shMatrixMult(worldMatrix, float4(objSpacePosition,1)).xyz; +#endif + #if UNDERWATER - float3 worldPos = shMatrixMult(worldMatrix, float4(objSpacePosition,1)).xyz; float3 waterEyePos = float3(1,1,1); // NOTE: this calculation would be wrong for non-uniform scaling float4 worldNormal = shMatrixMult(worldMatrix, float4(normal.xyz, 0)); @@ -373,7 +378,6 @@ shOutputColour(0).xyz = gammaCorrectOutput(shOutputColour(0).xyz); - #if MRT shOutputColour(1) = float4(depth / far,1,1,1); #endif From 234716daa6fca5d0f92069fdf19a03e67cd2b9a9 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 23 Oct 2012 11:42:38 +0200 Subject: [PATCH 08/20] finished spell creation --- apps/openmw/mwgui/spellcreationdialog.cpp | 77 +++++++++++++++++-- apps/openmw/mwgui/spellcreationdialog.hpp | 4 + apps/openmw/mwmechanics/spellsuccess.hpp | 26 +++++-- .../mygui/openmw_spellcreation_dialog.layout | 3 - 4 files changed, 93 insertions(+), 17 deletions(-) diff --git a/apps/openmw/mwgui/spellcreationdialog.cpp b/apps/openmw/mwgui/spellcreationdialog.cpp index bb066e8ffe..4ce0560108 100644 --- a/apps/openmw/mwgui/spellcreationdialog.cpp +++ b/apps/openmw/mwgui/spellcreationdialog.cpp @@ -15,10 +15,14 @@ #include "../mwmechanics/spells.hpp" #include "../mwmechanics/creaturestats.hpp" +#include "../mwmechanics/spellsuccess.hpp" + #include "tooltips.hpp" #include "widgets.hpp" #include "class.hpp" +#include "inventorywindow.hpp" +#include "tradewindow.hpp" namespace { @@ -310,14 +314,25 @@ namespace MWGui return; } - ESM::Spell newSpell; - ESM::EffectList effectList; - effectList.mList = mEffects; - newSpell.mEffects = effectList; - newSpell.mName = mNameEdit->getCaption(); - newSpell.mData.mType = ESM::Spell::ST_Spell; + if (mMagickaCost->getCaption() == "0") + { + mWindowManager.messageBox ("#{sEnchantmentMenu8}", std::vector()); + return; + } - std::pair result = MWBase::Environment::get().getWorld()->createRecord(newSpell); + if (boost::lexical_cast(mPriceLabel->getCaption()) > mWindowManager.getInventoryWindow()->getPlayerGold()) + { + mWindowManager.messageBox ("#{sNotifyMessage18}", std::vector()); + return; + } + + mSpell.mName = mNameEdit->getCaption(); + + mWindowManager.getTradeWindow()->addOrRemoveGold(-boost::lexical_cast(mPriceLabel->getCaption())); + + MWBase::Environment::get().getSoundManager()->playSound ("Item Gold Up", 1.0, 1.0); + + std::pair result = MWBase::Environment::get().getWorld()->createRecord(mSpell); MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player); @@ -340,6 +355,47 @@ namespace MWGui mWindowManager.removeGuiMode (GM_SpellCreation); } + void SpellCreationDialog::notifyEffectsChanged () + { + float y = 0; + + 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); + 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(); + y += x * fEffectCostMult; + y = std::max(1.f,y); + + if (effect->mData.mFlags & ESM::MagicEffect::CastTarget) + y *= 1.5; + } + + mSpell.mData.mCost = int(y); + + ESM::EffectList effectList; + effectList.mList = mEffects; + mSpell.mEffects = effectList; + mSpell.mData.mType = ESM::Spell::ST_Spell; + + mMagickaCost->setCaption(boost::lexical_cast(int(y))); + + float fSpellMakingValueMult = MWBase::Environment::get().getWorld()->getStore().gameSettings.find("fSpellMakingValueMult")->getFloat(); + + /// \todo mercantile + int price = int(y) * fSpellMakingValueMult; + + mPriceLabel->setCaption(boost::lexical_cast(int(price))); + + float chance = MWMechanics::getSpellSuccessChance(&mSpell, MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); + mSuccessChance->setCaption(boost::lexical_cast(int(chance))); + } + // ------------------------------------------------------------------------------------------------ @@ -443,6 +499,11 @@ namespace MWGui void EffectEditorBase::onAvailableEffectClicked (MyGUI::Widget* sender) { + if (mEffects.size() >= 8) + { + MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage28}", std::vector()); + return; + } short effectId = *sender->getUserData(); @@ -534,6 +595,8 @@ namespace MWGui } mUsedEffectsView->setCanvasSize(size); + + notifyEffectsChanged(); } void EffectEditorBase::onEffectAdded (ESM::ENAMstruct effect) diff --git a/apps/openmw/mwgui/spellcreationdialog.hpp b/apps/openmw/mwgui/spellcreationdialog.hpp index 255b04cf6e..4d27ec1c6f 100644 --- a/apps/openmw/mwgui/spellcreationdialog.hpp +++ b/apps/openmw/mwgui/spellcreationdialog.hpp @@ -116,6 +116,7 @@ namespace MWGui void startEditing(); void setWidgets (Widgets::MWList* availableEffectsList, MyGUI::ScrollView* usedEffectsView); + virtual void notifyEffectsChanged () {} }; class SpellCreationDialog : public WindowBase, public ReferenceInterface, public EffectEditorBase @@ -133,6 +134,7 @@ namespace MWGui void onCancelButtonClicked (MyGUI::Widget* sender); void onBuyButtonClicked (MyGUI::Widget* sender); + virtual void notifyEffectsChanged (); MyGUI::EditBox* mNameEdit; MyGUI::TextBox* mMagickaCost; @@ -143,6 +145,8 @@ namespace MWGui Widgets::MWEffectList* mUsedEffectsList; + ESM::Spell mSpell; + }; } diff --git a/apps/openmw/mwmechanics/spellsuccess.hpp b/apps/openmw/mwmechanics/spellsuccess.hpp index 43db42aab1..a46667cdc4 100644 --- a/apps/openmw/mwmechanics/spellsuccess.hpp +++ b/apps/openmw/mwmechanics/spellsuccess.hpp @@ -27,9 +27,8 @@ namespace MWMechanics return schoolSkillMap[school]; } - inline int getSpellSchool(const std::string& spellId, const MWWorld::Ptr& actor) + inline int getSpellSchool(const ESM::Spell* spell, const MWWorld::Ptr& actor) { - const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(spellId); NpcStats& stats = MWWorld::Class::get(actor).getNpcStats(actor); // determine the spell's school @@ -60,27 +59,34 @@ namespace MWMechanics return school; } + inline int getSpellSchool(const std::string& spellId, const MWWorld::Ptr& actor) + { + const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(spellId); + return getSpellSchool(spell, actor); + } + // UESP wiki / Morrowind/Spells: // Chance of success is (Spell's skill * 2 + Willpower / 5 + Luck / 10 - Spell cost - Sound magnitude) * (Current fatigue + Maximum Fatigue * 1.5) / Maximum fatigue * 2 /** - * @param spellId ID of spell + * @param spell spell to cast * @param actor calculate spell success chance for this actor (depends on actor's skills) * @attention actor has to be an NPC and not a creature! * @return success chance from 0 to 100 (in percent) */ - inline float getSpellSuccessChance (const std::string& spellId, const MWWorld::Ptr& actor) + inline float getSpellSuccessChance (const ESM::Spell* spell, const MWWorld::Ptr& actor) { - const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(spellId); - if (spell->mData.mFlags & ESM::Spell::F_Always // spells with this flag always succeed (usually birthsign spells) || spell->mData.mType == ESM::Spell::ST_Power) // powers always succeed, but can be cast only once per day return 100.0; + if (spell->mEffects.mList.size() == 0) + return 0.0; + NpcStats& stats = MWWorld::Class::get(actor).getNpcStats(actor); CreatureStats& creatureStats = MWWorld::Class::get(actor).getCreatureStats(actor); - int skillLevel = stats.getSkill (getSpellSchool(spellId, actor)).getModified(); + int skillLevel = stats.getSkill (getSpellSchool(spell, actor)).getModified(); // Sound magic effect (reduces spell casting chance) int soundMagnitude = creatureStats.getMagicEffects().get (MWMechanics::EffectKey (48)).mMagnitude; @@ -98,6 +104,12 @@ namespace MWMechanics return chance; } + + inline float getSpellSuccessChance (const std::string& spellId, const MWWorld::Ptr& actor) + { + const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(spellId); + return getSpellSuccessChance(spell, actor); + } } #endif diff --git a/files/mygui/openmw_spellcreation_dialog.layout b/files/mygui/openmw_spellcreation_dialog.layout index 4992243620..78d3f3de73 100644 --- a/files/mygui/openmw_spellcreation_dialog.layout +++ b/files/mygui/openmw_spellcreation_dialog.layout @@ -22,7 +22,6 @@ - @@ -31,7 +30,6 @@ - @@ -64,7 +62,6 @@ - From 9172c3ec4d840b9b3960ef3cae03e14fe90b8dff Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 23 Oct 2012 13:54:36 +0200 Subject: [PATCH 09/20] Issue #68: stop NPCs from instantly dropping dead --- apps/openmw/mwclass/npc.cpp | 7 +++++++ apps/openmw/mwmechanics/actors.cpp | 2 +- apps/openmw/mwmechanics/creaturestats.cpp | 4 ++-- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 7e7e4937bf..bcde31b265 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -98,6 +98,13 @@ namespace MWClass else { /// \todo do something with mNpdt12 maybe:p + for (int i=0; i<8; ++i) + data->mCreatureStats.getAttribute (i).set (10); + + for (int i=0; i<3; ++i) + data->mCreatureStats.setDynamic (i, 10); + + data->mCreatureStats.setLevel (1); } data->mCreatureStats.setHello(ref->base->mAiData.mHello); diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index a33ef7240c..e8b6fc14d8 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -24,8 +24,8 @@ namespace MWMechanics { // magic effects adjustMagicEffects (ptr); - calculateCreatureStatModifiers (ptr); calculateDynamicStats (ptr); + calculateCreatureStatModifiers (ptr); // AI CreatureStats& creatureStats = MWWorld::Class::get (ptr).getCreatureStats (ptr); diff --git a/apps/openmw/mwmechanics/creaturestats.cpp b/apps/openmw/mwmechanics/creaturestats.cpp index 1ce7bdb93a..8be4b93693 100644 --- a/apps/openmw/mwmechanics/creaturestats.cpp +++ b/apps/openmw/mwmechanics/creaturestats.cpp @@ -173,9 +173,9 @@ namespace MWMechanics { if (index < 0 || index > 2) throw std::runtime_error("dynamic stat index is out of range"); - + mDynamic[index] = value; - + if (index==2 && mDynamic[index].getCurrent()<1) mDead = true; } From 4ca0eb93eec7ef18f453ac8d086911bcc34f8a04 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 24 Oct 2012 17:47:03 +0200 Subject: [PATCH 10/20] fix markers used for raycasting and blocking activation --- components/nifbullet/bullet_nif_loader.cpp | 7 ++++--- libs/openengine/bullet/BulletShapeLoader.cpp | 3 ++- libs/openengine/bullet/BulletShapeLoader.h | 4 +++- libs/openengine/bullet/physic.cpp | 10 +++++++--- libs/openengine/bullet/physic.hpp | 3 ++- 5 files changed, 18 insertions(+), 9 deletions(-) diff --git a/components/nifbullet/bullet_nif_loader.cpp b/components/nifbullet/bullet_nif_loader.cpp index 6449ad246c..d2ec7ca825 100644 --- a/components/nifbullet/bullet_nif_loader.cpp +++ b/components/nifbullet/bullet_nif_loader.cpp @@ -71,7 +71,7 @@ void ManualBulletShapeLoader::loadResource(Ogre::Resource *resource) { cShape = static_cast(resource); resourceName = cShape->getName(); - cShape->collide = false; + cShape->mCollide = false; mBoundingBox = NULL; cShape->boxTranslation = Ogre::Vector3(0,0,0); cShape->boxRotation = Ogre::Quaternion::IDENTITY; @@ -108,7 +108,7 @@ void ManualBulletShapeLoader::loadResource(Ogre::Resource *resource) handleNode(node,0,NULL,hasCollisionNode,false,false); //if collide = false, then it does a second pass which create a shape for raycasting. - if(cShape->collide == false) + if(cShape->mCollide == false) { handleNode(node,0,NULL,hasCollisionNode,false,true); } @@ -177,6 +177,7 @@ void ManualBulletShapeLoader::handleNode(Nif::Node *node, int flags, if (node->name.find("marker") != std::string::npos) { flags |= 0x800; + cShape->mIgnore = true; } // Check for extra data @@ -254,7 +255,7 @@ void ManualBulletShapeLoader::handleNode(Nif::Node *node, int flags, } else if (node->recType == Nif::RC_NiTriShape && (isCollisionNode || !hasCollisionNode)) { - cShape->collide = !(flags&0x800); + cShape->mCollide = !(flags&0x800); handleNiTriShape(dynamic_cast(node), flags,node->trafo.rotation,node->trafo.pos,node->trafo.scale,raycastingOnly); } else if(node->recType == Nif::RC_RootCollisionNode) diff --git a/libs/openengine/bullet/BulletShapeLoader.cpp b/libs/openengine/bullet/BulletShapeLoader.cpp index 59a414f301..dd3bca692c 100644 --- a/libs/openengine/bullet/BulletShapeLoader.cpp +++ b/libs/openengine/bullet/BulletShapeLoader.cpp @@ -16,7 +16,8 @@ Ogre::Resource(creator, name, handle, group, isManual, loader) we have none as such. Full details can be set through scripts. */ Shape = NULL; - collide = true; + mCollide = true; + mIgnore = false; createParamDictionary("BulletShape"); } diff --git a/libs/openengine/bullet/BulletShapeLoader.h b/libs/openengine/bullet/BulletShapeLoader.h index 8640fd54f0..21d21777a2 100644 --- a/libs/openengine/bullet/BulletShapeLoader.h +++ b/libs/openengine/bullet/BulletShapeLoader.h @@ -34,7 +34,9 @@ public: Ogre::Vector3 boxTranslation; Ogre::Quaternion boxRotation; //this flag indicate if the shape is used for collision or if it's for raycasting only. - bool collide; + bool mCollide; + + bool mIgnore; }; /** diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index 4f16a41438..d78e25ce7f 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -169,6 +169,7 @@ namespace Physic RigidBody::RigidBody(btRigidBody::btRigidBodyConstructionInfo& CI,std::string name) : btRigidBody(CI) , mName(name) + , mIgnore(false) { } @@ -327,7 +328,7 @@ namespace Physic btRigidBody::btRigidBodyConstructionInfo CI = btRigidBody::btRigidBodyConstructionInfo(0,newMotionState,hfShape); RigidBody* body = new RigidBody(CI,name); - body->collide = true; + body->mCollide = true; body->getWorldTransform().setOrigin(btVector3( (x+0.5)*triSize*(sqrtVerts-1), (y+0.5)*triSize*(sqrtVerts-1), (maxh+minh)/2.f)); HeightField hf; @@ -397,7 +398,8 @@ namespace Physic //create the real body btRigidBody::btRigidBodyConstructionInfo CI = btRigidBody::btRigidBodyConstructionInfo(0,newMotionState,shape->Shape); RigidBody* body = new RigidBody(CI,name); - body->collide = shape->collide; + body->mCollide = shape->mCollide; + body->mIgnore = shape->mIgnore; if(scaledBoxTranslation != 0) *scaledBoxTranslation = shape->boxTranslation * scale; @@ -414,7 +416,9 @@ namespace Physic { if(body) { - if(body->collide) + if (body->mIgnore) + return; + if(body->mCollide) { dynamicsWorld->addRigidBody(body,COL_WORLD,COL_WORLD|COL_ACTOR_INTERNAL|COL_ACTOR_EXTERNAL); } diff --git a/libs/openengine/bullet/physic.hpp b/libs/openengine/bullet/physic.hpp index e4e71706f7..f320d009d9 100644 --- a/libs/openengine/bullet/physic.hpp +++ b/libs/openengine/bullet/physic.hpp @@ -152,7 +152,8 @@ namespace Physic std::string mName; //is this body used for raycasting only? - bool collide; + bool mCollide; + bool mIgnore; }; struct HeightField From 0ab432b074243f157520a80fd79e7df5ede9acde Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 25 Oct 2012 12:22:48 +0200 Subject: [PATCH 11/20] Issue #68: fixed death detection --- apps/openmw/mwmechanics/creaturestats.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/creaturestats.cpp b/apps/openmw/mwmechanics/creaturestats.cpp index 8be4b93693..1e57ba3136 100644 --- a/apps/openmw/mwmechanics/creaturestats.cpp +++ b/apps/openmw/mwmechanics/creaturestats.cpp @@ -176,7 +176,7 @@ namespace MWMechanics mDynamic[index] = value; - if (index==2 && mDynamic[index].getCurrent()<1) + if (index==0 && mDynamic[index].getCurrent()<1) mDead = true; } From 21c24dedb63971c6c1d61b136ff4414964cd8b9f Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 25 Oct 2012 12:28:45 +0200 Subject: [PATCH 12/20] Issue #68: Stop player from dying (temporary workaround) --- apps/openmw/mwmechanics/actors.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index e8b6fc14d8..0623db4b1c 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -213,7 +213,27 @@ namespace MWMechanics } if (MWWorld::Class::get (*iter).getCreatureStats (*iter).isDead()) + { + // workaround: always keep player alive for now + // \todo remove workaround, once player death can be handled + if (iter->getRefData().getHandle()=="player") + { + MWMechanics::DynamicStat stat ( + MWWorld::Class::get (*iter).getCreatureStats (*iter).getHealth()); + + if (stat.getModified()<1) + { + stat.setModified (1, 0); + MWWorld::Class::get (*iter).getCreatureStats (*iter).setHealth (stat); + } + + MWWorld::Class::get (*iter).getCreatureStats (*iter).resurrect(); + ++iter; + continue; + } + mActors.erase (iter++); + } else ++iter; } From 9f923e7963a00e13e6e288e1867f6f1089434d4f Mon Sep 17 00:00:00 2001 From: greye Date: Thu, 25 Oct 2012 15:14:34 +0400 Subject: [PATCH 13/20] fix crashing if /home/greye/.cache not exist --- apps/openmw/mwrender/renderingmanager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 21299e25c1..5b5fdce68e 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -67,7 +67,7 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const // material system sh::OgrePlatform* platform = new sh::OgrePlatform("General", (resDir / "materials").string()); if (!boost::filesystem::exists (cacheDir)) - boost::filesystem::create_directory (cacheDir); + boost::filesystem::create_directories (cacheDir); platform->setCacheFolder (cacheDir.string()); mFactory = new sh::Factory(platform); From 5d45d328b8e1d6359555dd95c757ac83d76d78b5 Mon Sep 17 00:00:00 2001 From: bwrsandman Date: Fri, 26 Oct 2012 21:28:22 -0400 Subject: [PATCH 14/20] Fixed uninitialized variable that caused a segfault when going to previous page. --- apps/openmw/mwgui/journalwindow.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/openmw/mwgui/journalwindow.cpp b/apps/openmw/mwgui/journalwindow.cpp index 597c27c6df..9d5d236be0 100644 --- a/apps/openmw/mwgui/journalwindow.cpp +++ b/apps/openmw/mwgui/journalwindow.cpp @@ -85,6 +85,7 @@ MWGui::JournalWindow::JournalWindow (MWBase::WindowManager& parWindowManager) : WindowBase("openmw_journal.layout", parWindowManager) , mLastPos(0) , mVisible(false) + , mPageNumber(0) { //setCoord(0,0,498, 342); center(); From 6b09b3ad61ac9959c640fb70b0051264dce06739 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 27 Oct 2012 10:36:42 +0200 Subject: [PATCH 15/20] Issue #68: Play death animations --- apps/openmw/mwmechanics/actors.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 0623db4b1c..5c1560032c 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -167,6 +167,8 @@ namespace MWMechanics { if (!MWWorld::Class::get (ptr).getCreatureStats (ptr).isDead()) mActors.insert (ptr); + else + MWBase::Environment::get().getWorld()->playAnimationGroup (ptr, "death1", 2); } void Actors::removeActor (const MWWorld::Ptr& ptr) @@ -231,7 +233,9 @@ namespace MWMechanics ++iter; continue; } - + + MWBase::Environment::get().getWorld()->playAnimationGroup (*iter, "death1", 0); + mActors.erase (iter++); } else From f72c35fc172c5d66596fdac5588b8eebe2a5123e Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 27 Oct 2012 11:15:52 +0200 Subject: [PATCH 16/20] Issue #68: tally deaths --- apps/openmw/mwmechanics/actors.cpp | 2 ++ apps/openmw/mwmechanics/actors.hpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 5c1560032c..0b1d0ba043 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -234,6 +234,8 @@ namespace MWMechanics continue; } + ++mDeathCount[MWWorld::Class::get (*iter).getId (*iter)]; + MWBase::Environment::get().getWorld()->playAnimationGroup (*iter, "death1", 0); mActors.erase (iter++); diff --git a/apps/openmw/mwmechanics/actors.hpp b/apps/openmw/mwmechanics/actors.hpp index f8a00f3492..fb6a42c472 100644 --- a/apps/openmw/mwmechanics/actors.hpp +++ b/apps/openmw/mwmechanics/actors.hpp @@ -4,6 +4,7 @@ #include #include #include +#include namespace Ogre { @@ -22,6 +23,7 @@ namespace MWMechanics { std::set mActors; float mDuration; + std::map mDeathCount; void updateNpc (const MWWorld::Ptr& ptr, float duration, bool paused); From 453f347ee8f0d801cc67dd9be63afa7574358fc7 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 27 Oct 2012 11:33:18 +0200 Subject: [PATCH 17/20] Issue #68: added getdeadcount script function --- apps/openmw/mwbase/mechanicsmanager.hpp | 3 +++ apps/openmw/mwmechanics/actors.cpp | 10 ++++++++++ apps/openmw/mwmechanics/actors.hpp | 3 +++ apps/openmw/mwmechanics/mechanicsmanagerimp.cpp | 5 +++++ apps/openmw/mwmechanics/mechanicsmanagerimp.hpp | 4 ++++ apps/openmw/mwscript/docs/vmformat.txt | 3 ++- apps/openmw/mwscript/statsextensions.cpp | 17 +++++++++++++++++ 7 files changed, 44 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwbase/mechanicsmanager.hpp b/apps/openmw/mwbase/mechanicsmanager.hpp index c5d721e264..750fc2fff8 100644 --- a/apps/openmw/mwbase/mechanicsmanager.hpp +++ b/apps/openmw/mwbase/mechanicsmanager.hpp @@ -76,6 +76,9 @@ namespace MWBase virtual void restoreDynamicStats() = 0; ///< If the player is sleeping, this should be called every hour. + + 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/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 0b1d0ba043..1c9fefa16a 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -262,4 +262,14 @@ namespace MWMechanics calculateRestoration (*iter, 3600); } } + + int Actors::countDeaths (const std::string& id) const + { + std::map::const_iterator iter = mDeathCount.find (id); + + if (iter!=mDeathCount.end()) + return iter->second; + + return 0; + } } diff --git a/apps/openmw/mwmechanics/actors.hpp b/apps/openmw/mwmechanics/actors.hpp index fb6a42c472..79ae16fc34 100644 --- a/apps/openmw/mwmechanics/actors.hpp +++ b/apps/openmw/mwmechanics/actors.hpp @@ -63,6 +63,9 @@ namespace MWMechanics void restoreDynamicStats(); ///< If the player is sleeping, this should be called every hour. + + int countDeaths (const std::string& id) const; + ///< Return the number of deaths for actors with the given ID. }; } diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 6d8bdb3321..873dd94988 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -326,4 +326,9 @@ namespace MWMechanics buildPlayer(); mUpdatePlayer = true; } + + 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 205deaf714..38536d3bd7 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp @@ -78,6 +78,10 @@ namespace MWMechanics virtual void restoreDynamicStats(); ///< If the player is sleeping, this should be called every hour. + + virtual int countDeaths (const std::string& id) const; + ///< Return the number of deaths for actors with the given ID. + }; } diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index 584a299267..cb984e257c 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -206,5 +206,6 @@ op 0x200019f: GetPcSleep op 0x20001a0: ShowMap op 0x20001a1: FillMap op 0x20001a2: WakeUpPc -opcodes 0x20001a3-0x3ffffff unused +op 0x20001a3: GetDeadCount +opcodes 0x20001a4-0x3ffffff unused diff --git a/apps/openmw/mwscript/statsextensions.cpp b/apps/openmw/mwscript/statsextensions.cpp index fc57bb6545..0d69608e1c 100644 --- a/apps/openmw/mwscript/statsextensions.cpp +++ b/apps/openmw/mwscript/statsextensions.cpp @@ -17,6 +17,7 @@ #include "../mwbase/environment.hpp" #include "../mwbase/dialoguemanager.hpp" +#include "../mwbase/mechanicsmanager.hpp" #include "../mwworld/class.hpp" #include "../mwworld/player.hpp" @@ -591,6 +592,17 @@ namespace MWScript /// \todo modify disposition towards the player } }; + + class OpGetDeadCount : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + std::string id = runtime.getStringLiteral (runtime[0].mInteger); + runtime[0].mInteger = MWBase::Environment::get().getMechanicsManager()->countDeaths (id); + } + }; const int numberOfAttributes = 8; @@ -643,6 +655,8 @@ namespace MWScript const int opcodeGetLevelExplicit = 0x200018d; const int opcodeSetLevel = 0x200018e; const int opcodeSetLevelExplicit = 0x200018f; + + const int opcodeGetDeadCount = 0x20001a3; void registerExtensions (Compiler::Extensions& extensions) { @@ -729,6 +743,8 @@ namespace MWScript extensions.registerInstruction("setlevel", "l", opcodeSetLevel, opcodeSetLevelExplicit); extensions.registerFunction("getlevel", 'l', "", opcodeGetLevel, opcodeGetLevelExplicit); + + extensions.registerFunction("getdeadcount", 'l', "c", opcodeGetDeadCount); } void installOpcodes (Interpreter::Interpreter& interpreter) @@ -806,6 +822,7 @@ namespace MWScript interpreter.installSegment5 (opcodeSetLevel, new OpSetLevel); interpreter.installSegment5 (opcodeSetLevelExplicit, new OpSetLevel); + interpreter.installSegment5 (opcodeGetDeadCount, new OpGetDeadCount); } } } From ed3641b21445f26de214cd2ea7a64d50d98b9ddc Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 27 Oct 2012 13:33:54 +0200 Subject: [PATCH 18/20] Issue #68: check for essential actors --- apps/openmw/mwclass/creature.cpp | 8 ++++++++ apps/openmw/mwclass/creature.hpp | 3 +++ apps/openmw/mwclass/npc.cpp | 8 ++++++++ apps/openmw/mwclass/npc.hpp | 3 +++ apps/openmw/mwmechanics/actors.cpp | 4 ++++ apps/openmw/mwworld/class.cpp | 5 +++++ apps/openmw/mwworld/class.hpp | 5 +++++ 7 files changed, 36 insertions(+) diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index 0fb9daf195..e007c50ab3 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -149,6 +149,14 @@ namespace MWClass return ref->base->mScript; } + bool Creature::isEssential (const MWWorld::Ptr& ptr) const + { + MWWorld::LiveCellRef *ref = + ptr.get(); + + return ref->base->mFlags & ESM::Creature::Essential; + } + void Creature::registerSelf() { boost::shared_ptr instance (new Creature); diff --git a/apps/openmw/mwclass/creature.hpp b/apps/openmw/mwclass/creature.hpp index 4de877b31d..a158fa743e 100644 --- a/apps/openmw/mwclass/creature.hpp +++ b/apps/openmw/mwclass/creature.hpp @@ -56,6 +56,9 @@ namespace MWClass ///< Returns total weight of objects inside this object (including modifications from magic /// effects). Throws an exception, if the object can't hold other objects. + virtual bool isEssential (const MWWorld::Ptr& ptr) const; + ///< Is \a ptr essential? (i.e. may losing \a ptr make the game unwinnable) + static void registerSelf(); virtual std::string getModel(const MWWorld::Ptr &ptr) const; diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index bcde31b265..ef3946efef 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -315,7 +315,15 @@ namespace MWClass return vector; } + + bool Npc::isEssential (const MWWorld::Ptr& ptr) const + { + MWWorld::LiveCellRef *ref = + ptr.get(); + return ref->base->mFlags & ESM::NPC::Essential; + } + void Npc::registerSelf() { boost::shared_ptr instance (new Npc); diff --git a/apps/openmw/mwclass/npc.hpp b/apps/openmw/mwclass/npc.hpp index edb6ca40fa..20c2da4b14 100644 --- a/apps/openmw/mwclass/npc.hpp +++ b/apps/openmw/mwclass/npc.hpp @@ -90,6 +90,9 @@ namespace MWClass virtual void adjustRotation(const MWWorld::Ptr& ptr,float& x,float& y,float& z) const; + virtual bool isEssential (const MWWorld::Ptr& ptr) const; + ///< Is \a ptr essential? (i.e. may losing \a ptr make the game unwinnable) + static void registerSelf(); virtual std::string getModel(const MWWorld::Ptr &ptr) const; diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 1c9fefa16a..f3b6b16162 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -238,6 +238,10 @@ namespace MWMechanics MWBase::Environment::get().getWorld()->playAnimationGroup (*iter, "death1", 0); + if (MWWorld::Class::get (*iter).isEssential (*iter)) + MWBase::Environment::get().getWindowManager()->messageBox ( + "#{sKilledEssential}", std::vector()); + mActors.erase (iter++); } else diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index 5267e368dd..8c639a874c 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -157,6 +157,11 @@ namespace MWWorld throw std::runtime_error ("encumbrance not supported by class"); } + bool Class::isEssential (const MWWorld::Ptr& ptr) 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 3c3b0e34be..4662cbab63 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -186,6 +186,11 @@ namespace MWWorld /// /// (default implementations: throws an exception) + virtual bool isEssential (const MWWorld::Ptr& ptr) const; + ///< Is \a ptr essential? (i.e. may losing \a ptr make the game unwinnable) + /// + /// (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. From d7add0b9e679c1a7db6c2df0a288fc2bdafac083 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 28 Oct 2012 14:07:36 +0100 Subject: [PATCH 19/20] Issue #61: fixed alchemy skill --- apps/openmw/mwmechanics/alchemy.cpp | 62 +++++++---------------------- apps/openmw/mwmechanics/alchemy.hpp | 5 +-- 2 files changed, 15 insertions(+), 52 deletions(-) diff --git a/apps/openmw/mwmechanics/alchemy.cpp b/apps/openmw/mwmechanics/alchemy.cpp index df7c786b1e..962350472e 100644 --- a/apps/openmw/mwmechanics/alchemy.cpp +++ b/apps/openmw/mwmechanics/alchemy.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -28,7 +29,7 @@ std::set MWMechanics::Alchemy::listEffects() const { - std::set effects; + std::map effects; for (TIngredientsIterator iter (mIngredients.begin()); iter!=mIngredients.end(); ++iter) { @@ -38,57 +39,23 @@ std::set MWMechanics::Alchemy::listEffects() const for (int i=0; i<4; ++i) if (ingredient->base->mData.mEffectID[i]!=-1) - effects.insert (EffectKey ( + { + EffectKey key ( ingredient->base->mData.mEffectID[i], ingredient->base->mData.mSkills[i]!=-1 ? - ingredient->base->mData.mSkills[i] : ingredient->base->mData.mAttributes[i])); + ingredient->base->mData.mSkills[i] : ingredient->base->mData.mAttributes[i]); + + ++effects[key]; + } } } - return effects; -} - -void MWMechanics::Alchemy::filterEffects (std::set& effects) const -{ - std::set::iterator iter = effects.begin(); + std::set effects2; - while (iter!=effects.end()) - { - bool remove = false; - - const EffectKey& key = *iter; - - { // dodge pointless g++ warning - for (TIngredientsIterator iter (mIngredients.begin()); iter!=mIngredients.end(); ++iter) - { - bool found = false; - - if (iter->isEmpty()) - continue; - - const MWWorld::LiveCellRef *ingredient = iter->get(); - - for (int i=0; i<4; ++i) - if (key.mId==ingredient->base->mData.mEffectID[i] && - (key.mArg==ingredient->base->mData.mSkills[i] || - key.mArg==ingredient->base->mData.mAttributes[i])) - { - found = true; - break; - } - - if (!found) - { - remove = true; - break; - } - } - } - - if (remove) - effects.erase (iter++); - else - ++iter; - } + for (std::map::const_iterator iter (effects.begin()); iter!=effects.end(); ++iter) + if (iter->second>1) + effects2.insert (iter->first); + + return effects2; } void MWMechanics::Alchemy::applyTools (int flags, float& value) const @@ -159,7 +126,6 @@ void MWMechanics::Alchemy::updateEffects() // find effects std::set effects (listEffects()); - filterEffects (effects); // general alchemy factor float x = getChance(); diff --git a/apps/openmw/mwmechanics/alchemy.hpp b/apps/openmw/mwmechanics/alchemy.hpp index 7f3e2c0eaa..957e3122c7 100644 --- a/apps/openmw/mwmechanics/alchemy.hpp +++ b/apps/openmw/mwmechanics/alchemy.hpp @@ -46,10 +46,7 @@ namespace MWMechanics int mValue; std::set listEffects() const; - ///< List all effects of all used ingredients. - - void filterEffects (std::set& effects) const; - ///< Filter out effects not shared by all ingredients. + ///< List all effects shared by at least two ingredients. void applyTools (int flags, float& value) const; From a04df37f83097ac5b88a6fd98a43623eea2caa97 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 28 Oct 2012 16:04:33 +0100 Subject: [PATCH 20/20] implemented looting corpses --- apps/openmw/mwclass/creature.cpp | 6 +++++- apps/openmw/mwclass/npc.cpp | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index e007c50ab3..e4ff3c95ba 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -12,6 +12,7 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/actiontalk.hpp" +#include "../mwworld/actionopen.hpp" #include "../mwworld/customdata.hpp" #include "../mwworld/containerstore.hpp" #include "../mwworld/physicssystem.hpp" @@ -130,7 +131,10 @@ namespace MWClass boost::shared_ptr Creature::activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const { - return boost::shared_ptr (new MWWorld::ActionTalk (ptr)); + if (MWWorld::Class::get (ptr).getCreatureStats (ptr).isDead()) + return boost::shared_ptr (new MWWorld::ActionOpen(ptr)); + else + return boost::shared_ptr (new MWWorld::ActionTalk (ptr)); } MWWorld::ContainerStore& Creature::getContainerStore (const MWWorld::Ptr& ptr) diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index ef3946efef..2e21f8f63f 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -20,6 +20,7 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/actiontalk.hpp" +#include "../mwworld/actionopen.hpp" #include "../mwworld/inventorystore.hpp" #include "../mwworld/customdata.hpp" #include "../mwworld/physicssystem.hpp" @@ -189,7 +190,10 @@ namespace MWClass boost::shared_ptr Npc::activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const { - return boost::shared_ptr (new MWWorld::ActionTalk (ptr)); + if (MWWorld::Class::get (ptr).getCreatureStats (ptr).isDead()) + return boost::shared_ptr (new MWWorld::ActionOpen(ptr)); + else + return boost::shared_ptr (new MWWorld::ActionTalk (ptr)); } MWWorld::ContainerStore& Npc::getContainerStore (const MWWorld::Ptr& ptr)