Factor out safePlaceObject function

move
scrawl 9 years ago
parent 11f00e3aa9
commit 6df71f6250

@ -279,7 +279,11 @@ namespace MWBase
virtual void rotateObject(const MWWorld::Ptr& ptr,float x,float y,float z, bool adjust = false) = 0; virtual void rotateObject(const MWWorld::Ptr& ptr,float x,float y,float z, bool adjust = false) = 0;
virtual MWWorld::Ptr placeObject(const MWWorld::ConstPtr& ptr, MWWorld::CellStore* cell, ESM::Position pos) = 0; virtual MWWorld::Ptr placeObject(const MWWorld::ConstPtr& ptr, MWWorld::CellStore* cell, ESM::Position pos) = 0;
///< place an object in a "safe" location (ie not in the void, etc). ///< Place an object. Makes a copy of the Ptr.
virtual MWWorld::Ptr safePlaceObject (const MWWorld::ConstPtr& ptr, const MWWorld::ConstPtr& referenceObject, MWWorld::CellStore* referenceCell, int direction, float distance) = 0;
///< Place an object in a safe place next to \a referenceObject. \a direction and \a distance specify the wanted placement
/// relative to \a referenceObject (but the object may be placed somewhere else if the wanted location is obstructed).
virtual void indexToPosition (int cellX, int cellY, float &x, float &y, bool centre = false) virtual void indexToPosition (int cellX, int cellY, float &x, float &y, bool centre = false)
const = 0; const = 0;

@ -492,15 +492,6 @@ namespace MWScript
{ {
public: public:
osg::Vec3f getSpawnPosition(const osg::Vec3f& origin, const osg::Quat& orientation, int direction, float distance)
{
if(direction == 0) return origin + (orientation * osg::Vec3f(0,1,0)) * distance;
else if(direction == 1) return origin - (orientation * osg::Vec3f(0,1,0)) * distance;
else if(direction == 2) return origin - (orientation * osg::Vec3f(1,0,0)) * distance;
else if(direction == 3) return origin + (orientation * osg::Vec3f(1,0,0)) * distance;
else return origin;
}
virtual void execute (Interpreter::Runtime& runtime) virtual void execute (Interpreter::Runtime& runtime)
{ {
MWWorld::Ptr actor = pc MWWorld::Ptr actor = pc
@ -523,52 +514,12 @@ namespace MWScript
if (!actor.isInCell()) if (!actor.isInCell())
throw std::runtime_error ("actor is not in a cell"); throw std::runtime_error ("actor is not in a cell");
ESM::Position ipos = actor.getRefData().getPosition();
osg::Vec3f pos(ipos.asVec3());
osg::Quat rot(ipos.rot[2], osg::Vec3f(0,0,-1));
for (int i=0; i<4; ++i)
{
// check if spawn point is safe, fall back to another direction if not
osg::Vec3f spawnPoint = getSpawnPosition(ipos.asVec3(), rot, direction, distance);
spawnPoint.z() += 30; // move up a little to account for slopes, will snap down later
if (!MWBase::Environment::get().getWorld()->castRay(spawnPoint.x(), spawnPoint.y(), spawnPoint.z(),
pos.x(), pos.y(), pos.z() + 20))
{
// safe
ipos.pos[0] = spawnPoint.x();
ipos.pos[1] = spawnPoint.y();
ipos.pos[2] = spawnPoint.z();
break;
}
direction = (direction+1) % 4;
}
if (actor.getClass().isActor())
{
// TODO: should this depend on the 'direction' parameter?
ipos.rot[0] = 0;
ipos.rot[1] = 0;
ipos.rot[2] = 0;
}
else
{
ipos.rot[0] = actor.getRefData().getPosition().rot[0];
ipos.rot[1] = actor.getRefData().getPosition().rot[1];
ipos.rot[2] = actor.getRefData().getPosition().rot[2];
}
for (int i=0; i<count; ++i) for (int i=0; i<count; ++i)
{ {
// create item // create item
MWWorld::CellStore* store = actor.getCell();
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), itemID, 1); MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), itemID, 1);
ref.getPtr().getCellRef().setPosition(ipos);
MWWorld::Ptr placed = MWBase::Environment::get().getWorld()->placeObject(ref.getPtr(),store,ipos); MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(), actor, actor.getCell(), direction, distance);
placed.getClass().adjustPosition(placed, true); // snap to ground
} }
} }
}; };

@ -1330,6 +1330,43 @@ namespace MWWorld
return copyObjectToCell(ptr,cell,pos,ptr.getRefData().getCount(),false); return copyObjectToCell(ptr,cell,pos,ptr.getRefData().getCount(),false);
} }
MWWorld::Ptr World::safePlaceObject(const ConstPtr &ptr, const ConstPtr &referenceObject, MWWorld::CellStore* referenceCell, int direction, float distance)
{
ESM::Position ipos = referenceObject.getRefData().getPosition();
osg::Vec3f pos(ipos.asVec3());
osg::Quat orientation(ipos.rot[2], osg::Vec3f(0,0,-1));
for (int i=0; i<4; ++i)
{
// check if spawn point is safe, fall back to another direction if not
osg::Vec3f spawnPoint = pos;
if (direction == 0) spawnPoint = pos + (orientation * osg::Vec3f(0,1,0)) * distance;
else if(direction == 1) spawnPoint = pos - (orientation * osg::Vec3f(0,1,0)) * distance;
else if(direction == 2) spawnPoint = pos - (orientation * osg::Vec3f(1,0,0)) * distance;
else if(direction == 3) spawnPoint = pos + (orientation * osg::Vec3f(1,0,0)) * distance;
spawnPoint.z() += 30; // move up a little to account for slopes, will snap down later
if (!castRay(spawnPoint.x(), spawnPoint.y(), spawnPoint.z(),
pos.x(), pos.y(), pos.z() + 20))
{
// safe
ipos.pos[0] = spawnPoint.x();
ipos.pos[1] = spawnPoint.y();
ipos.pos[2] = spawnPoint.z();
break;
}
direction = (direction+1) % 4;
}
ipos.rot[0] = referenceObject.getRefData().getPosition().rot[0];
ipos.rot[1] = referenceObject.getRefData().getPosition().rot[1];
ipos.rot[2] = referenceObject.getRefData().getPosition().rot[2];
MWWorld::Ptr placed = copyObjectToCell(ptr, referenceCell, ipos, ptr.getRefData().getCount(), false);
placed.getClass().adjustPosition(placed, true); // snap to ground
return placed;
}
void World::indexToPosition (int cellX, int cellY, float &x, float &y, bool centre) const void World::indexToPosition (int cellX, int cellY, float &x, float &y, bool centre) const
{ {
const int cellSize = 8192; const int cellSize = 8192;

@ -368,7 +368,11 @@ namespace MWWorld
virtual void rotateObject (const Ptr& ptr,float x,float y,float z, bool adjust = false); virtual void rotateObject (const Ptr& ptr,float x,float y,float z, bool adjust = false);
virtual MWWorld::Ptr placeObject(const MWWorld::ConstPtr& ptr, MWWorld::CellStore* cell, ESM::Position pos); virtual MWWorld::Ptr placeObject(const MWWorld::ConstPtr& ptr, MWWorld::CellStore* cell, ESM::Position pos);
///< place an object. Makes a copy of the Ptr. ///< Place an object. Makes a copy of the Ptr.
virtual MWWorld::Ptr safePlaceObject (const MWWorld::ConstPtr& ptr, const MWWorld::ConstPtr& referenceObject, MWWorld::CellStore* referenceCell, int direction, float distance);
///< Place an object in a safe place next to \a referenceObject. \a direction and \a distance specify the wanted placement
/// relative to \a referenceObject (but the object may be placed somewhere else if the wanted location is obstructed).
virtual float getMaxActivationDistance(); virtual float getMaxActivationDistance();

Loading…
Cancel
Save