mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-10-08 22:03:43 +00:00
poggers rotation on the strip
This commit is contained in:
@@ -46,12 +46,10 @@ bool ModelComponent::OnResetModelToDefaults(GameMessages::ResetModelToDefaults&
|
||||
if (reset.bResetPos) m_Parent->SetPosition(m_OriginalPosition);
|
||||
if (reset.bResetRot) m_Parent->SetRotation(m_OriginalRotation);
|
||||
m_Parent->SetVelocity(NiPoint3Constant::ZERO);
|
||||
m_MoveDirection = NiPoint3Constant::ZERO;
|
||||
m_WasMoving = false;
|
||||
m_Move = MoveState{};
|
||||
SyncLinearVelocity();
|
||||
ResetRotationState(m_Parent->GetRotation());
|
||||
|
||||
m_Speed = 3.0f;
|
||||
m_NumListeningInteract = 0;
|
||||
|
||||
m_NumActiveAttack = 0;
|
||||
@@ -295,85 +293,77 @@ void ModelComponent::RemoveUnSmash() {
|
||||
m_NumActiveUnSmash--;
|
||||
}
|
||||
|
||||
bool ModelComponent::TryStartMove(const int axis, const float direction) {
|
||||
if (axis < 0 || axis > 2 || direction == 0.0f) return false;
|
||||
if (m_MoveDirection[axis] != 0.0f) return false;
|
||||
bool ModelComponent::TryStartMove(const int axis, const float direction, const float speed) {
|
||||
if (axis < 0 || axis > 2 || direction == 0.0f || speed <= 0.0f) return false;
|
||||
if (m_Move.velocity[axis] != 0.0f) return false;
|
||||
|
||||
m_MoveDirection[axis] = direction > 0.0f ? 1.0f : -1.0f;
|
||||
m_Move.velocity[axis] = std::copysign(speed, direction);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ModelComponent::StopMove(const int axis) {
|
||||
if (axis < 0 || axis > 2) return;
|
||||
m_MoveDirection[axis] = 0.0f;
|
||||
m_Move.velocity[axis] = 0.0f;
|
||||
}
|
||||
|
||||
void ModelComponent::SyncLinearVelocity() {
|
||||
const auto& rotation = m_Parent->GetRotation();
|
||||
m_MoveBasis = { QuatUtils::Right(rotation), QuatUtils::Up(rotation), QuatUtils::Forward(rotation) };
|
||||
m_Move.basis = { QuatUtils::Right(rotation), QuatUtils::Up(rotation), QuatUtils::Forward(rotation) };
|
||||
|
||||
NiPoint3 velocity = NiPoint3Constant::ZERO;
|
||||
for (int axis = 0; axis < 3; axis++) velocity += m_MoveBasis[axis] * (m_MoveDirection[axis] * m_Speed);
|
||||
for (int axis = 0; axis < 3; axis++) velocity += m_Move.basis[axis] * m_Move.velocity[axis];
|
||||
|
||||
// Leave velocity alone unless a move owns it, e.g. pets are driven elsewhere
|
||||
const bool isMoving = velocity != NiPoint3Constant::ZERO;
|
||||
if (!isMoving && !m_WasMoving) return;
|
||||
m_WasMoving = isMoving;
|
||||
if (!isMoving && !m_Move.wasMoving) return;
|
||||
m_Move.wasMoving = isMoving;
|
||||
|
||||
// Setting velocity always marks it dirty for serialization
|
||||
if (velocity != m_Parent->GetVelocity()) m_Parent->SetVelocity(velocity);
|
||||
}
|
||||
|
||||
bool ModelComponent::TryStartRotation(const int axis, const float direction) {
|
||||
if (axis < 0 || axis > 2 || direction == 0.0f) return false;
|
||||
if (m_RotationDirection[axis] != 0.0f) return false;
|
||||
bool ModelComponent::TryStartRotation(const int axis, const float direction, const float speed) {
|
||||
if (axis < 0 || axis > 2 || direction == 0.0f || speed <= 0.0f) return false;
|
||||
if (m_Rotation.velocity[axis] != 0.0f) return false;
|
||||
|
||||
// Rebase only when nothing is rotating so simultaneous rotations stay relative to the same base
|
||||
if (m_RotationDirection == NiPoint3Constant::ZERO) ResetRotationState(m_Parent->GetRotation());
|
||||
if (m_Rotation.velocity == NiPoint3Constant::ZERO) ResetRotationState(m_Parent->GetRotation());
|
||||
|
||||
m_RotationDegrees[axis] = std::fmod(m_RotationDegrees[axis], 360.0f);
|
||||
m_RotationActionStart[axis] = m_RotationDegrees[axis];
|
||||
m_RotationDirection[axis] = direction > 0.0f ? 1.0f : -1.0f;
|
||||
m_Rotation.degrees[axis] = std::fmod(m_Rotation.degrees[axis], 360.0f);
|
||||
m_Rotation.actionStart[axis] = m_Rotation.degrees[axis];
|
||||
m_Rotation.velocity[axis] = std::copysign(BASE_ANGULAR_SPEED * speed, direction);
|
||||
SyncAngularVelocity();
|
||||
return true;
|
||||
}
|
||||
|
||||
void ModelComponent::SetRotationProgress(const int axis, const float degrees) {
|
||||
if (axis < 0 || axis > 2) return;
|
||||
m_RotationDegrees[axis] = m_RotationActionStart[axis] + degrees;
|
||||
m_Rotation.degrees[axis] = m_Rotation.actionStart[axis] + degrees;
|
||||
|
||||
// Whole turns wrap to exactly 0 so e.g. 720 degrees yields exactly the base rotation
|
||||
const NiPoint3 radians(
|
||||
Math::DegToRad(std::fmod(m_RotationDegrees.x, 360.0f)),
|
||||
Math::DegToRad(std::fmod(m_RotationDegrees.y, 360.0f)),
|
||||
Math::DegToRad(std::fmod(m_RotationDegrees.z, 360.0f))
|
||||
Math::DegToRad(std::fmod(m_Rotation.degrees.x, 360.0f)),
|
||||
Math::DegToRad(std::fmod(m_Rotation.degrees.y, 360.0f)),
|
||||
Math::DegToRad(std::fmod(m_Rotation.degrees.z, 360.0f))
|
||||
);
|
||||
m_Parent->SetRotation(QuatUtils::FromEuler(radians) * m_RotationBase);
|
||||
m_Parent->SetRotation(QuatUtils::FromEuler(radians) * m_Rotation.base);
|
||||
}
|
||||
|
||||
void ModelComponent::StopRotation(const int axis) {
|
||||
if (axis < 0 || axis > 2) return;
|
||||
m_RotationDirection[axis] = 0.0f;
|
||||
m_Rotation.velocity[axis] = 0.0f;
|
||||
SyncAngularVelocity();
|
||||
}
|
||||
|
||||
void ModelComponent::SetSpeed(const float newSpeed) {
|
||||
m_Speed = newSpeed;
|
||||
if (m_RotationDirection != NiPoint3Constant::ZERO) SyncAngularVelocity();
|
||||
}
|
||||
|
||||
void ModelComponent::SyncAngularVelocity() const {
|
||||
GameMessages::SetAngularVelocity setAngVel{};
|
||||
setAngVel.target = m_Parent->GetObjectID();
|
||||
setAngVel.angVelocity = m_RotationDirection * Math::DegToRad(GetAngularSpeed());
|
||||
setAngVel.angVelocity = m_Rotation.velocity * Math::DegToRad(1.0f);
|
||||
setAngVel.Send();
|
||||
}
|
||||
|
||||
void ModelComponent::ResetRotationState(const NiQuaternion& newBase) {
|
||||
m_RotationBase = newBase;
|
||||
m_RotationDegrees = NiPoint3Constant::ZERO;
|
||||
m_RotationActionStart = NiPoint3Constant::ZERO;
|
||||
m_RotationDirection = NiPoint3Constant::ZERO;
|
||||
m_Rotation = RotationState{ .base = newBase };
|
||||
SyncAngularVelocity();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
#include <map>
|
||||
|
||||
#include "dCommonVars.h"
|
||||
@@ -139,19 +140,19 @@ public:
|
||||
|
||||
void Resume();
|
||||
|
||||
// Attempts to claim a local axis (0 = right, 1 = up, 2 = forward) for movement in direction (+1 or -1).
|
||||
// Attempts to claim a local axis (0 = right, 1 = up, 2 = forward) for movement in direction (+1 or -1) at speed units per second.
|
||||
// Returns false if the axis is already controlled by a behavior.
|
||||
bool TryStartMove(const int axis, const float direction);
|
||||
bool TryStartMove(const int axis, const float direction, const float speed);
|
||||
|
||||
// Releases the local axis so another behavior can move along it.
|
||||
void StopMove(const int axis);
|
||||
|
||||
// World space direction of the local axis used for the most recently applied velocity.
|
||||
const NiPoint3& GetMoveAxis(const int axis) const { return m_MoveBasis[axis]; }
|
||||
const NiPoint3& GetMoveAxis(const int axis) const { return m_Move.basis[axis]; }
|
||||
|
||||
// Attempts to claim a world axis (0 = x, 1 = y, 2 = z) for rotation in direction (+1 or -1).
|
||||
// Attempts to claim a world axis (0 = x, 1 = y, 2 = z) for rotation in direction (+1 or -1) at the given behavior speed.
|
||||
// Returns false if the axis is already controlled by a behavior.
|
||||
bool TryStartRotation(const int axis, const float direction);
|
||||
bool TryStartRotation(const int axis, const float direction, const float speed);
|
||||
|
||||
// Sets how many signed degrees the active rotation on axis has progressed and updates the entity.
|
||||
void SetRotationProgress(const int axis, const float degrees);
|
||||
@@ -159,16 +160,13 @@ public:
|
||||
// Releases the axis so another behavior can rotate it.
|
||||
void StopRotation(const int axis);
|
||||
|
||||
// Degrees per second for rotation actions at the current speed.
|
||||
float GetAngularSpeed() const noexcept { return BASE_ANGULAR_SPEED * m_Speed; }
|
||||
// Degrees per second of the active rotation on axis.
|
||||
float GetAngularSpeed(const int axis) const noexcept { return std::abs(m_Rotation.velocity[axis]); }
|
||||
|
||||
void OnChatMessageReceived(const std::string& sMessage);
|
||||
|
||||
void OnHit();
|
||||
|
||||
// Sets the speed of the model
|
||||
void SetSpeed(const float newSpeed);
|
||||
|
||||
// Whether or not to restart at the end of the frame
|
||||
void RestartAtEndOfFrame() { m_RestartAtEndOfFrame = true; }
|
||||
|
||||
@@ -179,12 +177,35 @@ public:
|
||||
// Decrements the number of strips listening for an attack.
|
||||
// If this is the last strip removing an attack, it will reset the factions to the default of -1.
|
||||
void RemoveAttack();
|
||||
|
||||
float GetSpeed() const noexcept { return m_Speed; }
|
||||
private:
|
||||
// Degrees per second per unit of m_Speed
|
||||
// Degrees per second per unit of behavior speed
|
||||
static constexpr float BASE_ANGULAR_SPEED = 15.0f;
|
||||
|
||||
struct RotationState {
|
||||
// The rotation that degrees is applied on top of
|
||||
NiQuaternion base = QuatUtils::IDENTITY;
|
||||
|
||||
// Accumulated signed degrees per world axis since base was set
|
||||
NiPoint3 degrees{};
|
||||
|
||||
// degrees at the moment the current rotation on each axis started
|
||||
NiPoint3 actionStart{};
|
||||
|
||||
// Signed degrees per second per world axis. Non-zero means a behavior owns that axis.
|
||||
NiPoint3 velocity{};
|
||||
};
|
||||
|
||||
struct MoveState {
|
||||
// Signed units per second along local right, up and forward. Non-zero means a behavior owns that axis.
|
||||
NiPoint3 velocity{};
|
||||
|
||||
// Right, up and forward in world space as of the last velocity update
|
||||
std::array<NiPoint3, 3> basis{ NiPoint3Constant::UNIT_X, NiPoint3Constant::UNIT_Y, NiPoint3Constant::UNIT_Z };
|
||||
|
||||
// Whether the last velocity update came from an active move
|
||||
bool wasMoving{ false };
|
||||
};
|
||||
|
||||
// Sends the client-side angular velocity for the currently active rotation axes.
|
||||
void SyncAngularVelocity() const;
|
||||
|
||||
@@ -236,30 +257,10 @@ private:
|
||||
*/
|
||||
LWOOBJID m_userModelID;
|
||||
|
||||
// The speed at which this model moves
|
||||
float m_Speed{ 3.0f };
|
||||
|
||||
// Whether or not to restart at the end of the frame.
|
||||
bool m_RestartAtEndOfFrame{ false };
|
||||
|
||||
// The rotation that m_RotationDegrees is applied on top of
|
||||
NiQuaternion m_RotationBase = QuatUtils::IDENTITY;
|
||||
RotationState m_Rotation;
|
||||
|
||||
// Accumulated signed degrees per world axis since m_RotationBase was set
|
||||
NiPoint3 m_RotationDegrees{};
|
||||
|
||||
// m_RotationDegrees at the moment the current rotation on each axis started
|
||||
NiPoint3 m_RotationActionStart{};
|
||||
|
||||
// Per axis -1, 0 or 1. Non-zero means a behavior currently owns rotation on that axis.
|
||||
NiPoint3 m_RotationDirection{};
|
||||
|
||||
// Per local axis (right, up, forward) -1, 0 or 1. Non-zero means a behavior currently owns movement on that axis.
|
||||
NiPoint3 m_MoveDirection{};
|
||||
|
||||
// Right, up and forward in world space as of the last velocity update
|
||||
std::array<NiPoint3, 3> m_MoveBasis{ NiPoint3Constant::UNIT_X, NiPoint3Constant::UNIT_Y, NiPoint3Constant::UNIT_Z };
|
||||
|
||||
// Whether the last velocity update came from an active move
|
||||
bool m_WasMoving{ false };
|
||||
MoveState m_Move;
|
||||
};
|
||||
|
||||
@@ -109,6 +109,7 @@ void Strip::HandleMsg(GameMessages::ResetModelToDefaults& msg) {
|
||||
m_PreviousFramePosition = NiPoint3Constant::ZERO;
|
||||
m_InActionRotation = NiPoint3Constant::ZERO;
|
||||
m_RotationProgress = 0.0f;
|
||||
m_Speed = DEFAULT_SPEED;
|
||||
}
|
||||
|
||||
void Strip::OnChatMessageReceived(const std::string& sMessage) {
|
||||
@@ -176,21 +177,21 @@ void Strip::ProcNormalAction(float deltaTime, ModelComponent& modelComponent, Up
|
||||
if (nextActionType == "MoveRight" || nextActionType == "MoveLeft") {
|
||||
// Local right axis
|
||||
const bool isMoveLeft = nextActionType == "MoveLeft";
|
||||
if (modelComponent.TryStartMove(0, isMoveLeft ? -1.0f : 1.0f)) {
|
||||
if (modelComponent.TryStartMove(0, isMoveLeft ? -1.0f : 1.0f, m_Speed)) {
|
||||
m_PreviousFramePosition = entity.GetPosition();
|
||||
m_InActionTranslation.x = isMoveLeft ? -number : number;
|
||||
}
|
||||
} else if (nextActionType == "FlyUp" || nextActionType == "FlyDown") {
|
||||
// Local up axis
|
||||
const bool isFlyDown = nextActionType == "FlyDown";
|
||||
if (modelComponent.TryStartMove(1, isFlyDown ? -1.0f : 1.0f)) {
|
||||
if (modelComponent.TryStartMove(1, isFlyDown ? -1.0f : 1.0f, m_Speed)) {
|
||||
m_PreviousFramePosition = entity.GetPosition();
|
||||
m_InActionTranslation.y = isFlyDown ? -number : number;
|
||||
}
|
||||
} else if (nextActionType == "MoveForward" || nextActionType == "MoveBackward") {
|
||||
// Local forward axis
|
||||
const bool isMoveBackward = nextActionType == "MoveBackward";
|
||||
if (modelComponent.TryStartMove(2, isMoveBackward ? -1.0f : 1.0f)) {
|
||||
if (modelComponent.TryStartMove(2, isMoveBackward ? -1.0f : 1.0f, m_Speed)) {
|
||||
m_PreviousFramePosition = entity.GetPosition();
|
||||
m_InActionTranslation.z = isMoveBackward ? -number : number;
|
||||
}
|
||||
@@ -201,21 +202,21 @@ void Strip::ProcNormalAction(float deltaTime, ModelComponent& modelComponent, Up
|
||||
else if (nextActionType == "Spin" || nextActionType == "SpinNegative") {
|
||||
// Y axis
|
||||
const float direction = nextActionType == "SpinNegative" ? -1.0f : 1.0f;
|
||||
if (number != 0.0 && modelComponent.TryStartRotation(1, direction)) {
|
||||
if (number != 0.0 && modelComponent.TryStartRotation(1, direction, m_Speed)) {
|
||||
m_InActionRotation.y = direction * number;
|
||||
m_RotationProgress = 0.0f;
|
||||
}
|
||||
} else if (nextActionType == "Tilt" || nextActionType == "TiltNegative") {
|
||||
// X axis
|
||||
const float direction = nextActionType == "TiltNegative" ? -1.0f : 1.0f;
|
||||
if (number != 0.0 && modelComponent.TryStartRotation(0, direction)) {
|
||||
if (number != 0.0 && modelComponent.TryStartRotation(0, direction, m_Speed)) {
|
||||
m_InActionRotation.x = direction * number;
|
||||
m_RotationProgress = 0.0f;
|
||||
}
|
||||
} else if (nextActionType == "Roll" || nextActionType == "RollNegative") {
|
||||
// Z axis
|
||||
const float direction = nextActionType == "RollNegative" ? -1.0f : 1.0f;
|
||||
if (number != 0.0 && modelComponent.TryStartRotation(2, direction)) {
|
||||
if (number != 0.0 && modelComponent.TryStartRotation(2, direction, m_Speed)) {
|
||||
m_InActionRotation.z = direction * number;
|
||||
m_RotationProgress = 0.0f;
|
||||
}
|
||||
@@ -224,7 +225,8 @@ void Strip::ProcNormalAction(float deltaTime, ModelComponent& modelComponent, Up
|
||||
|
||||
/* BEGIN Navigation */
|
||||
else if (nextActionType == "SetSpeed") {
|
||||
modelComponent.SetSpeed(number);
|
||||
// Floored so a move or rotation can never stall forever
|
||||
m_Speed = std::max(static_cast<float>(number), MIN_SPEED);
|
||||
}
|
||||
/* END Navigation */
|
||||
|
||||
@@ -353,7 +355,7 @@ bool Strip::CheckRotation(float deltaTime, ModelComponent& modelComponent) {
|
||||
if (target == 0.0f) continue;
|
||||
|
||||
// Snapping to the target keeps the final angle exact regardless of speed or frame time
|
||||
const float step = modelComponent.GetAngularSpeed() * deltaTime;
|
||||
const float step = modelComponent.GetAngularSpeed(axis) * deltaTime;
|
||||
if (std::abs(target - m_RotationProgress) <= step) m_RotationProgress = target;
|
||||
else m_RotationProgress += std::copysign(step, target);
|
||||
|
||||
@@ -394,6 +396,7 @@ void Strip::Update(float deltaTime, ModelComponent& modelComponent, UpdateResult
|
||||
// Check for trigger blocks and if not a trigger block proc this blocks action
|
||||
if (m_NextActionIndex == 0) {
|
||||
LOG("Behavior strip started %s", nextAction.GetType().data());
|
||||
m_Speed = DEFAULT_SPEED;
|
||||
if (nextAction.GetType() == "OnInteract") {
|
||||
modelComponent.AddInteract();
|
||||
} else if (nextAction.GetType() == "OnChat") {
|
||||
|
||||
@@ -77,6 +77,12 @@ private:
|
||||
|
||||
// The signed degrees the current rotation action has progressed so far
|
||||
float m_RotationProgress{ 0.0f };
|
||||
|
||||
static constexpr float DEFAULT_SPEED = 3.0f;
|
||||
static constexpr float MIN_SPEED = 0.1f;
|
||||
|
||||
// Speed applied to moves and rotations started by this strip
|
||||
float m_Speed{ DEFAULT_SPEED };
|
||||
};
|
||||
|
||||
#endif //!__STRIP__H__
|
||||
|
||||
Reference in New Issue
Block a user