2021-12-05 17:54:36 +00:00
|
|
|
/*
|
|
|
|
* Darkflame Universe
|
|
|
|
* Copyright 2019
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "MovingPlatformComponent.h"
|
|
|
|
#include "BitStream.h"
|
|
|
|
#include "GeneralUtils.h"
|
|
|
|
#include "dZoneManager.h"
|
|
|
|
#include "EntityManager.h"
|
2023-10-21 23:31:55 +00:00
|
|
|
#include "Logger.h"
|
2021-12-05 17:54:36 +00:00
|
|
|
#include "GameMessages.h"
|
|
|
|
#include "CppScripts.h"
|
|
|
|
#include "SimplePhysicsComponent.h"
|
2023-01-07 05:17:05 +00:00
|
|
|
#include "Zone.h"
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
MoverSubComponent::MoverSubComponent(const NiPoint3& startPos) {
|
|
|
|
mPosition = {};
|
|
|
|
|
2023-01-07 05:17:05 +00:00
|
|
|
mState = eMovementPlatformState::Stopped;
|
2021-12-05 17:54:36 +00:00
|
|
|
mDesiredWaypointIndex = 0; // -1;
|
|
|
|
mInReverse = false;
|
|
|
|
mShouldStopAtDesiredWaypoint = false;
|
2022-07-25 02:26:51 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
mPercentBetweenPoints = 0.0f;
|
2022-07-25 02:26:51 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
mCurrentWaypointIndex = 0;
|
|
|
|
mNextWaypointIndex = 0; //mCurrentWaypointIndex + 1;
|
2022-07-25 02:26:51 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
mIdleTimeElapsed = 0.0f;
|
|
|
|
}
|
|
|
|
|
|
|
|
MoverSubComponent::~MoverSubComponent() = default;
|
|
|
|
|
2023-08-10 21:33:15 +00:00
|
|
|
void MoverSubComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) {
|
2021-12-05 17:54:36 +00:00
|
|
|
outBitStream->Write<bool>(true);
|
|
|
|
|
2023-12-28 04:18:20 +00:00
|
|
|
outBitStream->Write(mState);
|
2021-12-05 17:54:36 +00:00
|
|
|
outBitStream->Write<int32_t>(mDesiredWaypointIndex);
|
|
|
|
outBitStream->Write(mShouldStopAtDesiredWaypoint);
|
|
|
|
outBitStream->Write(mInReverse);
|
2022-07-25 02:26:51 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
outBitStream->Write<float_t>(mPercentBetweenPoints);
|
|
|
|
|
|
|
|
outBitStream->Write<float_t>(mPosition.x);
|
|
|
|
outBitStream->Write<float_t>(mPosition.y);
|
|
|
|
outBitStream->Write<float_t>(mPosition.z);
|
2022-07-25 02:26:51 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
outBitStream->Write<uint32_t>(mCurrentWaypointIndex);
|
|
|
|
outBitStream->Write<uint32_t>(mNextWaypointIndex);
|
2022-07-25 02:26:51 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
outBitStream->Write<float_t>(mIdleTimeElapsed);
|
|
|
|
outBitStream->Write<float_t>(0.0f); // Move time elapsed
|
|
|
|
}
|
|
|
|
|
|
|
|
//------------- MovingPlatformComponent below --------------
|
|
|
|
|
|
|
|
MovingPlatformComponent::MovingPlatformComponent(Entity* parent, const std::string& pathName) : Component(parent) {
|
|
|
|
m_MoverSubComponentType = eMoverSubComponentType::mover;
|
|
|
|
m_MoverSubComponent = new MoverSubComponent(m_Parent->GetDefaultPosition());
|
|
|
|
m_PathName = GeneralUtils::ASCIIToUTF16(pathName);
|
2023-07-17 22:55:33 +00:00
|
|
|
m_Path = Game::zoneManager->GetZone()->GetPath(pathName);
|
2021-12-05 17:54:36 +00:00
|
|
|
m_NoAutoStart = false;
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
if (m_Path == nullptr) {
|
2023-10-21 23:31:55 +00:00
|
|
|
LOG("Path not found: %s", pathName.c_str());
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
MovingPlatformComponent::~MovingPlatformComponent() {
|
|
|
|
delete static_cast<MoverSubComponent*>(m_MoverSubComponent);
|
|
|
|
}
|
|
|
|
|
2023-08-10 21:33:15 +00:00
|
|
|
void MovingPlatformComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) {
|
2021-12-05 17:54:36 +00:00
|
|
|
// Here we don't serialize the moving platform to let the client simulate the movement
|
2022-07-25 02:26:51 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
if (!m_Serialize) {
|
|
|
|
outBitStream->Write<bool>(false);
|
|
|
|
outBitStream->Write<bool>(false);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
outBitStream->Write<bool>(true);
|
|
|
|
|
|
|
|
auto hasPath = !m_PathingStopped && !m_PathName.empty();
|
|
|
|
outBitStream->Write(hasPath);
|
|
|
|
|
|
|
|
if (hasPath) {
|
|
|
|
// Is on rail
|
|
|
|
outBitStream->Write1();
|
2022-07-25 02:26:51 +00:00
|
|
|
|
2023-12-28 04:18:20 +00:00
|
|
|
outBitStream->Write<uint16_t>(m_PathName.size());
|
2021-12-05 17:54:36 +00:00
|
|
|
for (const auto& c : m_PathName) {
|
2023-12-28 04:18:20 +00:00
|
|
|
outBitStream->Write<uint16_t>(c);
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Starting point
|
|
|
|
outBitStream->Write<uint32_t>(0);
|
|
|
|
|
|
|
|
// Reverse
|
|
|
|
outBitStream->Write<bool>(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
const auto hasPlatform = m_MoverSubComponent != nullptr;
|
|
|
|
outBitStream->Write<bool>(hasPlatform);
|
|
|
|
|
|
|
|
if (hasPlatform) {
|
|
|
|
auto* mover = static_cast<MoverSubComponent*>(m_MoverSubComponent);
|
2023-12-28 04:18:20 +00:00
|
|
|
outBitStream->Write(m_MoverSubComponentType);
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
if (m_MoverSubComponentType == eMoverSubComponentType::simpleMover) {
|
|
|
|
// TODO
|
|
|
|
} else {
|
2023-08-10 21:33:15 +00:00
|
|
|
mover->Serialize(outBitStream, bIsInitialUpdate);
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void MovingPlatformComponent::OnRebuildInitilized() {
|
|
|
|
StopPathing();
|
|
|
|
}
|
|
|
|
|
|
|
|
void MovingPlatformComponent::OnCompleteRebuild() {
|
|
|
|
if (m_NoAutoStart)
|
|
|
|
return;
|
|
|
|
|
|
|
|
StartPathing();
|
|
|
|
}
|
|
|
|
|
2023-01-07 05:17:05 +00:00
|
|
|
void MovingPlatformComponent::SetMovementState(eMovementPlatformState value) {
|
2021-12-05 17:54:36 +00:00
|
|
|
auto* subComponent = static_cast<MoverSubComponent*>(m_MoverSubComponent);
|
|
|
|
|
|
|
|
subComponent->mState = value;
|
|
|
|
|
2023-07-15 20:56:33 +00:00
|
|
|
Game::entityManager->SerializeEntity(m_Parent);
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
2022-07-25 02:26:51 +00:00
|
|
|
void MovingPlatformComponent::GotoWaypoint(uint32_t index, bool stopAtWaypoint) {
|
2021-12-05 17:54:36 +00:00
|
|
|
auto* subComponent = static_cast<MoverSubComponent*>(m_MoverSubComponent);
|
2022-07-25 02:26:51 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
subComponent->mDesiredWaypointIndex = index;
|
|
|
|
subComponent->mNextWaypointIndex = index;
|
|
|
|
subComponent->mShouldStopAtDesiredWaypoint = stopAtWaypoint;
|
|
|
|
|
|
|
|
StartPathing();
|
|
|
|
}
|
|
|
|
|
2022-07-25 02:26:51 +00:00
|
|
|
void MovingPlatformComponent::StartPathing() {
|
2021-12-05 17:54:36 +00:00
|
|
|
//GameMessages::SendStartPathing(m_Parent);
|
|
|
|
m_PathingStopped = false;
|
2022-07-25 02:26:51 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
auto* subComponent = static_cast<MoverSubComponent*>(m_MoverSubComponent);
|
2022-07-25 02:26:51 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
subComponent->mShouldStopAtDesiredWaypoint = true;
|
2023-01-07 05:17:05 +00:00
|
|
|
subComponent->mState = eMovementPlatformState::Stationary;
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
NiPoint3 targetPosition;
|
|
|
|
|
|
|
|
if (m_Path != nullptr) {
|
|
|
|
const auto& currentWaypoint = m_Path->pathWaypoints[subComponent->mCurrentWaypointIndex];
|
|
|
|
const auto& nextWaypoint = m_Path->pathWaypoints[subComponent->mNextWaypointIndex];
|
|
|
|
|
|
|
|
subComponent->mPosition = currentWaypoint.position;
|
|
|
|
subComponent->mSpeed = currentWaypoint.movingPlatform.speed;
|
|
|
|
subComponent->mWaitTime = currentWaypoint.movingPlatform.wait;
|
|
|
|
|
|
|
|
targetPosition = nextWaypoint.position;
|
|
|
|
} else {
|
|
|
|
subComponent->mPosition = m_Parent->GetPosition();
|
|
|
|
subComponent->mSpeed = 1.0f;
|
|
|
|
subComponent->mWaitTime = 2.0f;
|
|
|
|
|
|
|
|
targetPosition = m_Parent->GetPosition() + NiPoint3(0.0f, 10.0f, 0.0f);
|
|
|
|
}
|
|
|
|
|
|
|
|
m_Parent->AddCallbackTimer(subComponent->mWaitTime, [this] {
|
2023-01-07 05:17:05 +00:00
|
|
|
SetMovementState(eMovementPlatformState::Moving);
|
2021-12-05 17:54:36 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
const auto travelTime = Vector3::Distance(targetPosition, subComponent->mPosition) / subComponent->mSpeed + 1.5f;
|
|
|
|
|
|
|
|
const auto travelNext = subComponent->mWaitTime + travelTime;
|
|
|
|
|
|
|
|
m_Parent->AddCallbackTimer(travelTime, [subComponent, this] {
|
|
|
|
for (CppScripts::Script* script : CppScripts::GetEntityScripts(m_Parent)) {
|
|
|
|
script->OnWaypointReached(m_Parent, subComponent->mNextWaypointIndex);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
m_Parent->AddCallbackTimer(travelNext, [this] {
|
|
|
|
ContinuePathing();
|
|
|
|
});
|
|
|
|
|
|
|
|
//GameMessages::SendPlatformResync(m_Parent, UNASSIGNED_SYSTEM_ADDRESS);
|
|
|
|
|
2023-07-15 20:56:33 +00:00
|
|
|
Game::entityManager->SerializeEntity(m_Parent);
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MovingPlatformComponent::ContinuePathing() {
|
|
|
|
auto* subComponent = static_cast<MoverSubComponent*>(m_MoverSubComponent);
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2023-01-07 05:17:05 +00:00
|
|
|
subComponent->mState = eMovementPlatformState::Stationary;
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
subComponent->mCurrentWaypointIndex = subComponent->mNextWaypointIndex;
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
NiPoint3 targetPosition;
|
|
|
|
uint32_t pathSize;
|
|
|
|
PathBehavior behavior;
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
if (m_Path != nullptr) {
|
|
|
|
const auto& currentWaypoint = m_Path->pathWaypoints[subComponent->mCurrentWaypointIndex];
|
|
|
|
const auto& nextWaypoint = m_Path->pathWaypoints[subComponent->mNextWaypointIndex];
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
subComponent->mPosition = currentWaypoint.position;
|
|
|
|
subComponent->mSpeed = currentWaypoint.movingPlatform.speed;
|
|
|
|
subComponent->mWaitTime = currentWaypoint.movingPlatform.wait; // + 2;
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
pathSize = m_Path->pathWaypoints.size() - 1;
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
behavior = static_cast<PathBehavior>(m_Path->pathBehavior);
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
targetPosition = nextWaypoint.position;
|
|
|
|
} else {
|
|
|
|
subComponent->mPosition = m_Parent->GetPosition();
|
|
|
|
subComponent->mSpeed = 1.0f;
|
|
|
|
subComponent->mWaitTime = 2.0f;
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
targetPosition = m_Parent->GetPosition() + NiPoint3(0.0f, 10.0f, 0.0f);
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
pathSize = 1;
|
|
|
|
behavior = PathBehavior::Loop;
|
|
|
|
}
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
if (m_Parent->GetLOT() == 9483) {
|
|
|
|
behavior = PathBehavior::Bounce;
|
|
|
|
} else {
|
|
|
|
return;
|
|
|
|
}
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
if (subComponent->mCurrentWaypointIndex >= pathSize) {
|
|
|
|
subComponent->mCurrentWaypointIndex = pathSize;
|
|
|
|
switch (behavior) {
|
|
|
|
case PathBehavior::Once:
|
2023-07-15 20:56:33 +00:00
|
|
|
Game::entityManager->SerializeEntity(m_Parent);
|
2021-12-05 17:54:36 +00:00
|
|
|
return;
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
case PathBehavior::Bounce:
|
|
|
|
subComponent->mInReverse = true;
|
|
|
|
break;
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
case PathBehavior::Loop:
|
|
|
|
subComponent->mNextWaypointIndex = 0;
|
|
|
|
break;
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else if (subComponent->mCurrentWaypointIndex == 0) {
|
|
|
|
subComponent->mInReverse = false;
|
|
|
|
}
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
if (subComponent->mInReverse) {
|
|
|
|
subComponent->mNextWaypointIndex = subComponent->mCurrentWaypointIndex - 1;
|
|
|
|
} else {
|
|
|
|
subComponent->mNextWaypointIndex = subComponent->mCurrentWaypointIndex + 1;
|
|
|
|
}
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
/*
|
|
|
|
subComponent->mNextWaypointIndex = 0;
|
|
|
|
subComponent->mCurrentWaypointIndex = 1;
|
|
|
|
*/
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
//GameMessages::SendPlatformResync(m_Parent, UNASSIGNED_SYSTEM_ADDRESS);
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
if (subComponent->mCurrentWaypointIndex == subComponent->mDesiredWaypointIndex) {
|
|
|
|
// TODO: Send event?
|
|
|
|
StopPathing();
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
return;
|
|
|
|
}
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
m_Parent->CancelCallbackTimers();
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
m_Parent->AddCallbackTimer(subComponent->mWaitTime, [this] {
|
2023-01-07 05:17:05 +00:00
|
|
|
SetMovementState(eMovementPlatformState::Moving);
|
2021-12-05 17:54:36 +00:00
|
|
|
});
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
auto travelTime = Vector3::Distance(targetPosition, subComponent->mPosition) / subComponent->mSpeed + 1.5;
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
if (m_Parent->GetLOT() == 9483) {
|
|
|
|
travelTime += 20;
|
|
|
|
}
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
const auto travelNext = subComponent->mWaitTime + travelTime;
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
m_Parent->AddCallbackTimer(travelTime, [subComponent, this] {
|
|
|
|
for (CppScripts::Script* script : CppScripts::GetEntityScripts(m_Parent)) {
|
|
|
|
script->OnWaypointReached(m_Parent, subComponent->mNextWaypointIndex);
|
|
|
|
}
|
|
|
|
});
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
m_Parent->AddCallbackTimer(travelNext, [this] {
|
|
|
|
ContinuePathing();
|
|
|
|
});
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2023-07-15 20:56:33 +00:00
|
|
|
Game::entityManager->SerializeEntity(m_Parent);
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MovingPlatformComponent::StopPathing() {
|
|
|
|
//m_Parent->CancelCallbackTimers();
|
|
|
|
|
|
|
|
auto* subComponent = static_cast<MoverSubComponent*>(m_MoverSubComponent);
|
|
|
|
|
|
|
|
m_PathingStopped = true;
|
|
|
|
|
2023-01-07 05:17:05 +00:00
|
|
|
subComponent->mState = eMovementPlatformState::Stopped;
|
2021-12-05 17:54:36 +00:00
|
|
|
subComponent->mDesiredWaypointIndex = -1;
|
|
|
|
subComponent->mShouldStopAtDesiredWaypoint = false;
|
|
|
|
|
2023-07-15 20:56:33 +00:00
|
|
|
Game::entityManager->SerializeEntity(m_Parent);
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
//GameMessages::SendPlatformResync(m_Parent, UNASSIGNED_SYSTEM_ADDRESS);
|
|
|
|
}
|
|
|
|
|
2022-07-25 02:26:51 +00:00
|
|
|
void MovingPlatformComponent::SetSerialized(bool value) {
|
2021-12-05 17:54:36 +00:00
|
|
|
m_Serialize = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MovingPlatformComponent::GetNoAutoStart() const {
|
|
|
|
return m_NoAutoStart;
|
|
|
|
}
|
|
|
|
|
2022-07-25 02:26:51 +00:00
|
|
|
void MovingPlatformComponent::SetNoAutoStart(const bool value) {
|
2021-12-05 17:54:36 +00:00
|
|
|
m_NoAutoStart = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MovingPlatformComponent::WarpToWaypoint(size_t index) {
|
|
|
|
const auto& waypoint = m_Path->pathWaypoints[index];
|
|
|
|
|
|
|
|
m_Parent->SetPosition(waypoint.position);
|
|
|
|
m_Parent->SetRotation(waypoint.rotation);
|
|
|
|
|
2023-07-15 20:56:33 +00:00
|
|
|
Game::entityManager->SerializeEntity(m_Parent);
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
size_t MovingPlatformComponent::GetLastWaypointIndex() const {
|
|
|
|
return m_Path->pathWaypoints.size() - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
MoverSubComponent* MovingPlatformComponent::GetMoverSubComponent() const {
|
|
|
|
return static_cast<MoverSubComponent*>(m_MoverSubComponent);
|
|
|
|
}
|