mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-02-28 17:09:39 +00:00
Improved strafe movement
This commit is contained in:
parent
d3bd67d747
commit
b4c699348f
10 changed files with 142 additions and 71 deletions
|
@ -536,10 +536,11 @@ namespace MWClass
|
||||||
moveSpeed = getSwimSpeed(ptr);
|
moveSpeed = getSwimSpeed(ptr);
|
||||||
else
|
else
|
||||||
moveSpeed = getWalkSpeed(ptr);
|
moveSpeed = getWalkSpeed(ptr);
|
||||||
if(getMovementSettings(ptr).mPosition[0] != 0 && getMovementSettings(ptr).mPosition[1] == 0)
|
|
||||||
moveSpeed *= 0.75f;
|
|
||||||
|
|
||||||
moveSpeed *= ptr.getClass().getMovementSettings(ptr).mSpeedFactor;
|
const MWMechanics::Movement& movementSettings = ptr.getClass().getMovementSettings(ptr);
|
||||||
|
if (movementSettings.mIsStrafing)
|
||||||
|
moveSpeed *= 0.75f;
|
||||||
|
moveSpeed *= movementSettings.mSpeedFactor;
|
||||||
|
|
||||||
return moveSpeed;
|
return moveSpeed;
|
||||||
}
|
}
|
||||||
|
|
|
@ -966,13 +966,14 @@ namespace MWClass
|
||||||
moveSpeed = getRunSpeed(ptr);
|
moveSpeed = getRunSpeed(ptr);
|
||||||
else
|
else
|
||||||
moveSpeed = getWalkSpeed(ptr);
|
moveSpeed = getWalkSpeed(ptr);
|
||||||
if(getMovementSettings(ptr).mPosition[0] != 0 && getMovementSettings(ptr).mPosition[1] == 0)
|
|
||||||
moveSpeed *= 0.75f;
|
|
||||||
|
|
||||||
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;
|
const MWMechanics::Movement& movementSettings = ptr.getClass().getMovementSettings(ptr);
|
||||||
|
if (movementSettings.mIsStrafing)
|
||||||
|
moveSpeed *= 0.75f;
|
||||||
|
moveSpeed *= movementSettings.mSpeedFactor;
|
||||||
|
|
||||||
return moveSpeed;
|
return moveSpeed;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1939,64 +1939,76 @@ void CharacterController::update(float duration, bool animationOnly)
|
||||||
bool sneak = cls.getCreatureStats(mPtr).getStance(MWMechanics::CreatureStats::Stance_Sneak) && !flying;
|
bool sneak = cls.getCreatureStats(mPtr).getStance(MWMechanics::CreatureStats::Stance_Sneak) && !flying;
|
||||||
bool isrunning = cls.getCreatureStats(mPtr).getStance(MWMechanics::CreatureStats::Stance_Run) && !flying;
|
bool isrunning = cls.getCreatureStats(mPtr).getStance(MWMechanics::CreatureStats::Stance_Run) && !flying;
|
||||||
CreatureStats &stats = cls.getCreatureStats(mPtr);
|
CreatureStats &stats = cls.getCreatureStats(mPtr);
|
||||||
|
Movement& movementSettings = cls.getMovementSettings(mPtr);
|
||||||
|
|
||||||
//Force Jump Logic
|
//Force Jump Logic
|
||||||
|
|
||||||
bool isMoving = (std::abs(cls.getMovementSettings(mPtr).mPosition[0]) > .5 || std::abs(cls.getMovementSettings(mPtr).mPosition[1]) > .5);
|
bool isMoving = (std::abs(movementSettings.mPosition[0]) > .5 || std::abs(movementSettings.mPosition[1]) > .5);
|
||||||
if(!inwater && !flying && solid)
|
if(!inwater && !flying && solid)
|
||||||
{
|
{
|
||||||
//Force Jump
|
//Force Jump
|
||||||
if(stats.getMovementFlag(MWMechanics::CreatureStats::Flag_ForceJump))
|
if(stats.getMovementFlag(MWMechanics::CreatureStats::Flag_ForceJump))
|
||||||
{
|
movementSettings.mPosition[2] = onground ? 1 : 0;
|
||||||
if(onground)
|
|
||||||
{
|
|
||||||
cls.getMovementSettings(mPtr).mPosition[2] = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
cls.getMovementSettings(mPtr).mPosition[2] = 0;
|
|
||||||
}
|
|
||||||
//Force Move Jump, only jump if they're otherwise moving
|
//Force Move Jump, only jump if they're otherwise moving
|
||||||
if(stats.getMovementFlag(MWMechanics::CreatureStats::Flag_ForceMoveJump) && isMoving)
|
if(stats.getMovementFlag(MWMechanics::CreatureStats::Flag_ForceMoveJump) && isMoving)
|
||||||
{
|
movementSettings.mPosition[2] = onground ? 1 : 0;
|
||||||
|
|
||||||
if(onground)
|
|
||||||
{
|
|
||||||
cls.getMovementSettings(mPtr).mPosition[2] = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
cls.getMovementSettings(mPtr).mPosition[2] = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
osg::Vec3f vec(cls.getMovementSettings(mPtr).asVec3());
|
osg::Vec3f rot = cls.getRotationVector(mPtr);
|
||||||
|
osg::Vec3f vec(movementSettings.asVec3());
|
||||||
vec.normalize();
|
vec.normalize();
|
||||||
|
|
||||||
if(mHitState != CharState_None && mJumpState == JumpState_None)
|
float analogueMult = 1.0f;
|
||||||
vec = osg::Vec3f(0.f, 0.f, 0.f);
|
if (isPlayer)
|
||||||
osg::Vec3f rot = cls.getRotationVector(mPtr);
|
|
||||||
|
|
||||||
speed = cls.getSpeed(mPtr);
|
|
||||||
float analogueMult = 1.f;
|
|
||||||
if(isPlayer)
|
|
||||||
{
|
{
|
||||||
|
// TODO: Move this code to mwinput.
|
||||||
// Joystick analogue movement.
|
// Joystick analogue movement.
|
||||||
float xAxis = std::abs(cls.getMovementSettings(mPtr).mPosition[0]);
|
float xAxis = std::abs(movementSettings.mPosition[0]);
|
||||||
float yAxis = std::abs(cls.getMovementSettings(mPtr).mPosition[1]);
|
float yAxis = std::abs(movementSettings.mPosition[1]);
|
||||||
analogueMult = ((xAxis > yAxis) ? xAxis : yAxis);
|
analogueMult = std::max(xAxis, yAxis);
|
||||||
|
|
||||||
// If Strafing, our max speed is slower so multiply by X axis instead.
|
|
||||||
if(std::abs(vec.x()/2.0f) > std::abs(vec.y()))
|
|
||||||
analogueMult = xAxis;
|
|
||||||
|
|
||||||
// Due to the half way split between walking/running, we multiply speed by 2 while walking, unless a keyboard was used.
|
// Due to the half way split between walking/running, we multiply speed by 2 while walking, unless a keyboard was used.
|
||||||
if(!isrunning && !sneak && !flying && analogueMult <= 0.5f)
|
if(!isrunning && !sneak && !flying && analogueMult <= 0.5f)
|
||||||
analogueMult *= 2.f;
|
analogueMult *= 2.f;
|
||||||
|
|
||||||
|
movementSettings.mSpeedFactor = analogueMult;
|
||||||
}
|
}
|
||||||
|
|
||||||
speed *= analogueMult;
|
float effectiveRotation = rot.z();
|
||||||
|
static const bool turnToMovementDirection = Settings::Manager::getBool("turn to movement direction", "Game");
|
||||||
|
static const float turnToMovementDirectionSpeedCoef = Settings::Manager::getFloat("turn to movement direction speed coef", "Game");
|
||||||
|
if (turnToMovementDirection && !(isPlayer && MWBase::Environment::get().getWorld()->isFirstPerson()))
|
||||||
|
{
|
||||||
|
float targetMovementAngle = vec.y() >= 0 ? std::atan2(-vec.x(), vec.y()) : std::atan2(vec.x(), -vec.y());
|
||||||
|
movementSettings.mIsStrafing = (stats.getDrawState() != MWMechanics::DrawState_Nothing || inwater)
|
||||||
|
&& std::abs(targetMovementAngle) > osg::DegreesToRadians(60.0f);
|
||||||
|
if (movementSettings.mIsStrafing)
|
||||||
|
targetMovementAngle = 0;
|
||||||
|
float delta = targetMovementAngle - stats.getSideMovementAngle();
|
||||||
|
float cosDelta = cosf(delta);
|
||||||
|
movementSettings.mSpeedFactor *= std::min(std::max(cosDelta, 0.f) + 0.3f, 1.f); // slow down when turn
|
||||||
|
float maxDelta = turnToMovementDirectionSpeedCoef * osg::PI * duration * (2.5f - cosDelta);
|
||||||
|
delta = std::min(delta, maxDelta);
|
||||||
|
delta = std::max(delta, -maxDelta);
|
||||||
|
stats.setSideMovementAngle(stats.getSideMovementAngle() + delta);
|
||||||
|
effectiveRotation += delta;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
movementSettings.mIsStrafing = std::abs(vec.x()) > std::abs(vec.y()) * 2;
|
||||||
|
|
||||||
|
mAnimation->setLegsYawRadians(stats.getSideMovementAngle());
|
||||||
|
if (stats.getDrawState() == MWMechanics::DrawState_Nothing || inwater)
|
||||||
|
mAnimation->setUpperBodyYawRadians(stats.getSideMovementAngle() / 2);
|
||||||
|
else
|
||||||
|
mAnimation->setUpperBodyYawRadians(stats.getSideMovementAngle() / 4);
|
||||||
|
|
||||||
|
speed = cls.getSpeed(mPtr);
|
||||||
vec.x() *= speed;
|
vec.x() *= speed;
|
||||||
vec.y() *= speed;
|
vec.y() *= speed;
|
||||||
|
|
||||||
|
if(mHitState != CharState_None && mJumpState == JumpState_None)
|
||||||
|
vec = osg::Vec3f();
|
||||||
|
|
||||||
CharacterState movestate = CharState_None;
|
CharacterState movestate = CharState_None;
|
||||||
CharacterState idlestate = CharState_SpecialIdle;
|
CharacterState idlestate = CharState_SpecialIdle;
|
||||||
JumpingState jumpstate = JumpState_None;
|
JumpingState jumpstate = JumpState_None;
|
||||||
|
@ -2158,7 +2170,7 @@ void CharacterController::update(float duration, bool animationOnly)
|
||||||
|
|
||||||
inJump = false;
|
inJump = false;
|
||||||
|
|
||||||
if(std::abs(vec.x()/2.0f) > std::abs(vec.y()))
|
if (movementSettings.mIsStrafing)
|
||||||
{
|
{
|
||||||
if(vec.x() > 0.0f)
|
if(vec.x() > 0.0f)
|
||||||
movestate = (inwater ? (isrunning ? CharState_SwimRunRight : CharState_SwimWalkRight)
|
movestate = (inwater ? (isrunning ? CharState_SwimRunRight : CharState_SwimWalkRight)
|
||||||
|
@ -2169,18 +2181,18 @@ void CharacterController::update(float duration, bool animationOnly)
|
||||||
: (sneak ? CharState_SneakLeft
|
: (sneak ? CharState_SneakLeft
|
||||||
: (isrunning ? CharState_RunLeft : CharState_WalkLeft)));
|
: (isrunning ? CharState_RunLeft : CharState_WalkLeft)));
|
||||||
}
|
}
|
||||||
else if(vec.y() != 0.0f)
|
else if (vec.length2() > 0.0f)
|
||||||
{
|
{
|
||||||
if(vec.y() > 0.0f)
|
if (vec.y() >= 0.0f)
|
||||||
movestate = (inwater ? (isrunning ? CharState_SwimRunForward : CharState_SwimWalkForward)
|
movestate = (inwater ? (isrunning ? CharState_SwimRunForward : CharState_SwimWalkForward)
|
||||||
: (sneak ? CharState_SneakForward
|
: (sneak ? CharState_SneakForward
|
||||||
: (isrunning ? CharState_RunForward : CharState_WalkForward)));
|
: (isrunning ? CharState_RunForward : CharState_WalkForward)));
|
||||||
else if(vec.y() < 0.0f)
|
else
|
||||||
movestate = (inwater ? (isrunning ? CharState_SwimRunBack : CharState_SwimWalkBack)
|
movestate = (inwater ? (isrunning ? CharState_SwimRunBack : CharState_SwimWalkBack)
|
||||||
: (sneak ? CharState_SneakBack
|
: (sneak ? CharState_SneakBack
|
||||||
: (isrunning ? CharState_RunBack : CharState_WalkBack)));
|
: (isrunning ? CharState_RunBack : CharState_WalkBack)));
|
||||||
}
|
}
|
||||||
else if(rot.z() != 0.0f)
|
else if (effectiveRotation != 0.0f)
|
||||||
{
|
{
|
||||||
// Do not play turning animation for player if rotation speed is very slow.
|
// Do not play turning animation for player if rotation speed is very slow.
|
||||||
// Actual threshold should take framerate in account.
|
// Actual threshold should take framerate in account.
|
||||||
|
@ -2193,9 +2205,9 @@ void CharacterController::update(float duration, bool animationOnly)
|
||||||
bool isFirstPlayer = isPlayer && MWBase::Environment::get().getWorld()->isFirstPerson();
|
bool isFirstPlayer = isPlayer && MWBase::Environment::get().getWorld()->isFirstPerson();
|
||||||
if (!sneak && jumpstate == JumpState_None && !isFirstPlayer && mPtr.getClass().isBipedal(mPtr))
|
if (!sneak && jumpstate == JumpState_None && !isFirstPlayer && mPtr.getClass().isBipedal(mPtr))
|
||||||
{
|
{
|
||||||
if(rot.z() > rotationThreshold)
|
if(effectiveRotation > rotationThreshold)
|
||||||
movestate = inwater ? CharState_SwimTurnRight : CharState_TurnRight;
|
movestate = inwater ? CharState_SwimTurnRight : CharState_TurnRight;
|
||||||
else if(rot.z() < -rotationThreshold)
|
else if(effectiveRotation < -rotationThreshold)
|
||||||
movestate = inwater ? CharState_SwimTurnLeft : CharState_TurnLeft;
|
movestate = inwater ? CharState_SwimTurnLeft : CharState_TurnLeft;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2317,9 +2329,9 @@ void CharacterController::update(float duration, bool animationOnly)
|
||||||
world->queueMovement(mPtr, osg::Vec3f(0.f, 0.f, 0.f));
|
world->queueMovement(mPtr, osg::Vec3f(0.f, 0.f, 0.f));
|
||||||
|
|
||||||
movement = vec;
|
movement = vec;
|
||||||
cls.getMovementSettings(mPtr).mPosition[0] = cls.getMovementSettings(mPtr).mPosition[1] = 0;
|
movementSettings.mPosition[0] = movementSettings.mPosition[1] = 0;
|
||||||
if (movement.z() == 0.f)
|
if (movement.z() == 0.f)
|
||||||
cls.getMovementSettings(mPtr).mPosition[2] = 0;
|
movementSettings.mPosition[2] = 0;
|
||||||
// Can't reset jump state (mPosition[2]) here in full; we don't know for sure whether the PhysicSystem will actually handle it in this frame
|
// Can't reset jump state (mPosition[2]) here in full; we don't know for sure whether the PhysicSystem will actually handle it in this frame
|
||||||
// due to the fixed minimum timestep used for the physics update. It will be reset in PhysicSystem::move once the jump is handled.
|
// due to the fixed minimum timestep used for the physics update. It will be reset in PhysicSystem::move once the jump is handled.
|
||||||
|
|
||||||
|
@ -2355,15 +2367,11 @@ void CharacterController::update(float duration, bool animationOnly)
|
||||||
if(speed > 0.f)
|
if(speed > 0.f)
|
||||||
{
|
{
|
||||||
float l = moved.length();
|
float l = moved.length();
|
||||||
|
if (std::abs(movement.x() - moved.x()) > std::abs(moved.x()) / 2)
|
||||||
if((movement.x() < 0.0f && movement.x() < moved.x()*2.0f) ||
|
|
||||||
(movement.x() > 0.0f && movement.x() > moved.x()*2.0f))
|
|
||||||
moved.x() = movement.x();
|
moved.x() = movement.x();
|
||||||
if((movement.y() < 0.0f && movement.y() < moved.y()*2.0f) ||
|
if (std::abs(movement.y() - moved.y()) > std::abs(moved.y()) / 2)
|
||||||
(movement.y() > 0.0f && movement.y() > moved.y()*2.0f))
|
|
||||||
moved.y() = movement.y();
|
moved.y() = movement.y();
|
||||||
if((movement.z() < 0.0f && movement.z() < moved.z()*2.0f) ||
|
if (std::abs(movement.z() - moved.z()) > std::abs(moved.z()) / 2)
|
||||||
(movement.z() > 0.0f && movement.z() > moved.z()*2.0f))
|
|
||||||
moved.z() = movement.z();
|
moved.z() = movement.z();
|
||||||
// but keep the original speed
|
// but keep the original speed
|
||||||
float newLength = moved.length();
|
float newLength = moved.length();
|
||||||
|
|
|
@ -23,7 +23,7 @@ namespace MWMechanics
|
||||||
mKnockdown(false), mKnockdownOneFrame(false), mKnockdownOverOneFrame(false),
|
mKnockdown(false), mKnockdownOneFrame(false), mKnockdownOverOneFrame(false),
|
||||||
mHitRecovery(false), mBlock(false), mMovementFlags(0),
|
mHitRecovery(false), mBlock(false), mMovementFlags(0),
|
||||||
mFallHeight(0), mRecalcMagicka(false), mLastRestock(0,0), mGoldPool(0), mActorId(-1), mHitAttemptActorId(-1),
|
mFallHeight(0), mRecalcMagicka(false), mLastRestock(0,0), mGoldPool(0), mActorId(-1), mHitAttemptActorId(-1),
|
||||||
mDeathAnimation(-1), mTimeOfDeath(), mLevel (0)
|
mDeathAnimation(-1), mTimeOfDeath(), mSideMovementAngle(0), mLevel (0)
|
||||||
{
|
{
|
||||||
for (int i=0; i<4; ++i)
|
for (int i=0; i<4; ++i)
|
||||||
mAiSettings[i] = 0;
|
mAiSettings[i] = 0;
|
||||||
|
|
|
@ -80,6 +80,9 @@ namespace MWMechanics
|
||||||
|
|
||||||
MWWorld::TimeStamp mTimeOfDeath;
|
MWWorld::TimeStamp mTimeOfDeath;
|
||||||
|
|
||||||
|
// The difference between view direction and lower body direction.
|
||||||
|
float mSideMovementAngle;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef std::pair<int, std::string> SummonKey; // <ESM::MagicEffect index, spell ID>
|
typedef std::pair<int, std::string> SummonKey; // <ESM::MagicEffect index, spell ID>
|
||||||
private:
|
private:
|
||||||
|
@ -298,6 +301,9 @@ namespace MWMechanics
|
||||||
void addCorprusSpell(const std::string& sourceId, CorprusStats& stats);
|
void addCorprusSpell(const std::string& sourceId, CorprusStats& stats);
|
||||||
|
|
||||||
void removeCorprusSpell(const std::string& sourceId);
|
void removeCorprusSpell(const std::string& sourceId);
|
||||||
|
|
||||||
|
float getSideMovementAngle() const { return mSideMovementAngle; }
|
||||||
|
void setSideMovementAngle(float angle) { mSideMovementAngle = angle; }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,12 +11,14 @@ namespace MWMechanics
|
||||||
float mPosition[3];
|
float mPosition[3];
|
||||||
float mRotation[3];
|
float mRotation[3];
|
||||||
float mSpeedFactor;
|
float mSpeedFactor;
|
||||||
|
bool mIsStrafing;
|
||||||
|
|
||||||
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;
|
mSpeedFactor = 1.f;
|
||||||
|
mIsStrafing = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
osg::Vec3f asVec3()
|
osg::Vec3f asVec3()
|
||||||
|
|
|
@ -621,6 +621,8 @@ namespace MWRender
|
||||||
, mTextKeyListener(nullptr)
|
, mTextKeyListener(nullptr)
|
||||||
, mHeadYawRadians(0.f)
|
, mHeadYawRadians(0.f)
|
||||||
, mHeadPitchRadians(0.f)
|
, mHeadPitchRadians(0.f)
|
||||||
|
, mUpperBodyYawRadians(0.f)
|
||||||
|
, mLegsYawRadians(0.f)
|
||||||
, mHasMagicEffects(false)
|
, mHasMagicEffects(false)
|
||||||
, mAlpha(1.f)
|
, mAlpha(1.f)
|
||||||
{
|
{
|
||||||
|
@ -1334,13 +1336,36 @@ namespace MWRender
|
||||||
|
|
||||||
updateEffects();
|
updateEffects();
|
||||||
|
|
||||||
|
const float epsilon = 0.001f;
|
||||||
|
float yawOffset = 0;
|
||||||
|
if (mRootController)
|
||||||
|
{
|
||||||
|
bool enable = std::abs(mLegsYawRadians) > epsilon;
|
||||||
|
mRootController->setEnabled(enable);
|
||||||
|
if (enable)
|
||||||
|
{
|
||||||
|
mRootController->setRotate(osg::Quat(mLegsYawRadians, osg::Vec3f(0,0,1)));
|
||||||
|
yawOffset = mLegsYawRadians;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mSpineController)
|
||||||
|
{
|
||||||
|
float yaw = mUpperBodyYawRadians - yawOffset;
|
||||||
|
bool enable = std::abs(yaw) > epsilon;
|
||||||
|
mSpineController->setEnabled(enable);
|
||||||
|
if (enable)
|
||||||
|
{
|
||||||
|
mSpineController->setRotate(osg::Quat(yaw, osg::Vec3f(0,0,1)));
|
||||||
|
yawOffset = mUpperBodyYawRadians;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (mHeadController)
|
if (mHeadController)
|
||||||
{
|
{
|
||||||
const float epsilon = 0.001f;
|
float yaw = mHeadYawRadians - yawOffset;
|
||||||
bool enable = (std::abs(mHeadPitchRadians) > epsilon || std::abs(mHeadYawRadians) > epsilon);
|
bool enable = (std::abs(mHeadPitchRadians) > epsilon || std::abs(yaw) > epsilon);
|
||||||
mHeadController->setEnabled(enable);
|
mHeadController->setEnabled(enable);
|
||||||
if (enable)
|
if (enable)
|
||||||
mHeadController->setRotate(osg::Quat(mHeadPitchRadians, osg::Vec3f(1,0,0)) * osg::Quat(mHeadYawRadians, osg::Vec3f(0,0,1)));
|
mHeadController->setRotate(osg::Quat(mHeadPitchRadians, osg::Vec3f(1,0,0)) * osg::Quat(yaw, osg::Vec3f(0,0,1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scripted animations should not cause movement
|
// Scripted animations should not cause movement
|
||||||
|
@ -1801,13 +1826,17 @@ namespace MWRender
|
||||||
|
|
||||||
void Animation::addControllers()
|
void Animation::addControllers()
|
||||||
{
|
{
|
||||||
mHeadController = nullptr;
|
mHeadController = addRotateController("bip01 head");
|
||||||
|
mSpineController = addRotateController("bip01 spine1");
|
||||||
|
mRootController = addRotateController("bip01");
|
||||||
|
}
|
||||||
|
|
||||||
NodeMap::const_iterator found = getNodeMap().find("bip01 head");
|
RotateController* Animation::addRotateController(std::string bone)
|
||||||
if (found == getNodeMap().end())
|
{
|
||||||
return;
|
auto iter = getNodeMap().find(bone);
|
||||||
|
if (iter == getNodeMap().end())
|
||||||
osg::MatrixTransform* node = found->second;
|
return nullptr;
|
||||||
|
osg::MatrixTransform* node = iter->second;
|
||||||
|
|
||||||
bool foundKeyframeCtrl = false;
|
bool foundKeyframeCtrl = false;
|
||||||
osg::Callback* cb = node->getUpdateCallback();
|
osg::Callback* cb = node->getUpdateCallback();
|
||||||
|
@ -1820,13 +1849,15 @@ namespace MWRender
|
||||||
}
|
}
|
||||||
cb = cb->getNestedCallback();
|
cb = cb->getNestedCallback();
|
||||||
}
|
}
|
||||||
|
// Without KeyframeController the orientation will not be reseted each frame, so
|
||||||
|
// RotateController shouldn't be used for such nodes.
|
||||||
if (!foundKeyframeCtrl)
|
if (!foundKeyframeCtrl)
|
||||||
return;
|
return nullptr;
|
||||||
|
|
||||||
mHeadController = new RotateController(mObjectRoot.get());
|
RotateController* controller = new RotateController(mObjectRoot.get());
|
||||||
node->addUpdateCallback(mHeadController);
|
node->addUpdateCallback(controller);
|
||||||
mActiveControllers.emplace_back(node, mHeadController);
|
mActiveControllers.emplace_back(node, controller);
|
||||||
|
return controller;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Animation::setHeadPitch(float pitchRadians)
|
void Animation::setHeadPitch(float pitchRadians)
|
||||||
|
|
|
@ -267,8 +267,15 @@ protected:
|
||||||
TextKeyListener* mTextKeyListener;
|
TextKeyListener* mTextKeyListener;
|
||||||
|
|
||||||
osg::ref_ptr<RotateController> mHeadController;
|
osg::ref_ptr<RotateController> mHeadController;
|
||||||
|
osg::ref_ptr<RotateController> mSpineController;
|
||||||
|
osg::ref_ptr<RotateController> mRootController;
|
||||||
float mHeadYawRadians;
|
float mHeadYawRadians;
|
||||||
float mHeadPitchRadians;
|
float mHeadPitchRadians;
|
||||||
|
float mUpperBodyYawRadians;
|
||||||
|
float mLegsYawRadians;
|
||||||
|
|
||||||
|
RotateController* addRotateController(std::string bone);
|
||||||
|
|
||||||
bool mHasMagicEffects;
|
bool mHasMagicEffects;
|
||||||
|
|
||||||
osg::ref_ptr<SceneUtil::LightSource> mGlowLight;
|
osg::ref_ptr<SceneUtil::LightSource> mGlowLight;
|
||||||
|
@ -477,6 +484,12 @@ public:
|
||||||
virtual void setHeadYaw(float yawRadians);
|
virtual void setHeadYaw(float yawRadians);
|
||||||
virtual float getHeadPitch() const;
|
virtual float getHeadPitch() const;
|
||||||
virtual float getHeadYaw() const;
|
virtual float getHeadYaw() const;
|
||||||
|
|
||||||
|
virtual void setUpperBodyYawRadians(float v) { mUpperBodyYawRadians = v; }
|
||||||
|
virtual void setLegsYawRadians(float v) { mLegsYawRadians = v; }
|
||||||
|
virtual float getUpperBodyYawRadians() const { return mUpperBodyYawRadians; }
|
||||||
|
virtual float getLegsYawRadians() const { return mLegsYawRadians; }
|
||||||
|
|
||||||
virtual void setAccurateAiming(bool enabled) {}
|
virtual void setAccurateAiming(bool enabled) {}
|
||||||
virtual bool canBeHarvested() const { return false; }
|
virtual bool canBeHarvested() const { return false; }
|
||||||
|
|
||||||
|
|
|
@ -244,6 +244,9 @@ namespace MWRender
|
||||||
else
|
else
|
||||||
mViewModeToggleQueued = false;
|
mViewModeToggleQueued = false;
|
||||||
|
|
||||||
|
if (mTrackingPtr.getClass().isActor())
|
||||||
|
mTrackingPtr.getClass().getCreatureStats(mTrackingPtr).setSideMovementAngle(0);
|
||||||
|
|
||||||
mFirstPersonView = !mFirstPersonView;
|
mFirstPersonView = !mFirstPersonView;
|
||||||
processViewChange();
|
processViewChange();
|
||||||
}
|
}
|
||||||
|
|
|
@ -302,6 +302,12 @@ projectiles enchant multiplier = 0
|
||||||
# This means that unlike Morrowind you will be able to knock down actors using this effect.
|
# This means that unlike Morrowind you will be able to knock down actors using this effect.
|
||||||
uncapped damage fatigue = false
|
uncapped damage fatigue = false
|
||||||
|
|
||||||
|
# Turn lower body to movement direction. 'true' makes diagonal movement more realistic.
|
||||||
|
turn to movement direction = false
|
||||||
|
|
||||||
|
# Turning speed multiplier. Makes difference only if 'turn to movement direction' is enabled.
|
||||||
|
turn to movement direction speed coef = 1.0
|
||||||
|
|
||||||
[General]
|
[General]
|
||||||
|
|
||||||
# Anisotropy reduces distortion in textures at low angles (e.g. 0 to 16).
|
# Anisotropy reduces distortion in textures at low angles (e.g. 0 to 16).
|
||||||
|
|
Loading…
Reference in a new issue