mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-01 03:21:41 +00:00
Merge branch 'whycantitalkthedoorintoopening' into 'master'
Let AI open moved doors (#7548) Closes #7548 See merge request OpenMW/openmw!4435
This commit is contained in:
commit
d356fea5b6
@ -49,47 +49,61 @@ namespace MWMechanics
|
||||
return true;
|
||||
}
|
||||
|
||||
const MWWorld::Ptr getNearbyDoor(const MWWorld::Ptr& actor, float minDist)
|
||||
struct GetNearbyDoorVisitor
|
||||
{
|
||||
MWWorld::CellStore* cell = actor.getCell();
|
||||
MWWorld::Ptr mResult;
|
||||
|
||||
// Check all the doors in this cell
|
||||
const MWWorld::CellRefList<ESM::Door>& doors = cell->getReadOnlyDoors();
|
||||
osg::Vec3f pos(actor.getRefData().getPosition().asVec3());
|
||||
pos.z() = 0;
|
||||
|
||||
osg::Vec3f actorDir = (actor.getRefData().getBaseNode()->getAttitude() * osg::Vec3f(0, 1, 0));
|
||||
|
||||
for (const auto& ref : doors.mList)
|
||||
GetNearbyDoorVisitor(const MWWorld::Ptr& actor, const float minDist)
|
||||
: mPos(actor.getRefData().getPosition().asVec3())
|
||||
, mDir(actor.getRefData().getBaseNode()->getAttitude() * osg::Vec3f(0, 1, 0))
|
||||
, mMinDist(minDist)
|
||||
{
|
||||
mPos.z() = 0;
|
||||
mDir.normalize();
|
||||
}
|
||||
|
||||
bool operator()(const MWWorld::Ptr& ptr)
|
||||
{
|
||||
MWWorld::LiveCellRef<ESM::Door>& ref = *static_cast<MWWorld::LiveCellRef<ESM::Door>*>(ptr.getBase());
|
||||
if (!ptr.getRefData().isEnabled() || ref.isDeleted())
|
||||
return true;
|
||||
|
||||
if (ptr.getClass().getDoorState(ptr) != MWWorld::DoorState::Idle)
|
||||
return true;
|
||||
|
||||
const float doorRot = ref.mData.getPosition().rot[2] - ptr.getCellRef().getPosition().rot[2];
|
||||
if (doorRot != 0)
|
||||
return true;
|
||||
|
||||
osg::Vec3f doorPos(ref.mData.getPosition().asVec3());
|
||||
|
||||
// FIXME: cast
|
||||
const MWWorld::Ptr doorPtr
|
||||
= MWWorld::Ptr(&const_cast<MWWorld::LiveCellRef<ESM::Door>&>(ref), actor.getCell());
|
||||
|
||||
const auto doorState = doorPtr.getClass().getDoorState(doorPtr);
|
||||
float doorRot = ref.mData.getPosition().rot[2] - doorPtr.getCellRef().getPosition().rot[2];
|
||||
|
||||
if (doorState != MWWorld::DoorState::Idle || doorRot != 0)
|
||||
continue; // the door is already opened/opening
|
||||
|
||||
doorPos.z() = 0;
|
||||
|
||||
float angle = std::acos(actorDir * (doorPos - pos) / (actorDir.length() * (doorPos - pos).length()));
|
||||
osg::Vec3f actorToDoor = doorPos - mPos;
|
||||
// Door is not close enough
|
||||
if (actorToDoor.length2() > mMinDist * mMinDist)
|
||||
return true;
|
||||
|
||||
actorToDoor.normalize();
|
||||
const float angle = std::acos(mDir * actorToDoor);
|
||||
|
||||
// Allow 60 degrees angle between actor and door
|
||||
if (angle < -osg::PI / 3 || angle > osg::PI / 3)
|
||||
continue;
|
||||
return true;
|
||||
|
||||
// Door is not close enough
|
||||
if ((pos - doorPos).length2() > minDist * minDist)
|
||||
continue;
|
||||
|
||||
return doorPtr; // found, stop searching
|
||||
mResult = ptr;
|
||||
return false; // found, stop searching
|
||||
}
|
||||
|
||||
return MWWorld::Ptr(); // none found
|
||||
private:
|
||||
osg::Vec3f mPos, mDir;
|
||||
float mMinDist;
|
||||
};
|
||||
|
||||
const MWWorld::Ptr getNearbyDoor(const MWWorld::Ptr& actor, float minDist)
|
||||
{
|
||||
GetNearbyDoorVisitor visitor(actor, minDist);
|
||||
actor.getCell()->forEachType<ESM::Door>(visitor);
|
||||
return visitor.mResult;
|
||||
}
|
||||
|
||||
bool isAreaOccupiedByOtherActor(const MWWorld::ConstPtr& actor, const osg::Vec3f& destination, bool ignorePlayer,
|
||||
|
Loading…
Reference in New Issue
Block a user