mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-10-15 09:04:10 +00:00
feat: make directional movements based on model rotation and not world axes
This commit is contained in:
@@ -46,6 +46,9 @@ 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;
|
||||
SyncLinearVelocity();
|
||||
ResetRotationState(m_Parent->GetRotation());
|
||||
|
||||
m_Speed = 3.0f;
|
||||
@@ -81,6 +84,9 @@ void ModelComponent::Update(float deltaTime) {
|
||||
behavior.Update(deltaTime, *this);
|
||||
}
|
||||
|
||||
// Done after all behaviors so the heading reflects any rotation applied this frame
|
||||
SyncLinearVelocity();
|
||||
|
||||
if (!m_RestartAtEndOfFrame) return;
|
||||
|
||||
GameMessages::ResetModelToDefaults reset{};
|
||||
@@ -289,32 +295,33 @@ void ModelComponent::RemoveUnSmash() {
|
||||
m_NumActiveUnSmash--;
|
||||
}
|
||||
|
||||
bool ModelComponent::TrySetVelocity(const NiPoint3& velocity) const {
|
||||
auto currentVelocity = m_Parent->GetVelocity();
|
||||
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;
|
||||
|
||||
// If we're currently moving on an axis, prevent the move so only 1 behavior can have control over an axis
|
||||
if (velocity != NiPoint3Constant::ZERO) {
|
||||
const auto [x, y, z] = velocity * m_Speed;
|
||||
if (x != 0.0f) {
|
||||
if (currentVelocity.x != 0.0f) return false;
|
||||
currentVelocity.x = x;
|
||||
} else if (y != 0.0f) {
|
||||
if (currentVelocity.y != 0.0f) return false;
|
||||
currentVelocity.y = y;
|
||||
} else if (z != 0.0f) {
|
||||
if (currentVelocity.z != 0.0f) return false;
|
||||
currentVelocity.z = z;
|
||||
}
|
||||
} else {
|
||||
currentVelocity = velocity;
|
||||
}
|
||||
|
||||
m_Parent->SetVelocity(currentVelocity);
|
||||
m_MoveDirection[axis] = direction > 0.0f ? 1.0f : -1.0f;
|
||||
return true;
|
||||
}
|
||||
|
||||
void ModelComponent::SetVelocity(const NiPoint3& velocity) const {
|
||||
m_Parent->SetVelocity(velocity);
|
||||
void ModelComponent::StopMove(const int axis) {
|
||||
if (axis < 0 || axis > 2) return;
|
||||
m_MoveDirection[axis] = 0.0f;
|
||||
}
|
||||
|
||||
void ModelComponent::SyncLinearVelocity() {
|
||||
const auto& rotation = m_Parent->GetRotation();
|
||||
m_MoveBasis = { 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);
|
||||
|
||||
// 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;
|
||||
|
||||
// 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) {
|
||||
|
||||
@@ -139,13 +139,15 @@ public:
|
||||
|
||||
void Resume();
|
||||
|
||||
// Attempts to set the velocity of an axis for movement.
|
||||
// If the axis currently has a velocity of zero, returns true.
|
||||
// If the axis is currently controlled by a behavior, returns false.
|
||||
bool TrySetVelocity(const NiPoint3& velocity) const;
|
||||
// Attempts to claim a local axis (0 = right, 1 = up, 2 = forward) for movement in direction (+1 or -1).
|
||||
// Returns false if the axis is already controlled by a behavior.
|
||||
bool TryStartMove(const int axis, const float direction);
|
||||
|
||||
// Force sets the velocity to a value.
|
||||
void SetVelocity(const NiPoint3& velocity) const;
|
||||
// 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]; }
|
||||
|
||||
// Attempts to claim a world axis (0 = x, 1 = y, 2 = z) for rotation in direction (+1 or -1).
|
||||
// Returns false if the axis is already controlled by a behavior.
|
||||
@@ -186,6 +188,9 @@ private:
|
||||
// Sends the client-side angular velocity for the currently active rotation axes.
|
||||
void SyncAngularVelocity() const;
|
||||
|
||||
// Recomputes the linear velocity from the active move axes and the current rotation.
|
||||
void SyncLinearVelocity();
|
||||
|
||||
// Clears all rotation state and makes rotation relative to newBase.
|
||||
void ResetRotationState(const NiQuaternion& newBase);
|
||||
|
||||
@@ -248,4 +253,13 @@ private:
|
||||
|
||||
// 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 };
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user