DarkflameServer/dGame/dComponents/MovingPlatformComponent.cpp

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

348 lines
9.8 KiB
C++
Raw Normal View History

/*
* Darkflame Universe
2023-07-10 03:44:08 +00:00
* Copyright 2023
*/
#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) {
2023-07-10 03:44:08 +00:00
mPosition = NiPoint3::ZERO;
mState = eMovementPlatformState::Stopped;
mDesiredWaypointIndex = 0; // -1;
mInReverse = false;
mShouldStopAtDesiredWaypoint = false;
mPercentBetweenPoints = 0.0f;
mCurrentWaypointIndex = 0;
mNextWaypointIndex = 0; //mCurrentWaypointIndex + 1;
mIdleTimeElapsed = 0.0f;
}
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_ParentEntity->GetDefaultPosition());
m_PathName = GeneralUtils::ASCIIToUTF16(pathName);
m_Path = dZoneManager::Instance()->GetZone()->GetPath(pathName);
m_NoAutoStart = false;
2022-07-28 13:39:57 +00:00
2023-07-10 03:44:08 +00:00
if (!m_Path) {
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) {
2023-07-10 03:44:08 +00:00
outBitStream->Write0();
outBitStream->Write0();
return;
}
2023-07-10 03:44:08 +00:00
outBitStream->Write1();
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;
EntityManager::Instance()->SerializeEntity(m_ParentEntity);
}
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_ParentEntity);
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_ParentEntity->GetPosition();
subComponent->mSpeed = 1.0f;
subComponent->mWaitTime = 2.0f;
targetPosition = m_ParentEntity->GetPosition() + NiPoint3(0.0f, 10.0f, 0.0f);
}
m_ParentEntity->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_ParentEntity->AddCallbackTimer(travelTime, [subComponent, this] {
2023-06-16 06:58:39 +00:00
m_ParentEntity->GetScript()->OnWaypointReached(m_ParentEntity, subComponent->mNextWaypointIndex);
});
m_ParentEntity->AddCallbackTimer(travelNext, [this] {
ContinuePathing();
});
//GameMessages::SendPlatformResync(m_ParentEntity, UNASSIGNED_SYSTEM_ADDRESS);
EntityManager::Instance()->SerializeEntity(m_ParentEntity);
}
void MovingPlatformComponent::ContinuePathing() {
auto* subComponent = static_cast<MoverSubComponent*>(m_MoverSubComponent);
2022-07-28 13:39:57 +00:00
subComponent->mState = eMovementPlatformState::Stationary;
2022-07-28 13:39:57 +00:00
subComponent->mCurrentWaypointIndex = subComponent->mNextWaypointIndex;
2022-07-28 13:39:57 +00:00
NiPoint3 targetPosition;
uint32_t pathSize;
PathBehavior behavior;
2022-07-28 13:39:57 +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
subComponent->mPosition = currentWaypoint.position;
subComponent->mSpeed = currentWaypoint.movingPlatform.speed;
subComponent->mWaitTime = currentWaypoint.movingPlatform.wait; // + 2;
2022-07-28 13:39:57 +00:00
pathSize = m_Path->pathWaypoints.size() - 1;
2022-07-28 13:39:57 +00:00
behavior = static_cast<PathBehavior>(m_Path->pathBehavior);
2022-07-28 13:39:57 +00:00
targetPosition = nextWaypoint.position;
} else {
subComponent->mPosition = m_ParentEntity->GetPosition();
subComponent->mSpeed = 1.0f;
subComponent->mWaitTime = 2.0f;
2022-07-28 13:39:57 +00:00
targetPosition = m_ParentEntity->GetPosition() + NiPoint3(0.0f, 10.0f, 0.0f);
2022-07-28 13:39:57 +00:00
pathSize = 1;
behavior = PathBehavior::Loop;
}
2022-07-28 13:39:57 +00:00
if (m_ParentEntity->GetLOT() == 9483) {
behavior = PathBehavior::Bounce;
} else {
return;
}
2022-07-28 13:39:57 +00:00
if (subComponent->mCurrentWaypointIndex >= pathSize) {
subComponent->mCurrentWaypointIndex = pathSize;
switch (behavior) {
case PathBehavior::Once:
EntityManager::Instance()->SerializeEntity(m_ParentEntity);
return;
2022-07-28 13:39:57 +00:00
case PathBehavior::Bounce:
subComponent->mInReverse = true;
break;
2022-07-28 13:39:57 +00:00
case PathBehavior::Loop:
subComponent->mNextWaypointIndex = 0;
break;
2022-07-28 13:39:57 +00:00
default:
break;
}
} else if (subComponent->mCurrentWaypointIndex == 0) {
subComponent->mInReverse = false;
}
2022-07-28 13:39:57 +00:00
if (subComponent->mInReverse) {
subComponent->mNextWaypointIndex = subComponent->mCurrentWaypointIndex - 1;
} else {
subComponent->mNextWaypointIndex = subComponent->mCurrentWaypointIndex + 1;
}
2022-07-28 13:39:57 +00:00
/*
subComponent->mNextWaypointIndex = 0;
subComponent->mCurrentWaypointIndex = 1;
*/
2022-07-28 13:39:57 +00:00
//GameMessages::SendPlatformResync(m_ParentEntity, UNASSIGNED_SYSTEM_ADDRESS);
2022-07-28 13:39:57 +00:00
if (subComponent->mCurrentWaypointIndex == subComponent->mDesiredWaypointIndex) {
// TODO: Send event?
StopPathing();
2022-07-28 13:39:57 +00:00
return;
}
2022-07-28 13:39:57 +00:00
m_ParentEntity->CancelCallbackTimers();
2022-07-28 13:39:57 +00:00
m_ParentEntity->AddCallbackTimer(subComponent->mWaitTime, [this] {
SetMovementState(eMovementPlatformState::Moving);
});
2022-07-28 13:39:57 +00:00
auto travelTime = Vector3::Distance(targetPosition, subComponent->mPosition) / subComponent->mSpeed + 1.5;
2022-07-28 13:39:57 +00:00
if (m_ParentEntity->GetLOT() == 9483) {
travelTime += 20;
}
2022-07-28 13:39:57 +00:00
const auto travelNext = subComponent->mWaitTime + travelTime;
2022-07-28 13:39:57 +00:00
m_ParentEntity->AddCallbackTimer(travelTime, [subComponent, this] {
2023-06-16 06:58:39 +00:00
m_ParentEntity->GetScript()->OnWaypointReached(m_ParentEntity, subComponent->mNextWaypointIndex);
});
2022-07-28 13:39:57 +00:00
m_ParentEntity->AddCallbackTimer(travelNext, [this] {
ContinuePathing();
});
2022-07-28 13:39:57 +00:00
EntityManager::Instance()->SerializeEntity(m_ParentEntity);
}
void MovingPlatformComponent::StopPathing() {
//m_ParentEntity->CancelCallbackTimers();
auto* subComponent = static_cast<MoverSubComponent*>(m_MoverSubComponent);
m_PathingStopped = true;
subComponent->mState = eMovementPlatformState::Stopped;
subComponent->mDesiredWaypointIndex = -1;
subComponent->mShouldStopAtDesiredWaypoint = false;
EntityManager::Instance()->SerializeEntity(m_ParentEntity);
//GameMessages::SendPlatformResync(m_ParentEntity, 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_ParentEntity->SetPosition(waypoint.position);
m_ParentEntity->SetRotation(waypoint.rotation);
EntityManager::Instance()->SerializeEntity(m_ParentEntity);
}
size_t MovingPlatformComponent::GetLastWaypointIndex() const {
return m_Path->pathWaypoints.size() - 1;
}
MoverSubComponent* MovingPlatformComponent::GetMoverSubComponent() const {
return static_cast<MoverSubComponent*>(m_MoverSubComponent);
}