mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-11-04 00:26:39 +00:00 
			
		
		
		
	Implement actors movement deceleration (feature #4544)
This commit is contained in:
		
							parent
							
								
									1aa4cc3388
								
							
						
					
					
						commit
						61ab7f3c1e
					
				
					 12 changed files with 63 additions and 0 deletions
				
			
		| 
						 | 
				
			
			@ -184,6 +184,7 @@
 | 
			
		|||
    Feature #4255: Handle broken RepairedOnMe script function
 | 
			
		||||
    Feature #4316: Implement RaiseRank/LowerRank functions properly
 | 
			
		||||
    Feature #4360: Improve default controller bindings
 | 
			
		||||
    Feature #4544: Actors movement deceleration
 | 
			
		||||
    Feature #4673: Weapon sheathing
 | 
			
		||||
    Feature #4675: Support for NiRollController
 | 
			
		||||
    Feature #4730: Native animated containers support
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -556,6 +556,8 @@ namespace MWClass
 | 
			
		|||
        if(getMovementSettings(ptr).mPosition[0] != 0 && getMovementSettings(ptr).mPosition[1] == 0)
 | 
			
		||||
            moveSpeed *= 0.75f;
 | 
			
		||||
 | 
			
		||||
        moveSpeed *= ptr.getClass().getMovementSettings(ptr).mSpeedFactor;
 | 
			
		||||
 | 
			
		||||
        return moveSpeed;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -990,6 +990,8 @@ namespace MWClass
 | 
			
		|||
        if(npcdata->mNpcStats.isWerewolf() && running && npcdata->mNpcStats.getDrawState() == MWMechanics::DrawState_Nothing)
 | 
			
		||||
            moveSpeed *= gmst.fWereWolfRunMult->mValue.getFloat();
 | 
			
		||||
 | 
			
		||||
        moveSpeed *= ptr.getClass().getMovementSettings(ptr).mSpeedFactor;
 | 
			
		||||
 | 
			
		||||
        return moveSpeed;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -144,6 +144,7 @@ namespace MWMechanics
 | 
			
		|||
{
 | 
			
		||||
    static const int GREETING_SHOULD_START = 4; //how many updates should pass before NPC can greet player
 | 
			
		||||
    static const int GREETING_SHOULD_END = 10;
 | 
			
		||||
    static const float DECELERATE_DISTANCE = 512.f;
 | 
			
		||||
 | 
			
		||||
    class GetStuntedMagickaDuration : public MWMechanics::EffectSourceVisitor
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			@ -422,6 +423,26 @@ namespace MWMechanics
 | 
			
		|||
            MWBase::Environment::get().getDialogueManager()->say(actor, "idle");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void Actors::updateMovementSpeed(const MWWorld::Ptr& actor)
 | 
			
		||||
    {
 | 
			
		||||
        float previousSpeedFactor = actor.getClass().getMovementSettings(actor).mSpeedFactor;
 | 
			
		||||
        float newSpeedFactor = 1.f;
 | 
			
		||||
 | 
			
		||||
        CreatureStats &stats = actor.getClass().getCreatureStats(actor);
 | 
			
		||||
        MWMechanics::AiSequence& seq = stats.getAiSequence();
 | 
			
		||||
 | 
			
		||||
        if (!seq.isEmpty() && seq.getActivePackage()->useVariableSpeed())
 | 
			
		||||
        {
 | 
			
		||||
            osg::Vec3f targetPos = seq.getActivePackage()->getDestination();
 | 
			
		||||
            osg::Vec3f actorPos = actor.getRefData().getPosition().asVec3();
 | 
			
		||||
            float distance = (targetPos - actorPos).length();
 | 
			
		||||
            if (distance < DECELERATE_DISTANCE)
 | 
			
		||||
                newSpeedFactor = std::max(0.7f, 0.1f * previousSpeedFactor * (distance/64.f + 2.f));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        actor.getClass().getMovementSettings(actor).mSpeedFactor = newSpeedFactor;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void Actors::updateGreetingState(const MWWorld::Ptr& actor, bool turnOnly)
 | 
			
		||||
    {
 | 
			
		||||
        if (!actor.getClass().isActor() || actor == getPlayer())
 | 
			
		||||
| 
						 | 
				
			
			@ -1668,6 +1689,7 @@ namespace MWMechanics
 | 
			
		|||
                                stats.getAiSequence().execute(iter->first, *ctrl, duration);
 | 
			
		||||
                                updateGreetingState(iter->first, timerUpdateHello > 0);
 | 
			
		||||
                                playIdleDialogue(iter->first);
 | 
			
		||||
                                updateMovementSpeed(iter->first);
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -121,6 +121,7 @@ namespace MWMechanics
 | 
			
		|||
            void engageCombat(const MWWorld::Ptr& actor1, const MWWorld::Ptr& actor2, std::map<const MWWorld::Ptr, const std::set<MWWorld::Ptr> >& cachedAllies, bool againstPlayer);
 | 
			
		||||
 | 
			
		||||
            void playIdleDialogue(const MWWorld::Ptr& actor);
 | 
			
		||||
            void updateMovementSpeed(const MWWorld::Ptr& actor);
 | 
			
		||||
            void updateGreetingState(const MWWorld::Ptr& actor, bool turnOnly);
 | 
			
		||||
            void turnActorToFacePlayer(const MWWorld::Ptr& actor, const osg::Vec3f& dir);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -36,12 +36,16 @@ namespace MWMechanics
 | 
			
		|||
 | 
			
		||||
            virtual int getTypeId() const;
 | 
			
		||||
 | 
			
		||||
            virtual bool useVariableSpeed() const { return true;}
 | 
			
		||||
 | 
			
		||||
            virtual bool sideWithTarget() const { return true; }
 | 
			
		||||
 | 
			
		||||
            void writeState(ESM::AiSequence::AiSequence &sequence) const;
 | 
			
		||||
 | 
			
		||||
            void fastForward(const MWWorld::Ptr& actor, AiState& state);
 | 
			
		||||
 | 
			
		||||
            virtual osg::Vec3f getDestination() { return osg::Vec3f(mX, mY, mZ); }
 | 
			
		||||
 | 
			
		||||
        private:
 | 
			
		||||
            std::string mCellId;
 | 
			
		||||
            float mX;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,6 +7,8 @@
 | 
			
		|||
 | 
			
		||||
#include <components/esm/defs.hpp>
 | 
			
		||||
 | 
			
		||||
#include "../mwworld/ptr.hpp"
 | 
			
		||||
 | 
			
		||||
#include "pathfinding.hpp"
 | 
			
		||||
 | 
			
		||||
namespace ESM
 | 
			
		||||
| 
						 | 
				
			
			@ -61,6 +63,8 @@ namespace MWMechanics
 | 
			
		|||
 | 
			
		||||
            virtual int getTypeId() const;
 | 
			
		||||
 | 
			
		||||
            virtual bool useVariableSpeed() const { return true;}
 | 
			
		||||
 | 
			
		||||
            /// Returns the actor being followed
 | 
			
		||||
            std::string getFollowedActor();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -72,6 +76,15 @@ namespace MWMechanics
 | 
			
		|||
 | 
			
		||||
            void fastForward(const MWWorld::Ptr& actor, AiState& state);
 | 
			
		||||
 | 
			
		||||
            virtual osg::Vec3f getDestination()
 | 
			
		||||
            {
 | 
			
		||||
                MWWorld::Ptr target = getTarget();
 | 
			
		||||
                if (target.isEmpty())
 | 
			
		||||
                    return osg::Vec3f(0, 0, 0);
 | 
			
		||||
 | 
			
		||||
                return target.getRefData().getPosition().asVec3();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        private:
 | 
			
		||||
            /// This will make the actor always follow.
 | 
			
		||||
            /** Thus ignoring mDuration and mX,mY,mZ (used for summoned creatures). **/
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -73,6 +73,9 @@ namespace MWMechanics
 | 
			
		|||
            /// Higher number is higher priority (0 being the lowest)
 | 
			
		||||
            virtual unsigned int getPriority() const {return 0;}
 | 
			
		||||
 | 
			
		||||
            /// Check if package use movement with variable speed
 | 
			
		||||
            virtual bool useVariableSpeed() const { return false;}
 | 
			
		||||
 | 
			
		||||
            virtual void writeState (ESM::AiSequence::AiSequence& sequence) const {}
 | 
			
		||||
 | 
			
		||||
            /// Simulates the passing of time
 | 
			
		||||
| 
						 | 
				
			
			@ -99,6 +102,8 @@ namespace MWMechanics
 | 
			
		|||
            /// Return true if this package should repeat. Currently only used for Wander packages.
 | 
			
		||||
            virtual bool getRepeat() const;
 | 
			
		||||
 | 
			
		||||
            virtual osg::Vec3f getDestination() { return osg::Vec3f(0, 0, 0); }
 | 
			
		||||
 | 
			
		||||
            /// Reset pathfinding state
 | 
			
		||||
            void reset();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -388,6 +388,11 @@ void AiSequence::stack (const AiPackage& package, const MWWorld::Ptr& actor, boo
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool MWMechanics::AiSequence::isEmpty() const
 | 
			
		||||
{
 | 
			
		||||
    return mPackages.empty();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
AiPackage* MWMechanics::AiSequence::getActivePackage()
 | 
			
		||||
{
 | 
			
		||||
    if(mPackages.empty())
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -132,6 +132,8 @@ namespace MWMechanics
 | 
			
		|||
                \see ESM::AIPackageList **/
 | 
			
		||||
            void fill (const ESM::AIPackageList& list);
 | 
			
		||||
 | 
			
		||||
            bool isEmpty() const;
 | 
			
		||||
 | 
			
		||||
            void writeState (ESM::AiSequence::AiSequence& sequence) const;
 | 
			
		||||
            void readState (const ESM::AiSequence::AiSequence& sequence);
 | 
			
		||||
    };
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -32,6 +32,10 @@ namespace MWMechanics
 | 
			
		|||
 | 
			
		||||
            virtual int getTypeId() const;
 | 
			
		||||
 | 
			
		||||
            virtual bool useVariableSpeed() const { return true;}
 | 
			
		||||
 | 
			
		||||
            virtual osg::Vec3f getDestination() { return osg::Vec3f(mX, mY, mZ); }
 | 
			
		||||
 | 
			
		||||
        private:
 | 
			
		||||
            float mX;
 | 
			
		||||
            float mY;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,11 +10,13 @@ namespace MWMechanics
 | 
			
		|||
    {
 | 
			
		||||
        float mPosition[3];
 | 
			
		||||
        float mRotation[3];
 | 
			
		||||
        float mSpeedFactor;
 | 
			
		||||
 | 
			
		||||
        Movement()
 | 
			
		||||
        {
 | 
			
		||||
            mPosition[0] = mPosition[1] = mPosition[2] = 0.0f;
 | 
			
		||||
            mRotation[0] = mRotation[1] = mRotation[2] = 0.0f;
 | 
			
		||||
            mSpeedFactor = 1.f;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        osg::Vec3f asVec3()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue