forked from teamnwah/openmw-tes3coop
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;
|
virtual Ogre::Vector2 getNorthVector (MWWorld::CellStore* cell) = 0;
|
||||||
///< get north vector (OGRE coordinates) for given interior cell
|
///< 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
|
///< 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;
|
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
|
/// @note id must be lower case
|
||||||
virtual void teleportToClosestMarker (const MWWorld::Ptr& ptr,
|
virtual void teleportToClosestMarker (const MWWorld::Ptr& ptr,
|
||||||
const std::string& id, Ogre::Vector3 worldPos) = 0;
|
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;
|
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 float getWeight (const MWWorld::Ptr& ptr) const;
|
||||||
|
|
||||||
virtual bool canSell (const MWWorld::Ptr& item, int npcServices) 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)
|
void LocalMapBase::onMarkerFocused (MyGUI::Widget* w1, MyGUI::Widget* w2)
|
||||||
{
|
{
|
||||||
|
// Workaround to not make the marker visible if it's under fog of war
|
||||||
applyFogOfWar ();
|
applyFogOfWar ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalMapBase::onMarkerUnfocused (MyGUI::Widget* w1, MyGUI::Widget* w2)
|
void LocalMapBase::onMarkerUnfocused (MyGUI::Widget* w1, MyGUI::Widget* w2)
|
||||||
{
|
{
|
||||||
|
// Workaround to not make the marker visible if it's under fog of war
|
||||||
applyFogOfWar ();
|
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)
|
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
|
// clear all previous markers
|
||||||
for (unsigned int i=0; i< mLocalMap->getChildCount(); ++i)
|
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));
|
MyGUI::Gui::getInstance ().destroyWidget (mLocalMap->getChildAt(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update the map textures
|
||||||
for (int mx=0; mx<3; ++mx)
|
for (int mx=0; mx<3; ++mx)
|
||||||
{
|
{
|
||||||
for (int my=0; my<3; ++my)
|
for (int my=0; my<3; ++my)
|
||||||
|
@ -138,78 +191,57 @@ namespace MWGui
|
||||||
box->setImageTexture(image);
|
box->setImageTexture(image);
|
||||||
else
|
else
|
||||||
box->setImageTexture("black.png");
|
box->setImageTexture("black.png");
|
||||||
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
if (interior)
|
|
||||||
cell = MWBase::Environment::get().getWorld ()->getInterior (mPrefix);
|
|
||||||
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 (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;
|
|
||||||
++counter;
|
|
||||||
MyGUI::Button* markerWidget = mLocalMap->createWidget<MyGUI::Button>("ButtonImage",
|
|
||||||
widgetCoord, MyGUI::Align::Default, "Marker" + 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;
|
|
||||||
|
|
||||||
markerWidget->setUserData(markerPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mInterior = interior;
|
|
||||||
mCurX = x;
|
|
||||||
mCurY = y;
|
|
||||||
mChanged = false;
|
|
||||||
|
|
||||||
// fog of war
|
MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||||
|
|
||||||
|
// Retrieve the door markers we want to show
|
||||||
|
std::vector<MWBase::World::DoorMarker> doors;
|
||||||
|
if (interior)
|
||||||
|
{
|
||||||
|
MWWorld::CellStore* cell = world->getInterior (mPrefix);
|
||||||
|
world->getDoorMarkers(cell, doors);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
|
||||||
|
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, "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->eventMouseSetFocus += MyGUI::newDelegate(this, &LocalMapBase::onMarkerFocused);
|
||||||
|
markerWidget->eventMouseLostFocus += MyGUI::newDelegate(this, &LocalMapBase::onMarkerUnfocused);
|
||||||
|
// Used by tooltips to not show the tooltip if marker is hidden by fog of war
|
||||||
|
markerWidget->setUserString("IsMarker", "true");
|
||||||
|
markerWidget->setUserData(markerPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateMarkers();
|
||||||
|
|
||||||
applyFogOfWar();
|
applyFogOfWar();
|
||||||
|
|
||||||
// set the compass texture again, because MyGUI determines sorting of ImageBox widgets
|
// 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)
|
void LocalMapBase::setPlayerPos(const float x, const float y)
|
||||||
{
|
{
|
||||||
|
updateMarkers();
|
||||||
|
|
||||||
if (x == mLastPositionX && y == mLastPositionY)
|
if (x == mLastPositionX && y == mLastPositionY)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -255,6 +289,88 @@ namespace MWGui
|
||||||
mLastDirectionY = y;
|
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)
|
MapWindow::MapWindow(const std::string& cacheDir)
|
||||||
|
@ -319,7 +435,7 @@ namespace MWGui
|
||||||
|
|
||||||
static int _counter=0;
|
static int _counter=0;
|
||||||
MyGUI::Button* markerWidget = mGlobalMapImage->createWidget<MyGUI::Button>("ButtonImage",
|
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->setImageResource("DoorMarker");
|
||||||
markerWidget->setUserString("ToolTipType", "Layout");
|
markerWidget->setUserString("ToolTipType", "Layout");
|
||||||
markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine");
|
markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine");
|
||||||
|
@ -385,7 +501,7 @@ namespace MWGui
|
||||||
|
|
||||||
for (unsigned int i=0; i<mGlobalMapImage->getChildCount (); ++i)
|
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");
|
mGlobalMapImage->getChildAt (i)->castType<MyGUI::Button>()->setImageResource("DoorMarker");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,9 +55,16 @@ namespace MWGui
|
||||||
void onMarkerFocused(MyGUI::Widget* w1, MyGUI::Widget* w2);
|
void onMarkerFocused(MyGUI::Widget* w1, MyGUI::Widget* w2);
|
||||||
void onMarkerUnfocused(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 notifyPlayerUpdate() {}
|
||||||
virtual void notifyMapChanged() {}
|
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;
|
OEngine::GUI::Layout* mLayout;
|
||||||
|
|
||||||
bool mMapDragAndDrop;
|
bool mMapDragAndDrop;
|
||||||
|
|
|
@ -225,64 +225,54 @@ void LocalMap::render(const float x, const float y,
|
||||||
tex = TextureManager::getSingleton().getByName(texture);
|
tex = TextureManager::getSingleton().getByName(texture);
|
||||||
if (tex.isNull())
|
if (tex.isNull())
|
||||||
{
|
{
|
||||||
// try loading from disk
|
// render
|
||||||
//if (boost::filesystem::exists(texture+".jpg"))
|
tex = TextureManager::getSingleton().createManual(
|
||||||
//{
|
texture,
|
||||||
/// \todo
|
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
||||||
//}
|
TEX_TYPE_2D,
|
||||||
//else
|
xw*sMapResolution/sSize, yw*sMapResolution/sSize,
|
||||||
|
0,
|
||||||
|
PF_R8G8B8,
|
||||||
|
TU_RENDERTARGET);
|
||||||
|
|
||||||
|
RenderTarget* rtt = tex->getBuffer()->getRenderTarget();
|
||||||
|
|
||||||
|
rtt->setAutoUpdated(false);
|
||||||
|
Viewport* vp = rtt->addViewport(mCellCamera);
|
||||||
|
vp->setOverlaysEnabled(false);
|
||||||
|
vp->setShadowsEnabled(false);
|
||||||
|
vp->setBackgroundColour(ColourValue(0, 0, 0));
|
||||||
|
vp->setVisibilityMask(RV_Map);
|
||||||
|
vp->setMaterialScheme("local_map");
|
||||||
|
|
||||||
|
rtt->update();
|
||||||
|
|
||||||
|
// create "fog of war" texture
|
||||||
|
TexturePtr tex2 = TextureManager::getSingleton().createManual(
|
||||||
|
texture + "_fog",
|
||||||
|
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
||||||
|
TEX_TYPE_2D,
|
||||||
|
xw*sFogOfWarResolution/sSize, yw*sFogOfWarResolution/sSize,
|
||||||
|
0,
|
||||||
|
PF_A8R8G8B8,
|
||||||
|
TU_DYNAMIC_WRITE_ONLY_DISCARDABLE);
|
||||||
|
|
||||||
|
// create a buffer to use for dynamic operations
|
||||||
|
std::vector<uint32> buffer;
|
||||||
|
buffer.resize(sFogOfWarResolution*sFogOfWarResolution);
|
||||||
|
|
||||||
|
// initialize to (0, 0, 0, 1)
|
||||||
|
for (int p=0; p<sFogOfWarResolution*sFogOfWarResolution; ++p)
|
||||||
{
|
{
|
||||||
// render
|
buffer[p] = (255 << 24);
|
||||||
tex = TextureManager::getSingleton().createManual(
|
|
||||||
texture,
|
|
||||||
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
|
||||||
TEX_TYPE_2D,
|
|
||||||
xw*sMapResolution/sSize, yw*sMapResolution/sSize,
|
|
||||||
0,
|
|
||||||
PF_R8G8B8,
|
|
||||||
TU_RENDERTARGET);
|
|
||||||
|
|
||||||
RenderTarget* rtt = tex->getBuffer()->getRenderTarget();
|
|
||||||
|
|
||||||
rtt->setAutoUpdated(false);
|
|
||||||
Viewport* vp = rtt->addViewport(mCellCamera);
|
|
||||||
vp->setOverlaysEnabled(false);
|
|
||||||
vp->setShadowsEnabled(false);
|
|
||||||
vp->setBackgroundColour(ColourValue(0, 0, 0));
|
|
||||||
vp->setVisibilityMask(RV_Map);
|
|
||||||
vp->setMaterialScheme("local_map");
|
|
||||||
|
|
||||||
rtt->update();
|
|
||||||
|
|
||||||
// create "fog of war" texture
|
|
||||||
TexturePtr tex2 = TextureManager::getSingleton().createManual(
|
|
||||||
texture + "_fog",
|
|
||||||
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
|
||||||
TEX_TYPE_2D,
|
|
||||||
xw*sFogOfWarResolution/sSize, yw*sFogOfWarResolution/sSize,
|
|
||||||
0,
|
|
||||||
PF_A8R8G8B8,
|
|
||||||
TU_DYNAMIC_WRITE_ONLY_DISCARDABLE);
|
|
||||||
|
|
||||||
// create a buffer to use for dynamic operations
|
|
||||||
std::vector<uint32> buffer;
|
|
||||||
buffer.resize(sFogOfWarResolution*sFogOfWarResolution);
|
|
||||||
|
|
||||||
// initialize to (0, 0, 0, 1)
|
|
||||||
for (int p=0; p<sFogOfWarResolution*sFogOfWarResolution; ++p)
|
|
||||||
{
|
|
||||||
buffer[p] = (255 << 24);
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(tex2->getBuffer()->lock(HardwareBuffer::HBL_DISCARD), &buffer[0], sFogOfWarResolution*sFogOfWarResolution*4);
|
|
||||||
tex2->getBuffer()->unlock();
|
|
||||||
|
|
||||||
mBuffers[texture] = buffer;
|
|
||||||
|
|
||||||
// save to cache for next time
|
|
||||||
//rtt->writeContentsToFile("./" + texture + ".jpg");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memcpy(tex2->getBuffer()->lock(HardwareBuffer::HBL_DISCARD), &buffer[0], sFogOfWarResolution*sFogOfWarResolution*4);
|
||||||
|
tex2->getBuffer()->unlock();
|
||||||
|
|
||||||
|
mBuffers[texture] = buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
mRenderingManager->enableLights(true);
|
mRenderingManager->enableLights(true);
|
||||||
mLight->setVisible(false);
|
mLight->setVisible(false);
|
||||||
|
|
||||||
|
@ -339,8 +329,6 @@ void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Quaterni
|
||||||
|
|
||||||
Vector3 playerdirection = mCameraRotNode->convertWorldToLocalOrientation(orientation).yAxis();
|
Vector3 playerdirection = mCameraRotNode->convertWorldToLocalOrientation(orientation).yAxis();
|
||||||
|
|
||||||
Vector2 min(mBounds.getMinimum().x, mBounds.getMinimum().y);
|
|
||||||
|
|
||||||
if (!mInterior)
|
if (!mInterior)
|
||||||
{
|
{
|
||||||
x = std::ceil(pos.x / sSize)-1;
|
x = std::ceil(pos.x / sSize)-1;
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "refdata.hpp"
|
#include "ptr.hpp"
|
||||||
|
|
||||||
namespace ESM
|
namespace ESM
|
||||||
{
|
{
|
||||||
|
@ -18,13 +18,13 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
std::vector<Ogre::SceneNode*> mHandles;
|
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)
|
if (handle)
|
||||||
mHandles.push_back (handle);
|
mHandles.push_back (handle);
|
||||||
|
|
||||||
data.setBaseNode(0);
|
ptr.getRefData().setBaseNode(0);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -143,7 +143,7 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
if (!iter->mData.getCount())
|
if (!iter->mData.getCount())
|
||||||
continue;
|
continue;
|
||||||
if (!functor (iter->mRef, iter->mData))
|
if (!functor (MWWorld::Ptr(&*iter, this)))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -290,6 +290,8 @@ namespace MWWorld
|
||||||
|
|
||||||
virtual bool isPersistent (const MWWorld::Ptr& ptr) const;
|
virtual bool isPersistent (const MWWorld::Ptr& ptr) const;
|
||||||
|
|
||||||
|
virtual bool isKey (const MWWorld::Ptr& ptr) const { return false; }
|
||||||
|
|
||||||
virtual Ptr
|
virtual Ptr
|
||||||
copyToCell(const Ptr &ptr, CellStore &cell) const;
|
copyToCell(const Ptr &ptr, CellStore &cell) const;
|
||||||
|
|
||||||
|
|
|
@ -1442,10 +1442,8 @@ namespace MWWorld
|
||||||
return d;
|
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;
|
MWWorld::CellRefList<ESM::Door>& doors = cell->mDoors;
|
||||||
CellRefList<ESM::Door>::List& refList = doors.mList;
|
CellRefList<ESM::Door>::List& refList = doors.mList;
|
||||||
for (CellRefList<ESM::Door>::List::iterator it = refList.begin(); it != refList.end(); ++it)
|
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.x = pos.pos[0];
|
||||||
newMarker.y = pos.pos[1];
|
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)
|
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;
|
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)
|
if (handle)
|
||||||
mHandles.push_back(handle->getName());
|
mHandles.push_back(handle->getName());
|
||||||
return true;
|
return true;
|
||||||
|
@ -2348,4 +2344,85 @@ namespace MWWorld
|
||||||
|
|
||||||
mWeatherManager->update(duration);
|
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);
|
virtual Ogre::Vector2 getNorthVector (CellStore* cell);
|
||||||
///< get north vector (OGRE coordinates) for given interior 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
|
///< 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);
|
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
|
/// @note id must be lower case
|
||||||
virtual void teleportToClosestMarker (const MWWorld::Ptr& ptr,
|
virtual void teleportToClosestMarker (const MWWorld::Ptr& ptr,
|
||||||
const std::string& id, Ogre::Vector3 worldPos);
|
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