mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-25 06:35:30 +00:00
Implement divine/almsivi intervention magic effects
This commit is contained in:
parent
c86760e3cd
commit
ea3b88951a
@ -432,6 +432,12 @@ namespace MWBase
|
||||
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;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
|
||||
#include "../mwworld/containerstore.hpp"
|
||||
#include "../mwworld/player.hpp"
|
||||
|
||||
#include "../mwrender/animation.hpp"
|
||||
|
||||
@ -238,14 +239,24 @@ 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)
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
// Same as above
|
||||
MWBase::Environment::get().getWorld()->teleportToClosestMarker(target, "templemarker",
|
||||
worldPos);
|
||||
}
|
||||
|
||||
else if (effectId == ESM::MagicEffect::Mark)
|
||||
|
@ -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);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
@ -2317,4 +2320,30 @@ namespace MWWorld
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
@ -520,6 +520,12 @@ namespace MWWorld
|
||||
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…
x
Reference in New Issue
Block a user