Make Move and MoveWorld console commands move actors standing on moving object (bug #2274)

pull/1889/head
Andrei Kortunov 6 years ago
parent 78d9787212
commit de08c1cb1b

@ -5,6 +5,7 @@
Bug #2131: Lustidrike's spell misses the player every time
Bug #2222: Fatigue's effect on selling price is backwards
Bug #2256: Landing sound not playing when jumping immediately after landing
Bug #2274: Thin platform clips through player character instead of lifting
Bug #2326: After a bound item expires the last equipped item of that type is not automatically re-equipped
Bug #2455: Creatures attacks degrade armor
Bug #2562: Forcing AI to activate a teleport door sometimes causes a crash

@ -412,6 +412,7 @@ namespace MWBase
/// @note throws an exception when invoked on a teleport door
virtual void activateDoor(const MWWorld::Ptr& door, int state) = 0;
virtual void getActorsStandingOn (const MWWorld::ConstPtr& object, std::vector<MWWorld::Ptr> &actors) = 0; ///< get a list of actors standing on \a object
virtual bool getPlayerStandingOn (const MWWorld::ConstPtr& object) = 0; ///< @return true if the player is standing on \a object
virtual bool getActorStandingOn (const MWWorld::ConstPtr& object) = 0; ///< @return true if any actor is standing on \a object
virtual bool getPlayerCollidingWith(const MWWorld::ConstPtr& object) = 0; ///< @return true if the player is colliding with \a object

@ -29,6 +29,18 @@ namespace MWScript
{
namespace Transformation
{
void moveStandingActors(const MWWorld::Ptr &ptr, const osg::Vec3f& diff)
{
std::vector<MWWorld::Ptr> actors;
MWBase::Environment::get().getWorld()->getActorsStandingOn (ptr, actors);
for (auto& actor : actors)
{
osg::Vec3f actorPos(actor.getRefData().getPosition().asVec3());
actorPos += diff;
MWBase::Environment::get().getWorld()->moveObject(actor, actorPos.x(), actorPos.y(), actorPos.z());
}
}
template<class R>
class OpSetScale : public Interpreter::Opcode0
{
@ -666,6 +678,10 @@ namespace MWScript
osg::Vec3f diff = ptr.getRefData().getBaseNode()->getAttitude() * posChange;
osg::Vec3f worldPos(ptr.getRefData().getPosition().asVec3());
worldPos += diff;
// We should move actors, standing on moving object, too.
// This approach can be used to create elevators.
moveStandingActors(ptr, diff);
MWBase::Environment::get().getWorld()->moveObject(ptr, worldPos.x(), worldPos.y(), worldPos.z());
}
};
@ -688,22 +704,21 @@ namespace MWScript
runtime.pop();
const float *objPos = ptr.getRefData().getPosition().pos;
osg::Vec3f diff;
MWWorld::Ptr updated;
if (axis == "x")
{
updated = MWBase::Environment::get().getWorld()->moveObject(ptr, objPos[0]+movement, objPos[1], objPos[2]);
}
diff.x() += movement;
else if (axis == "y")
{
updated = MWBase::Environment::get().getWorld()->moveObject(ptr, objPos[0], objPos[1]+movement, objPos[2]);
}
diff.y() += movement;
else if (axis == "z")
{
updated = MWBase::Environment::get().getWorld()->moveObject(ptr, objPos[0], objPos[1], objPos[2]+movement);
}
diff.z() += movement;
else
throw std::runtime_error ("invalid movement axis: " + axis);
// We should move actors, standing on moving object, too.
// This approach can be used to create elevators.
moveStandingActors(ptr, diff);
MWBase::Environment::get().getWorld()->moveObject(ptr, objPos[0]+diff.x(), objPos[1]+diff.y(), objPos[2]+diff.z());
}
};

@ -2377,6 +2377,11 @@ namespace MWWorld
return !actors.empty();
}
void World::getActorsStandingOn (const MWWorld::ConstPtr& object, std::vector<MWWorld::Ptr> &actors)
{
mPhysics->getActorsStandingOn(object, actors);
}
bool World::getPlayerCollidingWith (const MWWorld::ConstPtr& object)
{
MWWorld::Ptr player = getPlayerPtr();

@ -525,6 +525,7 @@ namespace MWWorld
/// @note throws an exception when invoked on a teleport door
void activateDoor(const MWWorld::Ptr& door, int state) override;
void getActorsStandingOn (const MWWorld::ConstPtr& object, std::vector<MWWorld::Ptr> &actors); ///< get a list of actors standing on \a object
bool getPlayerStandingOn (const MWWorld::ConstPtr& object) override; ///< @return true if the player is standing on \a object
bool getActorStandingOn (const MWWorld::ConstPtr& object) override; ///< @return true if any actor is standing on \a object
bool getPlayerCollidingWith(const MWWorld::ConstPtr& object) override; ///< @return true if the player is colliding with \a object

Loading…
Cancel
Save