mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-19 22:53:50 +00:00
Show marked position on map. Implement Detect X magic effects.
This commit is contained in:
parent
9245faf2aa
commit
5729672262
11 changed files with 362 additions and 145 deletions
|
@ -130,7 +130,7 @@ namespace MWBase
|
|||
virtual Ogre::Vector2 getNorthVector (MWWorld::CellStore* cell) = 0;
|
||||
///< get north vector (OGRE coordinates) for given interior cell
|
||||
|
||||
virtual std::vector<DoorMarker> getDoorMarkers (MWWorld::CellStore* cell) = 0;
|
||||
virtual void getDoorMarkers (MWWorld::CellStore* cell, std::vector<DoorMarker>& out) = 0;
|
||||
///< get a list of teleport door markers for a given cell, to be displayed on the local map
|
||||
|
||||
virtual void getInteriorMapPosition (Ogre::Vector2 position, float& nX, float& nY, int &x, int& y) = 0;
|
||||
|
@ -438,6 +438,18 @@ namespace MWBase
|
|||
/// @note id must be lower case
|
||||
virtual void teleportToClosestMarker (const MWWorld::Ptr& ptr,
|
||||
const std::string& id, Ogre::Vector3 worldPos) = 0;
|
||||
|
||||
enum DetectionType
|
||||
{
|
||||
Detect_Enchantment,
|
||||
Detect_Key,
|
||||
Detect_Creature
|
||||
};
|
||||
/// List all references (filtered by \a type) detected by \a ptr. The range
|
||||
/// is determined by the current magnitude of the "Detect X" magic effect belonging to \a type.
|
||||
/// @note This also works for references in containers.
|
||||
virtual void listDetectedReferences (const MWWorld::Ptr& ptr, std::vector<MWWorld::Ptr>& out,
|
||||
DetectionType type) = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -252,4 +252,11 @@ namespace MWClass
|
|||
return ref->mBase->mData.mWeight;
|
||||
}
|
||||
|
||||
bool Miscellaneous::isKey(const MWWorld::Ptr &ptr) const
|
||||
{
|
||||
MWWorld::LiveCellRef<ESM::Miscellaneous> *ref =
|
||||
ptr.get<ESM::Miscellaneous>();
|
||||
return ref->mBase->mData.mIsKey;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -57,6 +57,8 @@ namespace MWClass
|
|||
virtual float getWeight (const MWWorld::Ptr& ptr) const;
|
||||
|
||||
virtual bool canSell (const MWWorld::Ptr& item, int npcServices) const;
|
||||
|
||||
virtual bool isKey (const MWWorld::Ptr &ptr) const;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -103,27 +103,80 @@ namespace MWGui
|
|||
|
||||
void LocalMapBase::onMarkerFocused (MyGUI::Widget* w1, MyGUI::Widget* w2)
|
||||
{
|
||||
// Workaround to not make the marker visible if it's under fog of war
|
||||
applyFogOfWar ();
|
||||
}
|
||||
|
||||
void LocalMapBase::onMarkerUnfocused (MyGUI::Widget* w1, MyGUI::Widget* w2)
|
||||
{
|
||||
// Workaround to not make the marker visible if it's under fog of war
|
||||
applyFogOfWar ();
|
||||
}
|
||||
|
||||
MyGUI::IntPoint LocalMapBase::getMarkerPosition(float worldX, float worldY, MarkerPosition& markerPos)
|
||||
{
|
||||
MyGUI::IntPoint widgetPos;
|
||||
// normalized cell coordinates
|
||||
float nX,nY;
|
||||
|
||||
markerPos.interior = mInterior;
|
||||
|
||||
if (!mInterior)
|
||||
{
|
||||
int cellX, cellY;
|
||||
MWBase::Environment::get().getWorld()->positionToIndex(worldX, worldY, cellX, cellY);
|
||||
const int cellSize = 8192;
|
||||
nX = (worldX - cellSize * cellX) / cellSize;
|
||||
// Image space is -Y up, cells are Y up
|
||||
nY = 1 - (worldY - cellSize * cellY) / cellSize;
|
||||
|
||||
float cellDx = cellX - mCurX;
|
||||
float cellDy = cellY - mCurY;
|
||||
|
||||
markerPos.cellX = cellX;
|
||||
markerPos.cellY = cellY;
|
||||
|
||||
widgetPos = MyGUI::IntPoint(nX * 512 + (1+cellDx) * 512,
|
||||
nY * 512 - (cellDy-1) * 512);
|
||||
}
|
||||
else
|
||||
{
|
||||
int cellX, cellY;
|
||||
Ogre::Vector2 worldPos (worldX, worldY);
|
||||
MWBase::Environment::get().getWorld ()->getInteriorMapPosition (worldPos, nX, nY, cellX, cellY);
|
||||
|
||||
markerPos.cellX = cellX;
|
||||
markerPos.cellY = cellY;
|
||||
|
||||
widgetPos = MyGUI::IntPoint(nX * 512 + (1+cellX-mCurX) * 512,
|
||||
nY * 512 + (1+cellY-mCurY) * 512);
|
||||
}
|
||||
|
||||
markerPos.nX = nX;
|
||||
markerPos.nY = nY;
|
||||
return widgetPos;
|
||||
}
|
||||
|
||||
void LocalMapBase::setActiveCell(const int x, const int y, bool interior)
|
||||
{
|
||||
if (x==mCurX && y==mCurY && mInterior==interior && !mChanged) return; // don't do anything if we're still in the same cell
|
||||
if (x==mCurX && y==mCurY && mInterior==interior && !mChanged)
|
||||
return; // don't do anything if we're still in the same cell
|
||||
|
||||
mCurX = x;
|
||||
mCurY = y;
|
||||
mInterior = interior;
|
||||
mChanged = false;
|
||||
|
||||
// clear all previous markers
|
||||
for (unsigned int i=0; i< mLocalMap->getChildCount(); ++i)
|
||||
{
|
||||
if (mLocalMap->getChildAt(i)->getName ().substr (0, 6) == "Marker")
|
||||
if (mLocalMap->getChildAt(i)->getName ().substr (0, 4) == "Door")
|
||||
{
|
||||
MyGUI::Gui::getInstance ().destroyWidget (mLocalMap->getChildAt(i));
|
||||
}
|
||||
}
|
||||
|
||||
// Update the map textures
|
||||
for (int mx=0; mx<3; ++mx)
|
||||
{
|
||||
for (int my=0; my<3; ++my)
|
||||
|
@ -138,78 +191,57 @@ namespace MWGui
|
|||
box->setImageTexture(image);
|
||||
else
|
||||
box->setImageTexture("black.png");
|
||||
}
|
||||
}
|
||||
|
||||
MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||
|
||||
// door markers
|
||||
|
||||
// interior map only consists of one cell, so handle the markers only once
|
||||
if (interior && (mx != 2 || my != 2))
|
||||
continue;
|
||||
|
||||
MWWorld::CellStore* cell;
|
||||
// Retrieve the door markers we want to show
|
||||
std::vector<MWBase::World::DoorMarker> doors;
|
||||
if (interior)
|
||||
cell = MWBase::Environment::get().getWorld ()->getInterior (mPrefix);
|
||||
{
|
||||
MWWorld::CellStore* cell = world->getInterior (mPrefix);
|
||||
world->getDoorMarkers(cell, doors);
|
||||
}
|
||||
else
|
||||
cell = MWBase::Environment::get().getWorld ()->getExterior (x+mx-1, y-(my-1));
|
||||
|
||||
std::vector<MWBase::World::DoorMarker> doors = MWBase::Environment::get().getWorld ()->getDoorMarkers (cell);
|
||||
{
|
||||
for (int dX=-1; dX<2; ++dX)
|
||||
{
|
||||
for (int dY=-1; dY<2; ++dY)
|
||||
{
|
||||
MWWorld::CellStore* cell = world->getExterior (mCurX+dX, mCurY+dY);
|
||||
world->getDoorMarkers(cell, doors);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create a widget for each marker
|
||||
int counter = 0;
|
||||
for (std::vector<MWBase::World::DoorMarker>::iterator it = doors.begin(); it != doors.end(); ++it)
|
||||
{
|
||||
MWBase::World::DoorMarker marker = *it;
|
||||
|
||||
// convert world coordinates to normalized cell coordinates
|
||||
MyGUI::IntCoord widgetCoord;
|
||||
float nX,nY;
|
||||
int cellDx, cellDy;
|
||||
if (!interior)
|
||||
{
|
||||
const int cellSize = 8192;
|
||||
|
||||
nX = (marker.x - cellSize * (x+mx-1)) / cellSize;
|
||||
nY = 1 - (marker.y - cellSize * (y-(my-1))) / cellSize;
|
||||
|
||||
widgetCoord = MyGUI::IntCoord(nX * 512 - 4 + mx * 512, nY * 512 - 4 + my * 512, 8, 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
Ogre::Vector2 position (marker.x, marker.y);
|
||||
MWBase::Environment::get().getWorld ()->getInteriorMapPosition (position, nX, nY, cellDx, cellDy);
|
||||
|
||||
widgetCoord = MyGUI::IntCoord(nX * 512 - 4 + (1+cellDx-x) * 512, nY * 512 - 4 + (1+cellDy-y) * 512, 8, 8);
|
||||
}
|
||||
|
||||
static int counter = 0;
|
||||
MarkerPosition markerPos;
|
||||
MyGUI::IntPoint widgetPos = getMarkerPosition(marker.x, marker.y, markerPos);
|
||||
MyGUI::IntCoord widgetCoord(widgetPos.left - 4,
|
||||
widgetPos.top - 4,
|
||||
8, 8);
|
||||
++counter;
|
||||
MyGUI::Button* markerWidget = mLocalMap->createWidget<MyGUI::Button>("ButtonImage",
|
||||
widgetCoord, MyGUI::Align::Default, "Marker" + boost::lexical_cast<std::string>(counter));
|
||||
widgetCoord, MyGUI::Align::Default, "Door" + boost::lexical_cast<std::string>(counter));
|
||||
markerWidget->setImageResource("DoorMarker");
|
||||
markerWidget->setUserString("ToolTipType", "Layout");
|
||||
markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine");
|
||||
markerWidget->setUserString("Caption_TextOneLine", marker.name);
|
||||
markerWidget->setUserString("IsMarker", "true");
|
||||
markerWidget->eventMouseSetFocus += MyGUI::newDelegate(this, &LocalMapBase::onMarkerFocused);
|
||||
markerWidget->eventMouseLostFocus += MyGUI::newDelegate(this, &LocalMapBase::onMarkerUnfocused);
|
||||
|
||||
MarkerPosition markerPos;
|
||||
markerPos.interior = interior;
|
||||
markerPos.cellX = interior ? cellDx : x + mx - 1;
|
||||
markerPos.cellY = interior ? cellDy : y + ((my - 1)*-1);
|
||||
markerPos.nX = nX;
|
||||
markerPos.nY = nY;
|
||||
|
||||
// Used by tooltips to not show the tooltip if marker is hidden by fog of war
|
||||
markerWidget->setUserString("IsMarker", "true");
|
||||
markerWidget->setUserData(markerPos);
|
||||
}
|
||||
|
||||
updateMarkers();
|
||||
|
||||
}
|
||||
}
|
||||
mInterior = interior;
|
||||
mCurX = x;
|
||||
mCurY = y;
|
||||
mChanged = false;
|
||||
|
||||
// fog of war
|
||||
applyFogOfWar();
|
||||
|
||||
// set the compass texture again, because MyGUI determines sorting of ImageBox widgets
|
||||
|
@ -222,6 +254,8 @@ namespace MWGui
|
|||
|
||||
void LocalMapBase::setPlayerPos(const float x, const float y)
|
||||
{
|
||||
updateMarkers();
|
||||
|
||||
if (x == mLastPositionX && y == mLastPositionY)
|
||||
return;
|
||||
|
||||
|
@ -255,6 +289,88 @@ namespace MWGui
|
|||
mLastDirectionY = y;
|
||||
}
|
||||
|
||||
void LocalMapBase::addDetectionMarkers(int type)
|
||||
{
|
||||
std::vector<MWWorld::Ptr> markers;
|
||||
MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||
world->listDetectedReferences(
|
||||
world->getPlayer().getPlayer(),
|
||||
markers, MWBase::World::DetectionType(type));
|
||||
if (markers.empty())
|
||||
return;
|
||||
|
||||
std::string markerTexture;
|
||||
MyGUI::Colour markerColour;
|
||||
if (type == MWBase::World::Detect_Creature)
|
||||
{
|
||||
markerTexture = "textures\\menu_map_dcreature.dds";
|
||||
markerColour = MyGUI::Colour(1,0,0,1);
|
||||
}
|
||||
if (type == MWBase::World::Detect_Key)
|
||||
{
|
||||
markerTexture = "textures\\menu_map_dkey.dds";
|
||||
markerColour = MyGUI::Colour(0,1,0,1);
|
||||
}
|
||||
if (type == MWBase::World::Detect_Enchantment)
|
||||
{
|
||||
markerTexture = "textures\\menu_map_dmagic.dds";
|
||||
markerColour = MyGUI::Colour(0,0,1,1);
|
||||
}
|
||||
|
||||
int counter = 0;
|
||||
for (std::vector<MWWorld::Ptr>::iterator it = markers.begin(); it != markers.end(); ++it)
|
||||
{
|
||||
const ESM::Position& worldPos = it->getRefData().getPosition();
|
||||
MarkerPosition markerPos;
|
||||
MyGUI::IntPoint widgetPos = getMarkerPosition(worldPos.pos[0], worldPos.pos[1], markerPos);
|
||||
MyGUI::IntCoord widgetCoord(widgetPos.left - 4,
|
||||
widgetPos.top - 4,
|
||||
8, 8);
|
||||
++counter;
|
||||
MyGUI::ImageBox* markerWidget = mLocalMap->createWidget<MyGUI::ImageBox>("ImageBox",
|
||||
widgetCoord, MyGUI::Align::Default, "Marker" + boost::lexical_cast<std::string>(counter));
|
||||
markerWidget->setImageTexture(markerTexture);
|
||||
markerWidget->setUserString("IsMarker", "true");
|
||||
markerWidget->setUserData(markerPos);
|
||||
markerWidget->setColour(markerColour);
|
||||
}
|
||||
}
|
||||
|
||||
void LocalMapBase::updateMarkers()
|
||||
{
|
||||
// clear all previous markers
|
||||
for (unsigned int i=0; i< mLocalMap->getChildCount(); ++i)
|
||||
{
|
||||
if (mLocalMap->getChildAt(i)->getName ().substr (0, 6) == "Marker")
|
||||
{
|
||||
MyGUI::Gui::getInstance ().destroyWidget (mLocalMap->getChildAt(i));
|
||||
}
|
||||
}
|
||||
|
||||
addDetectionMarkers(MWBase::World::Detect_Creature);
|
||||
addDetectionMarkers(MWBase::World::Detect_Key);
|
||||
addDetectionMarkers(MWBase::World::Detect_Enchantment);
|
||||
|
||||
// Add marker for the spot marked with Mark magic effect
|
||||
MWWorld::CellStore* markedCell = NULL;
|
||||
ESM::Position markedPosition;
|
||||
MWBase::Environment::get().getWorld()->getPlayer().getMarkedPosition(markedCell, markedPosition);
|
||||
if (markedCell && markedCell->isExterior() == !mInterior
|
||||
&& (!mInterior || Misc::StringUtils::ciEqual(markedCell->mCell->mName, mPrefix)))
|
||||
{
|
||||
MarkerPosition markerPos;
|
||||
MyGUI::IntPoint widgetPos = getMarkerPosition(markedPosition.pos[0], markedPosition.pos[1], markerPos);
|
||||
MyGUI::IntCoord widgetCoord(widgetPos.left - 4,
|
||||
widgetPos.top - 4,
|
||||
8, 8);
|
||||
MyGUI::ImageBox* markerWidget = mLocalMap->createWidget<MyGUI::ImageBox>("ImageBox",
|
||||
widgetCoord, MyGUI::Align::Default, "MarkerMarked");
|
||||
markerWidget->setImageTexture("textures\\menu_map_smark.dds");
|
||||
markerWidget->setUserString("IsMarker", "true");
|
||||
markerWidget->setUserData(markerPos);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
|
||||
MapWindow::MapWindow(const std::string& cacheDir)
|
||||
|
@ -319,7 +435,7 @@ namespace MWGui
|
|||
|
||||
static int _counter=0;
|
||||
MyGUI::Button* markerWidget = mGlobalMapImage->createWidget<MyGUI::Button>("ButtonImage",
|
||||
widgetCoord, MyGUI::Align::Default, "Marker" + boost::lexical_cast<std::string>(_counter));
|
||||
widgetCoord, MyGUI::Align::Default, "Door" + boost::lexical_cast<std::string>(_counter));
|
||||
markerWidget->setImageResource("DoorMarker");
|
||||
markerWidget->setUserString("ToolTipType", "Layout");
|
||||
markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine");
|
||||
|
@ -385,7 +501,7 @@ namespace MWGui
|
|||
|
||||
for (unsigned int i=0; i<mGlobalMapImage->getChildCount (); ++i)
|
||||
{
|
||||
if (mGlobalMapImage->getChildAt (i)->getName().substr(0,6) == "Marker")
|
||||
if (mGlobalMapImage->getChildAt (i)->getName().substr(0,4) == "Door")
|
||||
mGlobalMapImage->getChildAt (i)->castType<MyGUI::Button>()->setImageResource("DoorMarker");
|
||||
}
|
||||
|
||||
|
|
|
@ -55,9 +55,16 @@ namespace MWGui
|
|||
void onMarkerFocused(MyGUI::Widget* w1, MyGUI::Widget* w2);
|
||||
void onMarkerUnfocused(MyGUI::Widget* w1, MyGUI::Widget* w2);
|
||||
|
||||
MyGUI::IntPoint getMarkerPosition (float worldX, float worldY, MarkerPosition& markerPos);
|
||||
|
||||
virtual void notifyPlayerUpdate() {}
|
||||
virtual void notifyMapChanged() {}
|
||||
|
||||
// Update markers (Detect X effects, Mark/Recall effects)
|
||||
// Note, door markers handled in setActiveCell
|
||||
void updateMarkers();
|
||||
void addDetectionMarkers(int type);
|
||||
|
||||
OEngine::GUI::Layout* mLayout;
|
||||
|
||||
bool mMapDragAndDrop;
|
||||
|
|
|
@ -224,13 +224,6 @@ void LocalMap::render(const float x, const float y,
|
|||
// try loading from memory
|
||||
tex = TextureManager::getSingleton().getByName(texture);
|
||||
if (tex.isNull())
|
||||
{
|
||||
// try loading from disk
|
||||
//if (boost::filesystem::exists(texture+".jpg"))
|
||||
//{
|
||||
/// \todo
|
||||
//}
|
||||
//else
|
||||
{
|
||||
// render
|
||||
tex = TextureManager::getSingleton().createManual(
|
||||
|
@ -278,11 +271,8 @@ void LocalMap::render(const float x, const float y,
|
|||
tex2->getBuffer()->unlock();
|
||||
|
||||
mBuffers[texture] = buffer;
|
||||
}
|
||||
|
||||
// save to cache for next time
|
||||
//rtt->writeContentsToFile("./" + texture + ".jpg");
|
||||
}
|
||||
}
|
||||
mRenderingManager->enableLights(true);
|
||||
mLight->setVisible(false);
|
||||
|
||||
|
@ -339,8 +329,6 @@ void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Quaterni
|
|||
|
||||
Vector3 playerdirection = mCameraRotNode->convertWorldToLocalOrientation(orientation).yAxis();
|
||||
|
||||
Vector2 min(mBounds.getMinimum().x, mBounds.getMinimum().y);
|
||||
|
||||
if (!mInterior)
|
||||
{
|
||||
x = std::ceil(pos.x / sSize)-1;
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "refdata.hpp"
|
||||
#include "ptr.hpp"
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
|
@ -18,13 +18,13 @@ namespace MWWorld
|
|||
{
|
||||
std::vector<Ogre::SceneNode*> mHandles;
|
||||
|
||||
bool operator() (ESM::CellRef& ref, RefData& data)
|
||||
bool operator() (MWWorld::Ptr ptr)
|
||||
{
|
||||
Ogre::SceneNode* handle = data.getBaseNode();
|
||||
Ogre::SceneNode* handle = ptr.getRefData().getBaseNode();
|
||||
if (handle)
|
||||
mHandles.push_back (handle);
|
||||
|
||||
data.setBaseNode(0);
|
||||
ptr.getRefData().setBaseNode(0);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -143,7 +143,7 @@ namespace MWWorld
|
|||
{
|
||||
if (!iter->mData.getCount())
|
||||
continue;
|
||||
if (!functor (iter->mRef, iter->mData))
|
||||
if (!functor (MWWorld::Ptr(&*iter, this)))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -290,6 +290,8 @@ namespace MWWorld
|
|||
|
||||
virtual bool isPersistent (const MWWorld::Ptr& ptr) const;
|
||||
|
||||
virtual bool isKey (const MWWorld::Ptr& ptr) const { return false; }
|
||||
|
||||
virtual Ptr
|
||||
copyToCell(const Ptr &ptr, CellStore &cell) const;
|
||||
|
||||
|
|
|
@ -1442,10 +1442,8 @@ namespace MWWorld
|
|||
return d;
|
||||
}
|
||||
|
||||
std::vector<World::DoorMarker> World::getDoorMarkers (CellStore* cell)
|
||||
void World::getDoorMarkers (CellStore* cell, std::vector<World::DoorMarker>& out)
|
||||
{
|
||||
std::vector<World::DoorMarker> result;
|
||||
|
||||
MWWorld::CellRefList<ESM::Door>& doors = cell->mDoors;
|
||||
CellRefList<ESM::Door>::List& refList = doors.mList;
|
||||
for (CellRefList<ESM::Door>::List::iterator it = refList.begin(); it != refList.end(); ++it)
|
||||
|
@ -1461,11 +1459,9 @@ namespace MWWorld
|
|||
|
||||
newMarker.x = pos.pos[0];
|
||||
newMarker.y = pos.pos[1];
|
||||
result.push_back(newMarker);
|
||||
out.push_back(newMarker);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void World::getInteriorMapPosition (Ogre::Vector2 position, float& nX, float& nY, int &x, int& y)
|
||||
|
@ -1829,9 +1825,9 @@ namespace MWWorld
|
|||
{
|
||||
std::vector<std::string> mHandles;
|
||||
|
||||
bool operator() (ESM::CellRef& ref, RefData& data)
|
||||
bool operator() (Ptr ptr)
|
||||
{
|
||||
Ogre::SceneNode* handle = data.getBaseNode();
|
||||
Ogre::SceneNode* handle = ptr.getRefData().getBaseNode();
|
||||
if (handle)
|
||||
mHandles.push_back(handle->getName());
|
||||
return true;
|
||||
|
@ -2348,4 +2344,85 @@ namespace MWWorld
|
|||
|
||||
mWeatherManager->update(duration);
|
||||
}
|
||||
|
||||
struct AddDetectedReference
|
||||
{
|
||||
AddDetectedReference(std::vector<Ptr>& out, Ptr detector, World::DetectionType type, float squaredDist)
|
||||
: mOut(out), mDetector(detector), mType(type), mSquaredDist(squaredDist)
|
||||
{
|
||||
}
|
||||
|
||||
std::vector<Ptr>& mOut;
|
||||
Ptr mDetector;
|
||||
float mSquaredDist;
|
||||
World::DetectionType mType;
|
||||
bool operator() (MWWorld::Ptr ptr)
|
||||
{
|
||||
if (Ogre::Vector3(ptr.getRefData().getPosition().pos).squaredDistance(
|
||||
Ogre::Vector3(mDetector.getRefData().getPosition().pos)) >= mSquaredDist)
|
||||
return true;
|
||||
|
||||
if (!ptr.getRefData().isEnabled())
|
||||
return true;
|
||||
|
||||
// Consider references inside containers as well
|
||||
if (ptr.getClass().isActor() || ptr.getClass().getTypeName() == typeid(ESM::Container).name())
|
||||
{
|
||||
MWWorld::ContainerStore& store = ptr.getClass().getContainerStore(ptr);
|
||||
{
|
||||
for (MWWorld::ContainerStoreIterator it = store.begin(); it != store.end(); ++it)
|
||||
{
|
||||
if (needToAdd(*it))
|
||||
{
|
||||
mOut.push_back(ptr);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (needToAdd(ptr))
|
||||
mOut.push_back(ptr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool needToAdd (MWWorld::Ptr ptr)
|
||||
{
|
||||
if (mType == World::Detect_Creature && ptr.getClass().getTypeName() != typeid(ESM::Creature).name())
|
||||
return false;
|
||||
if (mType == World::Detect_Key && !ptr.getClass().isKey(ptr))
|
||||
return false;
|
||||
if (mType == World::Detect_Enchantment && ptr.getClass().getEnchantment(ptr).empty())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
void World::listDetectedReferences(const Ptr &ptr, std::vector<Ptr> &out, DetectionType type)
|
||||
{
|
||||
const MWMechanics::MagicEffects& effects = ptr.getClass().getCreatureStats(ptr).getMagicEffects();
|
||||
float dist=0;
|
||||
if (type == World::Detect_Creature)
|
||||
dist = effects.get(MWMechanics::EffectKey(ESM::MagicEffect::DetectAnimal)).mMagnitude;
|
||||
else if (type == World::Detect_Key)
|
||||
dist = effects.get(MWMechanics::EffectKey(ESM::MagicEffect::DetectKey)).mMagnitude;
|
||||
else if (type == World::Detect_Enchantment)
|
||||
dist = effects.get(MWMechanics::EffectKey(ESM::MagicEffect::DetectEnchantment)).mMagnitude;
|
||||
|
||||
if (!dist)
|
||||
return;
|
||||
|
||||
// TODO: "1 foot" = 20 game units?
|
||||
dist *= 20;
|
||||
|
||||
AddDetectedReference functor (out, ptr, type, dist*dist);
|
||||
|
||||
const Scene::CellStoreCollection& active = mWorldScene->getActiveCells();
|
||||
for (Scene::CellStoreCollection::const_iterator it = active.begin(); it != active.end(); ++it)
|
||||
{
|
||||
MWWorld::CellStore* cellStore = *it;
|
||||
cellStore->forEach(functor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -202,7 +202,7 @@ namespace MWWorld
|
|||
virtual Ogre::Vector2 getNorthVector (CellStore* cell);
|
||||
///< get north vector (OGRE coordinates) for given interior cell
|
||||
|
||||
virtual std::vector<DoorMarker> getDoorMarkers (MWWorld::CellStore* cell);
|
||||
virtual void getDoorMarkers (MWWorld::CellStore* cell, std::vector<DoorMarker>& out);
|
||||
///< get a list of teleport door markers for a given cell, to be displayed on the local map
|
||||
|
||||
virtual void getInteriorMapPosition (Ogre::Vector2 position, float& nX, float& nY, int &x, int& y);
|
||||
|
@ -526,6 +526,12 @@ namespace MWWorld
|
|||
/// @note id must be lower case
|
||||
virtual void teleportToClosestMarker (const MWWorld::Ptr& ptr,
|
||||
const std::string& id, Ogre::Vector3 worldPos);
|
||||
|
||||
/// List all references (filtered by \a type) detected by \a ptr. The range
|
||||
/// is determined by the current magnitude of the "Detect X" magic effect belonging to \a type.
|
||||
/// @note This also works for references in containers.
|
||||
virtual void listDetectedReferences (const MWWorld::Ptr& ptr, std::vector<MWWorld::Ptr>& out,
|
||||
DetectionType type);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue