mirror of
https://github.com/OpenMW/openmw.git
synced 2025-04-27 13:36:49 +00:00
Merge pull request #2507 from elsid/door_stuck
Fix actors stuck in closing door (bug #5138)
This commit is contained in:
commit
6f99747fff
3 changed files with 36 additions and 19 deletions
|
@ -1,5 +1,7 @@
|
||||||
#include "aiavoiddoor.hpp"
|
#include "aiavoiddoor.hpp"
|
||||||
|
|
||||||
|
#include <components/misc/rng.hpp>
|
||||||
|
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/mechanicsmanager.hpp"
|
#include "../mwbase/mechanicsmanager.hpp"
|
||||||
|
@ -11,8 +13,10 @@
|
||||||
#include "actorutil.hpp"
|
#include "actorutil.hpp"
|
||||||
#include "steering.hpp"
|
#include "steering.hpp"
|
||||||
|
|
||||||
|
static const int MAX_DIRECTIONS = 4;
|
||||||
|
|
||||||
MWMechanics::AiAvoidDoor::AiAvoidDoor(const MWWorld::ConstPtr& doorPtr)
|
MWMechanics::AiAvoidDoor::AiAvoidDoor(const MWWorld::ConstPtr& doorPtr)
|
||||||
: AiPackage(), mDuration(1), mDoorPtr(doorPtr), mLastPos(ESM::Position()), mAdjAngle(0)
|
: AiPackage(), mDuration(1), mDoorPtr(doorPtr), mDirection(0)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -22,25 +26,18 @@ bool MWMechanics::AiAvoidDoor::execute (const MWWorld::Ptr& actor, CharacterCont
|
||||||
|
|
||||||
ESM::Position pos = actor.getRefData().getPosition();
|
ESM::Position pos = actor.getRefData().getPosition();
|
||||||
if(mDuration == 1) //If it just started, get the actor position as the stuck detection thing
|
if(mDuration == 1) //If it just started, get the actor position as the stuck detection thing
|
||||||
mLastPos = pos;
|
mLastPos = pos.asVec3();
|
||||||
|
|
||||||
mDuration -= duration; //Update timer
|
mDuration -= duration; //Update timer
|
||||||
|
|
||||||
if(mDuration < 0) {
|
if (mDuration < 0)
|
||||||
float x = pos.pos[0] - mLastPos.pos[0];
|
{
|
||||||
float y = pos.pos[1] - mLastPos.pos[1];
|
if (isStuck(pos.asVec3()))
|
||||||
float z = pos.pos[2] - mLastPos.pos[2];
|
{
|
||||||
float distance = x * x + y * y + z * z;
|
adjustDirection();
|
||||||
if(distance < 10 * 10) { //Got stuck, didn't move
|
|
||||||
if(mAdjAngle == 0) //Try going in various directions
|
|
||||||
mAdjAngle = osg::PI / 2;
|
|
||||||
else if (mAdjAngle == osg::PI / 2)
|
|
||||||
mAdjAngle = -osg::PI / 2;
|
|
||||||
else
|
|
||||||
mAdjAngle = 0;
|
|
||||||
mDuration = 1; //reset timer
|
mDuration = 1; //reset timer
|
||||||
}
|
}
|
||||||
else //Not stuck
|
else
|
||||||
return true; // We have tried backing up for more than one second, we've probably cleared it
|
return true; // We have tried backing up for more than one second, we've probably cleared it
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,7 +51,7 @@ bool MWMechanics::AiAvoidDoor::execute (const MWWorld::Ptr& actor, CharacterCont
|
||||||
actor.getClass().getCreatureStats(actor).setMovementFlag(CreatureStats::Flag_Run, true);
|
actor.getClass().getCreatureStats(actor).setMovementFlag(CreatureStats::Flag_Run, true);
|
||||||
|
|
||||||
// Turn away from the door and move when turn completed
|
// Turn away from the door and move when turn completed
|
||||||
if (zTurn(actor, std::atan2(x,y) + mAdjAngle, osg::DegreesToRadians(5.f)))
|
if (zTurn(actor, std::atan2(x,y) + getAdjustedAngle(), osg::DegreesToRadians(5.f)))
|
||||||
actor.getClass().getMovementSettings(actor).mPosition[1] = 1;
|
actor.getClass().getMovementSettings(actor).mPosition[1] = 1;
|
||||||
else
|
else
|
||||||
actor.getClass().getMovementSettings(actor).mPosition[1] = 0;
|
actor.getClass().getMovementSettings(actor).mPosition[1] = 0;
|
||||||
|
@ -90,4 +87,17 @@ unsigned int MWMechanics::AiAvoidDoor::getPriority() const
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MWMechanics::AiAvoidDoor::isStuck(const osg::Vec3f& actorPos) const
|
||||||
|
{
|
||||||
|
return (actorPos - mLastPos).length2() < 10 * 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MWMechanics::AiAvoidDoor::adjustDirection()
|
||||||
|
{
|
||||||
|
mDirection = Misc::Rng::rollDice(MAX_DIRECTIONS);
|
||||||
|
}
|
||||||
|
|
||||||
|
float MWMechanics::AiAvoidDoor::getAdjustedAngle() const
|
||||||
|
{
|
||||||
|
return 2 * osg::PI / MAX_DIRECTIONS * mDirection;
|
||||||
|
}
|
||||||
|
|
|
@ -36,8 +36,14 @@ namespace MWMechanics
|
||||||
private:
|
private:
|
||||||
float mDuration;
|
float mDuration;
|
||||||
MWWorld::ConstPtr mDoorPtr;
|
MWWorld::ConstPtr mDoorPtr;
|
||||||
ESM::Position mLastPos;
|
osg::Vec3f mLastPos;
|
||||||
float mAdjAngle;
|
int mDirection;
|
||||||
|
|
||||||
|
bool isStuck(const osg::Vec3f& actorPos) const;
|
||||||
|
|
||||||
|
void adjustDirection();
|
||||||
|
|
||||||
|
float getAdjustedAngle() const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1649,7 +1649,6 @@ namespace MWWorld
|
||||||
}
|
}
|
||||||
|
|
||||||
// we need to undo the rotation
|
// we need to undo the rotation
|
||||||
rotateObject(door, objPos.rot[0], objPos.rot[1], oldRot);
|
|
||||||
reached = false;
|
reached = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1671,6 +1670,8 @@ namespace MWWorld
|
||||||
if (!closeSound.empty() && MWBase::Environment::get().getSoundManager()->getSoundPlaying(door, closeSound))
|
if (!closeSound.empty() && MWBase::Environment::get().getSoundManager()->getSoundPlaying(door, closeSound))
|
||||||
MWBase::Environment::get().getSoundManager()->stopSound3D(door, closeSound);
|
MWBase::Environment::get().getSoundManager()->stopSound3D(door, closeSound);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rotateObject(door, objPos.rot[0], objPos.rot[1], oldRot);
|
||||||
}
|
}
|
||||||
|
|
||||||
// the rotation order we want to use
|
// the rotation order we want to use
|
||||||
|
|
Loading…
Reference in a new issue