mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-19 22:23:51 +00:00
Merge remote-tracking branch 'scrawl/master'
This commit is contained in:
commit
a6e6411686
37 changed files with 616 additions and 331 deletions
|
@ -99,8 +99,6 @@ set(OENGINE_BULLET
|
||||||
${LIBDIR}/openengine/bullet/BtOgreExtras.h
|
${LIBDIR}/openengine/bullet/BtOgreExtras.h
|
||||||
${LIBDIR}/openengine/bullet/BtOgreGP.h
|
${LIBDIR}/openengine/bullet/BtOgreGP.h
|
||||||
${LIBDIR}/openengine/bullet/BtOgrePG.h
|
${LIBDIR}/openengine/bullet/BtOgrePG.h
|
||||||
${LIBDIR}/openengine/bullet/CMotionState.cpp
|
|
||||||
${LIBDIR}/openengine/bullet/CMotionState.h
|
|
||||||
${LIBDIR}/openengine/bullet/physic.cpp
|
${LIBDIR}/openengine/bullet/physic.cpp
|
||||||
${LIBDIR}/openengine/bullet/physic.hpp
|
${LIBDIR}/openengine/bullet/physic.hpp
|
||||||
${LIBDIR}/openengine/bullet/BulletShapeLoader.cpp
|
${LIBDIR}/openengine/bullet/BulletShapeLoader.cpp
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -291,6 +291,9 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
MWWorld::InventoryStore& invStore = MWWorld::Class::get(npc).getInventoryStore(npc);
|
MWWorld::InventoryStore& invStore = MWWorld::Class::get(npc).getInventoryStore(npc);
|
||||||
|
|
||||||
|
if (ptr.getCellRef().mCharge == 0)
|
||||||
|
return std::make_pair(0, "#{sInventoryMessage1}");
|
||||||
|
|
||||||
// slots that this item can be equipped in
|
// slots that this item can be equipped in
|
||||||
std::pair<std::vector<int>, bool> slots_ = MWWorld::Class::get(ptr).getEquipmentSlots(ptr);
|
std::pair<std::vector<int>, bool> slots_ = MWWorld::Class::get(ptr).getEquipmentSlots(ptr);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -493,6 +493,11 @@ namespace MWClass
|
||||||
if (!MWBase::Environment::get().getWorld()->getGodModeState())
|
if (!MWBase::Environment::get().getWorld()->getGodModeState())
|
||||||
weapon.getCellRef().mCharge -= std::min(std::max(1,
|
weapon.getCellRef().mCharge -= std::min(std::max(1,
|
||||||
(int)(damage * gmst.find("fWeaponDamageMult")->getFloat())), weapon.getCellRef().mCharge);
|
(int)(damage * gmst.find("fWeaponDamageMult")->getFloat())), weapon.getCellRef().mCharge);
|
||||||
|
|
||||||
|
// Weapon broken? unequip it
|
||||||
|
if (weapon.getCellRef().mCharge == 0)
|
||||||
|
weapon = *inv.unequipItem(weapon, ptr);
|
||||||
|
|
||||||
}
|
}
|
||||||
healthdmg = true;
|
healthdmg = true;
|
||||||
}
|
}
|
||||||
|
@ -644,6 +649,11 @@ namespace MWClass
|
||||||
armorref.mCharge = armor.get<ESM::Armor>()->mBase->mData.mHealth;
|
armorref.mCharge = armor.get<ESM::Armor>()->mBase->mData.mHealth;
|
||||||
armorref.mCharge -= std::min(std::max(1, (int)damagediff),
|
armorref.mCharge -= std::min(std::max(1, (int)damagediff),
|
||||||
armorref.mCharge);
|
armorref.mCharge);
|
||||||
|
|
||||||
|
// Armor broken? unequip it
|
||||||
|
if (armorref.mCharge == 0)
|
||||||
|
inv.unequipItem(armor, ptr);
|
||||||
|
|
||||||
switch(get(armor).getEquipmentSkill(armor))
|
switch(get(armor).getEquipmentSkill(armor))
|
||||||
{
|
{
|
||||||
case ESM::Skill::LightArmor:
|
case ESM::Skill::LightArmor:
|
||||||
|
|
|
@ -388,6 +388,9 @@ namespace MWClass
|
||||||
|
|
||||||
std::pair<int, std::string> Weapon::canBeEquipped(const MWWorld::Ptr &ptr, const MWWorld::Ptr &npc) const
|
std::pair<int, std::string> Weapon::canBeEquipped(const MWWorld::Ptr &ptr, const MWWorld::Ptr &npc) const
|
||||||
{
|
{
|
||||||
|
if (ptr.getCellRef().mCharge == 0)
|
||||||
|
return std::make_pair(0, "#{sInventoryMessage1}");
|
||||||
|
|
||||||
std::pair<std::vector<int>, bool> slots_ = MWWorld::Class::get(ptr).getEquipmentSlots(ptr);
|
std::pair<std::vector<int>, bool> slots_ = MWWorld::Class::get(ptr).getEquipmentSlots(ptr);
|
||||||
|
|
||||||
if (slots_.first.empty())
|
if (slots_.first.empty())
|
||||||
|
|
|
@ -163,6 +163,14 @@ namespace MWGui
|
||||||
MWWorld::Ptr object = item.mBase;
|
MWWorld::Ptr object = item.mBase;
|
||||||
int count = item.mCount;
|
int count = item.mCount;
|
||||||
|
|
||||||
|
// Bound items may not be moved
|
||||||
|
if (item.mBase.getCellRef().mRefID.size() > 6
|
||||||
|
&& item.mBase.getCellRef().mRefID.substr(0,6) == "bound_")
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getWindowManager()->messageBox("#{sBarterDialog12}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (item.mType == ItemStack::Type_Equipped)
|
if (item.mType == ItemStack::Type_Equipped)
|
||||||
{
|
{
|
||||||
MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr);
|
MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr);
|
||||||
|
|
|
@ -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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||||
|
|
||||||
// door markers
|
// Retrieve the door markers we want to show
|
||||||
|
std::vector<MWBase::World::DoorMarker> doors;
|
||||||
// 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)
|
if (interior)
|
||||||
cell = MWBase::Environment::get().getWorld ()->getInterior (mPrefix);
|
{
|
||||||
|
MWWorld::CellStore* cell = world->getInterior (mPrefix);
|
||||||
|
world->getDoorMarkers(cell, doors);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
cell = MWBase::Environment::get().getWorld ()->getExterior (x+mx-1, y-(my-1));
|
{
|
||||||
|
for (int dX=-1; dX<2; ++dX)
|
||||||
std::vector<MWBase::World::DoorMarker> doors = MWBase::Environment::get().getWorld ()->getDoorMarkers (cell);
|
{
|
||||||
|
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)
|
for (std::vector<MWBase::World::DoorMarker>::iterator it = doors.begin(); it != doors.end(); ++it)
|
||||||
{
|
{
|
||||||
MWBase::World::DoorMarker marker = *it;
|
MWBase::World::DoorMarker marker = *it;
|
||||||
|
|
||||||
// convert world coordinates to normalized cell coordinates
|
MarkerPosition markerPos;
|
||||||
MyGUI::IntCoord widgetCoord;
|
MyGUI::IntPoint widgetPos = getMarkerPosition(marker.x, marker.y, markerPos);
|
||||||
float nX,nY;
|
MyGUI::IntCoord widgetCoord(widgetPos.left - 4,
|
||||||
int cellDx, cellDy;
|
widgetPos.top - 4,
|
||||||
if (!interior)
|
8, 8);
|
||||||
{
|
|
||||||
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;
|
++counter;
|
||||||
MyGUI::Button* markerWidget = mLocalMap->createWidget<MyGUI::Button>("ButtonImage",
|
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->setImageResource("DoorMarker");
|
||||||
markerWidget->setUserString("ToolTipType", "Layout");
|
markerWidget->setUserString("ToolTipType", "Layout");
|
||||||
markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine");
|
markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine");
|
||||||
markerWidget->setUserString("Caption_TextOneLine", marker.name);
|
markerWidget->setUserString("Caption_TextOneLine", marker.name);
|
||||||
markerWidget->setUserString("IsMarker", "true");
|
|
||||||
markerWidget->eventMouseSetFocus += MyGUI::newDelegate(this, &LocalMapBase::onMarkerFocused);
|
markerWidget->eventMouseSetFocus += MyGUI::newDelegate(this, &LocalMapBase::onMarkerFocused);
|
||||||
markerWidget->eventMouseLostFocus += MyGUI::newDelegate(this, &LocalMapBase::onMarkerUnfocused);
|
markerWidget->eventMouseLostFocus += MyGUI::newDelegate(this, &LocalMapBase::onMarkerUnfocused);
|
||||||
|
// Used by tooltips to not show the tooltip if marker is hidden by fog of war
|
||||||
MarkerPosition markerPos;
|
markerWidget->setUserString("IsMarker", "true");
|
||||||
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);
|
markerWidget->setUserData(markerPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateMarkers();
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mInterior = interior;
|
|
||||||
mCurX = x;
|
|
||||||
mCurY = y;
|
|
||||||
mChanged = false;
|
|
||||||
|
|
||||||
// fog of war
|
|
||||||
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;
|
||||||
|
|
|
@ -40,6 +40,14 @@ namespace MWGui
|
||||||
for (size_t i = 0; i<mSourceModel->getItemCount(); ++i)
|
for (size_t i = 0; i<mSourceModel->getItemCount(); ++i)
|
||||||
{
|
{
|
||||||
const ItemStack& item = mSourceModel->getItem(i);
|
const ItemStack& item = mSourceModel->getItem(i);
|
||||||
|
|
||||||
|
// Bound items may not be stolen
|
||||||
|
if (item.mBase.getCellRef().mRefID.size() > 6
|
||||||
|
&& item.mBase.getCellRef().mRefID.substr(0,6) == "bound_")
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (std::find(mHiddenItems.begin(), mHiddenItems.end(), item) == mHiddenItems.end()
|
if (std::find(mHiddenItems.begin(), mHiddenItems.end(), item) == mHiddenItems.end()
|
||||||
&& item.mType != ItemStack::Type_Equipped)
|
&& item.mType != ItemStack::Type_Equipped)
|
||||||
mItems.push_back(item);
|
mItems.push_back(item);
|
||||||
|
|
|
@ -154,6 +154,13 @@ namespace MWGui
|
||||||
if(!MWWorld::Class::get(base).canSell(base, services))
|
if(!MWWorld::Class::get(base).canSell(base, services))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// Bound items may not be bought
|
||||||
|
if (item.mBase.getCellRef().mRefID.size() > 6
|
||||||
|
&& item.mBase.getCellRef().mRefID.substr(0,6) == "bound_")
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// don't show equipped items
|
// don't show equipped items
|
||||||
if(mMerchant.getTypeName() == typeid(ESM::NPC).name())
|
if(mMerchant.getTypeName() == typeid(ESM::NPC).name())
|
||||||
{
|
{
|
||||||
|
|
|
@ -831,9 +831,11 @@ namespace MWInput
|
||||||
|
|
||||||
void InputManager::updateIdleTime(float dt)
|
void InputManager::updateIdleTime(float dt)
|
||||||
{
|
{
|
||||||
|
static const float vanityDelay = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
|
||||||
|
.find("fVanityDelay")->getFloat();
|
||||||
if (mTimeIdle >= 0.f)
|
if (mTimeIdle >= 0.f)
|
||||||
mTimeIdle += dt;
|
mTimeIdle += dt;
|
||||||
if (mTimeIdle > 30.f) {
|
if (mTimeIdle > vanityDelay) {
|
||||||
MWBase::Environment::get().getWorld()->toggleVanityMode(true);
|
MWBase::Environment::get().getWorld()->toggleVanityMode(true);
|
||||||
mTimeIdle = -1.f;
|
mTimeIdle = -1.f;
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,44 @@ void adjustBoundItem (const std::string& item, bool bound, const MWWorld::Ptr& a
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool disintegrateSlot (MWWorld::Ptr ptr, int slot, float disintegrate)
|
||||||
|
{
|
||||||
|
// TODO: remove this check once creatures support inventory store
|
||||||
|
if (ptr.getTypeName() == typeid(ESM::NPC).name())
|
||||||
|
{
|
||||||
|
MWWorld::InventoryStore& inv = ptr.getClass().getInventoryStore(ptr);
|
||||||
|
MWWorld::ContainerStoreIterator item =
|
||||||
|
inv.getSlot(slot);
|
||||||
|
if (item != inv.end())
|
||||||
|
{
|
||||||
|
if (!item->getClass().hasItemHealth(*item))
|
||||||
|
return false;
|
||||||
|
if (item->getCellRef().mCharge == -1)
|
||||||
|
item->getCellRef().mCharge = item->getClass().getItemMaxHealth(*item);
|
||||||
|
|
||||||
|
if (item->getCellRef().mCharge == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
item->getCellRef().mCharge -=
|
||||||
|
std::min(disintegrate,
|
||||||
|
static_cast<float>(item->getCellRef().mCharge));
|
||||||
|
|
||||||
|
if (item->getCellRef().mCharge == 0)
|
||||||
|
{
|
||||||
|
// Will unequip the broken item and try to find a replacement
|
||||||
|
if (ptr.getRefData().getHandle() != "player")
|
||||||
|
inv.autoEquip(ptr);
|
||||||
|
else
|
||||||
|
inv.unequipItem(*item, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace MWMechanics
|
namespace MWMechanics
|
||||||
|
@ -241,6 +279,33 @@ namespace MWMechanics
|
||||||
creatureStats.setDynamic(i, stat);
|
creatureStats.setDynamic(i, stat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Apply disintegration (reduces item health)
|
||||||
|
float disintegrateWeapon = effects.get(EffectKey(ESM::MagicEffect::DisintegrateWeapon)).mMagnitude;
|
||||||
|
if (disintegrateWeapon > 0)
|
||||||
|
disintegrateSlot(ptr, MWWorld::InventoryStore::Slot_CarriedRight, disintegrateWeapon*duration);
|
||||||
|
float disintegrateArmor = effects.get(EffectKey(ESM::MagicEffect::DisintegrateArmor)).mMagnitude;
|
||||||
|
if (disintegrateArmor > 0)
|
||||||
|
{
|
||||||
|
// According to UESP
|
||||||
|
int priorities[] = {
|
||||||
|
MWWorld::InventoryStore::Slot_CarriedLeft,
|
||||||
|
MWWorld::InventoryStore::Slot_Cuirass,
|
||||||
|
MWWorld::InventoryStore::Slot_LeftPauldron,
|
||||||
|
MWWorld::InventoryStore::Slot_RightPauldron,
|
||||||
|
MWWorld::InventoryStore::Slot_LeftGauntlet,
|
||||||
|
MWWorld::InventoryStore::Slot_RightGauntlet,
|
||||||
|
MWWorld::InventoryStore::Slot_Helmet,
|
||||||
|
MWWorld::InventoryStore::Slot_Greaves,
|
||||||
|
MWWorld::InventoryStore::Slot_Boots
|
||||||
|
};
|
||||||
|
|
||||||
|
for (unsigned int i=0; i<sizeof(priorities)/sizeof(int); ++i)
|
||||||
|
{
|
||||||
|
if (disintegrateSlot(ptr, priorities[i], disintegrateArmor*duration))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Apply damage ticks
|
// Apply damage ticks
|
||||||
int damageEffects[] = {
|
int damageEffects[] = {
|
||||||
ESM::MagicEffect::FireDamage, ESM::MagicEffect::ShockDamage, ESM::MagicEffect::FrostDamage, ESM::MagicEffect::Poison,
|
ESM::MagicEffect::FireDamage, ESM::MagicEffect::ShockDamage, ESM::MagicEffect::FrostDamage, ESM::MagicEffect::Poison,
|
||||||
|
@ -640,6 +705,11 @@ namespace MWMechanics
|
||||||
|
|
||||||
iter->second->kill();
|
iter->second->kill();
|
||||||
|
|
||||||
|
// Reset magic effects and recalculate derived effects
|
||||||
|
// One case where we need this is to make sure bound items are removed upon death
|
||||||
|
stats.setMagicEffects(MWMechanics::MagicEffects());
|
||||||
|
calculateCreatureStatModifiers(iter->first, 0);
|
||||||
|
|
||||||
++mDeathCount[cls.getId(iter->first)];
|
++mDeathCount[cls.getId(iter->first)];
|
||||||
|
|
||||||
if(cls.isEssential(iter->first))
|
if(cls.isEssential(iter->first))
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
#include "../mwworld/player.hpp"
|
#include "../mwworld/player.hpp"
|
||||||
|
|
||||||
|
#include "spellcasting.hpp"
|
||||||
|
|
||||||
namespace MWMechanics
|
namespace MWMechanics
|
||||||
{
|
{
|
||||||
void MechanicsManager::buildPlayer()
|
void MechanicsManager::buildPlayer()
|
||||||
|
@ -123,6 +125,19 @@ namespace MWMechanics
|
||||||
npcStats.getSkill (index).setBase (
|
npcStats.getSkill (index).setBase (
|
||||||
npcStats.getSkill (index).getBase() + bonus);
|
npcStats.getSkill (index).getBase() + bonus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (i==1)
|
||||||
|
{
|
||||||
|
// Major skill - add starting spells for this skill if existing
|
||||||
|
const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
|
||||||
|
MWWorld::Store<ESM::Spell>::iterator it = store.get<ESM::Spell>().begin();
|
||||||
|
for (; it != store.get<ESM::Spell>().end(); ++it)
|
||||||
|
{
|
||||||
|
if (it->mData.mFlags & ESM::Spell::F_PCStart
|
||||||
|
&& spellSchoolToSkill(getSpellSchool(&*it, ptr)) == index)
|
||||||
|
creatureStats.getSpells().add(it->mId);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
#include "../mwworld/containerstore.hpp"
|
#include "../mwworld/containerstore.hpp"
|
||||||
#include "../mwworld/player.hpp"
|
#include "../mwworld/player.hpp"
|
||||||
|
#include "../mwworld/actionteleport.hpp"
|
||||||
|
|
||||||
#include "../mwrender/animation.hpp"
|
#include "../mwrender/animation.hpp"
|
||||||
|
|
||||||
|
@ -250,26 +251,30 @@ namespace MWMechanics
|
||||||
|
|
||||||
if (effectId == ESM::MagicEffect::DivineIntervention)
|
if (effectId == ESM::MagicEffect::DivineIntervention)
|
||||||
{
|
{
|
||||||
MWBase::Environment::get().getWorld()->getPlayer().setTeleported(true);
|
|
||||||
|
|
||||||
MWBase::Environment::get().getWorld()->teleportToClosestMarker(target, "divinemarker", worldPos);
|
MWBase::Environment::get().getWorld()->teleportToClosestMarker(target, "divinemarker", worldPos);
|
||||||
}
|
}
|
||||||
else if (effectId == ESM::MagicEffect::AlmsiviIntervention)
|
else if (effectId == ESM::MagicEffect::AlmsiviIntervention)
|
||||||
{
|
{
|
||||||
MWBase::Environment::get().getWorld()->getPlayer().setTeleported(true);
|
|
||||||
|
|
||||||
MWBase::Environment::get().getWorld()->teleportToClosestMarker(target, "templemarker", worldPos);
|
MWBase::Environment::get().getWorld()->teleportToClosestMarker(target, "templemarker", worldPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (effectId == ESM::MagicEffect::Mark)
|
else if (effectId == ESM::MagicEffect::Mark)
|
||||||
{
|
{
|
||||||
// TODO
|
MWBase::Environment::get().getWorld()->getPlayer().markPosition(
|
||||||
|
target.getCell(), target.getRefData().getPosition());
|
||||||
}
|
}
|
||||||
else if (effectId == ESM::MagicEffect::Recall)
|
else if (effectId == ESM::MagicEffect::Recall)
|
||||||
{
|
{
|
||||||
MWBase::Environment::get().getWorld()->getPlayer().setTeleported(true);
|
MWWorld::CellStore* markedCell = NULL;
|
||||||
|
ESM::Position markedPosition;
|
||||||
|
|
||||||
// TODO
|
MWBase::Environment::get().getWorld()->getPlayer().getMarkedPosition(markedCell, markedPosition);
|
||||||
|
if (markedCell)
|
||||||
|
{
|
||||||
|
MWWorld::ActionTeleport action(markedCell->isExterior() ? "" : markedCell->mCell->mName,
|
||||||
|
markedPosition);
|
||||||
|
action.execute(target);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -280,6 +280,11 @@ namespace MWRender
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float Camera::getCameraDistance() const
|
||||||
|
{
|
||||||
|
return mCamera->getPosition().z;
|
||||||
|
}
|
||||||
|
|
||||||
void Camera::setCameraDistance(float dist, bool adjust, bool override)
|
void Camera::setCameraDistance(float dist, bool adjust, bool override)
|
||||||
{
|
{
|
||||||
if(mFirstPersonView && !mPreviewMode && !mVanity.enabled)
|
if(mFirstPersonView && !mPreviewMode && !mVanity.enabled)
|
||||||
|
|
|
@ -105,6 +105,8 @@ namespace MWRender
|
||||||
/// Restore default camera distance for current mode.
|
/// Restore default camera distance for current mode.
|
||||||
void setCameraDistance();
|
void setCameraDistance();
|
||||||
|
|
||||||
|
float getCameraDistance() const;
|
||||||
|
|
||||||
void setAnimation(NpcAnimation *anim);
|
void setAnimation(NpcAnimation *anim);
|
||||||
|
|
||||||
/// Stores focal and camera world positions in passed arguments
|
/// Stores focal and camera world positions in passed arguments
|
||||||
|
|
|
@ -224,13 +224,6 @@ void LocalMap::render(const float x, const float y,
|
||||||
// try loading from memory
|
// try loading from memory
|
||||||
tex = TextureManager::getSingleton().getByName(texture);
|
tex = TextureManager::getSingleton().getByName(texture);
|
||||||
if (tex.isNull())
|
if (tex.isNull())
|
||||||
{
|
|
||||||
// try loading from disk
|
|
||||||
//if (boost::filesystem::exists(texture+".jpg"))
|
|
||||||
//{
|
|
||||||
/// \todo
|
|
||||||
//}
|
|
||||||
//else
|
|
||||||
{
|
{
|
||||||
// render
|
// render
|
||||||
tex = TextureManager::getSingleton().createManual(
|
tex = TextureManager::getSingleton().createManual(
|
||||||
|
@ -278,11 +271,8 @@ void LocalMap::render(const float x, const float y,
|
||||||
tex2->getBuffer()->unlock();
|
tex2->getBuffer()->unlock();
|
||||||
|
|
||||||
mBuffers[texture] = buffer;
|
mBuffers[texture] = buffer;
|
||||||
|
}
|
||||||
|
|
||||||
// save to cache for next time
|
|
||||||
//rtt->writeContentsToFile("./" + texture + ".jpg");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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;
|
||||||
|
|
|
@ -1026,4 +1026,9 @@ void RenderingManager::enableTerrain(bool enable)
|
||||||
mTerrain->setVisible(false);
|
mTerrain->setVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float RenderingManager::getCameraDistance() const
|
||||||
|
{
|
||||||
|
return mCamera->getCameraDistance();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -90,6 +90,7 @@ public:
|
||||||
|
|
||||||
bool vanityRotateCamera(const float *rot);
|
bool vanityRotateCamera(const float *rot);
|
||||||
void setCameraDistance(float dist, bool adjust = false, bool override = true);
|
void setCameraDistance(float dist, bool adjust = false, bool override = true);
|
||||||
|
float getCameraDistance() const;
|
||||||
|
|
||||||
void setupPlayer(const MWWorld::Ptr &ptr);
|
void setupPlayer(const MWWorld::Ptr &ptr);
|
||||||
void renderPlayer(const MWWorld::Ptr &ptr);
|
void renderPlayer(const MWWorld::Ptr &ptr);
|
||||||
|
|
|
@ -207,6 +207,10 @@ namespace MWScript
|
||||||
virtual void execute (Interpreter::Runtime& runtime)
|
virtual void execute (Interpreter::Runtime& runtime)
|
||||||
{
|
{
|
||||||
MWWorld::Ptr ptr = R()(runtime);
|
MWWorld::Ptr ptr = R()(runtime);
|
||||||
|
|
||||||
|
if (!ptr.isInCell())
|
||||||
|
return;
|
||||||
|
|
||||||
if (ptr.getRefData().getHandle() == "player")
|
if (ptr.getRefData().getHandle() == "player")
|
||||||
{
|
{
|
||||||
MWBase::Environment::get().getWorld()->getPlayer().setTeleported(true);
|
MWBase::Environment::get().getWorld()->getPlayer().setTeleported(true);
|
||||||
|
@ -275,6 +279,10 @@ namespace MWScript
|
||||||
virtual void execute (Interpreter::Runtime& runtime)
|
virtual void execute (Interpreter::Runtime& runtime)
|
||||||
{
|
{
|
||||||
MWWorld::Ptr ptr = R()(runtime);
|
MWWorld::Ptr ptr = R()(runtime);
|
||||||
|
|
||||||
|
if (!ptr.isInCell())
|
||||||
|
return;
|
||||||
|
|
||||||
if (ptr.getRefData().getHandle() == "player")
|
if (ptr.getRefData().getHandle() == "player")
|
||||||
{
|
{
|
||||||
MWBase::Environment::get().getWorld()->getPlayer().setTeleported(true);
|
MWBase::Environment::get().getWorld()->getPlayer().setTeleported(true);
|
||||||
|
@ -336,6 +344,10 @@ namespace MWScript
|
||||||
virtual void execute (Interpreter::Runtime& runtime)
|
virtual void execute (Interpreter::Runtime& runtime)
|
||||||
{
|
{
|
||||||
MWWorld::Ptr ptr = R()(runtime);
|
MWWorld::Ptr ptr = R()(runtime);
|
||||||
|
|
||||||
|
if (!ptr.isInCell())
|
||||||
|
return;
|
||||||
|
|
||||||
if (ptr.getRefData().getHandle() == "player")
|
if (ptr.getRefData().getHandle() == "player")
|
||||||
{
|
{
|
||||||
MWBase::Environment::get().getWorld()->getPlayer().setTeleported(true);
|
MWBase::Environment::get().getWorld()->getPlayer().setTeleported(true);
|
||||||
|
@ -605,6 +617,10 @@ namespace MWScript
|
||||||
virtual void execute (Interpreter::Runtime& runtime)
|
virtual void execute (Interpreter::Runtime& runtime)
|
||||||
{
|
{
|
||||||
MWWorld::Ptr ptr = R()(runtime);
|
MWWorld::Ptr ptr = R()(runtime);
|
||||||
|
|
||||||
|
if (!ptr.isInCell())
|
||||||
|
return;
|
||||||
|
|
||||||
ptr.getRefData().getLocalRotation().rot[0] = 0;
|
ptr.getRefData().getLocalRotation().rot[0] = 0;
|
||||||
ptr.getRefData().getLocalRotation().rot[1] = 0;
|
ptr.getRefData().getLocalRotation().rot[1] = 0;
|
||||||
ptr.getRefData().getLocalRotation().rot[2] = 0;
|
ptr.getRefData().getLocalRotation().rot[2] = 0;
|
||||||
|
@ -624,6 +640,9 @@ namespace MWScript
|
||||||
{
|
{
|
||||||
const MWWorld::Ptr& ptr = R()(runtime);
|
const MWWorld::Ptr& ptr = R()(runtime);
|
||||||
|
|
||||||
|
if (!ptr.isInCell())
|
||||||
|
return;
|
||||||
|
|
||||||
std::string axis = runtime.getStringLiteral (runtime[0].mInteger);
|
std::string axis = runtime.getStringLiteral (runtime[0].mInteger);
|
||||||
runtime.pop();
|
runtime.pop();
|
||||||
Interpreter::Type_Float movement = (runtime[0].mFloat*MWBase::Environment::get().getFrameDuration());
|
Interpreter::Type_Float movement = (runtime[0].mFloat*MWBase::Environment::get().getFrameDuration());
|
||||||
|
@ -659,6 +678,9 @@ namespace MWScript
|
||||||
{
|
{
|
||||||
MWWorld::Ptr ptr = R()(runtime);
|
MWWorld::Ptr ptr = R()(runtime);
|
||||||
|
|
||||||
|
if (!ptr.isInCell())
|
||||||
|
return;
|
||||||
|
|
||||||
std::string axis = runtime.getStringLiteral (runtime[0].mInteger);
|
std::string axis = runtime.getStringLiteral (runtime[0].mInteger);
|
||||||
runtime.pop();
|
runtime.pop();
|
||||||
Interpreter::Type_Float movement = (runtime[0].mFloat*MWBase::Environment::get().getFrameDuration());
|
Interpreter::Type_Float movement = (runtime[0].mFloat*MWBase::Environment::get().getFrameDuration());
|
||||||
|
|
|
@ -252,7 +252,7 @@ namespace MWSound
|
||||||
float basevol = volumeFromType(Play_TypeVoice);
|
float basevol = volumeFromType(Play_TypeVoice);
|
||||||
std::string filePath = "Sound/"+filename;
|
std::string filePath = "Sound/"+filename;
|
||||||
const ESM::Position &pos = ptr.getRefData().getPosition();
|
const ESM::Position &pos = ptr.getRefData().getPosition();
|
||||||
const Ogre::Vector3 objpos(pos.pos[0], pos.pos[1], pos.pos[2]);
|
const Ogre::Vector3 objpos(pos.pos);
|
||||||
|
|
||||||
MWBase::SoundPtr sound = mOutput->playSound3D(filePath, objpos, 1.0f, basevol, 1.0f,
|
MWBase::SoundPtr sound = mOutput->playSound3D(filePath, objpos, 1.0f, basevol, 1.0f,
|
||||||
20.0f, 12750.0f, Play_Normal|Play_TypeVoice, 0);
|
20.0f, 12750.0f, Play_Normal|Play_TypeVoice, 0);
|
||||||
|
@ -354,7 +354,7 @@ namespace MWSound
|
||||||
float min, max;
|
float min, max;
|
||||||
std::string file = lookup(soundId, volume, min, max);
|
std::string file = lookup(soundId, volume, min, max);
|
||||||
const ESM::Position &pos = ptr.getRefData().getPosition();
|
const ESM::Position &pos = ptr.getRefData().getPosition();
|
||||||
const Ogre::Vector3 objpos(pos.pos[0], pos.pos[1], pos.pos[2]);
|
const Ogre::Vector3 objpos(pos.pos);
|
||||||
|
|
||||||
sound = mOutput->playSound3D(file, objpos, volume, basevol, pitch, min, max, mode|type, offset);
|
sound = mOutput->playSound3D(file, objpos, volume, basevol, pitch, min, max, mode|type, offset);
|
||||||
if((mode&Play_NoTrack))
|
if((mode&Play_NoTrack))
|
||||||
|
@ -584,7 +584,7 @@ namespace MWSound
|
||||||
if(!ptr.isEmpty())
|
if(!ptr.isEmpty())
|
||||||
{
|
{
|
||||||
const ESM::Position &pos = ptr.getRefData().getPosition();
|
const ESM::Position &pos = ptr.getRefData().getPosition();
|
||||||
const Ogre::Vector3 objpos(pos.pos[0], pos.pos[1], pos.pos[2]);
|
const Ogre::Vector3 objpos(pos.pos);
|
||||||
snditer->first->setPosition(objpos);
|
snditer->first->setPosition(objpos);
|
||||||
}
|
}
|
||||||
//update fade out
|
//update fade out
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -577,10 +577,28 @@ namespace MWWorld
|
||||||
|
|
||||||
float oldHeight = iter->first.getRefData().getPosition().pos[2];
|
float oldHeight = iter->first.getRefData().getPosition().pos[2];
|
||||||
|
|
||||||
|
bool waterCollision = false;
|
||||||
|
if (iter->first.getClass().getCreatureStats(iter->first).getMagicEffects()
|
||||||
|
.get(ESM::MagicEffect::WaterWalking).mMagnitude
|
||||||
|
&& cell->hasWater()
|
||||||
|
&& !world->isUnderwater(iter->first.getCell(),
|
||||||
|
Ogre::Vector3(iter->first.getRefData().getPosition().pos)))
|
||||||
|
waterCollision = true;
|
||||||
|
|
||||||
|
btStaticPlaneShape planeShape(btVector3(0,0,1), waterlevel);
|
||||||
|
btCollisionObject object;
|
||||||
|
object.setCollisionShape(&planeShape);
|
||||||
|
|
||||||
|
if (waterCollision)
|
||||||
|
mEngine->dynamicsWorld->addCollisionObject(&object);
|
||||||
|
|
||||||
Ogre::Vector3 newpos = MovementSolver::move(iter->first, iter->second, mTimeAccum,
|
Ogre::Vector3 newpos = MovementSolver::move(iter->first, iter->second, mTimeAccum,
|
||||||
world->isFlying(iter->first),
|
world->isFlying(iter->first),
|
||||||
waterlevel, mEngine);
|
waterlevel, mEngine);
|
||||||
|
|
||||||
|
if (waterCollision)
|
||||||
|
mEngine->dynamicsWorld->removeCollisionObject(&object);
|
||||||
|
|
||||||
float heightDiff = newpos.z - oldHeight;
|
float heightDiff = newpos.z - oldHeight;
|
||||||
|
|
||||||
if (heightDiff < 0)
|
if (heightDiff < 0)
|
||||||
|
|
|
@ -21,7 +21,8 @@ namespace MWWorld
|
||||||
mLastKnownExteriorPosition(0,0,0),
|
mLastKnownExteriorPosition(0,0,0),
|
||||||
mAutoMove(false),
|
mAutoMove(false),
|
||||||
mForwardBackward (0),
|
mForwardBackward (0),
|
||||||
mTeleported(false)
|
mTeleported(false),
|
||||||
|
mMarkedCell(NULL)
|
||||||
{
|
{
|
||||||
mPlayer.mBase = player;
|
mPlayer.mBase = player;
|
||||||
mPlayer.mRef.mRefID = "player";
|
mPlayer.mRef.mRefID = "player";
|
||||||
|
@ -157,4 +158,17 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
mTeleported = teleported;
|
mTeleported = teleported;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Player::markPosition(CellStore *markedCell, ESM::Position markedPosition)
|
||||||
|
{
|
||||||
|
mMarkedCell = markedCell;
|
||||||
|
mMarkedPosition = markedPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player::getMarkedPosition(CellStore*& markedCell, ESM::Position &markedPosition) const
|
||||||
|
{
|
||||||
|
markedCell = mMarkedCell;
|
||||||
|
if (mMarkedCell)
|
||||||
|
markedPosition = mMarkedPosition;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,10 @@ namespace MWWorld
|
||||||
|
|
||||||
Ogre::Vector3 mLastKnownExteriorPosition;
|
Ogre::Vector3 mLastKnownExteriorPosition;
|
||||||
|
|
||||||
|
ESM::Position mMarkedPosition;
|
||||||
|
// If no position was marked, this is NULL
|
||||||
|
CellStore* mMarkedCell;
|
||||||
|
|
||||||
bool mAutoMove;
|
bool mAutoMove;
|
||||||
int mForwardBackward;
|
int mForwardBackward;
|
||||||
bool mTeleported;
|
bool mTeleported;
|
||||||
|
@ -39,6 +43,10 @@ namespace MWWorld
|
||||||
|
|
||||||
Player(const ESM::NPC *player, const MWBase::World& world);
|
Player(const ESM::NPC *player, const MWBase::World& world);
|
||||||
|
|
||||||
|
// For mark/recall magic effects
|
||||||
|
void markPosition (CellStore* markedCell, ESM::Position markedPosition);
|
||||||
|
void getMarkedPosition (CellStore*& markedCell, ESM::Position& markedPosition) const;
|
||||||
|
|
||||||
/// Interiors can not always be mapped to a world position. However
|
/// Interiors can not always be mapped to a world position. However
|
||||||
/// world position is still required for divine / almsivi magic effects
|
/// world position is still required for divine / almsivi magic effects
|
||||||
/// and the player arrow on the global map.
|
/// and the player arrow on the global map.
|
||||||
|
|
|
@ -796,32 +796,9 @@ namespace MWWorld
|
||||||
|
|
||||||
MWWorld::Ptr World::getFacedObject()
|
MWWorld::Ptr World::getFacedObject()
|
||||||
{
|
{
|
||||||
std::pair<float, std::string> result;
|
if (mFacedHandle.empty())
|
||||||
|
|
||||||
if (!mRendering->occlusionQuerySupported())
|
|
||||||
result = mPhysics->getFacedHandle (getMaxActivationDistance ());
|
|
||||||
else
|
|
||||||
result = std::make_pair (mFacedDistance, mFacedHandle);
|
|
||||||
|
|
||||||
if (result.second.empty())
|
|
||||||
return MWWorld::Ptr();
|
return MWWorld::Ptr();
|
||||||
|
return searchPtrViaHandle(mFacedHandle);
|
||||||
MWWorld::Ptr object = searchPtrViaHandle (result.second);
|
|
||||||
if (object.isEmpty())
|
|
||||||
return object;
|
|
||||||
float ActivationDistance;
|
|
||||||
|
|
||||||
if (MWBase::Environment::get().getWindowManager()->isConsoleMode())
|
|
||||||
ActivationDistance = getObjectActivationDistance ()*50;
|
|
||||||
else if (object.getTypeName ().find("NPC") != std::string::npos)
|
|
||||||
ActivationDistance = getNpcActivationDistance ();
|
|
||||||
else
|
|
||||||
ActivationDistance = getObjectActivationDistance ();
|
|
||||||
|
|
||||||
if (result.first > ActivationDistance)
|
|
||||||
return MWWorld::Ptr ();
|
|
||||||
|
|
||||||
return object;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<MWWorld::Ptr,Ogre::Vector3> World::getHitContact(const MWWorld::Ptr &ptr, float distance)
|
std::pair<MWWorld::Ptr,Ogre::Vector3> World::getHitContact(const MWWorld::Ptr &ptr, float distance)
|
||||||
|
@ -934,7 +911,7 @@ namespace MWWorld
|
||||||
ptr.getRefData().setCount(0);
|
ptr.getRefData().setCount(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (haveToMove)
|
if (haveToMove && ptr.getRefData().getBaseNode())
|
||||||
{
|
{
|
||||||
mRendering->moveObject(ptr, vec);
|
mRendering->moveObject(ptr, vec);
|
||||||
mPhysics->moveObject (ptr);
|
mPhysics->moveObject (ptr);
|
||||||
|
@ -1063,7 +1040,7 @@ namespace MWWorld
|
||||||
|
|
||||||
void World::adjustPosition(const Ptr &ptr)
|
void World::adjustPosition(const Ptr &ptr)
|
||||||
{
|
{
|
||||||
Ogre::Vector3 pos (ptr.getRefData().getPosition().pos[0], ptr.getRefData().getPosition().pos[1], ptr.getRefData().getPosition().pos[2]);
|
Ogre::Vector3 pos (ptr.getRefData().getPosition().pos);
|
||||||
|
|
||||||
if(!ptr.getRefData().getBaseNode())
|
if(!ptr.getRefData().getBaseNode())
|
||||||
{
|
{
|
||||||
|
@ -1304,7 +1281,7 @@ namespace MWWorld
|
||||||
if (mPlayer->getPlayer().getCell()->isExterior())
|
if (mPlayer->getPlayer().getCell()->isExterior())
|
||||||
{
|
{
|
||||||
ESM::Position pos = mPlayer->getPlayer().getRefData().getPosition();
|
ESM::Position pos = mPlayer->getPlayer().getRefData().getPosition();
|
||||||
mPlayer->setLastKnownExteriorPosition(Ogre::Vector3(pos.pos[0], pos.pos[1], pos.pos[2]));
|
mPlayer->setLastKnownExteriorPosition(Ogre::Vector3(pos.pos));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1346,6 +1323,14 @@ namespace MWWorld
|
||||||
|
|
||||||
void World::updateFacedHandle ()
|
void World::updateFacedHandle ()
|
||||||
{
|
{
|
||||||
|
float telekinesisRangeBonus =
|
||||||
|
mPlayer->getPlayer().getClass().getCreatureStats(mPlayer->getPlayer()).getMagicEffects()
|
||||||
|
.get(ESM::MagicEffect::Telekinesis).mMagnitude;
|
||||||
|
telekinesisRangeBonus = feetToGameUnits(telekinesisRangeBonus);
|
||||||
|
|
||||||
|
float activationDistance = getMaxActivationDistance() + telekinesisRangeBonus;
|
||||||
|
activationDistance += mRendering->getCameraDistance();
|
||||||
|
|
||||||
// send new query
|
// send new query
|
||||||
// figure out which object we want to test against
|
// figure out which object we want to test against
|
||||||
std::vector < std::pair < float, std::string > > results;
|
std::vector < std::pair < float, std::string > > results;
|
||||||
|
@ -1353,13 +1338,13 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
float x, y;
|
float x, y;
|
||||||
MWBase::Environment::get().getWindowManager()->getMousePosition(x, y);
|
MWBase::Environment::get().getWindowManager()->getMousePosition(x, y);
|
||||||
results = mPhysics->getFacedHandles(x, y, getMaxActivationDistance ());
|
results = mPhysics->getFacedHandles(x, y, activationDistance);
|
||||||
if (MWBase::Environment::get().getWindowManager()->isConsoleMode())
|
if (MWBase::Environment::get().getWindowManager()->isConsoleMode())
|
||||||
results = mPhysics->getFacedHandles(x, y, getMaxActivationDistance ()*50);
|
results = mPhysics->getFacedHandles(x, y, getMaxActivationDistance ()*50);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
results = mPhysics->getFacedHandles(getMaxActivationDistance ());
|
results = mPhysics->getFacedHandles(activationDistance);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ignore the player and other things we're not interested in
|
// ignore the player and other things we're not interested in
|
||||||
|
@ -1442,10 +1427,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 +1444,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)
|
||||||
|
@ -1588,7 +1569,7 @@ namespace MWWorld
|
||||||
pos.rot[1] = 0;
|
pos.rot[1] = 0;
|
||||||
|
|
||||||
Ogre::Vector3 orig =
|
Ogre::Vector3 orig =
|
||||||
Ogre::Vector3(pos.pos[0], pos.pos[1], pos.pos[2]);
|
Ogre::Vector3(pos.pos);
|
||||||
Ogre::Vector3 dir = Ogre::Vector3(0, 0, -1);
|
Ogre::Vector3 dir = Ogre::Vector3(0, 0, -1);
|
||||||
|
|
||||||
float len = (pos.pos[2] >= 0) ? pos.pos[2] : -pos.pos[2];
|
float len = (pos.pos[2] >= 0) ? pos.pos[2] : -pos.pos[2];
|
||||||
|
@ -1829,9 +1810,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;
|
||||||
|
@ -1940,17 +1921,8 @@ namespace MWWorld
|
||||||
int y = ext->getGridY();
|
int y = ext->getGridY();
|
||||||
indexToPosition(x, y, pos.pos[0], pos.pos[1], true);
|
indexToPosition(x, y, pos.pos[0], pos.pos[1], true);
|
||||||
|
|
||||||
ESM::Land* land = getStore().get<ESM::Land>().search(x, y);
|
// Note: Z pos will be adjusted by adjustPosition later
|
||||||
if (land) {
|
|
||||||
if (!land->isDataLoaded(ESM::Land::DATA_VHGT)) {
|
|
||||||
land->loadData(ESM::Land::DATA_VHGT);
|
|
||||||
}
|
|
||||||
pos.pos[2] = land->mLandData->mHeights[ESM::Land::LAND_NUM_VERTS / 2 + 1];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
std::cerr << "Land data for cell at (" << x << ", " << y << ") not found\n";
|
|
||||||
pos.pos[2] = 0;
|
pos.pos[2] = 0;
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -2312,7 +2284,7 @@ namespace MWWorld
|
||||||
if (ref.mRef.mTeleport && ref.mRef.mDestCell.empty())
|
if (ref.mRef.mTeleport && ref.mRef.mDestCell.empty())
|
||||||
{
|
{
|
||||||
ESM::Position pos = ref.mRef.mDoorDest;
|
ESM::Position pos = ref.mRef.mDoorDest;
|
||||||
result = Ogre::Vector3(pos.pos[0], pos.pos[1], pos.pos[2]);
|
result = Ogre::Vector3(pos.pos);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2333,7 +2305,7 @@ namespace MWWorld
|
||||||
for (std::vector<MWWorld::Ptr>::iterator it = markers.begin(); it != markers.end(); ++it)
|
for (std::vector<MWWorld::Ptr>::iterator it = markers.begin(); it != markers.end(); ++it)
|
||||||
{
|
{
|
||||||
ESM::Position pos = it->getRefData().getPosition();
|
ESM::Position pos = it->getRefData().getPosition();
|
||||||
Ogre::Vector3 markerPos = Ogre::Vector3(pos.pos[0], pos.pos[1], pos.pos[2]);
|
Ogre::Vector3 markerPos = Ogre::Vector3(pos.pos);
|
||||||
float distance = worldPos.squaredDistance(markerPos);
|
float distance = worldPos.squaredDistance(markerPos);
|
||||||
if (distance < closestDistance)
|
if (distance < closestDistance)
|
||||||
{
|
{
|
||||||
|
@ -2357,4 +2329,91 @@ 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;
|
||||||
|
|
||||||
|
dist = feetToGameUnits(dist);
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float World::feetToGameUnits(float feet)
|
||||||
|
{
|
||||||
|
// Looks like there is no GMST for this. This factor was determined in experiments
|
||||||
|
// with the Telekinesis effect.
|
||||||
|
return feet * 22;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -155,6 +155,8 @@ namespace MWWorld
|
||||||
/// Called when \a object is moved to an inactive cell
|
/// Called when \a object is moved to an inactive cell
|
||||||
void objectLeftActiveCell (MWWorld::Ptr object, MWWorld::Ptr movedPtr);
|
void objectLeftActiveCell (MWWorld::Ptr object, MWWorld::Ptr movedPtr);
|
||||||
|
|
||||||
|
float feetToGameUnits(float feet);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
World (OEngine::Render::OgreRenderer& renderer,
|
World (OEngine::Render::OgreRenderer& renderer,
|
||||||
|
@ -202,7 +204,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 +528,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);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ namespace ESM
|
||||||
public:
|
public:
|
||||||
|
|
||||||
int mRefnum; // Reference number
|
int mRefnum; // Reference number
|
||||||
std::string mRefID; // ID of object being referenced
|
std::string mRefID; // ID of object being referenced (must be lowercase)
|
||||||
|
|
||||||
float mScale; // Scale applied to mesh
|
float mScale; // Scale applied to mesh
|
||||||
|
|
||||||
|
|
|
@ -1,46 +0,0 @@
|
||||||
#include "CMotionState.h"
|
|
||||||
#include "physic.hpp"
|
|
||||||
|
|
||||||
#include <btBulletDynamicsCommon.h>
|
|
||||||
#include <btBulletCollisionCommon.h>
|
|
||||||
#include <components/nifbullet/bulletnifloader.hpp>
|
|
||||||
|
|
||||||
namespace OEngine {
|
|
||||||
namespace Physic
|
|
||||||
{
|
|
||||||
|
|
||||||
CMotionState::CMotionState(PhysicEngine* eng,std::string name)
|
|
||||||
: isPC(false)
|
|
||||||
, isNPC(true)
|
|
||||||
{
|
|
||||||
pEng = eng;
|
|
||||||
tr.setIdentity();
|
|
||||||
pName = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CMotionState::getWorldTransform(btTransform &worldTrans) const
|
|
||||||
{
|
|
||||||
worldTrans = tr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CMotionState::setWorldTransform(const btTransform &worldTrans)
|
|
||||||
{
|
|
||||||
tr = worldTrans;
|
|
||||||
|
|
||||||
PhysicEvent evt;
|
|
||||||
evt.isNPC = isNPC;
|
|
||||||
evt.isPC = isPC;
|
|
||||||
evt.newTransform = tr;
|
|
||||||
evt.RigidBodyName = pName;
|
|
||||||
|
|
||||||
if(isPC)
|
|
||||||
{
|
|
||||||
pEng->PEventList.push_back(evt);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pEng->NPEventList.push_back(evt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}}
|
|
|
@ -1,52 +0,0 @@
|
||||||
#ifndef OENGINE_CMOTIONSTATE_H
|
|
||||||
#define OENGINE_CMOTIONSTATE_H
|
|
||||||
|
|
||||||
#include <BulletDynamics/Dynamics/btRigidBody.h>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace OEngine {
|
|
||||||
namespace Physic
|
|
||||||
{
|
|
||||||
class PhysicEngine;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A CMotionState is associated with a single RigidBody.
|
|
||||||
* When the RigidBody is moved by bullet, bullet will call the function setWorldTransform.
|
|
||||||
* for more info, see the bullet Wiki at btMotionState.
|
|
||||||
*/
|
|
||||||
class CMotionState:public btMotionState
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
CMotionState(PhysicEngine* eng,std::string name);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the position of the RigidBody.
|
|
||||||
*/
|
|
||||||
virtual void getWorldTransform(btTransform &worldTrans) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function called by bullet when the RigidBody is moved.
|
|
||||||
* It add an event to the EventList of the PhysicEngine class.
|
|
||||||
*/
|
|
||||||
virtual void setWorldTransform(const btTransform &worldTrans);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
PhysicEngine* pEng;
|
|
||||||
btTransform tr;
|
|
||||||
bool isNPC;
|
|
||||||
bool isPC;
|
|
||||||
|
|
||||||
std::string pName;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PhysicEvent
|
|
||||||
{
|
|
||||||
bool isNPC;
|
|
||||||
bool isPC;
|
|
||||||
btTransform newTransform;
|
|
||||||
std::string RigidBodyName;
|
|
||||||
};
|
|
||||||
|
|
||||||
}}
|
|
||||||
#endif
|
|
|
@ -3,7 +3,6 @@
|
||||||
#include <btBulletCollisionCommon.h>
|
#include <btBulletCollisionCommon.h>
|
||||||
#include <BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h>
|
#include <BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h>
|
||||||
#include <components/nifbullet/bulletnifloader.hpp>
|
#include <components/nifbullet/bulletnifloader.hpp>
|
||||||
#include "CMotionState.h"
|
|
||||||
#include "OgreRoot.h"
|
#include "OgreRoot.h"
|
||||||
#include "btKinematicCharacterController.h"
|
#include "btKinematicCharacterController.h"
|
||||||
#include "BtOgrePG.h"
|
#include "BtOgrePG.h"
|
||||||
|
@ -318,9 +317,7 @@ namespace Physic
|
||||||
btVector3 scl(triSize, triSize, 1);
|
btVector3 scl(triSize, triSize, 1);
|
||||||
hfShape->setLocalScaling(scl);
|
hfShape->setLocalScaling(scl);
|
||||||
|
|
||||||
CMotionState* newMotionState = new CMotionState(this,name);
|
btRigidBody::btRigidBodyConstructionInfo CI = btRigidBody::btRigidBodyConstructionInfo(0,0,hfShape);
|
||||||
|
|
||||||
btRigidBody::btRigidBodyConstructionInfo CI = btRigidBody::btRigidBodyConstructionInfo(0,newMotionState,hfShape);
|
|
||||||
RigidBody* body = new RigidBody(CI,name);
|
RigidBody* body = new RigidBody(CI,name);
|
||||||
body->getWorldTransform().setOrigin(btVector3( (x+0.5)*triSize*(sqrtVerts-1), (y+0.5)*triSize*(sqrtVerts-1), (maxh+minh)/2.f));
|
body->getWorldTransform().setOrigin(btVector3( (x+0.5)*triSize*(sqrtVerts-1), (y+0.5)*triSize*(sqrtVerts-1), (maxh+minh)/2.f));
|
||||||
|
|
||||||
|
@ -401,12 +398,9 @@ namespace Physic
|
||||||
else
|
else
|
||||||
shape->mRaycastingShape->setLocalScaling( btVector3(scale,scale,scale));
|
shape->mRaycastingShape->setLocalScaling( btVector3(scale,scale,scale));
|
||||||
|
|
||||||
//create the motionState
|
|
||||||
CMotionState* newMotionState = new CMotionState(this,name);
|
|
||||||
|
|
||||||
//create the real body
|
//create the real body
|
||||||
btRigidBody::btRigidBodyConstructionInfo CI = btRigidBody::btRigidBodyConstructionInfo
|
btRigidBody::btRigidBodyConstructionInfo CI = btRigidBody::btRigidBodyConstructionInfo
|
||||||
(0,newMotionState, raycasting ? shape->mRaycastingShape : shape->mCollisionShape);
|
(0,0, raycasting ? shape->mRaycastingShape : shape->mCollisionShape);
|
||||||
RigidBody* body = new RigidBody(CI,name);
|
RigidBody* body = new RigidBody(CI,name);
|
||||||
body->mPlaceable = placeable;
|
body->mPlaceable = placeable;
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,6 @@ namespace MWWorld
|
||||||
namespace OEngine {
|
namespace OEngine {
|
||||||
namespace Physic
|
namespace Physic
|
||||||
{
|
{
|
||||||
class CMotionState;
|
|
||||||
struct PhysicEvent;
|
struct PhysicEvent;
|
||||||
class PhysicEngine;
|
class PhysicEngine;
|
||||||
class RigidBody;
|
class RigidBody;
|
||||||
|
@ -157,17 +156,7 @@ namespace Physic
|
||||||
private:
|
private:
|
||||||
void disableCollisionBody();
|
void disableCollisionBody();
|
||||||
void enableCollisionBody();
|
void enableCollisionBody();
|
||||||
public:
|
|
||||||
//HACK: in Visual Studio 2010 and presumably above, this structures alignment
|
|
||||||
// must be 16, but the built in operator new & delete don't properly
|
|
||||||
// perform this alignment.
|
|
||||||
#if _MSC_VER >= 1600
|
|
||||||
void * operator new (size_t Size) { return _aligned_malloc (Size, 16); }
|
|
||||||
void operator delete (void * Data) { _aligned_free (Data); }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
OEngine::Physic::RigidBody* mBody;
|
OEngine::Physic::RigidBody* mBody;
|
||||||
OEngine::Physic::RigidBody* mRaycastingBody;
|
OEngine::Physic::RigidBody* mRaycastingBody;
|
||||||
|
|
||||||
|
@ -329,12 +318,6 @@ public:
|
||||||
const btVector3 &origin,
|
const btVector3 &origin,
|
||||||
btCollisionObject *object);
|
btCollisionObject *object);
|
||||||
|
|
||||||
//event list of non player object
|
|
||||||
std::list<PhysicEvent> NPEventList;
|
|
||||||
|
|
||||||
//event list affecting the player
|
|
||||||
std::list<PhysicEvent> PEventList;
|
|
||||||
|
|
||||||
//Bullet Stuff
|
//Bullet Stuff
|
||||||
btOverlappingPairCache* pairCache;
|
btOverlappingPairCache* pairCache;
|
||||||
btBroadphaseInterface* broadphase;
|
btBroadphaseInterface* broadphase;
|
||||||
|
|
|
@ -25,6 +25,7 @@ void OgreRenderer::cleanup()
|
||||||
delete mFader;
|
delete mFader;
|
||||||
mFader = NULL;
|
mFader = NULL;
|
||||||
|
|
||||||
|
if (mWindow)
|
||||||
Ogre::Root::getSingleton().destroyRenderTarget(mWindow);
|
Ogre::Root::getSingleton().destroyRenderTarget(mWindow);
|
||||||
mWindow = NULL;
|
mWindow = NULL;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue