mirror of
				https://github.com/TES3MP/openmw-tes3mp.git
				synced 2025-10-31 21:56:45 +00:00 
			
		
		
		
	Add an infinite fall failsafe (feature 1415)
This commit is contained in:
		
							parent
							
								
									10fafabd7f
								
							
						
					
					
						commit
						61b60c8a94
					
				
					 3 changed files with 28 additions and 3 deletions
				
			
		|  | @ -198,6 +198,7 @@ | ||||||
|     Bug #5261: Creatures can sometimes become stuck playing idles and never wander again |     Bug #5261: Creatures can sometimes become stuck playing idles and never wander again | ||||||
|     Bug #5269: Editor: Cell lighting in resaved cleaned content files is corrupted |     Bug #5269: Editor: Cell lighting in resaved cleaned content files is corrupted | ||||||
|     Bug #5278: Console command Show doesn't fall back to global variable after local var not found |     Bug #5278: Console command Show doesn't fall back to global variable after local var not found | ||||||
|  |     Feature #1415: Infinite fall failsafe | ||||||
|     Feature #1774: Handle AvoidNode |     Feature #1774: Handle AvoidNode | ||||||
|     Feature #2229: Improve pathfinding AI |     Feature #2229: Improve pathfinding AI | ||||||
|     Feature #3025: Analogue gamepad movement controls |     Feature #3025: Analogue gamepad movement controls | ||||||
|  |  | ||||||
|  | @ -33,6 +33,7 @@ | ||||||
| #include "../mwphysics/object.hpp" | #include "../mwphysics/object.hpp" | ||||||
| #include "../mwphysics/heightfield.hpp" | #include "../mwphysics/heightfield.hpp" | ||||||
| 
 | 
 | ||||||
|  | #include "actionteleport.hpp" | ||||||
| #include "player.hpp" | #include "player.hpp" | ||||||
| #include "localscripts.hpp" | #include "localscripts.hpp" | ||||||
| #include "esmstore.hpp" | #include "esmstore.hpp" | ||||||
|  | @ -255,12 +256,22 @@ namespace | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     struct AdjustPositionVisitor |     struct PositionVisitor | ||||||
|     { |     { | ||||||
|  |         float mLowestPos = std::numeric_limits<float>::max(); | ||||||
|  | 
 | ||||||
|         bool operator() (const MWWorld::Ptr& ptr) |         bool operator() (const MWWorld::Ptr& ptr) | ||||||
|         { |         { | ||||||
|             if (!ptr.getRefData().isDeleted() && ptr.getRefData().isEnabled()) |             if (!ptr.getRefData().isDeleted() && ptr.getRefData().isEnabled()) | ||||||
|  |             { | ||||||
|  |                 if (!ptr.getClass().isActor()) | ||||||
|  |                 { | ||||||
|  |                     float objectPosZ = ptr.getRefData().getPosition().pos[2]; | ||||||
|  |                     if (objectPosZ < mLowestPos) | ||||||
|  |                         mLowestPos = objectPosZ; | ||||||
|  |                 } | ||||||
|                 ptr.getClass().adjustPosition (ptr, false); |                 ptr.getClass().adjustPosition (ptr, false); | ||||||
|  |             } | ||||||
|             return true; |             return true; | ||||||
|         } |         } | ||||||
|     }; |     }; | ||||||
|  | @ -487,6 +498,16 @@ namespace MWWorld | ||||||
|         const auto player = MWBase::Environment::get().getWorld()->getPlayerPtr(); |         const auto player = MWBase::Environment::get().getWorld()->getPlayerPtr(); | ||||||
|         navigator->update(player.getRefData().getPosition().asVec3()); |         navigator->update(player.getRefData().getPosition().asVec3()); | ||||||
| 
 | 
 | ||||||
|  |         const float fallThreshold = 90.f; | ||||||
|  |         if (mCurrentCell && !mCurrentCell->isExterior() && pos.z() < mLowestPos - fallThreshold) | ||||||
|  |         { | ||||||
|  |             ESM::Position newPos; | ||||||
|  |             std::string cellName = mCurrentCell->getCell()->mName; | ||||||
|  |             MWBase::Environment::get().getWorld()->findInteriorPosition(cellName, newPos); | ||||||
|  |             if (newPos.pos[2] >= mLowestPos - fallThreshold) | ||||||
|  |                 MWWorld::ActionTeleport(cellName, newPos, false).execute(player); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         if (!mCurrentCell || !mCurrentCell->isExterior()) |         if (!mCurrentCell || !mCurrentCell->isExterior()) | ||||||
|             return; |             return; | ||||||
| 
 | 
 | ||||||
|  | @ -877,8 +898,10 @@ namespace MWWorld | ||||||
|         insertVisitor.insert([&] (const MWWorld::Ptr& ptr) { addObject(ptr, *mPhysics, mNavigator); }); |         insertVisitor.insert([&] (const MWWorld::Ptr& ptr) { addObject(ptr, *mPhysics, mNavigator); }); | ||||||
| 
 | 
 | ||||||
|         // do adjustPosition (snapping actors to ground) after objects are loaded, so we don't depend on the loading order
 |         // do adjustPosition (snapping actors to ground) after objects are loaded, so we don't depend on the loading order
 | ||||||
|         AdjustPositionVisitor adjustPosVisitor; |         // Also note the lowest object position in the cell to allow infinite fall fail safe to work
 | ||||||
|         cell.forEach (adjustPosVisitor); |         PositionVisitor posVisitor; | ||||||
|  |         cell.forEach (posVisitor); | ||||||
|  |         mLowestPos = posVisitor.mLowestPos; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void Scene::addObjectToScene (const Ptr& ptr) |     void Scene::addObjectToScene (const Ptr& ptr) | ||||||
|  |  | ||||||
|  | @ -84,6 +84,7 @@ namespace MWWorld | ||||||
|             float mPredictionTime; |             float mPredictionTime; | ||||||
| 
 | 
 | ||||||
|             osg::Vec3f mLastPlayerPos; |             osg::Vec3f mLastPlayerPos; | ||||||
|  |             float mLowestPos; | ||||||
| 
 | 
 | ||||||
|             void insertCell (CellStore &cell, Loading::Listener* loadingListener, bool test = false); |             void insertCell (CellStore &cell, Loading::Listener* loadingListener, bool test = false); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue