@@ -49,47 +49,61 @@ namespace MWMechanics
49
49
return true ;
50
50
}
51
51
52
- const MWWorld:: Ptr getNearbyDoor ( const MWWorld:: Ptr & actor, float minDist)
52
+ struct GetNearbyDoorVisitor
53
53
{
54
- MWWorld::CellStore* cell = actor.getCell ();
55
-
56
- // Check all the doors in this cell
57
- const MWWorld::CellRefList<ESM::Door>& doors = cell->getReadOnlyDoors ();
58
- osg::Vec3f pos (actor.getRefData ().getPosition ().asVec3 ());
59
- pos.z () = 0 ;
54
+ MWWorld::Ptr mResult ;
60
55
61
- osg::Vec3f actorDir = (actor.getRefData ().getBaseNode ()->getAttitude () * osg::Vec3f (0 , 1 , 0 ));
62
-
63
- for (const auto & ref : doors.mList )
56
+ GetNearbyDoorVisitor (const MWWorld::Ptr & actor, const float minDist)
57
+ : mPos (actor.getRefData().getPosition().asVec3())
58
+ , mDir (actor.getRefData().getBaseNode()->getAttitude () * osg::Vec3f(0 , 1 , 0 ))
59
+ , mMinDist(minDist)
64
60
{
65
- osg::Vec3f doorPos (ref.mData .getPosition ().asVec3 ());
61
+ mPos .z () = 0 ;
62
+ mDir .normalize ();
63
+ }
66
64
67
- // FIXME: cast
68
- const MWWorld::Ptr doorPtr
69
- = MWWorld::Ptr (&const_cast <MWWorld::LiveCellRef<ESM::Door>&>(ref), actor.getCell ());
65
+ bool operator ()(const MWWorld::Ptr & ptr)
66
+ {
67
+ MWWorld::LiveCellRef<ESM::Door>& ref = *static_cast <MWWorld::LiveCellRef<ESM::Door>*>(ptr.getBase ());
68
+ if (!ptr.getRefData ().isEnabled () || ref.isDeleted ())
69
+ return true ;
70
70
71
- const auto doorState = doorPtr .getClass ().getDoorState (doorPtr);
72
- float doorRot = ref. mData . getPosition (). rot [ 2 ] - doorPtr. getCellRef (). getPosition (). rot [ 2 ] ;
71
+ if (ptr .getClass ().getDoorState (ptr) != MWWorld::DoorState::Idle)
72
+ return true ;
73
73
74
- if (doorState != MWWorld::DoorState::Idle || doorRot != 0 )
75
- continue ; // the door is already opened/opening
74
+ const float doorRot = ref.mData .getPosition ().rot [2 ] - ptr.getCellRef ().getPosition ().rot [2 ];
75
+ if (doorRot != 0 )
76
+ return true ;
76
77
78
+ osg::Vec3f doorPos (ref.mData .getPosition ().asVec3 ());
77
79
doorPos.z () = 0 ;
78
80
79
- float angle = std::acos (actorDir * (doorPos - pos) / (actorDir.length () * (doorPos - pos).length ()));
81
+ osg::Vec3f actorToDoor = doorPos - mPos ;
82
+ // Door is not close enough
83
+ if (actorToDoor.length2 () > mMinDist * mMinDist )
84
+ return true ;
85
+
86
+ actorToDoor.normalize ();
87
+ const float angle = std::acos (mDir * actorToDoor);
80
88
81
89
// Allow 60 degrees angle between actor and door
82
90
if (angle < -osg::PI / 3 || angle > osg::PI / 3 )
83
- continue ;
84
-
85
- // Door is not close enough
86
- if ((pos - doorPos).length2 () > minDist * minDist)
87
- continue ;
91
+ return true ;
88
92
89
- return doorPtr; // found, stop searching
93
+ mResult = ptr;
94
+ return false ; // found, stop searching
90
95
}
91
96
92
- return MWWorld::Ptr (); // none found
97
+ private:
98
+ osg::Vec3f mPos , mDir ;
99
+ float mMinDist ;
100
+ };
101
+
102
+ const MWWorld::Ptr getNearbyDoor (const MWWorld::Ptr & actor, float minDist)
103
+ {
104
+ GetNearbyDoorVisitor visitor (actor, minDist);
105
+ actor.getCell ()->forEachType <ESM::Door>(visitor);
106
+ return visitor.mResult ;
93
107
}
94
108
95
109
bool isAreaOccupiedByOtherActor (const MWWorld::ConstPtr& actor, const osg::Vec3f& destination, bool ignorePlayer,
0 commit comments