aiavoiddoor.cpp 3.03 KB
Newer Older
Thomas's avatar
Thomas committed
1
#include "aiavoiddoor.hpp"
scrawl's avatar
scrawl committed
2

Thomas's avatar
Thomas committed
3 4
#include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp"
scrawl's avatar
scrawl committed
5
#include "../mwbase/mechanicsmanager.hpp"
6

Thomas's avatar
Thomas committed
7
#include "../mwworld/class.hpp"
8

Thomas's avatar
Thomas committed
9 10
#include "creaturestats.hpp"
#include "movement.hpp"
11
#include "actorutil.hpp"
Thomas's avatar
Thomas committed
12 13
#include "steering.hpp"

14
MWMechanics::AiAvoidDoor::AiAvoidDoor(const MWWorld::ConstPtr& doorPtr)
15
: AiPackage(), mDuration(1), mDoorPtr(doorPtr), mAdjAngle(0)
Thomas's avatar
Thomas committed
16
{
17

Thomas's avatar
Thomas committed
18 19
}

20
bool MWMechanics::AiAvoidDoor::execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration)
Thomas's avatar
Thomas committed
21
{
22 23

    ESM::Position pos = actor.getRefData().getPosition();
24
    if(mDuration == 1) //If it just started, get the actor position as the stuck detection thing
25 26
        mLastPos = pos;

Thomas's avatar
Thomas committed
27 28
    mDuration -= duration; //Update timer

29 30 31 32
    if(mDuration < 0) {
        float x = pos.pos[0] - mLastPos.pos[0];
        float y = pos.pos[1] - mLastPos.pos[1];
        float z = pos.pos[2] - mLastPos.pos[2];
33
        float distance = x * x + y * y + z * z;
34 35
        if(distance < 10 * 10) { //Got stuck, didn't move
            if(mAdjAngle == 0) //Try going in various directions
36 37 38
                mAdjAngle = osg::PI / 2;
            else if (mAdjAngle == osg::PI / 2)
                mAdjAngle = -osg::PI / 2;
39 40 41 42 43 44 45
            else
                mAdjAngle = 0;
            mDuration = 1; //reset timer
        }
        else //Not stuck
            return true; // We have tried backing up for more than one second, we've probably cleared it
    }
Thomas's avatar
Thomas committed
46

47
    if (!mDoorPtr.getClass().getDoorState(mDoorPtr))
Thomas's avatar
Thomas committed
48 49 50 51 52 53
        return true; //Door is no longer opening

    ESM::Position tPos = mDoorPtr.getRefData().getPosition(); //Position of the door
    float x = pos.pos[0] - tPos.pos[0];
    float y = pos.pos[1] - tPos.pos[1];

54
    actor.getClass().getCreatureStats(actor).setMovementFlag(CreatureStats::Flag_Run, true);
Thomas's avatar
Thomas committed
55

56
    // Turn away from the door and move when turn completed
scrawl's avatar
scrawl committed
57
    if (zTurn(actor, std::atan2(x,y) + mAdjAngle, osg::DegreesToRadians(5.f)))
58 59 60 61 62 63
        actor.getClass().getMovementSettings(actor).mPosition[1] = 1;
    else
        actor.getClass().getMovementSettings(actor).mPosition[1] = 0;
    actor.getClass().getMovementSettings(actor).mPosition[0] = 0;

    // Make all nearby actors also avoid the door
64
    std::vector<MWWorld::Ptr> actors;
scrawl's avatar
scrawl committed
65
    MWBase::Environment::get().getMechanicsManager()->getActorsInRange(pos.asVec3(),100,actors);
scrawl's avatar
scrawl committed
66
    for(std::vector<MWWorld::Ptr>::iterator it = actors.begin(); it != actors.end(); ++it) {
67
        if(*it != getPlayer()) { //Not the player
68
            MWMechanics::AiSequence& seq = it->getClass().getCreatureStats(*it).getAiSequence();
69 70 71 72 73 74
            if(seq.getTypeId() != MWMechanics::AiPackage::TypeIdAvoidDoor) { //Only add it once
                seq.stack(MWMechanics::AiAvoidDoor(mDoorPtr),*it);
            }
        }
    }

Thomas's avatar
Thomas committed
75 76 77 78 79 80 81 82
    return false;
}

MWMechanics::AiAvoidDoor *MWMechanics::AiAvoidDoor::clone() const
{
    return new AiAvoidDoor(*this);
}

scrawl's avatar
scrawl committed
83
int MWMechanics::AiAvoidDoor::getTypeId() const
Thomas's avatar
Thomas committed
84 85 86 87
{
    return TypeIdAvoidDoor;
}

scrawl's avatar
scrawl committed
88 89 90 91 92 93
unsigned int MWMechanics::AiAvoidDoor::getPriority() const
{
 return 2;
}