go home works

This commit is contained in:
David Markowitz
2026-09-26 22:37:34 -07:00
parent 59f74e2dd5
commit 1a27ecb59d
4 changed files with 65 additions and 1 deletions

View File

@@ -78,6 +78,12 @@ bool ModelComponent::OnRequestUse(GameMessages::RequestUse& requestUse) {
void ModelComponent::Update(float deltaTime) {
if (m_IsPaused) return;
// Arrived once this frame's movement reached or passed the target
if (m_Move.target && (*m_Move.target - m_Parent->GetPosition()).DotProduct(m_Move.targetDirection) <= 0.0f) {
m_Parent->SetPosition(*m_Move.target);
m_Move.target.reset();
}
for (auto& behavior : m_Behaviors) {
behavior.Update(deltaTime, *this);
}
@@ -297,6 +303,7 @@ bool ModelComponent::TryStartMove(const int axis, const float direction, const f
if (axis < 0 || axis > 2 || direction == 0.0f || speed <= 0.0f) return false;
if (m_Move.velocity[axis] != 0.0f) return false;
m_Move.target.reset();
m_Move.velocity[axis] = std::copysign(speed, direction);
return true;
}
@@ -306,6 +313,13 @@ void ModelComponent::StopMove(const int axis) {
m_Move.velocity[axis] = 0.0f;
}
void ModelComponent::StartMoveTo(const NiPoint3& target, const float speed) {
m_Move.velocity = NiPoint3Constant::ZERO;
m_Move.interruptCount++;
m_Move.target = target;
m_Move.targetSpeed = speed;
}
void ModelComponent::SyncLinearVelocity() {
const auto& rotation = m_Parent->GetRotation();
m_Move.basis = { QuatUtils::Right(rotation), QuatUtils::Up(rotation), QuatUtils::Forward(rotation) };
@@ -313,6 +327,13 @@ void ModelComponent::SyncLinearVelocity() {
NiPoint3 velocity = NiPoint3Constant::ZERO;
for (int axis = 0; axis < 3; axis++) velocity += m_Move.basis[axis] * m_Move.velocity[axis];
if (m_Move.target) {
const auto toTarget = *m_Move.target - m_Parent->GetPosition();
const float distance = toTarget.Length();
m_Move.targetDirection = distance > 0.0f ? toTarget / distance : NiPoint3Constant::ZERO;
velocity += m_Move.targetDirection * m_Move.targetSpeed;
}
// Leave velocity alone unless a move owns it, e.g. pets are driven elsewhere
const bool isMoving = velocity != NiPoint3Constant::ZERO;
if (!isMoving && !m_Move.wasMoving) return;

View File

@@ -3,6 +3,7 @@
#include <array>
#include <cmath>
#include <map>
#include <optional>
#include "dCommonVars.h"
#include "RakNetTypes.h"
@@ -141,7 +142,7 @@ public:
void Resume();
// 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.
// Returns false if the axis is already controlled by a behavior. Cancels any active StartMoveTo.
bool TryStartMove(const int axis, const float direction, const float speed);
// Releases the local axis so another behavior can move along it.
@@ -150,6 +151,15 @@ public:
// World space direction of the local axis used for the most recently applied velocity.
const NiPoint3& GetMoveAxis(const int axis) const { return m_Move.basis[axis]; }
// Interrupts all active moves and moves in a straight line to target at speed units per second.
void StartMoveTo(const NiPoint3& target, const float speed);
// Whether a StartMoveTo move has yet to arrive or be overridden.
bool IsMovingToTarget() const noexcept { return m_Move.target.has_value(); }
// Changes whenever active moves are interrupted, so strips can tell their move was cancelled.
uint32_t GetMoveInterruptCount() const noexcept { return m_Move.interruptCount; }
// 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, const float speed);
@@ -204,6 +214,18 @@ private:
// Whether the last velocity update came from an active move
bool wasMoving{ false };
// World position of an active StartMoveTo move
std::optional<NiPoint3> target;
// Units per second of the move to target
float targetSpeed{};
// Direction to target as of the last velocity update, zero once there
NiPoint3 targetDirection{};
// Incremented each time StartMoveTo interrupts the active moves
uint32_t interruptCount{};
};
// Sends the client-side angular velocity for the currently active rotation axes.

View File

@@ -111,6 +111,7 @@ void Strip::HandleMsg(GameMessages::ResetModelToDefaults& msg) {
m_RotationProgress = 0.0f;
m_Speed = DEFAULT_SPEED;
m_PausedFromOnTimer = false;
m_MovingToStart = false;
}
void Strip::OnChatMessageReceived(const std::string& sMessage) {
@@ -180,6 +181,7 @@ void Strip::ProcNormalAction(float deltaTime, ModelComponent& modelComponent, Up
const bool isMoveLeft = nextActionType == "MoveLeft";
if (modelComponent.TryStartMove(0, isMoveLeft ? -1.0f : 1.0f, m_Speed)) {
m_PreviousFramePosition = entity.GetPosition();
m_MoveInterruptCount = modelComponent.GetMoveInterruptCount();
m_InActionTranslation.x = isMoveLeft ? -number : number;
}
} else if (nextActionType == "FlyUp" || nextActionType == "FlyDown") {
@@ -187,6 +189,7 @@ void Strip::ProcNormalAction(float deltaTime, ModelComponent& modelComponent, Up
const bool isFlyDown = nextActionType == "FlyDown";
if (modelComponent.TryStartMove(1, isFlyDown ? -1.0f : 1.0f, m_Speed)) {
m_PreviousFramePosition = entity.GetPosition();
m_MoveInterruptCount = modelComponent.GetMoveInterruptCount();
m_InActionTranslation.y = isFlyDown ? -number : number;
}
} else if (nextActionType == "MoveForward" || nextActionType == "MoveBackward") {
@@ -194,6 +197,7 @@ void Strip::ProcNormalAction(float deltaTime, ModelComponent& modelComponent, Up
const bool isMoveBackward = nextActionType == "MoveBackward";
if (modelComponent.TryStartMove(2, isMoveBackward ? -1.0f : 1.0f, m_Speed)) {
m_PreviousFramePosition = entity.GetPosition();
m_MoveInterruptCount = modelComponent.GetMoveInterruptCount();
m_InActionTranslation.z = isMoveBackward ? -number : number;
}
}
@@ -228,6 +232,9 @@ void Strip::ProcNormalAction(float deltaTime, ModelComponent& modelComponent, Up
else if (nextActionType == "SetSpeed") {
// Floored so a move or rotation can never stall forever
m_Speed = std::max(static_cast<float>(number), MIN_SPEED);
} else if (nextActionType == "MoveBackToStart") {
modelComponent.StartMoveTo(modelComponent.GetOriginalPosition(), m_Speed);
m_MovingToStart = true;
}
/* END Navigation */
@@ -325,6 +332,14 @@ void Strip::RemoveStates(ModelComponent& modelComponent) const {
}
bool Strip::CheckMovement(float deltaTime, ModelComponent& modelComponent) {
if (m_MovingToStart) {
if (modelComponent.IsMovingToTarget()) return false;
m_MovingToStart = false;
}
// A MoveBackToStart cancelled our move, so skip to the next action
if (m_MoveInterruptCount != modelComponent.GetMoveInterruptCount()) m_InActionTranslation = NiPoint3Constant::ZERO;
auto& entity = *modelComponent.GetParent();
const auto& currentPos = entity.GetPosition();
const auto diff = currentPos - m_PreviousFramePosition;

View File

@@ -79,6 +79,12 @@ private:
// The signed degrees the current rotation action has progressed so far
float m_RotationProgress{ 0.0f };
// Whether this strip is waiting on a MoveBackToStart to arrive
bool m_MovingToStart{ false };
// The model's move interrupt count when this strip's current move started
uint32_t m_MoveInterruptCount{};
static constexpr float DEFAULT_SPEED = 3.0f;
static constexpr float MIN_SPEED = 0.1f;