mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-10-31 20:26:43 +00:00 
			
		
		
		
	Factor out safePlaceObject function
This commit is contained in:
		
							parent
							
								
									11f00e3aa9
								
							
						
					
					
						commit
						6df71f6250
					
				
					 4 changed files with 48 additions and 52 deletions
				
			
		|  | @ -279,7 +279,11 @@ namespace MWBase | |||
|             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; | ||||
|             ///< 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) | ||||
|                 const = 0; | ||||
|  |  | |||
|  | @ -492,15 +492,6 @@ namespace MWScript | |||
|         { | ||||
|             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) | ||||
|                 { | ||||
|                     MWWorld::Ptr actor = pc | ||||
|  | @ -523,52 +514,12 @@ namespace MWScript | |||
|                     if (!actor.isInCell()) | ||||
|                         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) | ||||
|                     { | ||||
|                         // create item
 | ||||
|                         MWWorld::CellStore* store = actor.getCell(); | ||||
|                         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); | ||||
|                         placed.getClass().adjustPosition(placed, true); // snap to ground
 | ||||
|                         MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(), actor, actor.getCell(), direction, distance); | ||||
|                     } | ||||
|                 } | ||||
|         }; | ||||
|  |  | |||
|  | @ -1330,6 +1330,43 @@ namespace MWWorld | |||
|         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 | ||||
|     { | ||||
|         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 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(); | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue