mirror of
https://github.com/DarkflameUniverse/DarkflameServer
synced 2024-08-30 18:43:58 +00:00
455f9470a5
* Move EntityManager to Game namespace * move initialization to later Need to wait for dZoneManager to be initialized. * Fix bugs - Cannot delete from a RandomAccessIterator while in a range based for loop. Touchup zone manager initialize replace magic numbers with better named constants replace magic zonecontrol id with a more readable hex alternative condense stack variables move initializers closer to their use initialize entity manager with zone control change initialize timings If zone is not zero we expect to initialize the entity manager during zone manager initialization Add constexpr for zone control LOT * Add proper error handling * revert vanity changes * Update WorldServer.cpp * Update dZoneManager.cpp
354 lines
9.8 KiB
C++
354 lines
9.8 KiB
C++
/*
|
|
* Darkflame Universe
|
|
* Copyright 2019
|
|
*/
|
|
|
|
#include "MovingPlatformComponent.h"
|
|
#include "BitStream.h"
|
|
#include "GeneralUtils.h"
|
|
#include "dZoneManager.h"
|
|
#include "EntityManager.h"
|
|
#include "dLogger.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, unsigned int& flags) const {
|
|
outBitStream->Write<bool>(true);
|
|
|
|
outBitStream->Write<uint32_t>(static_cast<uint32_t>(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 = dZoneManager::Instance()->GetZone()->GetPath(pathName);
|
|
m_NoAutoStart = false;
|
|
|
|
if (m_Path == nullptr) {
|
|
Game::logger->Log("MovingPlatformComponent", "Path not found: %s", pathName.c_str());
|
|
}
|
|
}
|
|
|
|
MovingPlatformComponent::~MovingPlatformComponent() {
|
|
delete static_cast<MoverSubComponent*>(m_MoverSubComponent);
|
|
}
|
|
|
|
void MovingPlatformComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) {
|
|
// 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(static_cast<uint16_t>(m_PathName.size()));
|
|
for (const auto& c : m_PathName) {
|
|
outBitStream->Write(static_cast<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<uint32_t>(static_cast<uint32_t>(m_MoverSubComponentType));
|
|
|
|
if (m_MoverSubComponentType == eMoverSubComponentType::simpleMover) {
|
|
// TODO
|
|
} else {
|
|
mover->Serialize(outBitStream, bIsInitialUpdate, flags);
|
|
}
|
|
}
|
|
}
|
|
|
|
void MovingPlatformComponent::OnRebuildInitilized() {
|
|
StopPathing();
|
|
}
|
|
|
|
void MovingPlatformComponent::OnCompleteRebuild() {
|
|
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.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] {
|
|
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.movingPlatform.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);
|
|
}
|