Merge remote-tracking branch 'scrawl/master'

Conflicts:
	apps/openmw/mwmechanics/spellcasting.cpp
actorid
Marc Zinnschlag 11 years ago
commit c3482b6f24

3
.gitignore vendored

@ -3,7 +3,6 @@ CMakeFiles
*/CMakeFiles */CMakeFiles
CMakeCache.txt CMakeCache.txt
cmake_install.cmake cmake_install.cmake
CMakeLists.txt.user
Makefile Makefile
makefile makefile
build build
@ -22,6 +21,8 @@ Doxygen
.project .project
.settings .settings
.directory .directory
## qt-creator
CMakeLists.txt.user*
## resources ## resources
data data

@ -430,6 +430,14 @@ namespace MWBase
// Are we in an exterior or pseudo-exterior cell and it's night? // Are we in an exterior or pseudo-exterior cell and it's night?
virtual bool isDark() const = 0; virtual bool isDark() const = 0;
virtual bool findInteriorPositionInWorldSpace(MWWorld::CellStore* cell, Ogre::Vector3& result) = 0;
/// Teleports \a ptr to the reference of \a id (e.g. DivineMarker, PrisonMarker, TempleMarker)
/// closest to \a worldPos.
/// @note id must be lower case
virtual void teleportToClosestMarker (const MWWorld::Ptr& ptr,
const std::string& id, Ogre::Vector3 worldPos) = 0;
}; };
} }

@ -396,20 +396,18 @@ namespace MWGui
void MapWindow::globalMapUpdatePlayer () void MapWindow::globalMapUpdatePlayer ()
{ {
Ogre::Vector3 pos = MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer().getRefData ().getBaseNode ()->_getDerivedPosition (); // For interiors, position is set by WindowManager via setGlobalMapPlayerPosition
Ogre::Quaternion orient = MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer().getRefData ().getBaseNode ()->_getDerivedOrientation ();
Ogre::Vector2 dir (orient.yAxis ().x, orient.yAxis().y);
float worldX, worldY;
mGlobalMapRender->worldPosToImageSpace (pos.x, pos.y, worldX, worldY);
worldX *= mGlobalMapRender->getWidth();
worldY *= mGlobalMapRender->getHeight();
// for interiors, we have no choice other than using the last position & direction.
/// \todo save this last position in the savegame?
if (MWBase::Environment::get().getWorld ()->isCellExterior ()) if (MWBase::Environment::get().getWorld ()->isCellExterior ())
{ {
Ogre::Vector3 pos = MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer().getRefData ().getBaseNode ()->_getDerivedPosition ();
Ogre::Quaternion orient = MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer().getRefData ().getBaseNode ()->_getDerivedOrientation ();
Ogre::Vector2 dir (orient.yAxis ().x, orient.yAxis().y);
float worldX, worldY;
mGlobalMapRender->worldPosToImageSpace (pos.x, pos.y, worldX, worldY);
worldX *= mGlobalMapRender->getWidth();
worldY *= mGlobalMapRender->getHeight();
mPlayerArrowGlobal->setPosition(MyGUI::IntPoint(worldX - 16, worldY - 16)); mPlayerArrowGlobal->setPosition(MyGUI::IntPoint(worldX - 16, worldY - 16));
MyGUI::ISubWidget* main = mPlayerArrowGlobal->getSubWidgetMain(); MyGUI::ISubWidget* main = mPlayerArrowGlobal->getSubWidgetMain();
@ -444,4 +442,19 @@ namespace MWGui
"#{sWorld}"); "#{sWorld}");
} }
void MapWindow::setGlobalMapPlayerPosition(float worldX, float worldY)
{
float x, y;
mGlobalMapRender->worldPosToImageSpace (worldX, worldY, x, y);
x *= mGlobalMapRender->getWidth();
y *= mGlobalMapRender->getHeight();
mPlayerArrowGlobal->setPosition(MyGUI::IntPoint(x - 16, y - 16));
// set the view offset so that player is in the center
MyGUI::IntSize viewsize = mGlobalMap->getSize();
MyGUI::IntPoint viewoffs(0.5*viewsize.width - x, 0.5*viewsize.height - y);
mGlobalMap->setViewOffset(viewoffs);
}
} }

@ -81,6 +81,8 @@ namespace MWGui
void addVisitedLocation(const std::string& name, int x, int y); // adds the marker to the global map void addVisitedLocation(const std::string& name, int x, int y); // adds the marker to the global map
void cellExplored(int x, int y); void cellExplored(int x, int y);
void setGlobalMapPlayerPosition (float worldX, float worldY);
virtual void open(); virtual void open();
private: private:

@ -16,6 +16,7 @@
#include "../mwbase/inputmanager.hpp" #include "../mwbase/inputmanager.hpp"
#include "../mwworld/class.hpp" #include "../mwworld/class.hpp"
#include "../mwworld/player.hpp"
#include "console.hpp" #include "console.hpp"
#include "journalwindow.hpp" #include "journalwindow.hpp"
@ -774,6 +775,13 @@ namespace MWGui
mHud->setCellName( cell->mCell->mName ); mHud->setCellName( cell->mCell->mName );
mMap->setCellPrefix( cell->mCell->mName ); mMap->setCellPrefix( cell->mCell->mName );
mHud->setCellPrefix( cell->mCell->mName ); mHud->setCellPrefix( cell->mCell->mName );
Ogre::Vector3 worldPos;
if (!MWBase::Environment::get().getWorld()->findInteriorPositionInWorldSpace(cell, worldPos))
worldPos = MWBase::Environment::get().getWorld()->getPlayer().getLastKnownExteriorPosition();
else
MWBase::Environment::get().getWorld()->getPlayer().setLastKnownExteriorPosition(worldPos);
mMap->setGlobalMapPlayerPosition(worldPos.x, worldPos.y);
} }
} }

@ -132,7 +132,7 @@ namespace MWMechanics
{ {
float random = std::rand() / static_cast<float>(RAND_MAX); float random = std::rand() / static_cast<float>(RAND_MAX);
float magnitude = effectIt->mMagnMin + (effectIt->mMagnMax - effectIt->mMagnMin) * random; float magnitude = effectIt->mMagnMin + (effectIt->mMagnMax - effectIt->mMagnMin) * random;
magnitude *= magnitudeMult; magnitude *= magnitudeMult;
if (target.getClass().isActor() && !(magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration)) if (target.getClass().isActor() && !(magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration))
{ {
@ -239,18 +239,26 @@ namespace MWMechanics
else if (effectId == ESM::MagicEffect::RemoveCurse) else if (effectId == ESM::MagicEffect::RemoveCurse)
target.getClass().getCreatureStats(target).getSpells().purgeCurses(); target.getClass().getCreatureStats(target).getSpells().purgeCurses();
else if (effectId == ESM::MagicEffect::DivineIntervention) if (target.getRefData().getHandle() != "player")
return;
if (!MWBase::Environment::get().getWorld()->isTeleportingEnabled())
return;
Ogre::Vector3 worldPos;
if (!MWBase::Environment::get().getWorld()->findInteriorPositionInWorldSpace(target.getCell(), worldPos))
worldPos = MWBase::Environment::get().getWorld()->getPlayer().getLastKnownExteriorPosition();
if (effectId == ESM::MagicEffect::DivineIntervention)
{ {
MWBase::Environment::get().getWorld()->getPlayer().setTeleported(true); MWBase::Environment::get().getWorld()->getPlayer().setTeleported(true);
// We need to be able to get the world location of an interior cell before implementing this MWBase::Environment::get().getWorld()->teleportToClosestMarker(target, "divinemarker", worldPos);
// or alternatively, the last known exterior location of the player, which is how vanilla does it.
} }
else if (effectId == ESM::MagicEffect::AlmsiviIntervention) else if (effectId == ESM::MagicEffect::AlmsiviIntervention)
{ {
MWBase::Environment::get().getWorld()->getPlayer().setTeleported(true); MWBase::Environment::get().getWorld()->getPlayer().setTeleported(true);
// Same as above MWBase::Environment::get().getWorld()->teleportToClosestMarker(target, "templemarker", worldPos);
} }
else if (effectId == ESM::MagicEffect::Mark) else if (effectId == ESM::MagicEffect::Mark)

@ -1211,7 +1211,8 @@ void ObjectAnimation::fillBatch(Ogre::StaticGeometry *sg)
for(;iter != mObjectRoot->mEntities.rend();++iter) for(;iter != mObjectRoot->mEntities.rend();++iter)
{ {
Ogre::Node *node = (*iter)->getParentNode(); Ogre::Node *node = (*iter)->getParentNode();
sg->addEntity(*iter, node->_getDerivedPosition(), node->_getDerivedOrientation(), node->_getDerivedScale()); if ((*iter)->isVisible())
sg->addEntity(*iter, node->_getDerivedPosition(), node->_getDerivedOrientation(), node->_getDerivedScale());
} }
} }

@ -355,8 +355,6 @@ namespace MWScript
if (newLevel<0) if (newLevel<0)
newLevel = 0; newLevel = 0;
else if (newLevel>100)
newLevel = 100;
progress = (progress / stats.getSkillGain (mIndex, class_, -1, level)) progress = (progress / stats.getSkillGain (mIndex, class_, -1, level))
* stats.getSkillGain (mIndex, class_, -1, newLevel); * stats.getSkillGain (mIndex, class_, -1, newLevel);

@ -129,9 +129,7 @@ MWWorld::Ptr MWWorld::Cells::getPtr (const std::string& name, Ptr::CellStore& ce
if (cell.mState==Ptr::CellStore::State_Preloaded) if (cell.mState==Ptr::CellStore::State_Preloaded)
{ {
std::string lowerCase = Misc::StringUtils::lowerCase(name); if (std::binary_search (cell.mIds.begin(), cell.mIds.end(), name))
if (std::binary_search (cell.mIds.begin(), cell.mIds.end(), lowerCase))
{ {
cell.load (mStore, mReader); cell.load (mStore, mReader);
} }
@ -261,3 +259,15 @@ MWWorld::Ptr MWWorld::Cells::getPtr (const std::string& name)
// giving up // giving up
return Ptr(); return Ptr();
} }
void MWWorld::Cells::getExteriorPtrs(const std::string &name, std::vector<MWWorld::Ptr> &out)
{
for (std::map<std::pair<int, int>, Ptr::CellStore>::iterator iter = mExteriors.begin();
iter!=mExteriors.end(); ++iter)
{
Ptr ptr = getPtrAndCache (name, iter->second);
if (!ptr.isEmpty())
out.push_back(ptr);
}
}

@ -47,8 +47,15 @@ namespace MWWorld
Ptr getPtr (const std::string& name, CellStore& cellStore, bool searchInContainers = false); Ptr getPtr (const std::string& name, CellStore& cellStore, bool searchInContainers = false);
///< \param searchInContainers Only affect loaded cells. ///< \param searchInContainers Only affect loaded cells.
/// @note name must be lower case
/// @note name must be lower case
Ptr getPtr (const std::string& name); Ptr getPtr (const std::string& name);
/// Get all Ptrs referencing \a name in exterior cells
/// @note Due to the current implementation of getPtr this only supports one Ptr per cell.
/// @note name must be lower case
void getExteriorPtrs (const std::string& name, std::vector<MWWorld::Ptr>& out);
}; };
} }

@ -18,6 +18,7 @@ namespace MWWorld
{ {
Player::Player (const ESM::NPC *player, const MWBase::World& world) Player::Player (const ESM::NPC *player, const MWBase::World& world)
: mCellStore(0), : mCellStore(0),
mLastKnownExteriorPosition(0,0,0),
mAutoMove(false), mAutoMove(false),
mForwardBackward (0), mForwardBackward (0),
mTeleported(false) mTeleported(false)

@ -6,6 +6,8 @@
#include "../mwmechanics/drawstate.hpp" #include "../mwmechanics/drawstate.hpp"
#include <OgreVector3.h>
namespace ESM namespace ESM
{ {
struct NPC; struct NPC;
@ -28,6 +30,8 @@ namespace MWWorld
MWWorld::CellStore *mCellStore; MWWorld::CellStore *mCellStore;
std::string mSign; std::string mSign;
Ogre::Vector3 mLastKnownExteriorPosition;
bool mAutoMove; bool mAutoMove;
int mForwardBackward; int mForwardBackward;
bool mTeleported; bool mTeleported;
@ -35,6 +39,13 @@ namespace MWWorld
Player(const ESM::NPC *player, const MWBase::World& world); Player(const ESM::NPC *player, const MWBase::World& world);
/// 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.
/// TODO: This should be stored in the savegame, too.
void setLastKnownExteriorPosition (const Ogre::Vector3& position) { mLastKnownExteriorPosition = position; }
Ogre::Vector3 getLastKnownExteriorPosition() const { return mLastKnownExteriorPosition; }
void set (const ESM::NPC *player); void set (const ESM::NPC *player);
void setCell (MWWorld::CellStore *cellStore); void setCell (MWWorld::CellStore *cellStore);

@ -39,6 +39,7 @@
#include "cellfunctors.hpp" #include "cellfunctors.hpp"
#include "containerstore.hpp" #include "containerstore.hpp"
#include "inventorystore.hpp" #include "inventorystore.hpp"
#include "actionteleport.hpp"
#include "contentloader.hpp" #include "contentloader.hpp"
#include "esmloader.hpp" #include "esmloader.hpp"
@ -498,12 +499,14 @@ namespace MWWorld
if (!ptr.isEmpty()) if (!ptr.isEmpty())
return ptr; return ptr;
std::string lowerCaseName = Misc::StringUtils::lowerCase(name);
// active cells // active cells
for (Scene::CellStoreCollection::const_iterator iter (mWorldScene->getActiveCells().begin()); for (Scene::CellStoreCollection::const_iterator iter (mWorldScene->getActiveCells().begin());
iter!=mWorldScene->getActiveCells().end(); ++iter) iter!=mWorldScene->getActiveCells().end(); ++iter)
{ {
Ptr::CellStore* cellstore = *iter; Ptr::CellStore* cellstore = *iter;
Ptr ptr = mCells.getPtr (name, *cellstore, true); Ptr ptr = mCells.getPtr (lowerCaseName, *cellstore, true);
if (!ptr.isEmpty()) if (!ptr.isEmpty())
return ptr; return ptr;
@ -511,7 +514,7 @@ namespace MWWorld
if (!activeOnly) if (!activeOnly)
{ {
Ptr ptr = mCells.getPtr (name); Ptr ptr = mCells.getPtr (lowerCaseName);
if (!ptr.isEmpty()) if (!ptr.isEmpty())
return ptr; return ptr;
@ -1297,6 +1300,12 @@ namespace MWWorld
performUpdateSceneQueries (); performUpdateSceneQueries ();
updateWindowManager (); updateWindowManager ();
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]));
}
} }
void World::updateWindowManager () void World::updateWindowManager ()
@ -2288,7 +2297,54 @@ namespace MWWorld
bool World::isDark() const bool World::isDark() const
{ {
return mWeatherManager->isDark(); return mWeatherManager->isDark();
}
bool World::findInteriorPositionInWorldSpace(MWWorld::CellStore* cell, Ogre::Vector3& result)
{
MWWorld::CellRefList<ESM::Door>& doors = cell->mDoors;
CellRefList<ESM::Door>::List& refList = doors.mList;
// Check if any door in the cell leads to an exterior directly
for (CellRefList<ESM::Door>::List::iterator it = refList.begin(); it != refList.end(); ++it)
{
MWWorld::LiveCellRef<ESM::Door>& ref = *it;
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]);
return true;
}
}
// No luck :(
return false;
}
void World::teleportToClosestMarker (const MWWorld::Ptr& ptr,
const std::string& id, Ogre::Vector3 worldPos)
{
MWWorld::Ptr closestMarker;
float closestDistance = FLT_MAX;
std::vector<MWWorld::Ptr> markers;
mCells.getExteriorPtrs(id, markers);
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]);
float distance = worldPos.squaredDistance(markerPos);
if (distance < closestDistance)
{
closestDistance = distance;
closestMarker = *it;
}
}
MWWorld::ActionTeleport action("", closestMarker.getRefData().getPosition());
action.execute(ptr);
} }
void World::updateWeather(float duration) void World::updateWeather(float duration)

@ -518,6 +518,14 @@ namespace MWWorld
virtual void breakInvisibility (const MWWorld::Ptr& actor); virtual void breakInvisibility (const MWWorld::Ptr& actor);
// Are we in an exterior or pseudo-exterior cell and it's night? // Are we in an exterior or pseudo-exterior cell and it's night?
virtual bool isDark() const; virtual bool isDark() const;
virtual bool findInteriorPositionInWorldSpace(MWWorld::CellStore* cell, Ogre::Vector3& result);
/// Teleports \a ptr to the reference of \a id (e.g. DivineMarker, PrisonMarker, TempleMarker)
/// closest to \a worldPos.
/// @note id must be lower case
virtual void teleportToClosestMarker (const MWWorld::Ptr& ptr,
const std::string& id, Ogre::Vector3 worldPos);
}; };
} }

Loading…
Cancel
Save