Add MWMechanics::Actor class for temporary actor state, move AiState there

moveref
scrawl 10 years ago
parent 42d63a4eb2
commit edc128572d

@ -76,7 +76,7 @@ add_openmw_dir (mwmechanics
mechanicsmanagerimp stat character creaturestats magiceffects movement actors objects
drawstate spells activespells npcstats aipackage aisequence aipursue alchemy aiwander aitravel aifollow aiavoiddoor
aiescort aiactivate aicombat repair enchanting pathfinding pathgrid security spellsuccess spellcasting
disease pickpocket levelledlist combat steering obstacle autocalcspell difficultyscaling aicombataction
disease pickpocket levelledlist combat steering obstacle autocalcspell difficultyscaling aicombataction actor
)
add_openmw_dir (mwstate

@ -0,0 +1,28 @@
#include "actor.hpp"
#include "character.hpp"
namespace MWMechanics
{
Actor::Actor(const MWWorld::Ptr &ptr, MWRender::Animation *animation)
{
mCharacterController.reset(new CharacterController(ptr, animation));
}
void Actor::updatePtr(const MWWorld::Ptr &newPtr)
{
mCharacterController->updatePtr(newPtr);
}
CharacterController* Actor::getCharacterController()
{
return mCharacterController.get();
}
AiState& Actor::getAiState()
{
return mAiState;
}
}

@ -0,0 +1,42 @@
#ifndef OPENMW_MECHANICS_ACTOR_H
#define OPENMW_MECHANICS_ACTOR_H
#include <memory>
#include "aistate.hpp"
namespace MWRender
{
class Animation;
}
namespace MWWorld
{
class Ptr;
}
namespace MWMechanics
{
class CharacterController;
/// @brief Holds temporary state for an actor that will be discarded when the actor leaves the scene.
class Actor
{
public:
Actor(const MWWorld::Ptr& ptr, MWRender::Animation* animation);
/// Notify this actor of its new base object Ptr, use when the object changed cells
void updatePtr(const MWWorld::Ptr& newPtr);
CharacterController* getCharacterController();
AiState& getAiState();
private:
std::auto_ptr<CharacterController> mCharacterController;
AiState mAiState;
};
}
#endif

@ -35,6 +35,8 @@
#include "aifollow.hpp"
#include "aipursue.hpp"
#include "actor.hpp"
namespace
{
@ -920,10 +922,10 @@ namespace MWMechanics
void Actors::updateDrowning(const MWWorld::Ptr& ptr, float duration)
{
PtrControllerMap::iterator it = mActors.find(ptr);
PtrActorMap::iterator it = mActors.find(ptr);
if (it == mActors.end())
return;
CharacterController* ctrl = it->second;
CharacterController* ctrl = it->second->getCharacterController();
NpcStats &stats = ptr.getClass().getNpcStats(ptr);
MWBase::World *world = MWBase::Environment::get().getWorld();
@ -1128,14 +1130,14 @@ namespace MWMechanics
removeActor(ptr);
MWRender::Animation *anim = MWBase::Environment::get().getWorld()->getAnimation(ptr);
mActors.insert(std::make_pair(ptr, new CharacterController(ptr, anim)));
mActors.insert(std::make_pair(ptr, new Actor(ptr, anim)));
if (updateImmediately)
mActors[ptr]->update(0);
mActors[ptr]->getCharacterController()->update(0);
}
void Actors::removeActor (const MWWorld::Ptr& ptr)
{
PtrControllerMap::iterator iter = mActors.find(ptr);
PtrActorMap::iterator iter = mActors.find(ptr);
if(iter != mActors.end())
{
delete iter->second;
@ -1145,20 +1147,20 @@ namespace MWMechanics
void Actors::updateActor(const MWWorld::Ptr &old, const MWWorld::Ptr &ptr)
{
PtrControllerMap::iterator iter = mActors.find(old);
PtrActorMap::iterator iter = mActors.find(old);
if(iter != mActors.end())
{
CharacterController *ctrl = iter->second;
Actor *actor = iter->second;
mActors.erase(iter);
ctrl->updatePtr(ptr);
mActors.insert(std::make_pair(ptr, ctrl));
actor->updatePtr(ptr);
mActors.insert(std::make_pair(ptr, actor));
}
}
void Actors::dropActors (const MWWorld::CellStore *cellStore, const MWWorld::Ptr& ignore)
{
PtrControllerMap::iterator iter = mActors.begin();
PtrActorMap::iterator iter = mActors.begin();
while(iter != mActors.end())
{
if(iter->first.getCell()==cellStore && iter->first != ignore)
@ -1192,8 +1194,10 @@ namespace MWMechanics
// using higher values will make a quest in Bloodmoon harder or impossible to complete (bug #1876)
const float sqrProcessingDistance = 7168*7168;
/// \todo move update logic to Actor class where appropriate
// AI and magic effects update
for(PtrControllerMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter)
for(PtrActorMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter)
{
if (!iter->first.getClass().getCreatureStats(iter->first).isDead())
{
@ -1207,7 +1211,7 @@ namespace MWMechanics
if (iter->first != player)
adjustCommandedActor(iter->first);
for(PtrControllerMap::iterator it(mActors.begin()); it != mActors.end(); ++it)
for(PtrActorMap::iterator it(mActors.begin()); it != mActors.end(); ++it)
{
if (it->first == iter->first || iter->first == player) // player is not AI-controlled
continue;
@ -1219,13 +1223,13 @@ namespace MWMechanics
float sqrHeadTrackDistance = std::numeric_limits<float>::max();
MWWorld::Ptr headTrackTarget;
for(PtrControllerMap::iterator it(mActors.begin()); it != mActors.end(); ++it)
for(PtrActorMap::iterator it(mActors.begin()); it != mActors.end(); ++it)
{
if (it->first == iter->first)
continue;
updateHeadTracking(iter->first, it->first, headTrackTarget, sqrHeadTrackDistance);
}
iter->second->setHeadTrackTarget(headTrackTarget);
iter->second->getCharacterController()->setHeadTrackTarget(headTrackTarget);
}
if (iter->first.getClass().isNpc() && iter->first != player)
@ -1254,12 +1258,12 @@ namespace MWMechanics
// Reaching the text keys may trigger Hit / Spellcast (and as such, particles),
// so updating VFX immediately after that would just remove the particle effects instantly.
// There needs to be a magic effect update in between.
for(PtrControllerMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter)
iter->second->updateContinuousVfx();
for(PtrActorMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter)
iter->second->getCharacterController()->updateContinuousVfx();
// Animation/movement update
CharacterController* playerCharacter = NULL;
for(PtrControllerMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter)
for(PtrActorMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter)
{
if (iter->first != player &&
Ogre::Vector3(player.getRefData().getPosition().pos).squaredDistance(Ogre::Vector3(iter->first.getRefData().getPosition().pos))
@ -1268,22 +1272,22 @@ namespace MWMechanics
if (iter->first.getClass().getCreatureStats(iter->first).getMagicEffects().get(
ESM::MagicEffect::Paralyze).getMagnitude() > 0)
iter->second->skipAnim();
iter->second->getCharacterController()->skipAnim();
// Handle player last, in case a cell transition occurs by casting a teleportation spell
// (would invalidate the iterator)
if (iter->first.getCellRef().getRefId() == "player")
{
playerCharacter = iter->second;
playerCharacter = iter->second->getCharacterController();
continue;
}
iter->second->update(duration);
iter->second->getCharacterController()->update(duration);
}
if (playerCharacter)
playerCharacter->update(duration);
for(PtrControllerMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter)
for(PtrActorMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter)
{
const MWWorld::Class &cls = iter->first.getClass();
CreatureStats &stats = cls.getCreatureStats(iter->first);
@ -1341,7 +1345,7 @@ namespace MWMechanics
bool detected = false;
for (PtrControllerMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter)
for (PtrActorMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter)
{
if (iter->first == player) // not the player
continue;
@ -1384,32 +1388,32 @@ namespace MWMechanics
void Actors::killDeadActors()
{
for(PtrControllerMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter)
for(PtrActorMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter)
{
const MWWorld::Class &cls = iter->first.getClass();
CreatureStats &stats = cls.getCreatureStats(iter->first);
if(!stats.isDead())
{
if(iter->second->isDead())
if(iter->second->getCharacterController()->isDead())
{
// Actor has been resurrected. Notify the CharacterController and re-enable collision.
MWBase::Environment::get().getWorld()->enableActorCollision(iter->first, true);
iter->second->resurrect();
iter->second->getCharacterController()->resurrect();
}
if(!stats.isDead())
continue;
}
if (iter->second->kill())
if (iter->second->getCharacterController()->kill())
{
iter->first.getClass().getCreatureStats(iter->first).notifyDied();
++mDeathCount[Misc::StringUtils::lowerCase(iter->first.getCellRef().getRefId())];
// Make sure spell effects with CasterLinked flag are removed
for (PtrControllerMap::iterator iter2(mActors.begin());iter2 != mActors.end();++iter2)
for (PtrActorMap::iterator iter2(mActors.begin());iter2 != mActors.end();++iter2)
{
MWMechanics::ActiveSpells& spells = iter2->first.getClass().getCreatureStats(iter2->first).getActiveSpells();
spells.purge(stats.getActorId());
@ -1438,7 +1442,7 @@ namespace MWMechanics
void Actors::restoreDynamicStats(bool sleep)
{
for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();++iter)
for(PtrActorMap::iterator iter(mActors.begin());iter != mActors.end();++iter)
restoreDynamicStats(iter->first, sleep);
}
@ -1470,35 +1474,35 @@ namespace MWMechanics
void Actors::forceStateUpdate(const MWWorld::Ptr & ptr)
{
PtrControllerMap::iterator iter = mActors.find(ptr);
PtrActorMap::iterator iter = mActors.find(ptr);
if(iter != mActors.end())
iter->second->forceStateUpdate();
iter->second->getCharacterController()->forceStateUpdate();
}
void Actors::playAnimationGroup(const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number)
{
PtrControllerMap::iterator iter = mActors.find(ptr);
PtrActorMap::iterator iter = mActors.find(ptr);
if(iter != mActors.end())
iter->second->playGroup(groupName, mode, number);
iter->second->getCharacterController()->playGroup(groupName, mode, number);
}
void Actors::skipAnimation(const MWWorld::Ptr& ptr)
{
PtrControllerMap::iterator iter = mActors.find(ptr);
PtrActorMap::iterator iter = mActors.find(ptr);
if(iter != mActors.end())
iter->second->skipAnim();
iter->second->getCharacterController()->skipAnim();
}
bool Actors::checkAnimationPlaying(const MWWorld::Ptr& ptr, const std::string& groupName)
{
PtrControllerMap::iterator iter = mActors.find(ptr);
PtrActorMap::iterator iter = mActors.find(ptr);
if(iter != mActors.end())
return iter->second->isAnimPlaying(groupName);
return iter->second->getCharacterController()->isAnimPlaying(groupName);
return false;
}
void Actors::getObjectsInRange(const Ogre::Vector3& position, float radius, std::vector<MWWorld::Ptr>& out)
{
for (PtrControllerMap::iterator iter = mActors.begin(); iter != mActors.end(); ++iter)
for (PtrActorMap::iterator iter = mActors.begin(); iter != mActors.end(); ++iter)
{
if (Ogre::Vector3(iter->first.getRefData().getPosition().pos).squaredDistance(position) <= radius*radius)
out.push_back(iter->first);
@ -1508,7 +1512,7 @@ namespace MWMechanics
std::list<MWWorld::Ptr> Actors::getActorsFollowing(const MWWorld::Ptr& actor)
{
std::list<MWWorld::Ptr> list;
for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();++iter)
for(PtrActorMap::iterator iter(mActors.begin());iter != mActors.end();++iter)
{
const MWWorld::Class &cls = iter->first.getClass();
CreatureStats &stats = cls.getCreatureStats(iter->first);
@ -1538,7 +1542,7 @@ namespace MWMechanics
std::list<int> Actors::getActorsFollowingIndices(const MWWorld::Ptr &actor)
{
std::list<int> list;
for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();++iter)
for(PtrActorMap::iterator iter(mActors.begin());iter != mActors.end();++iter)
{
const MWWorld::Class &cls = iter->first.getClass();
CreatureStats &stats = cls.getCreatureStats(iter->first);
@ -1611,7 +1615,7 @@ namespace MWMechanics
void Actors::clear()
{
PtrControllerMap::iterator it(mActors.begin());
PtrActorMap::iterator it(mActors.begin());
for (; it != mActors.end(); ++it)
{
delete it->second;
@ -1631,10 +1635,10 @@ namespace MWMechanics
bool Actors::isReadyToBlock(const MWWorld::Ptr &ptr) const
{
PtrControllerMap::const_iterator it = mActors.find(ptr);
PtrActorMap::const_iterator it = mActors.find(ptr);
if (it == mActors.end())
return false;
return it->second->isReadyToBlock();
return it->second->getCharacterController()->isReadyToBlock();
}
}

@ -6,7 +6,6 @@
#include <string>
#include <map>
#include "character.hpp"
#include "movement.hpp"
#include "../mwbase/world.hpp"
@ -23,6 +22,8 @@ namespace MWWorld
namespace MWMechanics
{
class Actor;
class Actors
{
std::map<std::string, int> mDeathCount;
@ -51,10 +52,10 @@ namespace MWMechanics
Actors();
~Actors();
typedef std::map<MWWorld::Ptr,CharacterController*> PtrControllerMap;
typedef std::map<MWWorld::Ptr,Actor*> PtrActorMap;
PtrControllerMap::const_iterator begin() { return mActors.begin(); }
PtrControllerMap::const_iterator end() { return mActors.end(); }
PtrActorMap::const_iterator begin() { return mActors.begin(); }
PtrActorMap::const_iterator end() { return mActors.end(); }
/// Update magic effects for an actor. Usually done automatically once per frame, but if we're currently
/// paused we may want to do it manually (after equipping permanent enchantment)
@ -131,7 +132,7 @@ namespace MWMechanics
bool isReadyToBlock(const MWWorld::Ptr& ptr) const;
private:
PtrControllerMap mActors;
PtrActorMap mActors;
};
}

@ -6,7 +6,6 @@
#include <components/esm/loadmgef.hpp>
#include "../mwworld/ptr.hpp"
#include "aistate.hpp"
namespace MWWorld
{
@ -140,9 +139,6 @@ class CharacterController
MWWorld::Ptr mPtr;
MWRender::Animation *mAnimation;
//
AiState mAiState;
typedef std::deque<std::pair<std::string,size_t> > AnimationQueue;
AnimationQueue mAnimQueue;
@ -229,8 +225,6 @@ public:
void forceStateUpdate();
AiState& getAiState() { return mAiState; }
bool isReadyToBlock() const;
bool isKnockedOut() const;

@ -1289,7 +1289,7 @@ namespace MWMechanics
// if guard starts combat with player, guards pursuing player should do the same
if (ptr.getClass().isClass(ptr, "Guard"))
{
for (Actors::PtrControllerMap::const_iterator iter = mActors.begin(); iter != mActors.end(); ++iter)
for (Actors::PtrActorMap::const_iterator iter = mActors.begin(); iter != mActors.end(); ++iter)
{
if (iter->first.getClass().isClass(iter->first, "Guard"))
{

Loading…
Cancel
Save