mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-30 15:15:31 +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