mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-16 21:49:55 +00:00
Merge branch 'master' into openmw-28
This commit is contained in:
commit
0d3e67dafc
54 changed files with 777 additions and 385 deletions
|
@ -15,7 +15,7 @@ before_install:
|
|||
- sudo apt-get install -qq libqt4-dev libxaw7-dev libxrandr-dev libfreeimage-dev libpng-dev
|
||||
- sudo apt-get install -qq libopenal-dev libmpg123-dev libsndfile1-dev
|
||||
- sudo apt-get install -qq libavcodec-dev libavformat-dev libavdevice-dev libavutil-dev libswscale-dev libpostproc-dev
|
||||
- sudo apt-get install -qq libbullet-dev libogre-1.8-dev libmygui-dev libsdl2-dev libunshield-dev
|
||||
- sudo apt-get install -qq libbullet-dev libogre-1.9-dev libmygui-dev libsdl2-dev libunshield-dev
|
||||
- sudo mkdir /usr/src/gtest/build
|
||||
- cd /usr/src/gtest/build
|
||||
- sudo cmake .. -DBUILD_SHARED_LIBS=1
|
||||
|
|
|
@ -99,8 +99,6 @@ set(OENGINE_BULLET
|
|||
${LIBDIR}/openengine/bullet/BtOgreExtras.h
|
||||
${LIBDIR}/openengine/bullet/BtOgreGP.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.hpp
|
||||
${LIBDIR}/openengine/bullet/BulletShapeLoader.cpp
|
||||
|
|
|
@ -130,7 +130,7 @@ namespace MWBase
|
|||
virtual Ogre::Vector2 getNorthVector (MWWorld::CellStore* cell) = 0;
|
||||
///< get north vector (OGRE coordinates) for given interior cell
|
||||
|
||||
virtual std::vector<DoorMarker> getDoorMarkers (MWWorld::CellStore* cell) = 0;
|
||||
virtual void getDoorMarkers (MWWorld::CellStore* cell, std::vector<DoorMarker>& out) = 0;
|
||||
///< get a list of teleport door markers for a given cell, to be displayed on the local map
|
||||
|
||||
virtual void getInteriorMapPosition (Ogre::Vector2 position, float& nX, float& nY, int &x, int& y) = 0;
|
||||
|
@ -438,6 +438,18 @@ namespace MWBase
|
|||
/// @note id must be lower case
|
||||
virtual void teleportToClosestMarker (const MWWorld::Ptr& ptr,
|
||||
const std::string& id, Ogre::Vector3 worldPos) = 0;
|
||||
|
||||
enum DetectionType
|
||||
{
|
||||
Detect_Enchantment,
|
||||
Detect_Key,
|
||||
Detect_Creature
|
||||
};
|
||||
/// List all references (filtered by \a type) detected by \a ptr. The range
|
||||
/// is determined by the current magnitude of the "Detect X" magic effect belonging to \a type.
|
||||
/// @note This also works for references in containers.
|
||||
virtual void listDetectedReferences (const MWWorld::Ptr& ptr, std::vector<MWWorld::Ptr>& out,
|
||||
DetectionType type) = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -291,6 +291,9 @@ namespace MWClass
|
|||
{
|
||||
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
|
||||
std::pair<std::vector<int>, bool> slots_ = MWWorld::Class::get(ptr).getEquipmentSlots(ptr);
|
||||
|
||||
|
|
|
@ -252,4 +252,11 @@ namespace MWClass
|
|||
return ref->mBase->mData.mWeight;
|
||||
}
|
||||
|
||||
bool Miscellaneous::isKey(const MWWorld::Ptr &ptr) const
|
||||
{
|
||||
MWWorld::LiveCellRef<ESM::Miscellaneous> *ref =
|
||||
ptr.get<ESM::Miscellaneous>();
|
||||
return ref->mBase->mData.mIsKey;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -57,6 +57,8 @@ namespace MWClass
|
|||
virtual float getWeight (const MWWorld::Ptr& ptr) const;
|
||||
|
||||
virtual bool canSell (const MWWorld::Ptr& item, int npcServices) const;
|
||||
|
||||
virtual bool isKey (const MWWorld::Ptr &ptr) const;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -493,6 +493,11 @@ namespace MWClass
|
|||
if (!MWBase::Environment::get().getWorld()->getGodModeState())
|
||||
weapon.getCellRef().mCharge -= std::min(std::max(1,
|
||||
(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;
|
||||
}
|
||||
|
@ -644,6 +649,11 @@ namespace MWClass
|
|||
armorref.mCharge = armor.get<ESM::Armor>()->mBase->mData.mHealth;
|
||||
armorref.mCharge -= std::min(std::max(1, (int)damagediff),
|
||||
armorref.mCharge);
|
||||
|
||||
// Armor broken? unequip it
|
||||
if (armorref.mCharge == 0)
|
||||
inv.unequipItem(armor, ptr);
|
||||
|
||||
switch(get(armor).getEquipmentSkill(armor))
|
||||
{
|
||||
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
|
||||
{
|
||||
if (ptr.getCellRef().mCharge == 0)
|
||||
return std::make_pair(0, "#{sInventoryMessage1}");
|
||||
|
||||
std::pair<std::vector<int>, bool> slots_ = MWWorld::Class::get(ptr).getEquipmentSlots(ptr);
|
||||
|
||||
if (slots_.first.empty())
|
||||
|
|
|
@ -55,6 +55,8 @@ namespace MWGui
|
|||
, mWorldMouseOver(false)
|
||||
, mEnemyHealthTimer(0)
|
||||
, mIsDrowning(false)
|
||||
, mWeaponSpellTimer(0.f)
|
||||
, mDrowningFlashTheta(0.f)
|
||||
{
|
||||
setCoord(0,0, width, height);
|
||||
|
||||
|
|
|
@ -163,6 +163,14 @@ namespace MWGui
|
|||
MWWorld::Ptr object = item.mBase;
|
||||
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)
|
||||
{
|
||||
MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr);
|
||||
|
|
|
@ -103,27 +103,80 @@ namespace MWGui
|
|||
|
||||
void LocalMapBase::onMarkerFocused (MyGUI::Widget* w1, MyGUI::Widget* w2)
|
||||
{
|
||||
// Workaround to not make the marker visible if it's under fog of war
|
||||
applyFogOfWar ();
|
||||
}
|
||||
|
||||
void LocalMapBase::onMarkerUnfocused (MyGUI::Widget* w1, MyGUI::Widget* w2)
|
||||
{
|
||||
// Workaround to not make the marker visible if it's under fog of war
|
||||
applyFogOfWar ();
|
||||
}
|
||||
|
||||
MyGUI::IntPoint LocalMapBase::getMarkerPosition(float worldX, float worldY, MarkerPosition& markerPos)
|
||||
{
|
||||
MyGUI::IntPoint widgetPos;
|
||||
// normalized cell coordinates
|
||||
float nX,nY;
|
||||
|
||||
markerPos.interior = mInterior;
|
||||
|
||||
if (!mInterior)
|
||||
{
|
||||
int cellX, cellY;
|
||||
MWBase::Environment::get().getWorld()->positionToIndex(worldX, worldY, cellX, cellY);
|
||||
const int cellSize = 8192;
|
||||
nX = (worldX - cellSize * cellX) / cellSize;
|
||||
// Image space is -Y up, cells are Y up
|
||||
nY = 1 - (worldY - cellSize * cellY) / cellSize;
|
||||
|
||||
float cellDx = cellX - mCurX;
|
||||
float cellDy = cellY - mCurY;
|
||||
|
||||
markerPos.cellX = cellX;
|
||||
markerPos.cellY = cellY;
|
||||
|
||||
widgetPos = MyGUI::IntPoint(nX * 512 + (1+cellDx) * 512,
|
||||
nY * 512 - (cellDy-1) * 512);
|
||||
}
|
||||
else
|
||||
{
|
||||
int cellX, cellY;
|
||||
Ogre::Vector2 worldPos (worldX, worldY);
|
||||
MWBase::Environment::get().getWorld ()->getInteriorMapPosition (worldPos, nX, nY, cellX, cellY);
|
||||
|
||||
markerPos.cellX = cellX;
|
||||
markerPos.cellY = cellY;
|
||||
|
||||
widgetPos = MyGUI::IntPoint(nX * 512 + (1+cellX-mCurX) * 512,
|
||||
nY * 512 + (1+cellY-mCurY) * 512);
|
||||
}
|
||||
|
||||
markerPos.nX = nX;
|
||||
markerPos.nY = nY;
|
||||
return widgetPos;
|
||||
}
|
||||
|
||||
void LocalMapBase::setActiveCell(const int x, const int y, bool interior)
|
||||
{
|
||||
if (x==mCurX && y==mCurY && mInterior==interior && !mChanged) return; // don't do anything if we're still in the same cell
|
||||
if (x==mCurX && y==mCurY && mInterior==interior && !mChanged)
|
||||
return; // don't do anything if we're still in the same cell
|
||||
|
||||
mCurX = x;
|
||||
mCurY = y;
|
||||
mInterior = interior;
|
||||
mChanged = false;
|
||||
|
||||
// clear all previous markers
|
||||
for (unsigned int i=0; i< mLocalMap->getChildCount(); ++i)
|
||||
{
|
||||
if (mLocalMap->getChildAt(i)->getName ().substr (0, 6) == "Marker")
|
||||
if (mLocalMap->getChildAt(i)->getName ().substr (0, 4) == "Door")
|
||||
{
|
||||
MyGUI::Gui::getInstance ().destroyWidget (mLocalMap->getChildAt(i));
|
||||
}
|
||||
}
|
||||
|
||||
// Update the map textures
|
||||
for (int mx=0; mx<3; ++mx)
|
||||
{
|
||||
for (int my=0; my<3; ++my)
|
||||
|
@ -138,78 +191,57 @@ namespace MWGui
|
|||
box->setImageTexture(image);
|
||||
else
|
||||
box->setImageTexture("black.png");
|
||||
}
|
||||
}
|
||||
|
||||
MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||
|
||||
// door markers
|
||||
|
||||
// interior map only consists of one cell, so handle the markers only once
|
||||
if (interior && (mx != 2 || my != 2))
|
||||
continue;
|
||||
|
||||
MWWorld::CellStore* cell;
|
||||
// Retrieve the door markers we want to show
|
||||
std::vector<MWBase::World::DoorMarker> doors;
|
||||
if (interior)
|
||||
cell = MWBase::Environment::get().getWorld ()->getInterior (mPrefix);
|
||||
{
|
||||
MWWorld::CellStore* cell = world->getInterior (mPrefix);
|
||||
world->getDoorMarkers(cell, doors);
|
||||
}
|
||||
else
|
||||
cell = MWBase::Environment::get().getWorld ()->getExterior (x+mx-1, y-(my-1));
|
||||
|
||||
std::vector<MWBase::World::DoorMarker> doors = MWBase::Environment::get().getWorld ()->getDoorMarkers (cell);
|
||||
{
|
||||
for (int dX=-1; dX<2; ++dX)
|
||||
{
|
||||
for (int dY=-1; dY<2; ++dY)
|
||||
{
|
||||
MWWorld::CellStore* cell = world->getExterior (mCurX+dX, mCurY+dY);
|
||||
world->getDoorMarkers(cell, doors);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create a widget for each marker
|
||||
int counter = 0;
|
||||
for (std::vector<MWBase::World::DoorMarker>::iterator it = doors.begin(); it != doors.end(); ++it)
|
||||
{
|
||||
MWBase::World::DoorMarker marker = *it;
|
||||
|
||||
// convert world coordinates to normalized cell coordinates
|
||||
MyGUI::IntCoord widgetCoord;
|
||||
float nX,nY;
|
||||
int cellDx, cellDy;
|
||||
if (!interior)
|
||||
{
|
||||
const int cellSize = 8192;
|
||||
|
||||
nX = (marker.x - cellSize * (x+mx-1)) / cellSize;
|
||||
nY = 1 - (marker.y - cellSize * (y-(my-1))) / cellSize;
|
||||
|
||||
widgetCoord = MyGUI::IntCoord(nX * 512 - 4 + mx * 512, nY * 512 - 4 + my * 512, 8, 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
Ogre::Vector2 position (marker.x, marker.y);
|
||||
MWBase::Environment::get().getWorld ()->getInteriorMapPosition (position, nX, nY, cellDx, cellDy);
|
||||
|
||||
widgetCoord = MyGUI::IntCoord(nX * 512 - 4 + (1+cellDx-x) * 512, nY * 512 - 4 + (1+cellDy-y) * 512, 8, 8);
|
||||
}
|
||||
|
||||
static int counter = 0;
|
||||
MarkerPosition markerPos;
|
||||
MyGUI::IntPoint widgetPos = getMarkerPosition(marker.x, marker.y, markerPos);
|
||||
MyGUI::IntCoord widgetCoord(widgetPos.left - 4,
|
||||
widgetPos.top - 4,
|
||||
8, 8);
|
||||
++counter;
|
||||
MyGUI::Button* markerWidget = mLocalMap->createWidget<MyGUI::Button>("ButtonImage",
|
||||
widgetCoord, MyGUI::Align::Default, "Marker" + boost::lexical_cast<std::string>(counter));
|
||||
widgetCoord, MyGUI::Align::Default, "Door" + boost::lexical_cast<std::string>(counter));
|
||||
markerWidget->setImageResource("DoorMarker");
|
||||
markerWidget->setUserString("ToolTipType", "Layout");
|
||||
markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine");
|
||||
markerWidget->setUserString("Caption_TextOneLine", marker.name);
|
||||
markerWidget->setUserString("IsMarker", "true");
|
||||
markerWidget->eventMouseSetFocus += MyGUI::newDelegate(this, &LocalMapBase::onMarkerFocused);
|
||||
markerWidget->eventMouseLostFocus += MyGUI::newDelegate(this, &LocalMapBase::onMarkerUnfocused);
|
||||
|
||||
MarkerPosition markerPos;
|
||||
markerPos.interior = interior;
|
||||
markerPos.cellX = interior ? cellDx : x + mx - 1;
|
||||
markerPos.cellY = interior ? cellDy : y + ((my - 1)*-1);
|
||||
markerPos.nX = nX;
|
||||
markerPos.nY = nY;
|
||||
|
||||
// Used by tooltips to not show the tooltip if marker is hidden by fog of war
|
||||
markerWidget->setUserString("IsMarker", "true");
|
||||
markerWidget->setUserData(markerPos);
|
||||
}
|
||||
|
||||
updateMarkers();
|
||||
|
||||
}
|
||||
}
|
||||
mInterior = interior;
|
||||
mCurX = x;
|
||||
mCurY = y;
|
||||
mChanged = false;
|
||||
|
||||
// fog of war
|
||||
applyFogOfWar();
|
||||
|
||||
// set the compass texture again, because MyGUI determines sorting of ImageBox widgets
|
||||
|
@ -222,6 +254,8 @@ namespace MWGui
|
|||
|
||||
void LocalMapBase::setPlayerPos(const float x, const float y)
|
||||
{
|
||||
updateMarkers();
|
||||
|
||||
if (x == mLastPositionX && y == mLastPositionY)
|
||||
return;
|
||||
|
||||
|
@ -255,6 +289,88 @@ namespace MWGui
|
|||
mLastDirectionY = y;
|
||||
}
|
||||
|
||||
void LocalMapBase::addDetectionMarkers(int type)
|
||||
{
|
||||
std::vector<MWWorld::Ptr> markers;
|
||||
MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||
world->listDetectedReferences(
|
||||
world->getPlayer().getPlayer(),
|
||||
markers, MWBase::World::DetectionType(type));
|
||||
if (markers.empty())
|
||||
return;
|
||||
|
||||
std::string markerTexture;
|
||||
MyGUI::Colour markerColour;
|
||||
if (type == MWBase::World::Detect_Creature)
|
||||
{
|
||||
markerTexture = "textures\\menu_map_dcreature.dds";
|
||||
markerColour = MyGUI::Colour(1,0,0,1);
|
||||
}
|
||||
if (type == MWBase::World::Detect_Key)
|
||||
{
|
||||
markerTexture = "textures\\menu_map_dkey.dds";
|
||||
markerColour = MyGUI::Colour(0,1,0,1);
|
||||
}
|
||||
if (type == MWBase::World::Detect_Enchantment)
|
||||
{
|
||||
markerTexture = "textures\\menu_map_dmagic.dds";
|
||||
markerColour = MyGUI::Colour(0,0,1,1);
|
||||
}
|
||||
|
||||
int counter = 0;
|
||||
for (std::vector<MWWorld::Ptr>::iterator it = markers.begin(); it != markers.end(); ++it)
|
||||
{
|
||||
const ESM::Position& worldPos = it->getRefData().getPosition();
|
||||
MarkerPosition markerPos;
|
||||
MyGUI::IntPoint widgetPos = getMarkerPosition(worldPos.pos[0], worldPos.pos[1], markerPos);
|
||||
MyGUI::IntCoord widgetCoord(widgetPos.left - 4,
|
||||
widgetPos.top - 4,
|
||||
8, 8);
|
||||
++counter;
|
||||
MyGUI::ImageBox* markerWidget = mLocalMap->createWidget<MyGUI::ImageBox>("ImageBox",
|
||||
widgetCoord, MyGUI::Align::Default, "Marker" + boost::lexical_cast<std::string>(counter));
|
||||
markerWidget->setImageTexture(markerTexture);
|
||||
markerWidget->setUserString("IsMarker", "true");
|
||||
markerWidget->setUserData(markerPos);
|
||||
markerWidget->setColour(markerColour);
|
||||
}
|
||||
}
|
||||
|
||||
void LocalMapBase::updateMarkers()
|
||||
{
|
||||
// clear all previous markers
|
||||
for (unsigned int i=0; i< mLocalMap->getChildCount(); ++i)
|
||||
{
|
||||
if (mLocalMap->getChildAt(i)->getName ().substr (0, 6) == "Marker")
|
||||
{
|
||||
MyGUI::Gui::getInstance ().destroyWidget (mLocalMap->getChildAt(i));
|
||||
}
|
||||
}
|
||||
|
||||
addDetectionMarkers(MWBase::World::Detect_Creature);
|
||||
addDetectionMarkers(MWBase::World::Detect_Key);
|
||||
addDetectionMarkers(MWBase::World::Detect_Enchantment);
|
||||
|
||||
// Add marker for the spot marked with Mark magic effect
|
||||
MWWorld::CellStore* markedCell = NULL;
|
||||
ESM::Position markedPosition;
|
||||
MWBase::Environment::get().getWorld()->getPlayer().getMarkedPosition(markedCell, markedPosition);
|
||||
if (markedCell && markedCell->isExterior() == !mInterior
|
||||
&& (!mInterior || Misc::StringUtils::ciEqual(markedCell->mCell->mName, mPrefix)))
|
||||
{
|
||||
MarkerPosition markerPos;
|
||||
MyGUI::IntPoint widgetPos = getMarkerPosition(markedPosition.pos[0], markedPosition.pos[1], markerPos);
|
||||
MyGUI::IntCoord widgetCoord(widgetPos.left - 4,
|
||||
widgetPos.top - 4,
|
||||
8, 8);
|
||||
MyGUI::ImageBox* markerWidget = mLocalMap->createWidget<MyGUI::ImageBox>("ImageBox",
|
||||
widgetCoord, MyGUI::Align::Default, "MarkerMarked");
|
||||
markerWidget->setImageTexture("textures\\menu_map_smark.dds");
|
||||
markerWidget->setUserString("IsMarker", "true");
|
||||
markerWidget->setUserData(markerPos);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
|
||||
MapWindow::MapWindow(const std::string& cacheDir)
|
||||
|
@ -319,7 +435,7 @@ namespace MWGui
|
|||
|
||||
static int _counter=0;
|
||||
MyGUI::Button* markerWidget = mGlobalMapImage->createWidget<MyGUI::Button>("ButtonImage",
|
||||
widgetCoord, MyGUI::Align::Default, "Marker" + boost::lexical_cast<std::string>(_counter));
|
||||
widgetCoord, MyGUI::Align::Default, "Door" + boost::lexical_cast<std::string>(_counter));
|
||||
markerWidget->setImageResource("DoorMarker");
|
||||
markerWidget->setUserString("ToolTipType", "Layout");
|
||||
markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine");
|
||||
|
@ -385,7 +501,7 @@ namespace MWGui
|
|||
|
||||
for (unsigned int i=0; i<mGlobalMapImage->getChildCount (); ++i)
|
||||
{
|
||||
if (mGlobalMapImage->getChildAt (i)->getName().substr(0,6) == "Marker")
|
||||
if (mGlobalMapImage->getChildAt (i)->getName().substr(0,4) == "Door")
|
||||
mGlobalMapImage->getChildAt (i)->castType<MyGUI::Button>()->setImageResource("DoorMarker");
|
||||
}
|
||||
|
||||
|
|
|
@ -55,9 +55,16 @@ namespace MWGui
|
|||
void onMarkerFocused(MyGUI::Widget* w1, MyGUI::Widget* w2);
|
||||
void onMarkerUnfocused(MyGUI::Widget* w1, MyGUI::Widget* w2);
|
||||
|
||||
MyGUI::IntPoint getMarkerPosition (float worldX, float worldY, MarkerPosition& markerPos);
|
||||
|
||||
virtual void notifyPlayerUpdate() {}
|
||||
virtual void notifyMapChanged() {}
|
||||
|
||||
// Update markers (Detect X effects, Mark/Recall effects)
|
||||
// Note, door markers handled in setActiveCell
|
||||
void updateMarkers();
|
||||
void addDetectionMarkers(int type);
|
||||
|
||||
OEngine::GUI::Layout* mLayout;
|
||||
|
||||
bool mMapDragAndDrop;
|
||||
|
|
|
@ -16,6 +16,15 @@ namespace MWGui
|
|||
mLastButtonPressed = -1;
|
||||
}
|
||||
|
||||
MessageBoxManager::~MessageBoxManager ()
|
||||
{
|
||||
std::vector<MessageBox*>::iterator it(mMessageBoxes.begin());
|
||||
for (; it != mMessageBoxes.end(); ++it)
|
||||
{
|
||||
delete *it;
|
||||
}
|
||||
}
|
||||
|
||||
void MessageBoxManager::onFrame (float frameDuration)
|
||||
{
|
||||
std::vector<MessageBox*>::iterator it;
|
||||
|
|
|
@ -23,6 +23,7 @@ namespace MWGui
|
|||
{
|
||||
public:
|
||||
MessageBoxManager ();
|
||||
~MessageBoxManager ();
|
||||
void onFrame (float frameDuration);
|
||||
void createMessageBox (const std::string& message, bool stat = false);
|
||||
void removeStaticMessageBox ();
|
||||
|
|
|
@ -40,6 +40,14 @@ namespace MWGui
|
|||
for (size_t i = 0; i<mSourceModel->getItemCount(); ++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()
|
||||
&& item.mType != ItemStack::Type_Equipped)
|
||||
mItems.push_back(item);
|
||||
|
|
|
@ -154,6 +154,13 @@ namespace MWGui
|
|||
if(!MWWorld::Class::get(base).canSell(base, services))
|
||||
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
|
||||
if(mMerchant.getTypeName() == typeid(ESM::NPC).name())
|
||||
{
|
||||
|
|
|
@ -323,6 +323,7 @@ namespace MWGui
|
|||
delete mSoulgemDialog;
|
||||
delete mCursorManager;
|
||||
delete mRecharge;
|
||||
delete mCompanionWindow;
|
||||
|
||||
cleanupGarbage();
|
||||
|
||||
|
|
|
@ -831,9 +831,11 @@ namespace MWInput
|
|||
|
||||
void InputManager::updateIdleTime(float dt)
|
||||
{
|
||||
static const float vanityDelay = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
|
||||
.find("fVanityDelay")->getFloat();
|
||||
if (mTimeIdle >= 0.f)
|
||||
mTimeIdle += dt;
|
||||
if (mTimeIdle > 30.f) {
|
||||
if (mTimeIdle > vanityDelay) {
|
||||
MWBase::Environment::get().getWorld()->toggleVanityMode(true);
|
||||
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
|
||||
|
@ -241,6 +279,33 @@ namespace MWMechanics
|
|||
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
|
||||
int damageEffects[] = {
|
||||
ESM::MagicEffect::FireDamage, ESM::MagicEffect::ShockDamage, ESM::MagicEffect::FrostDamage, ESM::MagicEffect::Poison,
|
||||
|
@ -537,6 +602,16 @@ namespace MWMechanics
|
|||
|
||||
Actors::Actors() {}
|
||||
|
||||
Actors::~Actors()
|
||||
{
|
||||
PtrControllerMap::iterator it(mActors.begin());
|
||||
for (; it != mActors.end(); ++it)
|
||||
{
|
||||
delete it->second;
|
||||
it->second = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void Actors::addActor (const MWWorld::Ptr& ptr)
|
||||
{
|
||||
// erase previous death events since we are currently only tracking them while in an active cell
|
||||
|
@ -630,6 +705,11 @@ namespace MWMechanics
|
|||
|
||||
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)];
|
||||
|
||||
if(cls.isEssential(iter->first))
|
||||
|
|
|
@ -48,6 +48,7 @@ namespace MWMechanics
|
|||
public:
|
||||
|
||||
Actors();
|
||||
~Actors();
|
||||
|
||||
/// Update magic effects for an actor. Usually done automatically once per frame, but if we're currently
|
||||
/// paused we may want to do it manually (after equipping permanent enchantment)
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
#include "../mwworld/class.hpp"
|
||||
#include "../mwworld/player.hpp"
|
||||
|
||||
#include "spellcasting.hpp"
|
||||
|
||||
namespace MWMechanics
|
||||
{
|
||||
void MechanicsManager::buildPlayer()
|
||||
|
@ -123,6 +125,19 @@ namespace MWMechanics
|
|||
npcStats.getSkill (index).setBase (
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,16 @@ Objects::Objects()
|
|||
{
|
||||
}
|
||||
|
||||
Objects::~Objects()
|
||||
{
|
||||
PtrControllerMap::iterator it(mObjects.begin());
|
||||
for (; it != mObjects.end();++it)
|
||||
{
|
||||
delete it->second;
|
||||
it->second = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void Objects::addObject(const MWWorld::Ptr& ptr)
|
||||
{
|
||||
removeObject(ptr);
|
||||
|
|
|
@ -21,6 +21,7 @@ namespace MWMechanics
|
|||
|
||||
public:
|
||||
Objects();
|
||||
~Objects();
|
||||
|
||||
void addObject (const MWWorld::Ptr& ptr);
|
||||
///< Register an animated object
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include "../mwworld/containerstore.hpp"
|
||||
#include "../mwworld/player.hpp"
|
||||
#include "../mwworld/actionteleport.hpp"
|
||||
|
||||
#include "../mwrender/animation.hpp"
|
||||
|
||||
|
@ -250,26 +251,30 @@ namespace MWMechanics
|
|||
|
||||
if (effectId == ESM::MagicEffect::DivineIntervention)
|
||||
{
|
||||
MWBase::Environment::get().getWorld()->getPlayer().setTeleported(true);
|
||||
|
||||
MWBase::Environment::get().getWorld()->teleportToClosestMarker(target, "divinemarker", worldPos);
|
||||
}
|
||||
else if (effectId == ESM::MagicEffect::AlmsiviIntervention)
|
||||
{
|
||||
MWBase::Environment::get().getWorld()->getPlayer().setTeleported(true);
|
||||
|
||||
MWBase::Environment::get().getWorld()->teleportToClosestMarker(target, "templemarker", worldPos);
|
||||
}
|
||||
|
||||
else if (effectId == ESM::MagicEffect::Mark)
|
||||
{
|
||||
// TODO
|
||||
MWBase::Environment::get().getWorld()->getPlayer().markPosition(
|
||||
target.getCell(), target.getRefData().getPosition());
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,25 +19,27 @@ namespace MWRender
|
|||
Camera::Camera (Ogre::Camera *camera)
|
||||
: mCamera(camera),
|
||||
mCameraNode(NULL),
|
||||
mAnimation(NULL),
|
||||
mFirstPersonView(true),
|
||||
mPreviewMode(false),
|
||||
mFreeLook(true),
|
||||
mHeight(128.f),
|
||||
mCameraDistance(300.f),
|
||||
mDistanceAdjusted(false),
|
||||
mAnimation(NULL),
|
||||
mNearest(30.f),
|
||||
mFurthest(800.f),
|
||||
mIsNearest(false),
|
||||
mIsFurthest(false),
|
||||
mHeight(128.f),
|
||||
mCameraDistance(300.f),
|
||||
mDistanceAdjusted(false),
|
||||
mVanityToggleQueued(false),
|
||||
mViewModeToggleQueued(false)
|
||||
{
|
||||
mVanity.enabled = false;
|
||||
mVanity.allowed = true;
|
||||
|
||||
mPreviewCam.pitch = 0.f;
|
||||
mPreviewCam.yaw = 0.f;
|
||||
mPreviewCam.offset = 400.f;
|
||||
mMainCam.pitch = 0.f;
|
||||
mMainCam.yaw = 0.f;
|
||||
mMainCam.offset = 400.f;
|
||||
}
|
||||
|
@ -278,6 +280,11 @@ namespace MWRender
|
|||
}
|
||||
}
|
||||
|
||||
float Camera::getCameraDistance() const
|
||||
{
|
||||
return mCamera->getPosition().z;
|
||||
}
|
||||
|
||||
void Camera::setCameraDistance(float dist, bool adjust, bool override)
|
||||
{
|
||||
if(mFirstPersonView && !mPreviewMode && !mVanity.enabled)
|
||||
|
|
|
@ -105,6 +105,8 @@ namespace MWRender
|
|||
/// Restore default camera distance for current mode.
|
||||
void setCameraDistance();
|
||||
|
||||
float getCameraDistance() const;
|
||||
|
||||
void setAnimation(NpcAnimation *anim);
|
||||
|
||||
/// 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
|
||||
tex = TextureManager::getSingleton().getByName(texture);
|
||||
if (tex.isNull())
|
||||
{
|
||||
// try loading from disk
|
||||
//if (boost::filesystem::exists(texture+".jpg"))
|
||||
//{
|
||||
/// \todo
|
||||
//}
|
||||
//else
|
||||
{
|
||||
// render
|
||||
tex = TextureManager::getSingleton().createManual(
|
||||
|
@ -278,11 +271,8 @@ void LocalMap::render(const float x, const float y,
|
|||
tex2->getBuffer()->unlock();
|
||||
|
||||
mBuffers[texture] = buffer;
|
||||
}
|
||||
|
||||
// save to cache for next time
|
||||
//rtt->writeContentsToFile("./" + texture + ".jpg");
|
||||
}
|
||||
}
|
||||
mRenderingManager->enableLights(true);
|
||||
mLight->setVisible(false);
|
||||
|
||||
|
@ -339,8 +329,6 @@ void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Quaterni
|
|||
|
||||
Vector3 playerdirection = mCameraRotNode->convertWorldToLocalOrientation(orientation).yAxis();
|
||||
|
||||
Vector2 min(mBounds.getMinimum().x, mBounds.getMinimum().y);
|
||||
|
||||
if (!mInterior)
|
||||
{
|
||||
x = std::ceil(pos.x / sSize)-1;
|
||||
|
|
|
@ -1026,4 +1026,9 @@ void RenderingManager::enableTerrain(bool enable)
|
|||
mTerrain->setVisible(false);
|
||||
}
|
||||
|
||||
float RenderingManager::getCameraDistance() const
|
||||
{
|
||||
return mCamera->getCameraDistance();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -90,6 +90,7 @@ public:
|
|||
|
||||
bool vanityRotateCamera(const float *rot);
|
||||
void setCameraDistance(float dist, bool adjust = false, bool override = true);
|
||||
float getCameraDistance() const;
|
||||
|
||||
void setupPlayer(const MWWorld::Ptr &ptr);
|
||||
void renderPlayer(const MWWorld::Ptr &ptr);
|
||||
|
|
|
@ -949,9 +949,25 @@ void VideoState::init(const std::string& resourceName)
|
|||
this->format_ctx->pb = ioCtx;
|
||||
|
||||
// Open video file
|
||||
/// \todo leak here, ffmpeg or valgrind bug ?
|
||||
///
|
||||
/// format_ctx->pb->buffer must be freed by hand,
|
||||
/// if not, valgrind will show memleak, see:
|
||||
///
|
||||
/// https://trac.ffmpeg.org/ticket/1357
|
||||
///
|
||||
if(!this->format_ctx || avformat_open_input(&this->format_ctx, resourceName.c_str(), NULL, NULL))
|
||||
{
|
||||
if (this->format_ctx != NULL)
|
||||
{
|
||||
if (this->format_ctx->pb != NULL)
|
||||
{
|
||||
av_free(this->format_ctx->pb->buffer);
|
||||
this->format_ctx->pb->buffer = NULL;
|
||||
|
||||
av_free(this->format_ctx->pb);
|
||||
this->format_ctx->pb = NULL;
|
||||
}
|
||||
}
|
||||
// "Note that a user-supplied AVFormatContext will be freed on failure."
|
||||
this->format_ctx = NULL;
|
||||
av_free(ioCtx);
|
||||
|
@ -1009,9 +1025,21 @@ void VideoState::deinit()
|
|||
|
||||
if(this->format_ctx)
|
||||
{
|
||||
AVIOContext *ioContext = this->format_ctx->pb;
|
||||
///
|
||||
/// format_ctx->pb->buffer must be freed by hand,
|
||||
/// if not, valgrind will show memleak, see:
|
||||
///
|
||||
/// https://trac.ffmpeg.org/ticket/1357
|
||||
///
|
||||
if (this->format_ctx->pb != NULL)
|
||||
{
|
||||
av_free(this->format_ctx->pb->buffer);
|
||||
this->format_ctx->pb->buffer = NULL;
|
||||
|
||||
av_free(this->format_ctx->pb);
|
||||
this->format_ctx->pb = NULL;;
|
||||
}
|
||||
avformat_close_input(&this->format_ctx);
|
||||
av_free(ioContext);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -292,6 +292,7 @@ Water::~Water()
|
|||
|
||||
delete mReflection;
|
||||
delete mRefraction;
|
||||
delete mSimulation;
|
||||
}
|
||||
|
||||
void Water::changeCell(const ESM::Cell* cell)
|
||||
|
|
|
@ -127,7 +127,6 @@ op 0x200007e-0x2000084: Enable Controls
|
|||
op 0x2000085-0x200008b: Disable Controls
|
||||
op 0x200008c: Unlock
|
||||
op 0x200008d: Unlock, explicit reference
|
||||
op 0x200008e: COE
|
||||
op 0x200008e-0x20000a8: GetSkill
|
||||
op 0x20000a9-0x20000c3: GetSkill, explicit reference
|
||||
op 0x20000c4-0x20000de: SetSkill
|
||||
|
@ -358,5 +357,6 @@ op 0x2000222: GetLineOfSight
|
|||
op 0x2000223: GetLineOfSightExplicit
|
||||
op 0x2000224: ToggleAI
|
||||
op 0x2000225: ToggleAIExplicit
|
||||
op 0x2000226: COE
|
||||
|
||||
opcodes 0x2000226-0x3ffffff unused
|
||||
opcodes 0x2000227-0x3ffffff unused
|
||||
|
|
|
@ -207,6 +207,10 @@ namespace MWScript
|
|||
virtual void execute (Interpreter::Runtime& runtime)
|
||||
{
|
||||
MWWorld::Ptr ptr = R()(runtime);
|
||||
|
||||
if (!ptr.isInCell())
|
||||
return;
|
||||
|
||||
if (ptr.getRefData().getHandle() == "player")
|
||||
{
|
||||
MWBase::Environment::get().getWorld()->getPlayer().setTeleported(true);
|
||||
|
@ -275,6 +279,10 @@ namespace MWScript
|
|||
virtual void execute (Interpreter::Runtime& runtime)
|
||||
{
|
||||
MWWorld::Ptr ptr = R()(runtime);
|
||||
|
||||
if (!ptr.isInCell())
|
||||
return;
|
||||
|
||||
if (ptr.getRefData().getHandle() == "player")
|
||||
{
|
||||
MWBase::Environment::get().getWorld()->getPlayer().setTeleported(true);
|
||||
|
@ -336,6 +344,10 @@ namespace MWScript
|
|||
virtual void execute (Interpreter::Runtime& runtime)
|
||||
{
|
||||
MWWorld::Ptr ptr = R()(runtime);
|
||||
|
||||
if (!ptr.isInCell())
|
||||
return;
|
||||
|
||||
if (ptr.getRefData().getHandle() == "player")
|
||||
{
|
||||
MWBase::Environment::get().getWorld()->getPlayer().setTeleported(true);
|
||||
|
@ -605,6 +617,10 @@ namespace MWScript
|
|||
virtual void execute (Interpreter::Runtime& runtime)
|
||||
{
|
||||
MWWorld::Ptr ptr = R()(runtime);
|
||||
|
||||
if (!ptr.isInCell())
|
||||
return;
|
||||
|
||||
ptr.getRefData().getLocalRotation().rot[0] = 0;
|
||||
ptr.getRefData().getLocalRotation().rot[1] = 0;
|
||||
ptr.getRefData().getLocalRotation().rot[2] = 0;
|
||||
|
@ -624,6 +640,9 @@ namespace MWScript
|
|||
{
|
||||
const MWWorld::Ptr& ptr = R()(runtime);
|
||||
|
||||
if (!ptr.isInCell())
|
||||
return;
|
||||
|
||||
std::string axis = runtime.getStringLiteral (runtime[0].mInteger);
|
||||
runtime.pop();
|
||||
Interpreter::Type_Float movement = (runtime[0].mFloat*MWBase::Environment::get().getFrameDuration());
|
||||
|
@ -659,6 +678,9 @@ namespace MWScript
|
|||
{
|
||||
MWWorld::Ptr ptr = R()(runtime);
|
||||
|
||||
if (!ptr.isInCell())
|
||||
return;
|
||||
|
||||
std::string axis = runtime.getStringLiteral (runtime[0].mInteger);
|
||||
runtime.pop();
|
||||
Interpreter::Type_Float movement = (runtime[0].mFloat*MWBase::Environment::get().getFrameDuration());
|
||||
|
|
|
@ -158,6 +158,16 @@ void FFmpeg_Decoder::open(const std::string &fname)
|
|||
mFormatCtx->pb = avio_alloc_context(NULL, 0, 0, this, readPacket, writePacket, seek);
|
||||
if(!mFormatCtx->pb || avformat_open_input(&mFormatCtx, fname.c_str(), NULL, NULL) != 0)
|
||||
{
|
||||
if (mFormatCtx->pb != NULL)
|
||||
{
|
||||
if (mFormatCtx->pb->buffer != NULL)
|
||||
{
|
||||
av_free(mFormatCtx->pb->buffer);
|
||||
mFormatCtx->pb->buffer = NULL;
|
||||
}
|
||||
av_free(mFormatCtx->pb);
|
||||
mFormatCtx->pb = NULL;
|
||||
}
|
||||
avformat_free_context(mFormatCtx);
|
||||
mFormatCtx = NULL;
|
||||
fail("Failed to allocate input stream");
|
||||
|
@ -195,6 +205,14 @@ void FFmpeg_Decoder::open(const std::string &fname)
|
|||
}
|
||||
catch(std::exception &e)
|
||||
{
|
||||
if (mFormatCtx->pb->buffer != NULL)
|
||||
{
|
||||
av_free(mFormatCtx->pb->buffer);
|
||||
mFormatCtx->pb->buffer = NULL;
|
||||
}
|
||||
av_free(mFormatCtx->pb);
|
||||
mFormatCtx->pb = NULL;
|
||||
|
||||
avformat_close_input(&mFormatCtx);
|
||||
throw;
|
||||
}
|
||||
|
@ -211,9 +229,22 @@ void FFmpeg_Decoder::close()
|
|||
|
||||
if(mFormatCtx)
|
||||
{
|
||||
AVIOContext* context = mFormatCtx->pb;
|
||||
if (mFormatCtx->pb != NULL)
|
||||
{
|
||||
// mFormatCtx->pb->buffer must be freed by hand,
|
||||
// if not, valgrind will show memleak, see:
|
||||
//
|
||||
// https://trac.ffmpeg.org/ticket/1357
|
||||
//
|
||||
if (mFormatCtx->pb->buffer != NULL)
|
||||
{
|
||||
av_free(mFormatCtx->pb->buffer);
|
||||
mFormatCtx->pb->buffer = NULL;
|
||||
}
|
||||
av_free(mFormatCtx->pb);
|
||||
mFormatCtx->pb = NULL;
|
||||
}
|
||||
avformat_close_input(&mFormatCtx);
|
||||
av_free(context);
|
||||
}
|
||||
|
||||
mDataStream.setNull();
|
||||
|
|
|
@ -252,7 +252,7 @@ namespace MWSound
|
|||
float basevol = volumeFromType(Play_TypeVoice);
|
||||
std::string filePath = "Sound/"+filename;
|
||||
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,
|
||||
20.0f, 12750.0f, Play_Normal|Play_TypeVoice, 0);
|
||||
|
@ -354,7 +354,7 @@ namespace MWSound
|
|||
float min, max;
|
||||
std::string file = lookup(soundId, volume, min, max);
|
||||
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);
|
||||
if((mode&Play_NoTrack))
|
||||
|
@ -584,7 +584,7 @@ namespace MWSound
|
|||
if(!ptr.isEmpty())
|
||||
{
|
||||
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);
|
||||
}
|
||||
//update fade out
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "refdata.hpp"
|
||||
#include "ptr.hpp"
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
|
@ -18,13 +18,13 @@ namespace MWWorld
|
|||
{
|
||||
std::vector<Ogre::SceneNode*> mHandles;
|
||||
|
||||
bool operator() (ESM::CellRef& ref, RefData& data)
|
||||
bool operator() (MWWorld::Ptr ptr)
|
||||
{
|
||||
Ogre::SceneNode* handle = data.getBaseNode();
|
||||
Ogre::SceneNode* handle = ptr.getRefData().getBaseNode();
|
||||
if (handle)
|
||||
mHandles.push_back (handle);
|
||||
|
||||
data.setBaseNode(0);
|
||||
ptr.getRefData().setBaseNode(0);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -143,7 +143,7 @@ namespace MWWorld
|
|||
{
|
||||
if (!iter->mData.getCount())
|
||||
continue;
|
||||
if (!functor (iter->mRef, iter->mData))
|
||||
if (!functor (MWWorld::Ptr(&*iter, this)))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -290,6 +290,8 @@ namespace MWWorld
|
|||
|
||||
virtual bool isPersistent (const MWWorld::Ptr& ptr) const;
|
||||
|
||||
virtual bool isKey (const MWWorld::Ptr& ptr) const { return false; }
|
||||
|
||||
virtual Ptr
|
||||
copyToCell(const Ptr &ptr, CellStore &cell) const;
|
||||
|
||||
|
|
|
@ -577,10 +577,28 @@ namespace MWWorld
|
|||
|
||||
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,
|
||||
world->isFlying(iter->first),
|
||||
waterlevel, mEngine);
|
||||
|
||||
if (waterCollision)
|
||||
mEngine->dynamicsWorld->removeCollisionObject(&object);
|
||||
|
||||
float heightDiff = newpos.z - oldHeight;
|
||||
|
||||
if (heightDiff < 0)
|
||||
|
|
|
@ -21,7 +21,8 @@ namespace MWWorld
|
|||
mLastKnownExteriorPosition(0,0,0),
|
||||
mAutoMove(false),
|
||||
mForwardBackward (0),
|
||||
mTeleported(false)
|
||||
mTeleported(false),
|
||||
mMarkedCell(NULL)
|
||||
{
|
||||
mPlayer.mBase = player;
|
||||
mPlayer.mRef.mRefID = "player";
|
||||
|
@ -157,4 +158,17 @@ namespace MWWorld
|
|||
{
|
||||
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;
|
||||
|
||||
ESM::Position mMarkedPosition;
|
||||
// If no position was marked, this is NULL
|
||||
CellStore* mMarkedCell;
|
||||
|
||||
bool mAutoMove;
|
||||
int mForwardBackward;
|
||||
bool mTeleported;
|
||||
|
@ -39,6 +43,10 @@ namespace MWWorld
|
|||
|
||||
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
|
||||
/// world position is still required for divine / almsivi magic effects
|
||||
/// and the player arrow on the global map.
|
||||
|
|
|
@ -324,6 +324,17 @@ void WeatherManager::update(float duration)
|
|||
|
||||
mWeatherUpdateTime -= timePassed;
|
||||
|
||||
MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||
const bool exterior = (world->isCellExterior() || world->isCellQuasiExterior());
|
||||
if (!exterior)
|
||||
{
|
||||
mRendering->sunDisable(false);
|
||||
mRendering->skyDisable();
|
||||
mRendering->getSkyManager()->setLightningStrength(0.f);
|
||||
stopSounds(true);
|
||||
return;
|
||||
}
|
||||
|
||||
switchToNextWeather(false);
|
||||
|
||||
if (mNextWeather != "")
|
||||
|
@ -683,17 +694,8 @@ bool WeatherManager::isDark() const
|
|||
void WeatherManager::switchToNextWeather(bool instantly)
|
||||
{
|
||||
MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||
const bool exterior = (world->isCellExterior() || world->isCellQuasiExterior());
|
||||
if (!exterior)
|
||||
if (world->isCellExterior() || world->isCellQuasiExterior())
|
||||
{
|
||||
mRendering->sunDisable(false);
|
||||
mRendering->skyDisable();
|
||||
mRendering->getSkyManager()->setLightningStrength(0.f);
|
||||
stopSounds(true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Exterior
|
||||
std::string regionstr = Misc::StringUtils::lowerCase(world->getPlayer().getPlayer().getCell()->mCell->mRegion);
|
||||
|
||||
if (mWeatherUpdateTime <= 0 || regionstr != mCurrentRegion)
|
||||
|
@ -720,4 +722,5 @@ void WeatherManager::switchToNextWeather(bool instantly)
|
|||
|
||||
setWeather(weatherType, instantly);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -796,32 +796,9 @@ namespace MWWorld
|
|||
|
||||
MWWorld::Ptr World::getFacedObject()
|
||||
{
|
||||
std::pair<float, std::string> result;
|
||||
|
||||
if (!mRendering->occlusionQuerySupported())
|
||||
result = mPhysics->getFacedHandle (getMaxActivationDistance ());
|
||||
else
|
||||
result = std::make_pair (mFacedDistance, mFacedHandle);
|
||||
|
||||
if (result.second.empty())
|
||||
return MWWorld::Ptr ();
|
||||
|
||||
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;
|
||||
if (mFacedHandle.empty())
|
||||
return MWWorld::Ptr();
|
||||
return searchPtrViaHandle(mFacedHandle);
|
||||
}
|
||||
|
||||
std::pair<MWWorld::Ptr,Ogre::Vector3> World::getHitContact(const MWWorld::Ptr &ptr, float distance)
|
||||
|
@ -934,7 +911,7 @@ namespace MWWorld
|
|||
ptr.getRefData().setCount(0);
|
||||
}
|
||||
}
|
||||
if (haveToMove)
|
||||
if (haveToMove && ptr.getRefData().getBaseNode())
|
||||
{
|
||||
mRendering->moveObject(ptr, vec);
|
||||
mPhysics->moveObject (ptr);
|
||||
|
@ -1063,7 +1040,7 @@ namespace MWWorld
|
|||
|
||||
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())
|
||||
{
|
||||
|
@ -1304,7 +1281,7 @@ namespace MWWorld
|
|||
if (mPlayer->getPlayer().getCell()->isExterior())
|
||||
{
|
||||
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 ()
|
||||
{
|
||||
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
|
||||
// figure out which object we want to test against
|
||||
std::vector < std::pair < float, std::string > > results;
|
||||
|
@ -1353,13 +1338,13 @@ namespace MWWorld
|
|||
{
|
||||
float 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())
|
||||
results = mPhysics->getFacedHandles(x, y, getMaxActivationDistance ()*50);
|
||||
}
|
||||
else
|
||||
{
|
||||
results = mPhysics->getFacedHandles(getMaxActivationDistance ());
|
||||
results = mPhysics->getFacedHandles(activationDistance);
|
||||
}
|
||||
|
||||
// ignore the player and other things we're not interested in
|
||||
|
@ -1442,10 +1427,8 @@ namespace MWWorld
|
|||
return d;
|
||||
}
|
||||
|
||||
std::vector<World::DoorMarker> World::getDoorMarkers (CellStore* cell)
|
||||
void World::getDoorMarkers (CellStore* cell, std::vector<World::DoorMarker>& out)
|
||||
{
|
||||
std::vector<World::DoorMarker> result;
|
||||
|
||||
MWWorld::CellRefList<ESM::Door>& doors = cell->mDoors;
|
||||
CellRefList<ESM::Door>::List& refList = doors.mList;
|
||||
for (CellRefList<ESM::Door>::List::iterator it = refList.begin(); it != refList.end(); ++it)
|
||||
|
@ -1461,11 +1444,9 @@ namespace MWWorld
|
|||
|
||||
newMarker.x = pos.pos[0];
|
||||
newMarker.y = pos.pos[1];
|
||||
result.push_back(newMarker);
|
||||
out.push_back(newMarker);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void World::getInteriorMapPosition (Ogre::Vector2 position, float& nX, float& nY, int &x, int& y)
|
||||
|
@ -1588,7 +1569,7 @@ namespace MWWorld
|
|||
pos.rot[1] = 0;
|
||||
|
||||
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);
|
||||
|
||||
float len = (pos.pos[2] >= 0) ? pos.pos[2] : -pos.pos[2];
|
||||
|
@ -1829,9 +1810,9 @@ namespace MWWorld
|
|||
{
|
||||
std::vector<std::string> mHandles;
|
||||
|
||||
bool operator() (ESM::CellRef& ref, RefData& data)
|
||||
bool operator() (Ptr ptr)
|
||||
{
|
||||
Ogre::SceneNode* handle = data.getBaseNode();
|
||||
Ogre::SceneNode* handle = ptr.getRefData().getBaseNode();
|
||||
if (handle)
|
||||
mHandles.push_back(handle->getName());
|
||||
return true;
|
||||
|
@ -1940,17 +1921,8 @@ namespace MWWorld
|
|||
int y = ext->getGridY();
|
||||
indexToPosition(x, y, pos.pos[0], pos.pos[1], true);
|
||||
|
||||
ESM::Land* land = getStore().get<ESM::Land>().search(x, y);
|
||||
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";
|
||||
// Note: Z pos will be adjusted by adjustPosition later
|
||||
pos.pos[2] = 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -2312,7 +2284,7 @@ namespace MWWorld
|
|||
if (ref.mRef.mTeleport && ref.mRef.mDestCell.empty())
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -2333,7 +2305,7 @@ namespace MWWorld
|
|||
for (std::vector<MWWorld::Ptr>::iterator it = markers.begin(); it != markers.end(); ++it)
|
||||
{
|
||||
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);
|
||||
if (distance < closestDistance)
|
||||
{
|
||||
|
@ -2357,4 +2329,91 @@ namespace MWWorld
|
|||
|
||||
mWeatherManager->update(duration);
|
||||
}
|
||||
|
||||
struct AddDetectedReference
|
||||
{
|
||||
AddDetectedReference(std::vector<Ptr>& out, Ptr detector, World::DetectionType type, float squaredDist)
|
||||
: mOut(out), mDetector(detector), mType(type), mSquaredDist(squaredDist)
|
||||
{
|
||||
}
|
||||
|
||||
std::vector<Ptr>& mOut;
|
||||
Ptr mDetector;
|
||||
float mSquaredDist;
|
||||
World::DetectionType mType;
|
||||
bool operator() (MWWorld::Ptr ptr)
|
||||
{
|
||||
if (Ogre::Vector3(ptr.getRefData().getPosition().pos).squaredDistance(
|
||||
Ogre::Vector3(mDetector.getRefData().getPosition().pos)) >= mSquaredDist)
|
||||
return true;
|
||||
|
||||
if (!ptr.getRefData().isEnabled())
|
||||
return true;
|
||||
|
||||
// Consider references inside containers as well
|
||||
if (ptr.getClass().isActor() || ptr.getClass().getTypeName() == typeid(ESM::Container).name())
|
||||
{
|
||||
MWWorld::ContainerStore& store = ptr.getClass().getContainerStore(ptr);
|
||||
{
|
||||
for (MWWorld::ContainerStoreIterator it = store.begin(); it != store.end(); ++it)
|
||||
{
|
||||
if (needToAdd(*it))
|
||||
{
|
||||
mOut.push_back(ptr);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (needToAdd(ptr))
|
||||
mOut.push_back(ptr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool needToAdd (MWWorld::Ptr ptr)
|
||||
{
|
||||
if (mType == World::Detect_Creature && ptr.getClass().getTypeName() != typeid(ESM::Creature).name())
|
||||
return false;
|
||||
if (mType == World::Detect_Key && !ptr.getClass().isKey(ptr))
|
||||
return false;
|
||||
if (mType == World::Detect_Enchantment && ptr.getClass().getEnchantment(ptr).empty())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
void World::listDetectedReferences(const Ptr &ptr, std::vector<Ptr> &out, DetectionType type)
|
||||
{
|
||||
const MWMechanics::MagicEffects& effects = ptr.getClass().getCreatureStats(ptr).getMagicEffects();
|
||||
float dist=0;
|
||||
if (type == World::Detect_Creature)
|
||||
dist = effects.get(MWMechanics::EffectKey(ESM::MagicEffect::DetectAnimal)).mMagnitude;
|
||||
else if (type == World::Detect_Key)
|
||||
dist = effects.get(MWMechanics::EffectKey(ESM::MagicEffect::DetectKey)).mMagnitude;
|
||||
else if (type == World::Detect_Enchantment)
|
||||
dist = effects.get(MWMechanics::EffectKey(ESM::MagicEffect::DetectEnchantment)).mMagnitude;
|
||||
|
||||
if (!dist)
|
||||
return;
|
||||
|
||||
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
|
||||
void objectLeftActiveCell (MWWorld::Ptr object, MWWorld::Ptr movedPtr);
|
||||
|
||||
float feetToGameUnits(float feet);
|
||||
|
||||
public:
|
||||
|
||||
World (OEngine::Render::OgreRenderer& renderer,
|
||||
|
@ -202,7 +204,7 @@ namespace MWWorld
|
|||
virtual Ogre::Vector2 getNorthVector (CellStore* cell);
|
||||
///< get north vector (OGRE coordinates) for given interior cell
|
||||
|
||||
virtual std::vector<DoorMarker> getDoorMarkers (MWWorld::CellStore* cell);
|
||||
virtual void getDoorMarkers (MWWorld::CellStore* cell, std::vector<DoorMarker>& out);
|
||||
///< get a list of teleport door markers for a given cell, to be displayed on the local map
|
||||
|
||||
virtual void getInteriorMapPosition (Ogre::Vector2 position, float& nX, float& nY, int &x, int& y);
|
||||
|
@ -526,6 +528,12 @@ namespace MWWorld
|
|||
/// @note id must be lower case
|
||||
virtual void teleportToClosestMarker (const MWWorld::Ptr& ptr,
|
||||
const std::string& id, Ogre::Vector3 worldPos);
|
||||
|
||||
/// List all references (filtered by \a type) detected by \a ptr. The range
|
||||
/// is determined by the current magnitude of the "Detect X" magic effect belonging to \a type.
|
||||
/// @note This also works for references in containers.
|
||||
virtual void listDetectedReferences (const MWWorld::Ptr& ptr, std::vector<MWWorld::Ptr>& out,
|
||||
DetectionType type);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace Compiler
|
|||
const int opcodeAiFollowExplicit = 0x20023;
|
||||
const int opcodeAiFollowCell = 0x20024;
|
||||
const int opcodeAiFollowCellExplicit = 0x20025;
|
||||
const int opcodeSetHello = 0x200015e;
|
||||
const int opcodeSetHello = 0x200015c;
|
||||
const int opcodeSetHelloExplicit = 0x200015d;
|
||||
const int opcodeSetFight = 0x200015e;
|
||||
const int opcodeSetFightExplicit = 0x200015f;
|
||||
|
@ -69,7 +69,7 @@ namespace Compiler
|
|||
{
|
||||
const int opcodeCellChanged = 0x2000000;
|
||||
const int opcodeCOC = 0x2000026;
|
||||
const int opcodeCOE = 0x200008e;
|
||||
const int opcodeCOE = 0x2000226;
|
||||
const int opcodeGetInterior = 0x2000131;
|
||||
const int opcodeGetPCCell = 0x2000136;
|
||||
const int opcodeGetWaterLevel = 0x2000141;
|
||||
|
|
|
@ -20,7 +20,7 @@ namespace ESM
|
|||
public:
|
||||
|
||||
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
|
||||
|
||||
|
|
|
@ -166,31 +166,37 @@ namespace Interpreter
|
|||
|
||||
void Interpreter::installSegment0 (int code, Opcode1 *opcode)
|
||||
{
|
||||
assert(mSegment0.find(code) == mSegment0.end());
|
||||
mSegment0.insert (std::make_pair (code, opcode));
|
||||
}
|
||||
|
||||
void Interpreter::installSegment1 (int code, Opcode2 *opcode)
|
||||
{
|
||||
assert(mSegment1.find(code) == mSegment1.end());
|
||||
mSegment1.insert (std::make_pair (code, opcode));
|
||||
}
|
||||
|
||||
void Interpreter::installSegment2 (int code, Opcode1 *opcode)
|
||||
{
|
||||
assert(mSegment2.find(code) == mSegment2.end());
|
||||
mSegment2.insert (std::make_pair (code, opcode));
|
||||
}
|
||||
|
||||
void Interpreter::installSegment3 (int code, Opcode1 *opcode)
|
||||
{
|
||||
assert(mSegment3.find(code) == mSegment3.end());
|
||||
mSegment3.insert (std::make_pair (code, opcode));
|
||||
}
|
||||
|
||||
void Interpreter::installSegment4 (int code, Opcode2 *opcode)
|
||||
{
|
||||
assert(mSegment4.find(code) == mSegment4.end());
|
||||
mSegment4.insert (std::make_pair (code, opcode));
|
||||
}
|
||||
|
||||
void Interpreter::installSegment5 (int code, Opcode0 *opcode)
|
||||
{
|
||||
assert(mSegment5.find(code) == mSegment5.end());
|
||||
mSegment5.insert (std::make_pair (code, opcode));
|
||||
}
|
||||
|
||||
|
|
|
@ -140,17 +140,19 @@ namespace
|
|||
}
|
||||
|
||||
QuadTreeNode::QuadTreeNode(World* terrain, ChildDirection dir, float size, const Ogre::Vector2 ¢er, QuadTreeNode* parent)
|
||||
: mSize(size)
|
||||
, mCenter(center)
|
||||
, mParent(parent)
|
||||
, mDirection(dir)
|
||||
: mMaterialGenerator(NULL)
|
||||
, mIsActive(false)
|
||||
, mIsDummy(false)
|
||||
, mSceneNode(NULL)
|
||||
, mTerrain(terrain)
|
||||
, mChunk(NULL)
|
||||
, mMaterialGenerator(NULL)
|
||||
, mSize(size)
|
||||
, mLodLevel(Log2(mSize))
|
||||
, mBounds(Ogre::AxisAlignedBox::BOX_NULL)
|
||||
, mWorldBounds(Ogre::AxisAlignedBox::BOX_NULL)
|
||||
, mDirection(dir)
|
||||
, mCenter(center)
|
||||
, mSceneNode(NULL)
|
||||
, mParent(parent)
|
||||
, mTerrain(terrain)
|
||||
, mChunk(NULL)
|
||||
{
|
||||
mBounds.setNull();
|
||||
for (int i=0; i<4; ++i)
|
||||
|
@ -168,8 +170,6 @@ QuadTreeNode::QuadTreeNode(World* terrain, ChildDirection dir, float size, const
|
|||
pos = mCenter - pos;
|
||||
mSceneNode->setPosition(Ogre::Vector3(pos.x*8192, pos.y*8192, 0));
|
||||
|
||||
mLodLevel = Log2(mSize);
|
||||
|
||||
mMaterialGenerator = new MaterialGenerator(mTerrain->getShadersEnabled());
|
||||
}
|
||||
|
||||
|
|
|
@ -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 <BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h>
|
||||
#include <components/nifbullet/bulletnifloader.hpp>
|
||||
#include "CMotionState.h"
|
||||
#include "OgreRoot.h"
|
||||
#include "btKinematicCharacterController.h"
|
||||
#include "BtOgrePG.h"
|
||||
|
@ -318,9 +317,7 @@ namespace Physic
|
|||
btVector3 scl(triSize, triSize, 1);
|
||||
hfShape->setLocalScaling(scl);
|
||||
|
||||
CMotionState* newMotionState = new CMotionState(this,name);
|
||||
|
||||
btRigidBody::btRigidBodyConstructionInfo CI = btRigidBody::btRigidBodyConstructionInfo(0,newMotionState,hfShape);
|
||||
btRigidBody::btRigidBodyConstructionInfo CI = btRigidBody::btRigidBodyConstructionInfo(0,0,hfShape);
|
||||
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));
|
||||
|
||||
|
@ -401,12 +398,9 @@ namespace Physic
|
|||
else
|
||||
shape->mRaycastingShape->setLocalScaling( btVector3(scale,scale,scale));
|
||||
|
||||
//create the motionState
|
||||
CMotionState* newMotionState = new CMotionState(this,name);
|
||||
|
||||
//create the real body
|
||||
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);
|
||||
body->mPlaceable = placeable;
|
||||
|
||||
|
|
|
@ -38,7 +38,6 @@ namespace MWWorld
|
|||
namespace OEngine {
|
||||
namespace Physic
|
||||
{
|
||||
class CMotionState;
|
||||
struct PhysicEvent;
|
||||
class PhysicEngine;
|
||||
class RigidBody;
|
||||
|
@ -157,17 +156,7 @@ namespace Physic
|
|||
private:
|
||||
void disableCollisionBody();
|
||||
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* mRaycastingBody;
|
||||
|
||||
|
@ -329,12 +318,6 @@ public:
|
|||
const btVector3 &origin,
|
||||
btCollisionObject *object);
|
||||
|
||||
//event list of non player object
|
||||
std::list<PhysicEvent> NPEventList;
|
||||
|
||||
//event list affecting the player
|
||||
std::list<PhysicEvent> PEventList;
|
||||
|
||||
//Bullet Stuff
|
||||
btOverlappingPairCache* pairCache;
|
||||
btBroadphaseInterface* broadphase;
|
||||
|
|
|
@ -25,6 +25,7 @@ void OgreRenderer::cleanup()
|
|||
delete mFader;
|
||||
mFader = NULL;
|
||||
|
||||
if (mWindow)
|
||||
Ogre::Root::getSingleton().destroyRenderTarget(mWindow);
|
||||
mWindow = NULL;
|
||||
|
||||
|
|
|
@ -74,8 +74,9 @@ namespace OEngine
|
|||
, mScene(NULL)
|
||||
, mCamera(NULL)
|
||||
, mView(NULL)
|
||||
, mWindowListener(NULL)
|
||||
, mOgreInit(NULL)
|
||||
, mFader(NULL)
|
||||
, mWindowListener(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue