Draft how to move temporary package state to CharacterController.

Example for a few values shown in AiWander.
deque
terrorfisch 10 years ago
parent 9ab8d0a8e6
commit 0871d45790

@ -25,6 +25,7 @@
#include "npcstats.hpp"
#include "creaturestats.hpp"
#include "movement.hpp"
#include "character.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/mechanicsmanager.hpp"
@ -1153,7 +1154,7 @@ namespace MWMechanics
updateCrimePersuit(iter->first, duration);
if (iter->first != player)
iter->first.getClass().getCreatureStats(iter->first).getAiSequence().execute(iter->first, duration);
iter->first.getClass().getCreatureStats(iter->first).getAiSequence().execute(iter->first,iter->second->getAiState(), duration);
CreatureStats &stats = iter->first.getClass().getCreatureStats(iter->first);
if(!stats.isDead())

@ -21,7 +21,7 @@ MWMechanics::AiActivate *MWMechanics::AiActivate::clone() const
{
return new AiActivate(*this);
}
bool MWMechanics::AiActivate::execute (const MWWorld::Ptr& actor,float duration)
bool MWMechanics::AiActivate::execute (const MWWorld::Ptr& actor, AiState& state, float duration)
{
ESM::Position pos = actor.getRefData().getPosition(); //position of the actor
const MWWorld::Ptr target = MWBase::Environment::get().getWorld()->searchPtr(mObjectId, false); //The target to follow

@ -28,7 +28,7 @@ namespace MWMechanics
AiActivate(const ESM::AiSequence::AiActivate* activate);
virtual AiActivate *clone() const;
virtual bool execute (const MWWorld::Ptr& actor,float duration);
virtual bool execute (const MWWorld::Ptr& actor, AiState& state, float duration);
virtual int getTypeId() const;
virtual void writeState(ESM::AiSequence::AiSequence& sequence) const;

@ -18,7 +18,7 @@ MWMechanics::AiAvoidDoor::AiAvoidDoor(const MWWorld::Ptr& doorPtr)
}
bool MWMechanics::AiAvoidDoor::execute (const MWWorld::Ptr& actor,float duration)
bool MWMechanics::AiAvoidDoor::execute (const MWWorld::Ptr& actor, AiState& state, float duration)
{
ESM::Position pos = actor.getRefData().getPosition();

@ -20,7 +20,7 @@ namespace MWMechanics
virtual AiAvoidDoor *clone() const;
virtual bool execute (const MWWorld::Ptr& actor,float duration);
virtual bool execute (const MWWorld::Ptr& actor, AiState& state, float duration);
virtual int getTypeId() const;

@ -170,7 +170,7 @@ namespace MWMechanics
* Use the Observer Pattern to co-ordinate attacks, provide intelligence on
* whether the target was hit, etc.
*/
bool AiCombat::execute (const MWWorld::Ptr& actor,float duration)
bool AiCombat::execute (const MWWorld::Ptr& actor, AiState& state, float duration)
{
//General description
if(actor.getClass().getCreatureStats(actor).isDead())

@ -42,7 +42,7 @@ namespace MWMechanics
virtual AiCombat *clone() const;
virtual bool execute (const MWWorld::Ptr& actor,float duration);
virtual bool execute (const MWWorld::Ptr& actor, AiState& state, float duration);
virtual int getTypeId() const;

@ -64,7 +64,7 @@ namespace MWMechanics
return new AiEscort(*this);
}
bool AiEscort::execute (const MWWorld::Ptr& actor,float duration)
bool AiEscort::execute (const MWWorld::Ptr& actor, AiState& state, float duration)
{
// If AiEscort has ran for as long or longer then the duration specified
// and the duration is not infinite, the package is complete.

@ -33,7 +33,7 @@ namespace MWMechanics
virtual AiEscort *clone() const;
virtual bool execute (const MWWorld::Ptr& actor,float duration);
virtual bool execute (const MWWorld::Ptr& actor, AiState& state, float duration);
virtual int getTypeId() const;

@ -41,7 +41,7 @@ MWMechanics::AiFollow::AiFollow(const ESM::AiSequence::AiFollow *follow)
}
bool MWMechanics::AiFollow::execute (const MWWorld::Ptr& actor,float duration)
bool MWMechanics::AiFollow::execute (const MWWorld::Ptr& actor, AiState& state, float duration)
{
MWWorld::Ptr target = getTarget();

@ -35,7 +35,7 @@ namespace MWMechanics
virtual AiFollow *clone() const;
virtual bool execute (const MWWorld::Ptr& actor,float duration);
virtual bool execute (const MWWorld::Ptr& actor, AiState& state, float duration);
virtual int getTypeId() const;

@ -6,6 +6,7 @@
#include "../mwbase/world.hpp"
#include "obstacle.hpp"
#include "aistate.hpp"
namespace MWWorld
{
@ -20,8 +21,10 @@ namespace ESM
}
}
namespace MWMechanics
{
/// \brief Base class for AI packages
class AiPackage
{
@ -50,7 +53,7 @@ namespace MWMechanics
/// Updates and runs the package (Should run every frame)
/// \return Package completed?
virtual bool execute (const MWWorld::Ptr& actor,float duration) = 0;
virtual bool execute (const MWWorld::Ptr& actor, AiState& state, float duration) = 0;
/// Returns the TypeID of the AiPackage
/// \see enum TypeId

@ -30,7 +30,7 @@ AiPursue *MWMechanics::AiPursue::clone() const
{
return new AiPursue(*this);
}
bool AiPursue::execute (const MWWorld::Ptr& actor, float duration)
bool AiPursue::execute (const MWWorld::Ptr& actor, AiState& state, float duration)
{
if(actor.getClass().getCreatureStats(actor).isDead())
return true;

@ -31,7 +31,7 @@ namespace MWMechanics
AiPursue(const ESM::AiSequence::AiPursue* pursue);
virtual AiPursue *clone() const;
virtual bool execute (const MWWorld::Ptr& actor,float duration);
virtual bool execute (const MWWorld::Ptr& actor, AiState& state, float duration);
virtual int getTypeId() const;
MWWorld::Ptr getTarget() const;

@ -2,6 +2,7 @@
#include "aisequence.hpp"
#include "aipackage.hpp"
#include "aistate.hpp"
#include "aiwander.hpp"
#include "aiescort.hpp"
@ -146,7 +147,7 @@ bool AiSequence::isPackageDone() const
return mDone;
}
void AiSequence::execute (const MWWorld::Ptr& actor,float duration)
void AiSequence::execute (const MWWorld::Ptr& actor, AiState& state,float duration)
{
if(actor != MWBase::Environment::get().getWorld()->getPlayerPtr()
&& !actor.getClass().getCreatureStats(actor).getKnockedDown())
@ -208,7 +209,7 @@ void AiSequence::execute (const MWWorld::Ptr& actor,float duration)
}
}
if (package->execute (actor,duration))
if (package->execute (actor,state,duration))
{
// To account for the rare case where AiPackage::execute() queued another AI package
// (e.g. AiPursue executing a dialogue script that uses startCombat)

@ -4,6 +4,7 @@
#include <list>
#include <components/esm/loadnpc.hpp>
//#include "aistate.hpp"
namespace MWWorld
{
@ -18,9 +19,15 @@ namespace ESM
}
}
template< class Base > class DerivedClassStorage;
namespace MWMechanics
{
class AiPackage;
class AiTemporaryBase;
typedef DerivedClassStorage<AiTemporaryBase> AiState;
/// \brief Sequence of AI-packages for a single actor
/** The top-most AI package is run each frame. When completed, it is removed from the stack. **/
@ -88,7 +95,7 @@ namespace MWMechanics
void stopPursuit();
/// Execute current package, switching if needed.
void execute (const MWWorld::Ptr& actor,float duration);
void execute (const MWWorld::Ptr& actor, MWMechanics::AiState& state, float duration);
/// Remove all packages.
void clear();

@ -0,0 +1,120 @@
#ifndef AISTATE_H
#define AISTATE_H
#include <typeinfo>
#include <stdexcept>
// c++11 replacement
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_base_of.hpp>
/// \brief stores an object of any class derived from Base
template< class Base >
class DerivedClassStorage
{
private:
Base* mStorage;
// assert that Derived is derived from Base.
template< class Derived >
void assert_derived()
{
// c++11:
// static_assert( std::is_base_of<Base,Derived> , "DerivedClassStorage may only store derived classes" );
// boost:
BOOST_STATIC_ASSERT(boost::is_base_of<Base,Derived>::value);//,"DerivedClassStorage may only store derived classes");
}
DerivedClassStorage( const DerivedClassStorage& );
public:
/// \brief returns reference to stored object or deletes it and creates a fitting
template< class Derived >
Derived& get()
{
assert_derived<Derived>();
Derived* result = dynamic_cast<Derived*>(mStorage);
if(!result)
{
if(mStorage)
delete mStorage;
mStorage = result = new Derived();
}
//return a reference to the (new allocated) object
return *result;
}
template< class Derived >
void store( const Derived& payload )
{
assert_derived<Derived>();
if(mStorage)
delete mStorage;
mStorage = new Derived(payload);
}
/// \brief takes ownership of the passed object
template< class Derived >
void moveIn( Derived* p )
{
assert_derived<Derived>();
if(mStorage)
delete mStorage;
mStorage = p;
}
/// \brief gives away ownership of object. Throws exception if storage does not contain Derived or is empty.
template< class Derived >
Derived* moveOut()
{
assert_derived<Derived>();
if(!mStorage)
throw std::runtime_error("Cant move out: empty storage.");
Derived* result = dynamic_cast<Derived*>(mStorage);
if(!mStorage)
throw std::runtime_error("Cant move out: wrong type requested.");
return result;
}
bool empty() const
{
return mStorage == NULL;
}
const std::type_info& getType() const
{
return typeid(mStorage);
}
DerivedClassStorage():mStorage(NULL){};
~DerivedClassStorage()
{
if(mStorage)
delete mStorage;
};
};
namespace MWMechanics
{
/// \brief base class for the temporary storage of AiPackages
struct AiTemporaryBase
{
virtual ~AiTemporaryBase(){};
};
/// \brief Container for AI package status
typedef DerivedClassStorage<AiTemporaryBase> AiState;
}
#endif // AISTATE_H

@ -37,7 +37,7 @@ namespace MWMechanics
return new AiTravel(*this);
}
bool AiTravel::execute (const MWWorld::Ptr& actor,float duration)
bool AiTravel::execute (const MWWorld::Ptr& actor, AiState& state, float duration)
{
MWBase::World *world = MWBase::Environment::get().getWorld();
ESM::Position pos = actor.getRefData().getPosition();

@ -27,7 +27,7 @@ namespace MWMechanics
virtual AiTravel *clone() const;
virtual bool execute (const MWWorld::Ptr& actor,float duration);
virtual bool execute (const MWWorld::Ptr& actor, AiState& state, float duration);
virtual int getTypeId() const;

@ -18,6 +18,8 @@
#include "steering.hpp"
#include "movement.hpp"
namespace MWMechanics
{
static const int COUNT_BEFORE_RESET = 200; // TODO: maybe no longer needed
@ -45,9 +47,9 @@ namespace MWMechanics
mStuckCount = 0;// TODO: maybe no longer needed
mDoorCheckDuration = 0;
mTrimCurrentNode = false;
mReaction = 0;
mRotate = false;
mTargetAngle = 0;
// mReaction = 0;
// mRotate = false;
// mTargetAngle = 0;
mSaidGreeting = Greet_None;
mGreetingTimer = 0;
mHasReturnPosition = false;
@ -125,8 +127,13 @@ namespace MWMechanics
* actors will enter combat (i.e. no longer wandering) and different pathfinding
* will kick in.
*/
bool AiWander::execute (const MWWorld::Ptr& actor,float duration)
bool AiWander::execute (const MWWorld::Ptr& actor, AiState& state, float duration)
{
AiWanderStorage& storage = state.get<AiWanderStorage>();
float& mTargetAngle = storage.mTargetAngle;
bool& mRotate = storage.mRotate;
float& mReaction = storage.mReaction;
MWMechanics::CreatureStats& cStats = actor.getClass().getCreatureStats(actor);
if(cStats.isDead() || cStats.getHealth().getCurrent() <= 0)
return true; // Don't bother with dead actors

@ -12,6 +12,9 @@
#include "../mwworld/timestamp.hpp"
#include "aistate.hpp"
namespace ESM
{
namespace AiSequence
@ -22,6 +25,17 @@ namespace ESM
namespace MWMechanics
{
/// \brief Temporary values used by AiWander
struct AiWanderStorage : AiTemporaryBase
{
// the z rotation angle (degrees) we want to reach
// used every frame when mRotate is true
float mTargetAngle;
bool mRotate;
float mReaction; // update some actions infrequently
AiWanderStorage():mTargetAngle(0),mRotate(false),mReaction(0){};
};
/// \brief Causes the Actor to wander within a specified range
class AiWander : public AiPackage
{
@ -41,7 +55,7 @@ namespace MWMechanics
virtual AiPackage *clone() const;
virtual bool execute (const MWWorld::Ptr& actor,float duration);
virtual bool execute (const MWWorld::Ptr& actor, AiState& state, float duration);
virtual int getTypeId() const;
@ -109,11 +123,7 @@ namespace MWMechanics
float mDoorCheckDuration;
int mStuckCount;
// the z rotation angle (degrees) we want to reach
// used every frame when mRotate is true
float mTargetAngle;
bool mRotate;
float mReaction; // update some actions infrequently
};
}

@ -6,6 +6,7 @@
#include <components/esm/loadmgef.hpp>
#include "../mwworld/ptr.hpp"
#include "aistate.hpp"
namespace MWWorld
{
@ -138,6 +139,9 @@ class CharacterController
{
MWWorld::Ptr mPtr;
MWRender::Animation *mAnimation;
//
AiState mAiState;
typedef std::deque<std::pair<std::string,size_t> > AnimationQueue;
AnimationQueue mAnimQueue;
@ -218,6 +222,8 @@ public:
{ return mDeathState != CharState_None; }
void forceStateUpdate();
AiState& getAiState() { return mAiState; }
};
void getWeaponGroup(WeaponType weaptype, std::string &group);

Loading…
Cancel
Save