Commit 7c0b51fb authored by jefhai's avatar jefhai

Ai pursue now controls guards pursuit of crimes

Should extend AiActivate in the future
parent 50dac98a
......@@ -67,7 +67,7 @@ add_openmw_dir (mwclass
add_openmw_dir (mwmechanics
mechanicsmanagerimp stat character creaturestats magiceffects movement actors objects
drawstate spells activespells npcstats aipackage aisequence alchemy aiwander aitravel aifollow
drawstate spells activespells npcstats aipackage aisequence aipersue alchemy aiwander aitravel aifollow
aiescort aiactivate aicombat repair enchanting pathfinding security spellsuccess spellcasting
disease pickpocket levelledlist combat steering
)
......
......@@ -9,11 +9,9 @@
#include "steering.hpp"
#include "movement.hpp"
#include "creaturestats.hpp"
MWMechanics::AiActivate::AiActivate(const std::string &objectId, int arg)
: mObjectId(objectId),
mArg(arg)
MWMechanics::AiActivate::AiActivate(const std::string &objectId)
: mObjectId(objectId)
{
}
MWMechanics::AiActivate *MWMechanics::AiActivate::clone() const
......@@ -27,9 +25,6 @@ bool MWMechanics::AiActivate::execute (const MWWorld::Ptr& actor,float duration)
Movement &movement = actor.getClass().getMovementSettings(actor);
const ESM::Cell *cell = actor.getCell()->getCell();
if (mArg == 1) // run to actor
actor.getClass().getCreatureStats(actor).setMovementFlag(CreatureStats::Flag_Run, true);
MWWorld::Ptr player = world->getPlayerPtr();
if(cell->mData.mX != player.getCell()->getCell()->mData.mX)
{
......
......@@ -12,7 +12,7 @@ namespace MWMechanics
class AiActivate : public AiPackage
{
public:
AiActivate(const std::string &objectId, int arg);
AiActivate(const std::string &objectId);
virtual AiActivate *clone() const;
virtual bool execute (const MWWorld::Ptr& actor,float duration);
///< \return Package completed?
......@@ -20,7 +20,6 @@ namespace MWMechanics
private:
std::string mObjectId;
int mArg;
PathFinder mPathFinder;
int mCellX;
......
......@@ -19,7 +19,8 @@ namespace MWMechanics
TypeIdEscort = 2,
TypeIdFollow = 3,
TypeIdActivate = 4,
TypeIdCombat = 5
TypeIdCombat = 5,
TypeIdPersue = 6
};
virtual ~AiPackage();
......
#include "aipersue.hpp"
#include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/action.hpp"
#include "../mwworld/cellstore.hpp"
#include "steering.hpp"
#include "movement.hpp"
#include "creaturestats.hpp"
MWMechanics::AiPersue::AiPersue(const std::string &objectId)
: mObjectId(objectId)
{
}
MWMechanics::AiPersue *MWMechanics::AiPersue::clone() const
{
return new AiPersue(*this);
}
bool MWMechanics::AiPersue::execute (const MWWorld::Ptr& actor,float duration)
{
//TODO: Guards should not dialague with player after crime reset
MWBase::World *world = MWBase::Environment::get().getWorld();
ESM::Position pos = actor.getRefData().getPosition();
Movement &movement = actor.getClass().getMovementSettings(actor);
const ESM::Cell *cell = actor.getCell()->getCell();
actor.getClass().getCreatureStats(actor).setMovementFlag(CreatureStats::Flag_Run, true);
MWWorld::Ptr player = world->getPlayerPtr();
if(cell->mData.mX != player.getCell()->getCell()->mData.mX)
{
int sideX = PathFinder::sgn(cell->mData.mX - player.getCell()->getCell()->mData.mX);
//check if actor is near the border of an inactive cell. If so, stop walking.
if(sideX * (pos.pos[0] - cell->mData.mX*ESM::Land::REAL_SIZE) >
sideX * (ESM::Land::REAL_SIZE/2.0f - 200.0f))
{
movement.mPosition[1] = 0;
return false;
}
}
if(cell->mData.mY != player.getCell()->getCell()->mData.mY)
{
int sideY = PathFinder::sgn(cell->mData.mY - player.getCell()->getCell()->mData.mY);
//check if actor is near the border of an inactive cell. If so, stop walking.
if(sideY * (pos.pos[1] - cell->mData.mY*ESM::Land::REAL_SIZE) >
sideY * (ESM::Land::REAL_SIZE/2.0f - 200.0f))
{
movement.mPosition[1] = 0;
return false;
}
}
MWWorld::Ptr target = world->getPtr(mObjectId,false);
ESM::Position targetPos = target.getRefData().getPosition();
bool cellChange = cell->mData.mX != mCellX || cell->mData.mY != mCellY;
if(!mPathFinder.isPathConstructed() || cellChange)
{
mCellX = cell->mData.mX;
mCellY = cell->mData.mY;
ESM::Pathgrid::Point dest;
dest.mX = targetPos.pos[0];
dest.mY = targetPos.pos[1];
dest.mZ = targetPos.pos[2];
ESM::Pathgrid::Point start;
start.mX = pos.pos[0];
start.mY = pos.pos[1];
start.mZ = pos.pos[2];
mPathFinder.buildPath(start, dest, actor.getCell(), true);
}
if((pos.pos[0]-targetPos.pos[0])*(pos.pos[0]-targetPos.pos[0])+
(pos.pos[1]-targetPos.pos[1])*(pos.pos[1]-targetPos.pos[1])+
(pos.pos[2]-targetPos.pos[2])*(pos.pos[2]-targetPos.pos[2]) < 200*200)
{
movement.mPosition[1] = 0;
MWWorld::Ptr target = world->getPtr(mObjectId,false);
MWWorld::Class::get(target).activate(target,actor).get()->execute(actor);
return true;
}
if(mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1], pos.pos[2]))
{
movement.mPosition[1] = 0;
MWWorld::Ptr target = world->getPtr(mObjectId,false);
MWWorld::Class::get(target).activate(target,actor).get()->execute(actor);
return true;
}
float zAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]);
zTurn(actor, Ogre::Degree(zAngle));
MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 1;
movement.mPosition[1] = 1;
return false;
}
int MWMechanics::AiPersue::getTypeId() const
{
return TypeIdPersue;
}
#ifndef GAME_MWMECHANICS_AIPERSUE_H
#define GAME_MWMECHANICS_AIPERSUE_H
#include "aipackage.hpp"
#include <string>
#include "pathfinding.hpp"
namespace MWMechanics
{
class AiPersue : public AiPackage
{
public:
AiPersue(const std::string &objectId);
virtual AiPersue *clone() const;
virtual bool execute (const MWWorld::Ptr& actor,float duration);
///< \return Package completed?
virtual int getTypeId() const;
private:
std::string mObjectId;
PathFinder mPathFinder;
int mCellX;
int mCellY;
};
}
#endif
......@@ -73,6 +73,15 @@ void MWMechanics::AiSequence::stopCombat()
}
}
void MWMechanics::AiSequence::stopPersue()
{
while (getTypeId() == AiPackage::TypeIdPersue)
{
delete *mPackages.begin();
mPackages.erase (mPackages.begin());
}
}
bool MWMechanics::AiSequence::isPackageDone() const
{
return mDone;
......@@ -161,7 +170,7 @@ void MWMechanics::AiSequence::fill(const ESM::AIPackageList &list)
else if (it->mType == ESM::AI_Activate)
{
ESM::AIActivate data = it->mActivate;
package = new MWMechanics::AiActivate(data.mName.toString(), 0);
package = new MWMechanics::AiActivate(data.mName.toString());
}
else //if (it->mType == ESM::AI_Follow)
{
......
......@@ -49,6 +49,9 @@ namespace MWMechanics
void stopCombat();
///< Removes all combat packages until first non-combat or stack empty.
void stopPersue();
///< Removes all persue packages until first non-persue or stack empty.
bool isPackageDone() const;
///< Has a package been completed during the last update?
......
......@@ -13,6 +13,7 @@
#include "../mwworld/player.hpp"
#include "aicombat.hpp"
#include "aipersue.hpp"
#include "aiactivate.hpp"
#include <OgreSceneNode.h>
......@@ -838,8 +839,6 @@ namespace MWMechanics
std::vector<MWWorld::Ptr> neighbors;
mActors.getObjectsInRange(Ogre::Vector3(ptr.getRefData().getPosition().pos),
esmStore.get<ESM::GameSetting>().find("fAlarmRadius")->getInt(), neighbors);
// Did anyone see the crime?
for (std::vector<MWWorld::Ptr>::iterator it = neighbors.begin(); it != neighbors.end(); ++it)
{
if (*it == ptr) // Not the player
......@@ -880,12 +879,12 @@ namespace MWMechanics
{
creatureStats1.getAiSequence().stack(AiCombat(ptr));
creatureStats1.setHostile(true);
creatureStats1.getAiSequence().execute(*it,0);
creatureStats1.getAiSequence().execute(*it1,0);
}
else // will the guard persue the player?
{
creatureStats1.getAiSequence().stack(AiActivate(ptr.getClass().getId(ptr), 1));
creatureStats1.getAiSequence().execute(*it,0);
creatureStats1.getAiSequence().stack(AiPersue(ptr.getClass().getId(ptr)));
creatureStats1.getAiSequence().execute(*it1,0);
}
}
// will the witness fight the player?
......
......@@ -47,7 +47,7 @@ namespace MWScript
// discard additional arguments (reset), because we have no idea what they mean.
for (unsigned int i=0; i<arg0; ++i) runtime.pop();
MWMechanics::AiActivate activatePackage(objectID, 0);
MWMechanics::AiActivate activatePackage(objectID);
MWWorld::Class::get (ptr).getCreatureStats (ptr).getAiSequence().stack(activatePackage);
std::cout << "AiActivate" << std::endl;
}
......
......@@ -29,6 +29,7 @@
#include "../mwmechanics/spellcasting.hpp"
#include "../mwmechanics/levelledlist.hpp"
#include "../mwmechanics/combat.hpp"
#include "../mwmechanics/actors.hpp"
#include "../mwrender/sky.hpp"
#include "../mwrender/animation.hpp"
......@@ -2762,6 +2763,9 @@ namespace MWWorld
message += "\n" + skillMsg;
}
// sleep the player, this doesn't work
//player.getClass().calculateRestoration(player, days, true);
resetCrimes(player);
std::vector<std::string> buttons;
......@@ -2776,10 +2780,15 @@ namespace MWWorld
std::vector<MWWorld::Ptr> neighbors = ptr.getClass().getCreatureStats(ptr).getPlayerWitnesses();
for (std::vector<MWWorld::Ptr>::iterator it = neighbors.begin(); it != neighbors.end(); ++it)
{
// This to reset for each witness:
// Reset states
// TODO: More research is needed to complete this list
it->getClass().getCreatureStats(*it).setHostile(false);
it->getClass().getCreatureStats(*it).setAlarmed(false);
// Stop guard persue
if(it->getClass().isClass(*it, "Guard"))
it->getClass().getCreatureStats(*it).getAiSequence().stopPersue();
}
ptr.getClass().getCreatureStats(ptr).resetPlayerWitnesses();
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment