forked from teamnwah/openmw-tes3coop
Merge remote-tracking branch 'scrawl/master'
Conflicts: apps/openmw/mwmechanics/spellcasting.cpp
This commit is contained in:
commit
c3482b6f24
14 changed files with 159 additions and 27 deletions
3
.gitignore
vendored
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…
Reference in a new issue