2010-08-03 18:44:52 +02:00
|
|
|
#include "actionteleport.hpp"
|
|
|
|
|
2022-06-26 16:42:29 +02:00
|
|
|
#include <components/esm3/loadcell.hpp>
|
|
|
|
|
2012-04-23 15:27:03 +02:00
|
|
|
#include "../mwbase/environment.hpp"
|
2014-01-12 14:03:11 +01:00
|
|
|
#include "../mwbase/mechanicsmanager.hpp"
|
2012-07-03 12:30:50 +02:00
|
|
|
#include "../mwbase/world.hpp"
|
2015-11-20 05:05:43 +01:00
|
|
|
|
2017-02-20 20:27:05 +01:00
|
|
|
#include "../mwmechanics/creaturestats.hpp"
|
|
|
|
|
2022-11-06 20:06:45 +01:00
|
|
|
#include "../mwworld/cells.hpp"
|
2021-10-06 18:25:28 +02:00
|
|
|
#include "../mwworld/cellstore.hpp"
|
2022-05-23 19:21:44 +02:00
|
|
|
#include "../mwworld/cellutils.hpp"
|
2015-11-20 05:05:43 +01:00
|
|
|
#include "../mwworld/class.hpp"
|
|
|
|
|
2013-12-31 20:40:23 +01:00
|
|
|
#include "player.hpp"
|
2010-08-03 18:44:52 +02:00
|
|
|
|
|
|
|
namespace MWWorld
|
|
|
|
{
|
2022-08-27 13:07:59 +02:00
|
|
|
ActionTeleport::ActionTeleport(std::string_view cellName, const ESM::Position& position, bool teleportFollowers)
|
2015-05-22 19:56:39 +02:00
|
|
|
: Action(true)
|
|
|
|
, mCellName(cellName)
|
|
|
|
, mPosition(position)
|
|
|
|
, mTeleportFollowers(teleportFollowers)
|
2012-08-26 11:47:45 -03:00
|
|
|
{
|
|
|
|
}
|
2010-08-03 18:44:52 +02:00
|
|
|
|
2012-07-27 12:00:10 +02:00
|
|
|
void ActionTeleport::executeImp(const Ptr& actor)
|
2010-08-03 18:44:52 +02:00
|
|
|
{
|
2015-05-22 19:56:39 +02:00
|
|
|
if (mTeleportFollowers)
|
2014-01-12 14:03:11 +01:00
|
|
|
{
|
2016-12-23 21:27:29 +01:00
|
|
|
// Find any NPCs that are following the actor and teleport them with him
|
2015-05-22 19:56:39 +02:00
|
|
|
std::set<MWWorld::Ptr> followers;
|
2021-10-06 18:25:28 +02:00
|
|
|
getFollowers(actor, followers, mCellName.empty(), true);
|
2016-12-20 12:38:51 +01:00
|
|
|
|
2016-12-23 21:27:29 +01:00
|
|
|
for (std::set<MWWorld::Ptr>::iterator it = followers.begin(); it != followers.end(); ++it)
|
|
|
|
teleport(*it);
|
2014-01-12 14:03:11 +01:00
|
|
|
}
|
|
|
|
|
2014-08-24 22:51:47 +02:00
|
|
|
teleport(actor);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ActionTeleport::teleport(const Ptr& actor)
|
|
|
|
{
|
|
|
|
MWBase::World* world = MWBase::Environment::get().getWorld();
|
2022-11-06 20:06:45 +01:00
|
|
|
MWWorld::Cells* worldModel = MWBase::Environment::get().getWorldModel();
|
2018-09-15 19:38:21 +04:00
|
|
|
actor.getClass().getCreatureStats(actor).land(actor == world->getPlayerPtr());
|
2014-01-12 14:03:11 +01:00
|
|
|
if (actor == world->getPlayerPtr())
|
|
|
|
{
|
|
|
|
world->getPlayer().setTeleported(true);
|
|
|
|
if (mCellName.empty())
|
2016-03-24 17:18:08 +01:00
|
|
|
world->changeToExteriorCell(mPosition, true);
|
2014-01-12 14:03:11 +01:00
|
|
|
else
|
2016-03-24 17:18:08 +01:00
|
|
|
world->changeToInteriorCell(mCellName, mPosition, true);
|
2014-01-12 14:03:11 +01:00
|
|
|
}
|
2010-08-20 14:56:26 +02:00
|
|
|
else
|
2014-01-12 14:03:11 +01:00
|
|
|
{
|
2020-10-03 20:05:17 +00:00
|
|
|
if (actor.getClass().getCreatureStats(actor).getAiSequence().isInCombat(world->getPlayerPtr()))
|
|
|
|
actor.getClass().getCreatureStats(actor).getAiSequence().stopCombat();
|
|
|
|
else if (mCellName.empty())
|
2014-01-12 14:03:11 +01:00
|
|
|
{
|
2022-05-23 19:21:44 +02:00
|
|
|
const osg::Vec2i index = positionToCellIndex(mPosition.pos[0], mPosition.pos[1]);
|
2022-11-06 20:06:45 +01:00
|
|
|
world->moveObject(actor, worldModel->getExterior(index.x(), index.y()), mPosition.asVec3(), true, true);
|
2014-01-12 14:03:11 +01:00
|
|
|
}
|
|
|
|
else
|
2022-11-06 20:06:45 +01:00
|
|
|
world->moveObject(actor, worldModel->getInterior(mCellName), mPosition.asVec3(), true, true);
|
2014-01-12 14:03:11 +01:00
|
|
|
}
|
2010-08-03 18:44:52 +02:00
|
|
|
}
|
2016-12-23 21:27:29 +01:00
|
|
|
|
2021-10-06 18:25:28 +02:00
|
|
|
void ActionTeleport::getFollowers(
|
|
|
|
const MWWorld::Ptr& actor, std::set<MWWorld::Ptr>& out, bool toExterior, bool includeHostiles)
|
|
|
|
{
|
2016-12-23 21:27:29 +01:00
|
|
|
std::set<MWWorld::Ptr> followers;
|
|
|
|
MWBase::Environment::get().getMechanicsManager()->getActorsFollowing(actor, followers);
|
|
|
|
|
|
|
|
for (std::set<MWWorld::Ptr>::iterator it = followers.begin(); it != followers.end(); ++it)
|
|
|
|
{
|
|
|
|
MWWorld::Ptr follower = *it;
|
|
|
|
|
2022-08-11 22:51:55 +02:00
|
|
|
std::string_view script = follower.getClass().getScript(follower);
|
2020-10-03 20:05:17 +00:00
|
|
|
|
|
|
|
if (!includeHostiles && follower.getClass().getCreatureStats(follower).getAiSequence().isInCombat(actor))
|
|
|
|
continue;
|
|
|
|
|
2021-10-06 18:25:28 +02:00
|
|
|
if (!toExterior && !script.empty()
|
|
|
|
&& follower.getRefData().getLocals().getIntVar(script, "stayoutside") == 1
|
|
|
|
&& follower.getCell()->getCell()->isExterior())
|
2016-12-23 21:27:29 +01:00
|
|
|
continue;
|
|
|
|
|
2020-10-03 20:05:17 +00:00
|
|
|
if ((follower.getRefData().getPosition().asVec3() - actor.getRefData().getPosition().asVec3()).length2()
|
|
|
|
> 800 * 800)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
out.emplace(follower);
|
2016-12-23 21:27:29 +01:00
|
|
|
}
|
|
|
|
}
|
2010-08-03 18:44:52 +02:00
|
|
|
}
|