This commit is contained in:
David Markowitz 2023-08-03 01:50:34 -07:00
parent c293b7a9d7
commit 2252088e1b
3 changed files with 184 additions and 17 deletions

View File

@ -27,7 +27,7 @@ PlatformSubComponent::PlatformSubComponent(MovingPlatformComponent* parentCompon
m_InReverse = false;
m_ShouldStopAtDesiredWaypoint = false;
m_PercentBetweenPoints = 0.0f;
m_PercentUntilNextWaypoint = 0.0f;
m_CurrentWaypointIndex = 0;
m_NextWaypointIndex = 0;
@ -35,6 +35,80 @@ PlatformSubComponent::PlatformSubComponent(MovingPlatformComponent* parentCompon
m_IdleTimeElapsed = 0.0f;
}
void PlatformSubComponent::AdvanceToNextWaypoint() {
uint32_t numWaypoints = m_Path->pathWaypoints.size();
m_CurrentWaypointIndex = m_NextWaypointIndex;
uint32_t nextWaypointIndex = m_CurrentWaypointIndex;
if (numWaypoints <= nextWaypointIndex) {
PathBehavior behavior = m_Path->pathBehavior;
if (behavior == PathBehavior::Once) {
nextWaypointIndex = m_Path->pathWaypoints.size() - 1;
} else if (behavior == PathBehavior::Bounce) {
nextWaypointIndex = m_Path->pathWaypoints.size() - 2;
m_InReverse = true;
} else {
m_NextWaypointIndex = 0;
}
}
m_NextWaypointIndex = nextWaypointIndex;
}
void PlatformSubComponent::AdvanceToNextReverseWaypoint() {
uint32_t numWaypoints = m_Path->pathWaypoints.size();
m_CurrentWaypointIndex = m_NextWaypointIndex;
int32_t nextWaypointIndex = m_CurrentWaypointIndex;
if (nextWaypointIndex < 0) {
PathBehavior behavior = m_Path->pathBehavior;
if (behavior == PathBehavior::Once) {
nextWaypointIndex = 0;
} else if (behavior == PathBehavior::Bounce) {
nextWaypointIndex = 1;
m_InReverse = false;
} else {
nextWaypointIndex = m_Path->pathWaypoints.size() - 1;
}
}
m_NextWaypointIndex = nextWaypointIndex;
}
void PlatformSubComponent::SetupPath(const std::string& pathName, uint32_t startingWaypointIndex, bool startsInReverse) {
m_Path = Game::zoneManager->GetZone()->GetPath(pathName);
if (!m_Path) {
Game::logger->Log("MovingPlatformComponent", "Failed to find path (%s)", pathName.c_str());
return;
}
m_InReverse = startsInReverse;
m_CurrentWaypointIndex = startingWaypointIndex;
m_TimeBasedMovement = m_Path->movingPlatform.timeBasedMovement;
}
const PathWaypoint PlatformSubComponent::GetNextWaypoint() const {
DluAssert(m_Path != nullptr);
if (m_NextWaypointIndex >= m_Path->pathWaypoints.size()) return PathWaypoint();
return m_Path->pathWaypoints.at(m_NextWaypointIndex);
}
const PathWaypoint PlatformSubComponent::GetCurrentWaypoint() const {
DluAssert(m_Path != nullptr);
if (m_CurrentWaypointIndex >= m_Path->pathWaypoints.size()) return PathWaypoint();
return m_Path->pathWaypoints.at(m_CurrentWaypointIndex);
}
float PlatformSubComponent::CalculateSpeed() const {
float speed;
if (m_TimeBasedMovement) {
float unitizedDirection = 1.0f / (GetNextWaypoint().position - GetCurrentWaypoint().position).Length();
speed = unitizedDirection / GetCurrentWaypoint().movingPlatform.speed;
} else {
speed = (GetNextWaypoint().movingPlatform.speed - GetCurrentWaypoint().movingPlatform.speed) * m_PercentUntilNextWaypoint + GetCurrentWaypoint().movingPlatform.speed;
}
return speed;
}
NiPoint3 PlatformSubComponent::CalculateLinearVelocity() {
return (GetNextWaypoint().position - GetCurrentWaypoint().position).Unitize() * CalculateSpeed();
}
void PlatformSubComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) {
outBitStream->Write(bIsInitialUpdate || m_IsDirty);
if (!(bIsInitialUpdate || m_IsDirty)) return;
@ -42,7 +116,7 @@ void PlatformSubComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsIn
outBitStream->Write(m_DesiredWaypointIndex);
outBitStream->Write(m_ShouldStopAtDesiredWaypoint);
outBitStream->Write(m_InReverse);
outBitStream->Write(m_PercentBetweenPoints);
outBitStream->Write(m_PercentUntilNextWaypoint);
outBitStream->Write(m_Position.x);
outBitStream->Write(m_Position.y);
outBitStream->Write(m_Position.z);
@ -145,8 +219,6 @@ void SimpleMoverPlatformSubComponent::LoadConfigData() {
);
m_PlatformMove = platformMove;
m_MoveTime = m_ParentComponent->GetParent()->GetVar<float>(u"platformMoveTime");
// idk either. client does it!
m_StartAtEnd = m_ParentComponent->GetParent()->GetVar<uint32_t>(u"attached_path_start") != 0;
m_StartAtEnd = m_ParentComponent->GetParent()->GetVar<bool>(u"platformStartAtEnd");
}
@ -197,6 +269,8 @@ void MovingPlatformComponent::LoadConfigData() {
if (m_Parent->GetVar<bool>(u"platformIsRotater")) {
AddMovingPlatform<RotatorPlatformSubComponent>();
}
m_StartingWaypointIndex = m_Parent->GetVar<uint32_t>(u"attached_path_start");
m_StartsIsInReverse = false;
m_DirtyPathInfo = true;
}

View File

@ -15,6 +15,7 @@
#include "Component.h"
#include "eReplicaComponentType.h"
class PathWaypoint;
class Path;
/**
@ -54,10 +55,20 @@ public:
virtual void ResumePathing();
virtual void StopPathing();
virtual void Update(float deltaTime);
float CalculateSpeed() const;
const PathWaypoint GetNextWaypoint() const;
const PathWaypoint GetCurrentWaypoint() const;
void SetupPath(const std::string& pathName, uint32_t startingWaypointIndex, bool startsInReverse);
void AdvanceToNextWaypoint();
void AdvanceToNextReverseWaypoint();
NiPoint3 CalculateLinearVelocity();
protected:
#ifdef _MOVING_PLATFORM_TEST
public:
void _SetPath(const Path* path) {
m_Path = path;
}
#endif
MovingPlatformComponent* m_ParentComponent = nullptr;
@ -66,10 +77,10 @@ public:
*/
uint32_t m_State = eMovementPlatformState::Stopped | eMovementPlatformState::ReachedDesiredWaypoint;
int32_t m_DesiredWaypointIndex = 0;
float m_PercentBetweenPoints = 0;
float m_PercentUntilNextWaypoint = 0;
NiPoint3 m_Position;
uint32_t m_CurrentWaypointIndex;
uint32_t m_NextWaypointIndex;
int32_t m_CurrentWaypointIndex;
int32_t m_NextWaypointIndex;
float m_IdleTimeElapsed = 0;
float m_Speed = 0;
float m_WaitTime = 0;
@ -80,6 +91,7 @@ public:
NiPoint3 m_LinearVelocity;
NiPoint3 m_AngularVelocity;
bool m_TimeBasedMovement = false;
const Path* m_Path = nullptr;
};
class MoverPlatformSubComponent : public PlatformSubComponent {
@ -209,10 +221,10 @@ public:
static_assert(std::is_base_of<PlatformSubComponent, MovingPlatform>::value, "MovingPlatform must derive from PlatformSubComponent");
auto hasPlatform = std::find_if(m_Platforms.begin(), m_Platforms.end(), [](const std::unique_ptr<PlatformSubComponent>& platform) {
return platform->GetPlatformType() == MovingPlatform::SubComponentType;
}) != m_Platforms.end();
if (!hasPlatform) {
m_Platforms.push_back(std::make_unique<MovingPlatform>(this, std::forward<ConstructorValues>(arguments)...));
}
}) != m_Platforms.end();
if (!hasPlatform) {
m_Platforms.push_back(std::make_unique<MovingPlatform>(this, std::forward<ConstructorValues>(arguments)...));
}
}
int32_t GetComponentId() const { return componentId; }
@ -220,8 +232,8 @@ public:
#ifdef _MOVING_PLATFORM_TEST
/**
* Only used for testing. Do not call in production code. Let the constructor take care of this.
*
* @param platformSubComponent
*
* @param platformSubComponent
*/
void _AddPlatformSubComponent(std::unique_ptr<PlatformSubComponent> platformSubComponent) {
m_Platforms.push_back(std::move(platformSubComponent));
@ -230,7 +242,7 @@ public:
void _SetPath(const std::u16string& path) {
m_PathName = path;
m_DirtyPathInfo = true;
}
}
#endif
private:
/**

View File

@ -7,6 +7,7 @@
#define _MOVING_PLATFORM_TEST
#include "MovingPlatformComponent.h"
#undef _MOVING_PLATFORM_TEST
#include "Zone.h"
#include "SimplePhysicsComponent.h"
#include "eReplicaComponentType.h"
@ -15,8 +16,22 @@ protected:
std::unique_ptr<Entity> baseEntity;
CBITSTREAM;
uint32_t flags = 0;
Path path;
void SetUp() override {
SetUpDependencies();
path.movingPlatform.timeBasedMovement = false;
path.pathBehavior = PathBehavior::Once;
PathWaypoint waypointStart;
waypointStart.position = NiPoint3(1, 2, 3);
waypointStart.rotation = NiQuaternion(4, 5, 6, 7);
PathWaypoint waypointEnd;
waypointEnd.position = NiPoint3(4, 5, 6);
waypointEnd.rotation = NiQuaternion(7, 8, 9, 10);
path.pathWaypoints.push_back(waypointStart);
path.pathWaypoints.push_back(waypointEnd);
baseEntity = std::make_unique<Entity>(15, GameDependenciesTest::info);
baseEntity->SetVar<bool>(u"dbonly", false);
baseEntity->SetVar<float>(u"platformMoveX", 23);
@ -33,7 +48,7 @@ protected:
auto moverPlatformSubComponent = std::make_unique<MoverPlatformSubComponent>(movingPlatformComponent);
moverPlatformSubComponent->m_State = eMovementPlatformState::Stopped | eMovementPlatformState::ReachedDesiredWaypoint;
moverPlatformSubComponent->m_DesiredWaypointIndex = 1;
moverPlatformSubComponent->m_PercentBetweenPoints = 2;
moverPlatformSubComponent->m_PercentUntilNextWaypoint = 2;
moverPlatformSubComponent->m_Position = NiPoint3(3, 4, 5);
moverPlatformSubComponent->m_CurrentWaypointIndex = 6;
moverPlatformSubComponent->m_NextWaypointIndex = 7;
@ -46,7 +61,7 @@ protected:
auto rotatorPlatformSubComponent = std::make_unique<RotatorPlatformSubComponent>(movingPlatformComponent);
rotatorPlatformSubComponent->m_State = eMovementPlatformState::Travelling;
rotatorPlatformSubComponent->m_DesiredWaypointIndex = 12;
rotatorPlatformSubComponent->m_PercentBetweenPoints = 13;
rotatorPlatformSubComponent->m_PercentUntilNextWaypoint = 13;
rotatorPlatformSubComponent->m_Position = NiPoint3(14, 15, 16);
rotatorPlatformSubComponent->m_CurrentWaypointIndex = 17;
rotatorPlatformSubComponent->m_NextWaypointIndex = 18;
@ -59,7 +74,7 @@ protected:
auto simpleMoverPlatformSubComponent = std::make_unique<SimpleMoverPlatformSubComponent>(movingPlatformComponent, NiPoint3(), true);
simpleMoverPlatformSubComponent->m_State = eMovementPlatformState::Waiting | eMovementPlatformState::ReachedDesiredWaypoint | eMovementPlatformState::ReachedFinalWaypoint;
simpleMoverPlatformSubComponent->m_DesiredWaypointIndex = 23;
simpleMoverPlatformSubComponent->m_PercentBetweenPoints = 24;
simpleMoverPlatformSubComponent->m_PercentUntilNextWaypoint = 24;
simpleMoverPlatformSubComponent->m_CurrentWaypointIndex = 28;
simpleMoverPlatformSubComponent->m_NextWaypointIndex = 29;
simpleMoverPlatformSubComponent->m_IdleTimeElapsed = 30;
@ -280,3 +295,69 @@ TEST_F(MovingPlatformComponentTests, MovingPlatformConstructionTest) {
TEST_F(MovingPlatformComponentTests, MovingPlatformSerializationTest) {
TestSerialization();
}
TEST_F(MovingPlatformComponentTests, MovingPlatformSubComponentPathAdvanceForwardTest) {
MoverPlatformSubComponent moverPlatformSubComponent(nullptr);
moverPlatformSubComponent._SetPath(&path);
moverPlatformSubComponent.m_CurrentWaypointIndex = 0;
moverPlatformSubComponent.m_NextWaypointIndex = 1;
moverPlatformSubComponent.m_InReverse = false;
moverPlatformSubComponent.AdvanceToNextWaypoint();
ASSERT_EQ(moverPlatformSubComponent.m_CurrentWaypointIndex, 1);
ASSERT_EQ(moverPlatformSubComponent.m_NextWaypointIndex, 0);
ASSERT_FALSE(moverPlatformSubComponent.m_InReverse);
moverPlatformSubComponent.AdvanceToNextWaypoint();
ASSERT_EQ(moverPlatformSubComponent.m_CurrentWaypointIndex, 1);
ASSERT_EQ(moverPlatformSubComponent.m_NextWaypointIndex, 0);
ASSERT_FALSE(moverPlatformSubComponent.m_InReverse);
path.pathBehavior = PathBehavior::Bounce;
moverPlatformSubComponent.AdvanceToNextWaypoint();
ASSERT_EQ(moverPlatformSubComponent.m_CurrentWaypointIndex, 0);
ASSERT_EQ(moverPlatformSubComponent.m_NextWaypointIndex, 1);
ASSERT_TRUE(moverPlatformSubComponent.m_InReverse);
}
TEST_F(MovingPlatformComponentTests, MovingPlatformSubComponentPathAdvanceReverseTest) {
MoverPlatformSubComponent moverPlatformSubComponent(nullptr);
moverPlatformSubComponent._SetPath(&path);
moverPlatformSubComponent.m_CurrentWaypointIndex = 1;
moverPlatformSubComponent.m_NextWaypointIndex = 0;
moverPlatformSubComponent.m_InReverse = true;
moverPlatformSubComponent.AdvanceToNextReverseWaypoint();
ASSERT_EQ(moverPlatformSubComponent.m_CurrentWaypointIndex, 0);
ASSERT_EQ(moverPlatformSubComponent.m_NextWaypointIndex, 0);
ASSERT_TRUE(moverPlatformSubComponent.m_InReverse);
path.pathBehavior = PathBehavior::Bounce;
moverPlatformSubComponent.m_CurrentWaypointIndex = 1;
moverPlatformSubComponent.m_NextWaypointIndex = 0;
moverPlatformSubComponent.AdvanceToNextReverseWaypoint();
ASSERT_EQ(moverPlatformSubComponent.m_CurrentWaypointIndex, 0);
ASSERT_EQ(moverPlatformSubComponent.m_NextWaypointIndex, 1);
ASSERT_TRUE(moverPlatformSubComponent.m_InReverse);
moverPlatformSubComponent.AdvanceToNextReverseWaypoint();
ASSERT_EQ(moverPlatformSubComponent.m_CurrentWaypointIndex, 1);
ASSERT_EQ(moverPlatformSubComponent.m_NextWaypointIndex, 0);
ASSERT_FALSE(moverPlatformSubComponent.m_InReverse);
}
TEST_F(MovingPlatformComponentTests, MovingPlatformMoverSpeedCalculationTest) {
MoverPlatformSubComponent moverPlatformSubComponent(nullptr);
path.pathWaypoints.at(0).position = NiPoint3(99.296440, 419.293335, 207.219498);
path.pathWaypoints.at(0).movingPlatform.speed = 16.0f;
path.pathWaypoints.at(1).position = NiPoint3(141.680099, 419.990051, 208.680450);
path.pathWaypoints.at(1).movingPlatform.speed = 16.0f;
path.pathBehavior = PathBehavior::Bounce;
moverPlatformSubComponent._SetPath(&path);
moverPlatformSubComponent.m_Speed = 16.0f;
moverPlatformSubComponent.m_TimeBasedMovement = false;
moverPlatformSubComponent.m_InReverse = false;
moverPlatformSubComponent.m_CurrentWaypointIndex = 0;
moverPlatformSubComponent.m_NextWaypointIndex = 1;
ASSERT_EQ(moverPlatformSubComponent.CalculateSpeed(), 16.0f);
NiPoint3 r = moverPlatformSubComponent.CalculateLinearVelocity();
ASSERT_FLOAT_EQ(r.x, 15.988346099854);
ASSERT_FLOAT_EQ(r.y, 0.26282161474228);
ASSERT_FLOAT_EQ(r.z, 0.5511137843132);
moverPlatformSubComponent.AdvanceToNextWaypoint();
}