mirror of
https://github.com/DarkflameUniverse/DarkflameServer
synced 2024-08-30 18:43:58 +00:00
c9a8be4fb9
Speed is used in more waypoints than not so we may as well reduce repeated references. tested that the data is still loaded as normal in avant gardens Update Zone.cpp
354 lines
9.6 KiB
C++
354 lines
9.6 KiB
C++
/*
|
|
* Darkflame Universe
|
|
* Copyright 2019
|
|
*/
|
|
|
|
#include "MovingPlatformComponent.h"
|
|
#include "BitStream.h"
|
|
#include "GeneralUtils.h"
|
|
#include "dZoneManager.h"
|
|
#include "EntityManager.h"
|
|
#include "Logger.h"
|
|
#include "GameMessages.h"
|
|
#include "CppScripts.h"
|
|
#include "SimplePhysicsComponent.h"
|
|
#include "Zone.h"
|
|
|
|
MoverSubComponent::MoverSubComponent(const NiPoint3& startPos) {
|
|
mPosition = {};
|
|
|
|
mState = eMovementPlatformState::Stopped;
|
|
mDesiredWaypointIndex = 0; // -1;
|
|
mInReverse = false;
|
|
mShouldStopAtDesiredWaypoint = false;
|
|
|
|
mPercentBetweenPoints = 0.0f;
|
|
|
|
mCurrentWaypointIndex = 0;
|
|
mNextWaypointIndex = 0; //mCurrentWaypointIndex + 1;
|
|
|
|
mIdleTimeElapsed = 0.0f;
|
|
}
|
|
|
|
MoverSubComponent::~MoverSubComponent() = default;
|
|
|
|
void MoverSubComponent::Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) {
|
|
outBitStream.Write<bool>(true);
|
|
|
|
outBitStream.Write(mState);
|
|
outBitStream.Write<int32_t>(mDesiredWaypointIndex);
|
|
outBitStream.Write(mShouldStopAtDesiredWaypoint);
|
|
outBitStream.Write(mInReverse);
|
|
|
|
outBitStream.Write<float_t>(mPercentBetweenPoints);
|
|
|
|
outBitStream.Write<float_t>(mPosition.x);
|
|
outBitStream.Write<float_t>(mPosition.y);
|
|
outBitStream.Write<float_t>(mPosition.z);
|
|
|
|
outBitStream.Write<uint32_t>(mCurrentWaypointIndex);
|
|
outBitStream.Write<uint32_t>(mNextWaypointIndex);
|
|
|
|
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);
|
|
m_Path = Game::zoneManager->GetZone()->GetPath(pathName);
|
|
m_NoAutoStart = false;
|
|
|
|
if (m_Path == nullptr) {
|
|
LOG("Path not found: %s", pathName.c_str());
|
|
}
|
|
}
|
|
|
|
MovingPlatformComponent::~MovingPlatformComponent() {
|
|
delete static_cast<MoverSubComponent*>(m_MoverSubComponent);
|
|
}
|
|
|
|
void MovingPlatformComponent::Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) {
|
|
// Here we don't serialize the moving platform to let the client simulate the movement
|
|
|
|
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();
|
|
|
|
outBitStream.Write<uint16_t>(m_PathName.size());
|
|
for (const auto& c : m_PathName) {
|
|
outBitStream.Write<uint16_t>(c);
|
|
}
|
|
|
|
// 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);
|
|
outBitStream.Write(m_MoverSubComponentType);
|
|
|
|
if (m_MoverSubComponentType == eMoverSubComponentType::simpleMover) {
|
|
// TODO
|
|
} else {
|
|
mover->Serialize(outBitStream, bIsInitialUpdate);
|
|
}
|
|
}
|
|
}
|
|
|
|
void MovingPlatformComponent::OnQuickBuildInitilized() {
|
|
StopPathing();
|
|
}
|
|
|
|
void MovingPlatformComponent::OnCompleteQuickBuild() {
|
|
if (m_NoAutoStart)
|
|
return;
|
|
|
|
StartPathing();
|
|
}
|
|
|
|
void MovingPlatformComponent::SetMovementState(eMovementPlatformState value) {
|
|
auto* subComponent = static_cast<MoverSubComponent*>(m_MoverSubComponent);
|
|
|
|
subComponent->mState = value;
|
|
|
|
Game::entityManager->SerializeEntity(m_Parent);
|
|
}
|
|
|
|
void MovingPlatformComponent::GotoWaypoint(uint32_t index, bool stopAtWaypoint) {
|
|
auto* subComponent = static_cast<MoverSubComponent*>(m_MoverSubComponent);
|
|
|
|
subComponent->mDesiredWaypointIndex = index;
|
|
subComponent->mNextWaypointIndex = index;
|
|
subComponent->mShouldStopAtDesiredWaypoint = stopAtWaypoint;
|
|
|
|
StartPathing();
|
|
}
|
|
|
|
void MovingPlatformComponent::StartPathing() {
|
|
//GameMessages::SendStartPathing(m_Parent);
|
|
m_PathingStopped = false;
|
|
|
|
auto* subComponent = static_cast<MoverSubComponent*>(m_MoverSubComponent);
|
|
|
|
subComponent->mShouldStopAtDesiredWaypoint = true;
|
|
subComponent->mState = eMovementPlatformState::Stationary;
|
|
|
|
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.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] {
|
|
SetMovementState(eMovementPlatformState::Moving);
|
|
});
|
|
|
|
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);
|
|
|
|
Game::entityManager->SerializeEntity(m_Parent);
|
|
}
|
|
|
|
void MovingPlatformComponent::ContinuePathing() {
|
|
auto* subComponent = static_cast<MoverSubComponent*>(m_MoverSubComponent);
|
|
|
|
subComponent->mState = eMovementPlatformState::Stationary;
|
|
|
|
subComponent->mCurrentWaypointIndex = subComponent->mNextWaypointIndex;
|
|
|
|
NiPoint3 targetPosition;
|
|
uint32_t pathSize;
|
|
PathBehavior behavior;
|
|
|
|
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.speed;
|
|
subComponent->mWaitTime = currentWaypoint.movingPlatform.wait; // + 2;
|
|
|
|
pathSize = m_Path->pathWaypoints.size() - 1;
|
|
|
|
behavior = static_cast<PathBehavior>(m_Path->pathBehavior);
|
|
|
|
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);
|
|
|
|
pathSize = 1;
|
|
behavior = PathBehavior::Loop;
|
|
}
|
|
|
|
if (m_Parent->GetLOT() == 9483) {
|
|
behavior = PathBehavior::Bounce;
|
|
} else {
|
|
return;
|
|
}
|
|
|
|
if (subComponent->mCurrentWaypointIndex >= pathSize) {
|
|
subComponent->mCurrentWaypointIndex = pathSize;
|
|
switch (behavior) {
|
|
case PathBehavior::Once:
|
|
Game::entityManager->SerializeEntity(m_Parent);
|
|
return;
|
|
|
|
case PathBehavior::Bounce:
|
|
subComponent->mInReverse = true;
|
|
break;
|
|
|
|
case PathBehavior::Loop:
|
|
subComponent->mNextWaypointIndex = 0;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
} else if (subComponent->mCurrentWaypointIndex == 0) {
|
|
subComponent->mInReverse = false;
|
|
}
|
|
|
|
if (subComponent->mInReverse) {
|
|
subComponent->mNextWaypointIndex = subComponent->mCurrentWaypointIndex - 1;
|
|
} else {
|
|
subComponent->mNextWaypointIndex = subComponent->mCurrentWaypointIndex + 1;
|
|
}
|
|
|
|
/*
|
|
subComponent->mNextWaypointIndex = 0;
|
|
subComponent->mCurrentWaypointIndex = 1;
|
|
*/
|
|
|
|
//GameMessages::SendPlatformResync(m_Parent, UNASSIGNED_SYSTEM_ADDRESS);
|
|
|
|
if (subComponent->mCurrentWaypointIndex == subComponent->mDesiredWaypointIndex) {
|
|
// TODO: Send event?
|
|
StopPathing();
|
|
|
|
return;
|
|
}
|
|
|
|
m_Parent->CancelCallbackTimers();
|
|
|
|
m_Parent->AddCallbackTimer(subComponent->mWaitTime, [this] {
|
|
SetMovementState(eMovementPlatformState::Moving);
|
|
});
|
|
|
|
auto travelTime = Vector3::Distance(targetPosition, subComponent->mPosition) / subComponent->mSpeed + 1.5;
|
|
|
|
if (m_Parent->GetLOT() == 9483) {
|
|
travelTime += 20;
|
|
}
|
|
|
|
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();
|
|
});
|
|
|
|
Game::entityManager->SerializeEntity(m_Parent);
|
|
}
|
|
|
|
void MovingPlatformComponent::StopPathing() {
|
|
//m_Parent->CancelCallbackTimers();
|
|
|
|
auto* subComponent = static_cast<MoverSubComponent*>(m_MoverSubComponent);
|
|
|
|
m_PathingStopped = true;
|
|
|
|
subComponent->mState = eMovementPlatformState::Stopped;
|
|
subComponent->mDesiredWaypointIndex = -1;
|
|
subComponent->mShouldStopAtDesiredWaypoint = false;
|
|
|
|
Game::entityManager->SerializeEntity(m_Parent);
|
|
|
|
//GameMessages::SendPlatformResync(m_Parent, UNASSIGNED_SYSTEM_ADDRESS);
|
|
}
|
|
|
|
void MovingPlatformComponent::SetSerialized(bool value) {
|
|
m_Serialize = value;
|
|
}
|
|
|
|
bool MovingPlatformComponent::GetNoAutoStart() const {
|
|
return m_NoAutoStart;
|
|
}
|
|
|
|
void MovingPlatformComponent::SetNoAutoStart(const bool value) {
|
|
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);
|
|
|
|
Game::entityManager->SerializeEntity(m_Parent);
|
|
}
|
|
|
|
size_t MovingPlatformComponent::GetLastWaypointIndex() const {
|
|
return m_Path->pathWaypoints.size() - 1;
|
|
}
|
|
|
|
MoverSubComponent* MovingPlatformComponent::GetMoverSubComponent() const {
|
|
return static_cast<MoverSubComponent*>(m_MoverSubComponent);
|
|
}
|