const MWWorld::Ptr getNearbyDoor(const MWWorld::Ptr& actor, float minDist) { MWWorld::CellStore *cell = actor.getCell(); // Check all the doors in this cell const MWWorld::CellRefList<ESM::Door>& doors = cell->getReadOnlyDoors(); const MWWorld::CellRefList<ESM::Door>::List& refList = doors.mList; MWWorld::CellRefList<ESM::Door>::List::const_iterator it = refList.begin(); osg::Vec3f pos(actor.getRefData().getPosition().asVec3()); pos.z() = 0; osg::Vec3f actorDir = (actor.getRefData().getBaseNode()->getAttitude() * osg::Vec3f(0,1,0)); for (; it != refList.end(); ++it) { const MWWorld::LiveCellRef<ESM::Door>& ref = *it; osg::Vec3f doorPos(ref.mData.getPosition().asVec3()); // FIXME: cast const MWWorld::Ptr doorPtr = MWWorld::Ptr(&const_cast<MWWorld::LiveCellRef<ESM::Door> &>(ref), actor.getCell()); int doorState = doorPtr.getClass().getDoorState(doorPtr); float doorRot = ref.mData.getPosition().rot[2] - doorPtr.getCellRef().getPosition().rot[2]; if (doorState != 0 || doorRot != 0) continue; // the door is already opened/opening doorPos.z() = 0; float angle = std::acos(actorDir * (doorPos - pos) / (actorDir.length() * (doorPos - pos).length())); // Allow 60 degrees angle between actor and door if (angle < -osg::PI / 3 || angle > osg::PI / 3) continue; // Door is not close enough if ((pos - doorPos).length2() > minDist*minDist) continue; return doorPtr; // found, stop searching } return MWWorld::Ptr(); // none found }
float DoorsDebugUI::GetDistance(PDOOR door) { PCHARINFO charInfo = GetCharInfo(); if (!charInfo) return 0; glm::vec3 myPos(charInfo->pSpawn->X, charInfo->pSpawn->Y, charInfo->pSpawn->Z); if (myPos != m_lastPos) m_distanceCache.clear(); m_lastPos = myPos; auto it = m_distanceCache.find(door->ID); if (it != m_distanceCache.end()) return it->second; glm::vec3 doorPos(door->DefaultX, door->DefaultY, door->DefaultZ); float distance = glm::distance(myPos, doorPos); m_distanceCache[door->ID] = distance; return distance; }