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
CMakeCache.txt
cmake_install.cmake
CMakeLists.txt.user
Makefile
makefile
build
@ -22,6 +21,8 @@ Doxygen
.project
.settings
.directory
## qt-creator
CMakeLists.txt.user*
## resources
data

@ -430,6 +430,14 @@ namespace MWBase
// Are we in an exterior or pseudo-exterior cell and it's night?
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 ()
{
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();
// for interiors, we have no choice other than using the last position & direction.
/// \todo save this last position in the savegame?
// For interiors, position is set by WindowManager via setGlobalMapPlayerPosition
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));
MyGUI::ISubWidget* main = mPlayerArrowGlobal->getSubWidgetMain();
@ -444,4 +442,19 @@ namespace MWGui
"#{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 cellExplored(int x, int y);
void setGlobalMapPlayerPosition (float worldX, float worldY);
virtual void open();
private:

@ -16,6 +16,7 @@
#include "../mwbase/inputmanager.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/player.hpp"
#include "console.hpp"
#include "journalwindow.hpp"
@ -774,6 +775,13 @@ namespace MWGui
mHud->setCellName( cell->mCell->mName );
mMap->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 magnitude = effectIt->mMagnMin + (effectIt->mMagnMax - effectIt->mMagnMin) * random;
magnitude *= magnitudeMult;
magnitude *= magnitudeMult;
if (target.getClass().isActor() && !(magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration))
{
@ -239,18 +239,26 @@ namespace MWMechanics
else if (effectId == ESM::MagicEffect::RemoveCurse)
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);
// We need to be able to get the world location of an interior cell before implementing this
// or alternatively, the last known exterior location of the player, which is how vanilla does it.
MWBase::Environment::get().getWorld()->teleportToClosestMarker(target, "divinemarker", worldPos);
}
else if (effectId == ESM::MagicEffect::AlmsiviIntervention)
{
MWBase::Environment::get().getWorld()->getPlayer().setTeleported(true);
// Same as above
MWBase::Environment::get().getWorld()->teleportToClosestMarker(target, "templemarker", worldPos);
}
else if (effectId == ESM::MagicEffect::Mark)

@ -1211,7 +1211,8 @@ void ObjectAnimation::fillBatch(Ogre::StaticGeometry *sg)
for(;iter != mObjectRoot->mEntities.rend();++iter)
{
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)
newLevel = 0;
else if (newLevel>100)
newLevel = 100;
progress = (progress / stats.getSkillGain (mIndex, class_, -1, level))
* 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)
{
std::string lowerCase = Misc::StringUtils::lowerCase(name);
if (std::binary_search (cell.mIds.begin(), cell.mIds.end(), lowerCase))
if (std::binary_search (cell.mIds.begin(), cell.mIds.end(), name))
{
cell.load (mStore, mReader);
}
@ -261,3 +259,15 @@ MWWorld::Ptr MWWorld::Cells::getPtr (const std::string& name)
// giving up
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);
///< \param searchInContainers Only affect loaded cells.
/// @note name must be lower case
/// @note name must be lower case
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)
: mCellStore(0),
mLastKnownExteriorPosition(0,0,0),
mAutoMove(false),
mForwardBackward (0),
mTeleported(false)

@ -6,6 +6,8 @@
#include "../mwmechanics/drawstate.hpp"
#include <OgreVector3.h>
namespace ESM
{
struct NPC;
@ -28,6 +30,8 @@ namespace MWWorld
MWWorld::CellStore *mCellStore;
std::string mSign;
Ogre::Vector3 mLastKnownExteriorPosition;
bool mAutoMove;
int mForwardBackward;
bool mTeleported;
@ -35,6 +39,13 @@ namespace MWWorld
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 setCell (MWWorld::CellStore *cellStore);

@ -39,6 +39,7 @@
#include "cellfunctors.hpp"
#include "containerstore.hpp"
#include "inventorystore.hpp"
#include "actionteleport.hpp"
#include "contentloader.hpp"
#include "esmloader.hpp"
@ -498,12 +499,14 @@ namespace MWWorld
if (!ptr.isEmpty())
return ptr;
std::string lowerCaseName = Misc::StringUtils::lowerCase(name);
// active cells
for (Scene::CellStoreCollection::const_iterator iter (mWorldScene->getActiveCells().begin());
iter!=mWorldScene->getActiveCells().end(); ++iter)
{
Ptr::CellStore* cellstore = *iter;
Ptr ptr = mCells.getPtr (name, *cellstore, true);
Ptr ptr = mCells.getPtr (lowerCaseName, *cellstore, true);
if (!ptr.isEmpty())
return ptr;
@ -511,7 +514,7 @@ namespace MWWorld
if (!activeOnly)
{
Ptr ptr = mCells.getPtr (name);
Ptr ptr = mCells.getPtr (lowerCaseName);
if (!ptr.isEmpty())
return ptr;
@ -1297,6 +1300,12 @@ namespace MWWorld
performUpdateSceneQueries ();
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 ()
@ -2288,7 +2297,54 @@ namespace MWWorld
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)

@ -518,6 +518,14 @@ namespace MWWorld
virtual void breakInvisibility (const MWWorld::Ptr& actor);
// Are we in an exterior or pseudo-exterior cell and it's night?
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