Use a separate class to handle activator mechanics

This commit is contained in:
Chris Robinson 2013-01-28 23:39:11 -08:00
parent 487c83e943
commit 8d98f3649c
12 changed files with 168 additions and 56 deletions

View file

@ -62,8 +62,9 @@ add_openmw_dir (mwclass
) )
add_openmw_dir (mwmechanics add_openmw_dir (mwmechanics
mechanicsmanagerimp stat character creaturestats magiceffects movement actors drawstate spells mechanicsmanagerimp stat character creaturestats magiceffects movement actors activators
activespells npcstats aipackage aisequence alchemy aiwander aitravel aifollow aiescort aiactivate drawstate spells activespells npcstats aipackage aisequence alchemy aiwander aitravel aifollow
aiescort aiactivate
) )
add_openmw_dir (mwbase add_openmw_dir (mwbase

View file

@ -37,21 +37,21 @@ namespace MWBase
virtual ~MechanicsManager() {} virtual ~MechanicsManager() {}
virtual void addActor (const MWWorld::Ptr& ptr) = 0; virtual void add (const MWWorld::Ptr& ptr) = 0;
///< Register an actor for stats management ///< Register an object for management
virtual void removeActor (const MWWorld::Ptr& ptr) = 0; virtual void remove (const MWWorld::Ptr& ptr) = 0;
///< Deregister an actor for stats management ///< Deregister an object for management
virtual void dropActors (const MWWorld::CellStore *cellStore) = 0; virtual void drop (const MWWorld::CellStore *cellStore) = 0;
///< Deregister all actors in the given cell. ///< Deregister all objects in the given cell.
virtual void watchActor (const MWWorld::Ptr& ptr) = 0; virtual void watchActor (const MWWorld::Ptr& ptr) = 0;
///< On each update look for changes in a previously registered actor and update the ///< On each update look for changes in a previously registered actor and update the
/// GUI accordingly. /// GUI accordingly.
virtual void update (float duration, bool paused) = 0; virtual void update (float duration, bool paused) = 0;
///< Update actor stats and store desired velocity vectors in \a movement ///< Update objects
/// ///
/// \param paused In game type does not currently advance (this usually means some GUI /// \param paused In game type does not currently advance (this usually means some GUI
/// component is up). /// component is up).

View file

@ -32,7 +32,7 @@ namespace MWClass
const std::string model = getModel(ptr); const std::string model = getModel(ptr);
if(!model.empty()) if(!model.empty())
physics.addObject(ptr); physics.addObject(ptr);
MWBase::Environment::get().getMechanicsManager()->addActor(ptr); MWBase::Environment::get().getMechanicsManager()->add(ptr);
} }
std::string Activator::getModel(const MWWorld::Ptr &ptr) const std::string Activator::getModel(const MWWorld::Ptr &ptr) const

View file

@ -97,7 +97,7 @@ namespace MWClass
const std::string model = getModel(ptr); const std::string model = getModel(ptr);
if(!model.empty()) if(!model.empty())
physics.addActor(ptr); physics.addActor(ptr);
MWBase::Environment::get().getMechanicsManager()->addActor (ptr); MWBase::Environment::get().getMechanicsManager()->add(ptr);
} }
std::string Creature::getModel(const MWWorld::Ptr &ptr) const std::string Creature::getModel(const MWWorld::Ptr &ptr) const

View file

@ -142,7 +142,7 @@ namespace MWClass
void Npc::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const void Npc::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const
{ {
physics.addActor(ptr); physics.addActor(ptr);
MWBase::Environment::get().getMechanicsManager()->addActor(ptr); MWBase::Environment::get().getMechanicsManager()->add(ptr);
} }
std::string Npc::getModel(const MWWorld::Ptr &ptr) const std::string Npc::getModel(const MWWorld::Ptr &ptr) const

View file

@ -0,0 +1,62 @@
#include "activators.hpp"
#include <OgreVector3.h>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
namespace MWMechanics
{
Activators::Activators()
{
}
void Activators::addActivator (const MWWorld::Ptr& ptr)
{
MWRender::Animation *anim = MWBase::Environment::get().getWorld()->getAnimation(ptr);
mActivators.insert(std::make_pair(ptr, CharacterController(ptr, anim, CharState_Idle, true)));
}
void Activators::removeActivator (const MWWorld::Ptr& ptr)
{
PtrControllerMap::iterator iter = mActivators.find(ptr);
if(iter != mActivators.end())
mActivators.erase(iter);
}
void Activators::dropActivators (const MWWorld::Ptr::CellStore *cellStore)
{
PtrControllerMap::iterator iter = mActivators.begin();
while(iter != mActivators.end())
{
if(iter->first.getCell()==cellStore)
mActivators.erase(iter++);
else
++iter;
}
}
void Activators::update(float duration, bool paused)
{
if(!paused)
{
for(PtrControllerMap::iterator iter(mActivators.begin());iter != mActivators.end();++iter)
iter->second.update(duration);
}
}
void Activators::playAnimationGroup(const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number)
{
PtrControllerMap::iterator iter = mActivators.find(ptr);
if(iter != mActivators.end())
iter->second.playGroup(groupName, mode, number);
}
void Activators::skipAnimation(const MWWorld::Ptr& ptr)
{
PtrControllerMap::iterator iter = mActivators.find(ptr);
if(iter != mActivators.end())
iter->second.skipAnim();
}
}

View file

@ -0,0 +1,42 @@
#ifndef GAME_MWMECHANICS_ACTIVATORS_H
#define GAME_MWMECHANICS_ACTOVATRS_H
#include <string>
#include <map>
#include "character.hpp"
namespace MWWorld
{
class Ptr;
class CellStore;
}
namespace MWMechanics
{
class Activators
{
typedef std::map<MWWorld::Ptr,CharacterController> PtrControllerMap;
PtrControllerMap mActivators;
public:
Activators();
void addActivator (const MWWorld::Ptr& ptr);
///< Register an activator
void removeActivator (const MWWorld::Ptr& ptr);
///< Deregister an activator
void dropActivators (const MWWorld::CellStore *cellStore);
///< Deregister all activators in the given cell.
void update (float duration, bool paused);
///< Update activator animations
void playAnimationGroup(const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number);
void skipAnimation(const MWWorld::Ptr& ptr);
};
}
#endif

View file

@ -166,9 +166,7 @@ namespace MWMechanics
void Actors::addActor (const MWWorld::Ptr& ptr) void Actors::addActor (const MWWorld::Ptr& ptr)
{ {
MWRender::Animation *anim = MWBase::Environment::get().getWorld()->getAnimation(ptr); MWRender::Animation *anim = MWBase::Environment::get().getWorld()->getAnimation(ptr);
/* Kind of a hack. Activators need a character controller to manage an idle state. */ if(!MWWorld::Class::get(ptr).getCreatureStats(ptr).isDead())
if(ptr.getTypeName() == typeid(ESM::Activator).name() ||
!MWWorld::Class::get(ptr).getCreatureStats(ptr).isDead())
mActors.insert(std::make_pair(ptr, CharacterController(ptr, anim, CharState_Idle, true))); mActors.insert(std::make_pair(ptr, CharacterController(ptr, anim, CharState_Idle, true)));
else else
mActors.insert(std::make_pair(ptr, CharacterController(ptr, anim, CharState_Dead, false))); mActors.insert(std::make_pair(ptr, CharacterController(ptr, anim, CharState_Dead, false)));
@ -205,11 +203,6 @@ namespace MWMechanics
PtrControllerMap::iterator iter(mActors.begin()); PtrControllerMap::iterator iter(mActors.begin());
while(iter != mActors.end()) while(iter != mActors.end())
{ {
if(iter->first.getTypeName() == typeid(ESM::Activator).name())
{
iter++;
continue;
}
if(!MWWorld::Class::get(iter->first).getCreatureStats(iter->first).isDead()) if(!MWWorld::Class::get(iter->first).getCreatureStats(iter->first).isDead())
{ {
if(iter->second.getState() == CharState_Dead) if(iter->second.getState() == CharState_Dead)
@ -304,10 +297,7 @@ namespace MWMechanics
void Actors::restoreDynamicStats() void Actors::restoreDynamicStats()
{ {
for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();++iter) for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();++iter)
{ calculateRestoration(iter->first, 3600);
if(iter->first.getTypeName() != typeid(ESM::Activator).name())
calculateRestoration(iter->first, 3600);
}
} }
int Actors::countDeaths (const std::string& id) const int Actors::countDeaths (const std::string& id) const

View file

@ -175,33 +175,37 @@ namespace MWMechanics
buildPlayer(); buildPlayer();
} }
void MechanicsManager::addActor (const MWWorld::Ptr& ptr) void MechanicsManager::add(const MWWorld::Ptr& ptr)
{ {
mActors.addActor (ptr); if(ptr.getTypeName() == typeid(ESM::Activator).name())
mActivators.addActivator(ptr);
else
mActors.addActor(ptr);
} }
void MechanicsManager::removeActor (const MWWorld::Ptr& ptr) void MechanicsManager::remove(const MWWorld::Ptr& ptr)
{ {
if (ptr==mWatched) if(ptr == mWatched)
mWatched = MWWorld::Ptr();
mActors.removeActor(ptr);
}
void MechanicsManager::drop(const MWWorld::CellStore *cellStore)
{
if(!mWatched.isEmpty() && mWatched.getCell() == cellStore)
mWatched = MWWorld::Ptr(); mWatched = MWWorld::Ptr();
mActors.removeActor (ptr); mActors.dropActors(cellStore);
mActivators.dropActivators(cellStore);
} }
void MechanicsManager::dropActors (const MWWorld::Ptr::CellStore *cellStore)
{
if (!mWatched.isEmpty() && mWatched.getCell()==cellStore)
mWatched = MWWorld::Ptr();
mActors.dropActors (cellStore); void MechanicsManager::watchActor(const MWWorld::Ptr& ptr)
}
void MechanicsManager::watchActor (const MWWorld::Ptr& ptr)
{ {
mWatched = ptr; mWatched = ptr;
} }
void MechanicsManager::update (float duration, bool paused) void MechanicsManager::update(float duration, bool paused)
{ {
if (!mWatched.isEmpty()) if (!mWatched.isEmpty())
{ {
@ -297,7 +301,8 @@ namespace MWMechanics
winMgr->configureSkills (majorSkills, minorSkills); winMgr->configureSkills (majorSkills, minorSkills);
} }
mActors.update (duration, paused); mActors.update(duration, paused);
mActivators.update(duration, paused);
} }
void MechanicsManager::restoreDynamicStats() void MechanicsManager::restoreDynamicStats()
@ -631,11 +636,17 @@ namespace MWMechanics
void MechanicsManager::playAnimationGroup(const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number) void MechanicsManager::playAnimationGroup(const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number)
{ {
mActors.playAnimationGroup(ptr, groupName, mode, number); if(ptr.getTypeName() == typeid(ESM::Activator).name())
mActivators.playAnimationGroup(ptr, groupName, mode, number);
else
mActors.playAnimationGroup(ptr, groupName, mode, number);
} }
void MechanicsManager::skipAnimation(const MWWorld::Ptr& ptr) void MechanicsManager::skipAnimation(const MWWorld::Ptr& ptr)
{ {
mActors.skipAnimation(ptr); if(ptr.getTypeName() == typeid(ESM::Activator).name())
mActivators.skipAnimation(ptr);
else
mActors.skipAnimation(ptr);
} }
} }

View file

@ -7,6 +7,7 @@
#include "creaturestats.hpp" #include "creaturestats.hpp"
#include "npcstats.hpp" #include "npcstats.hpp"
#include "activators.hpp"
#include "actors.hpp" #include "actors.hpp"
namespace Ogre namespace Ogre
@ -29,6 +30,8 @@ namespace MWMechanics
bool mUpdatePlayer; bool mUpdatePlayer;
bool mClassSelected; bool mClassSelected;
bool mRaceSelected; bool mRaceSelected;
Activators mActivators;
Actors mActors; Actors mActors;
void buildPlayer(); void buildPlayer();
@ -39,21 +42,21 @@ namespace MWMechanics
MechanicsManager(); MechanicsManager();
virtual void addActor (const MWWorld::Ptr& ptr); virtual void add (const MWWorld::Ptr& ptr);
///< Register an actor for stats management ///< Register an object for management
virtual void removeActor (const MWWorld::Ptr& ptr); virtual void remove (const MWWorld::Ptr& ptr);
///< Deregister an actor for stats management ///< Deregister an object for management
virtual void dropActors (const MWWorld::CellStore *cellStore); virtual void drop(const MWWorld::CellStore *cellStore);
///< Deregister all actors in the given cell. ///< Deregister all objects in the given cell.
virtual void watchActor (const MWWorld::Ptr& ptr); virtual void watchActor(const MWWorld::Ptr& ptr);
///< On each update look for changes in a previously registered actor and update the ///< On each update look for changes in a previously registered actor and update the
/// GUI accordingly. /// GUI accordingly.
virtual void update (float duration, bool paused); virtual void update (float duration, bool paused);
///< Update actor stats and store desired velocity vectors in \a movement ///< Update objects
/// ///
/// \param paused In game type does not currently advance (this usually means some GUI /// \param paused In game type does not currently advance (this usually means some GUI
/// component is up). /// component is up).

View file

@ -100,7 +100,7 @@ namespace MWWorld
//mPhysics->removeObject("Unnamed_43"); //mPhysics->removeObject("Unnamed_43");
MWBase::Environment::get().getWorld()->getLocalScripts().clearCell (*iter); MWBase::Environment::get().getWorld()->getLocalScripts().clearCell (*iter);
MWBase::Environment::get().getMechanicsManager()->dropActors (*iter); MWBase::Environment::get().getMechanicsManager()->drop (*iter);
MWBase::Environment::get().getSoundManager()->stopSound (*iter); MWBase::Environment::get().getSoundManager()->stopSound (*iter);
mActiveCells.erase(*iter); mActiveCells.erase(*iter);
} }
@ -166,7 +166,7 @@ namespace MWWorld
MWBase::MechanicsManager *mechMgr = MWBase::MechanicsManager *mechMgr =
MWBase::Environment::get().getMechanicsManager(); MWBase::Environment::get().getMechanicsManager();
mechMgr->addActor(player); mechMgr->add(player);
mechMgr->watchActor(player); mechMgr->watchActor(player);
MWBase::Environment::get().getWindowManager()->changeCell(mCurrentCell); MWBase::Environment::get().getWindowManager()->changeCell(mCurrentCell);
@ -179,7 +179,7 @@ namespace MWWorld
mRendering.preCellChange(mCurrentCell); mRendering.preCellChange(mCurrentCell);
// remove active // remove active
MWBase::Environment::get().getMechanicsManager()->removeActor (MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); MWBase::Environment::get().getMechanicsManager()->remove(MWBase::Environment::get().getWorld()->getPlayer().getPlayer());
CellStoreCollection::iterator active = mActiveCells.begin(); CellStoreCollection::iterator active = mActiveCells.begin();
@ -443,7 +443,7 @@ namespace MWWorld
void Scene::removeObjectFromScene (const Ptr& ptr) void Scene::removeObjectFromScene (const Ptr& ptr)
{ {
MWBase::Environment::get().getMechanicsManager()->removeActor (ptr); MWBase::Environment::get().getMechanicsManager()->remove (ptr);
MWBase::Environment::get().getSoundManager()->stopSound3D (ptr); MWBase::Environment::get().getSoundManager()->stopSound3D (ptr);
mPhysics->removeObject (ptr.getRefData().getHandle()); mPhysics->removeObject (ptr.getRefData().getHandle());
mRendering.removeObject (ptr); mRendering.removeObject (ptr);

View file

@ -700,6 +700,7 @@ namespace MWWorld
if (*currCell != newCell) if (*currCell != newCell)
{ {
if (isPlayer) if (isPlayer)
{
if (!newCell.isExterior()) if (!newCell.isExterior())
changeToInteriorCell(Misc::StringUtils::lowerCase(newCell.mCell->mName), pos); changeToInteriorCell(Misc::StringUtils::lowerCase(newCell.mCell->mName), pos);
else else
@ -708,7 +709,9 @@ namespace MWWorld
int cellY = newCell.mCell->getGridY(); int cellY = newCell.mCell->getGridY();
mWorldScene->changeCell(cellX, cellY, pos, false); mWorldScene->changeCell(cellX, cellY, pos, false);
} }
else { }
else
{
if (!mWorldScene->isCellActive(*currCell)) if (!mWorldScene->isCellActive(*currCell))
copyObjectToCell(ptr, newCell, pos); copyObjectToCell(ptr, newCell, pos);
else if (!mWorldScene->isCellActive(newCell)) else if (!mWorldScene->isCellActive(newCell))
@ -732,8 +735,8 @@ namespace MWWorld
MWBase::MechanicsManager *mechMgr = MWBase::MechanicsManager *mechMgr =
MWBase::Environment::get().getMechanicsManager(); MWBase::Environment::get().getMechanicsManager();
mechMgr->removeActor(ptr); mechMgr->remove(ptr);
mechMgr->addActor(copy); mechMgr->add(copy);
} }
else else
{ {