1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-01-20 08:53:52 +00:00

Implement Calm effect removing combat packages (Fixes #1985)

This commit is contained in:
scrawl 2014-12-14 19:35:34 +01:00
parent 4f3995a4d8
commit 2b78e9795d
11 changed files with 49 additions and 4 deletions

View file

@ -891,4 +891,10 @@ namespace MWClass
MWWorld::ContainerStore& store = getContainerStore(ptr); MWWorld::ContainerStore& store = getContainerStore(ptr);
store.restock(list, ptr, ptr.getCellRef().getRefId(), ptr.getCellRef().getFaction()); store.restock(list, ptr, ptr.getCellRef().getRefId(), ptr.getCellRef().getFaction());
} }
int Creature::getBaseFightRating(const MWWorld::Ptr &ptr) const
{
MWWorld::LiveCellRef<ESM::Creature> *ref = ptr.get<ESM::Creature>();
return ref->mBase->mAiData.mFight;
}
} }

View file

@ -154,6 +154,8 @@ namespace MWClass
virtual void respawn (const MWWorld::Ptr& ptr) const; virtual void respawn (const MWWorld::Ptr& ptr) const;
virtual void restock (const MWWorld::Ptr &ptr) const; virtual void restock (const MWWorld::Ptr &ptr) const;
virtual int getBaseFightRating(const MWWorld::Ptr &ptr) const;
}; };
} }

View file

@ -1266,6 +1266,7 @@ namespace MWClass
// TODO: I have no idea what these are supposed to do for NPCs since they use // 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 // voiced dialog for various conditions like health loss and combat taunts. Maybe
// only for biped creatures? // only for biped creatures?
if(name == "moan") if(name == "moan")
return ""; return "";
if(name == "roar") if(name == "roar")
@ -1380,4 +1381,10 @@ namespace MWClass
MWWorld::ContainerStore& store = getContainerStore(ptr); MWWorld::ContainerStore& store = getContainerStore(ptr);
store.restock(list, ptr, ptr.getCellRef().getRefId(), ptr.getCellRef().getFaction()); store.restock(list, ptr, ptr.getCellRef().getRefId(), ptr.getCellRef().getFaction());
} }
int Npc::getBaseFightRating (const MWWorld::Ptr& ptr) const
{
MWWorld::LiveCellRef<ESM::NPC> *ref = ptr.get<ESM::NPC>();
return ref->mBase->mAiData.mFight;
}
} }

View file

@ -185,6 +185,8 @@ namespace MWClass
virtual void respawn (const MWWorld::Ptr& ptr) const; virtual void respawn (const MWWorld::Ptr& ptr) const;
virtual void restock (const MWWorld::Ptr& ptr) const; virtual void restock (const MWWorld::Ptr& ptr) const;
virtual int getBaseFightRating (const MWWorld::Ptr& ptr) const;
}; };
} }

View file

@ -677,6 +677,19 @@ namespace MWMechanics
// TODO: dirty flag for magic effects to avoid some unnecessary work below? // 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<AiPackage*>::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 // Update bound effects
static std::map<int, std::string> boundItemsMap; static std::map<int, std::string> boundItemsMap;
if (boundItemsMap.empty()) if (boundItemsMap.empty())
@ -1056,6 +1069,7 @@ namespace MWMechanics
// Reset factors to attack // Reset factors to attack
creatureStats.setAttacked(false); creatureStats.setAttacked(false);
creatureStats.setAlarmed(false); creatureStats.setAlarmed(false);
creatureStats.setAiSetting(CreatureStats::AI_Fight, ptr.getClass().getBaseFightRating(ptr));
// Update witness crime id // Update witness crime id
npcStats.setCrimeId(-1); npcStats.setCrimeId(-1);

View file

@ -455,7 +455,10 @@ namespace MWMechanics
// Default to hand-to-hand combat // Default to hand-to-hand combat
boost::shared_ptr<Action> bestAction (new ActionWeapon(MWWorld::Ptr())); boost::shared_ptr<Action> bestAction (new ActionWeapon(MWWorld::Ptr()));
if (actor.getClass().isNpc() && actor.getClass().getNpcStats(actor).isWerewolf()) if (actor.getClass().isNpc() && actor.getClass().getNpcStats(actor).isWerewolf())
{
bestAction->prepare(actor);
return bestAction; return bestAction;
}
if (actor.getClass().hasInventoryStore(actor)) if (actor.getClass().hasInventoryStore(actor))
{ {

View file

@ -86,15 +86,14 @@ std::list<AiPackage*>::const_iterator AiSequence::end() const
return mPackages.end(); return mPackages.end();
} }
void AiSequence::erase(std::list<AiPackage*>::const_iterator package) std::list<AiPackage*>::const_iterator AiSequence::erase(std::list<AiPackage*>::const_iterator package)
{ {
// Not sure if manually terminated packages should trigger mDone, probably not? // Not sure if manually terminated packages should trigger mDone, probably not?
for(std::list<AiPackage*>::iterator it = mPackages.begin(); it != mPackages.end(); ++it) for(std::list<AiPackage*>::iterator it = mPackages.begin(); it != mPackages.end(); ++it)
{ {
if (package == it) if (package == it)
{ {
mPackages.erase(it); return mPackages.erase(it);
return;
} }
} }
throw std::runtime_error("can't find package to erase"); throw std::runtime_error("can't find package to erase");

View file

@ -61,7 +61,7 @@ namespace MWMechanics
std::list<AiPackage*>::const_iterator begin() const; std::list<AiPackage*>::const_iterator begin() const;
std::list<AiPackage*>::const_iterator end() const; std::list<AiPackage*>::const_iterator end() const;
void erase (std::list<AiPackage*>::const_iterator package); std::list<AiPackage*>::const_iterator erase (std::list<AiPackage*>::const_iterator package);
/// Returns currently executing AiPackage type /// Returns currently executing AiPackage type
/** \see enum AiPackage::TypeId **/ /** \see enum AiPackage::TypeId **/

View file

@ -1096,6 +1096,11 @@ namespace MWMechanics
{ {
startCombat(*it, player); 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 // Set the crime ID, which we will use to calm down participants
// once the bounty has been paid. // once the bounty has been paid.
it->getClass().getNpcStats(*it).setCrimeId(id); it->getClass().getNpcStats(*it).setCrimeId(id);

View file

@ -429,4 +429,9 @@ namespace MWWorld
{ {
return std::string(); return std::string();
} }
int Class::getBaseFightRating(const Ptr &ptr) const
{
throw std::runtime_error("class does not support fight rating");
}
} }

View file

@ -339,6 +339,8 @@ namespace MWWorld
/// Returns sound id /// Returns sound id
virtual std::string getSound(const MWWorld::Ptr& ptr) const; virtual std::string getSound(const MWWorld::Ptr& ptr) const;
virtual int getBaseFightRating (const MWWorld::Ptr& ptr) const;
}; };
} }