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