diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index 1b005270f..519216ec9 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -891,4 +891,10 @@ namespace MWClass MWWorld::ContainerStore& store = getContainerStore(ptr); store.restock(list, ptr, ptr.getCellRef().getRefId(), ptr.getCellRef().getFaction()); } + + int Creature::getBaseFightRating(const MWWorld::Ptr &ptr) const + { + MWWorld::LiveCellRef *ref = ptr.get(); + return ref->mBase->mAiData.mFight; + } } diff --git a/apps/openmw/mwclass/creature.hpp b/apps/openmw/mwclass/creature.hpp index 1820d4ea4..c52e85534 100644 --- a/apps/openmw/mwclass/creature.hpp +++ b/apps/openmw/mwclass/creature.hpp @@ -154,6 +154,8 @@ namespace MWClass virtual void respawn (const MWWorld::Ptr& ptr) const; virtual void restock (const MWWorld::Ptr &ptr) const; + + virtual int getBaseFightRating(const MWWorld::Ptr &ptr) const; }; } diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 3da744691..a3ebef582 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -1266,6 +1266,7 @@ namespace MWClass // TODO: I have no idea what these are supposed to do for NPCs since they use // voiced dialog for various conditions like health loss and combat taunts. Maybe // only for biped creatures? + if(name == "moan") return ""; if(name == "roar") @@ -1380,4 +1381,10 @@ namespace MWClass MWWorld::ContainerStore& store = getContainerStore(ptr); store.restock(list, ptr, ptr.getCellRef().getRefId(), ptr.getCellRef().getFaction()); } + + int Npc::getBaseFightRating (const MWWorld::Ptr& ptr) const + { + MWWorld::LiveCellRef *ref = ptr.get(); + return ref->mBase->mAiData.mFight; + } } diff --git a/apps/openmw/mwclass/npc.hpp b/apps/openmw/mwclass/npc.hpp index a92e72af5..3bc450088 100644 --- a/apps/openmw/mwclass/npc.hpp +++ b/apps/openmw/mwclass/npc.hpp @@ -185,6 +185,8 @@ namespace MWClass virtual void respawn (const MWWorld::Ptr& ptr) const; virtual void restock (const MWWorld::Ptr& ptr) const; + + virtual int getBaseFightRating (const MWWorld::Ptr& ptr) const; }; } diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 0730a4660..fecf18986 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -677,6 +677,19 @@ namespace MWMechanics // TODO: dirty flag for magic effects to avoid some unnecessary work below? + // any value of calm > 0 will stop the actor from fighting + if ((creatureStats.getMagicEffects().get(ESM::MagicEffect::CalmHumanoid).getMagnitude() > 0 && ptr.getClass().isNpc()) + || (creatureStats.getMagicEffects().get(ESM::MagicEffect::CalmCreature).getMagnitude() > 0 && !ptr.getClass().isNpc())) + { + for (std::list::const_iterator it = creatureStats.getAiSequence().begin(); it != creatureStats.getAiSequence().end(); ) + { + if ((*it)->getTypeId() == AiPackage::TypeIdCombat) + it = creatureStats.getAiSequence().erase(it); + else + ++it; + } + } + // Update bound effects static std::map boundItemsMap; if (boundItemsMap.empty()) @@ -1056,6 +1069,7 @@ namespace MWMechanics // Reset factors to attack creatureStats.setAttacked(false); creatureStats.setAlarmed(false); + creatureStats.setAiSetting(CreatureStats::AI_Fight, ptr.getClass().getBaseFightRating(ptr)); // Update witness crime id npcStats.setCrimeId(-1); diff --git a/apps/openmw/mwmechanics/aicombataction.cpp b/apps/openmw/mwmechanics/aicombataction.cpp index 73cb27626..356955b22 100644 --- a/apps/openmw/mwmechanics/aicombataction.cpp +++ b/apps/openmw/mwmechanics/aicombataction.cpp @@ -455,7 +455,10 @@ namespace MWMechanics // Default to hand-to-hand combat boost::shared_ptr bestAction (new ActionWeapon(MWWorld::Ptr())); if (actor.getClass().isNpc() && actor.getClass().getNpcStats(actor).isWerewolf()) + { + bestAction->prepare(actor); return bestAction; + } if (actor.getClass().hasInventoryStore(actor)) { diff --git a/apps/openmw/mwmechanics/aisequence.cpp b/apps/openmw/mwmechanics/aisequence.cpp index 990145c8d..2ee898405 100644 --- a/apps/openmw/mwmechanics/aisequence.cpp +++ b/apps/openmw/mwmechanics/aisequence.cpp @@ -86,15 +86,14 @@ std::list::const_iterator AiSequence::end() const return mPackages.end(); } -void AiSequence::erase(std::list::const_iterator package) +std::list::const_iterator AiSequence::erase(std::list::const_iterator package) { // Not sure if manually terminated packages should trigger mDone, probably not? for(std::list::iterator it = mPackages.begin(); it != mPackages.end(); ++it) { if (package == it) { - mPackages.erase(it); - return; + return mPackages.erase(it); } } throw std::runtime_error("can't find package to erase"); diff --git a/apps/openmw/mwmechanics/aisequence.hpp b/apps/openmw/mwmechanics/aisequence.hpp index 25605ff44..460a411ba 100644 --- a/apps/openmw/mwmechanics/aisequence.hpp +++ b/apps/openmw/mwmechanics/aisequence.hpp @@ -61,7 +61,7 @@ namespace MWMechanics std::list::const_iterator begin() const; std::list::const_iterator end() const; - void erase (std::list::const_iterator package); + std::list::const_iterator erase (std::list::const_iterator package); /// Returns currently executing AiPackage type /** \see enum AiPackage::TypeId **/ diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index cd9f0d0f7..520b6b8a7 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -1096,6 +1096,11 @@ namespace MWMechanics { startCombat(*it, player); + // Apply aggression value to the base Fight rating, so that the actor can continue fighting + // after a Calm spell wears off + int fightBase = it->getClass().getCreatureStats(*it).getAiSetting(CreatureStats::AI_Fight).getBase(); + it->getClass().getCreatureStats(*it).setAiSetting(CreatureStats::AI_Fight, fightBase + aggression); + // Set the crime ID, which we will use to calm down participants // once the bounty has been paid. it->getClass().getNpcStats(*it).setCrimeId(id); diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index 0a8486209..7c9585834 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -429,4 +429,9 @@ namespace MWWorld { return std::string(); } + + int Class::getBaseFightRating(const Ptr &ptr) const + { + throw std::runtime_error("class does not support fight rating"); + } } diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index dcac16b06..cc18d830c 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -339,6 +339,8 @@ namespace MWWorld /// Returns sound id virtual std::string getSound(const MWWorld::Ptr& ptr) const; + + virtual int getBaseFightRating (const MWWorld::Ptr& ptr) const; }; }