2021-12-05 17:54:36 +00:00
|
|
|
/*
|
|
|
|
* Darkflame Universe
|
|
|
|
* Copyright 2018
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <sstream>
|
|
|
|
#include <iostream>
|
|
|
|
|
|
|
|
#include "PhantomPhysicsComponent.h"
|
|
|
|
#include "Game.h"
|
|
|
|
#include "LDFFormat.h"
|
2023-10-21 23:31:55 +00:00
|
|
|
#include "Logger.h"
|
2021-12-05 17:54:36 +00:00
|
|
|
#include "Entity.h"
|
|
|
|
#include "EntityManager.h"
|
|
|
|
#include "ControllablePhysicsComponent.h"
|
|
|
|
#include "GameMessages.h"
|
2023-03-25 10:26:39 +00:00
|
|
|
#include "ePhysicsEffectType.h"
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
#include "CDClientManager.h"
|
|
|
|
#include "CDComponentsRegistryTable.h"
|
|
|
|
#include "CDPhysicsComponentTable.h"
|
|
|
|
#include "dServer.h"
|
2023-01-07 05:17:05 +00:00
|
|
|
#include "EntityInfo.h"
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
#include "dpWorld.h"
|
|
|
|
#include "dpEntity.h"
|
|
|
|
#include "dpShapeBox.h"
|
|
|
|
#include "dpShapeSphere.h"
|
|
|
|
|
2024-12-16 05:44:57 +00:00
|
|
|
PhantomPhysicsComponent::PhantomPhysicsComponent(Entity* parent, int32_t componentId) : PhysicsComponent(parent, componentId) {
|
2021-12-05 17:54:36 +00:00
|
|
|
m_Position = m_Parent->GetDefaultPosition();
|
|
|
|
m_Rotation = m_Parent->GetDefaultRotation();
|
|
|
|
m_Scale = m_Parent->GetDefaultScale();
|
|
|
|
m_dpEntity = nullptr;
|
2022-07-25 02:26:51 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
m_EffectInfoDirty = false;
|
2022-07-25 02:26:51 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
m_IsPhysicsEffectActive = false;
|
2023-03-25 10:26:39 +00:00
|
|
|
m_EffectType = ePhysicsEffectType::PUSH;
|
2021-12-05 17:54:36 +00:00
|
|
|
m_DirectionalMultiplier = 0.0f;
|
2022-07-25 02:26:51 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
m_MinMax = false;
|
|
|
|
m_Min = 0;
|
|
|
|
m_Max = 1;
|
2022-07-25 02:26:51 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
m_IsDirectional = false;
|
|
|
|
m_Direction = NiPoint3(); // * m_DirectionalMultiplier
|
|
|
|
|
|
|
|
if (m_Parent->GetVar<bool>(u"create_physics")) {
|
2024-05-10 14:22:26 +00:00
|
|
|
m_dpEntity = CreatePhysicsLnv(m_Scale, ComponentType);
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (m_Parent->GetVar<bool>(u"respawnVol")) {
|
|
|
|
m_IsRespawnVolume = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_IsRespawnVolume) {
|
|
|
|
{
|
|
|
|
auto respawnString = std::stringstream(m_Parent->GetVarAsString(u"rspPos"));
|
|
|
|
|
|
|
|
std::string segment;
|
|
|
|
std::vector<std::string> seglist;
|
|
|
|
|
|
|
|
while (std::getline(respawnString, segment, '\x1f')) {
|
|
|
|
seglist.push_back(segment);
|
|
|
|
}
|
|
|
|
|
|
|
|
m_RespawnPos = NiPoint3(std::stof(seglist[0]), std::stof(seglist[1]), std::stof(seglist[2]));
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
auto respawnString = std::stringstream(m_Parent->GetVarAsString(u"rspRot"));
|
|
|
|
|
|
|
|
std::string segment;
|
|
|
|
std::vector<std::string> seglist;
|
|
|
|
|
|
|
|
while (std::getline(respawnString, segment, '\x1f')) {
|
|
|
|
seglist.push_back(segment);
|
|
|
|
}
|
|
|
|
|
|
|
|
m_RespawnRot = NiQuaternion(std::stof(seglist[0]), std::stof(seglist[1]), std::stof(seglist[2]), std::stof(seglist[3]));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// HF - RespawnPoints. Legacy respawn entity.
|
2022-07-25 02:26:51 +00:00
|
|
|
if (m_Parent->GetLOT() == 4945) {
|
2021-12-05 17:54:36 +00:00
|
|
|
m_IsRespawnVolume = true;
|
|
|
|
m_RespawnPos = m_Position;
|
|
|
|
m_RespawnRot = m_Rotation;
|
|
|
|
}
|
|
|
|
|
2024-05-10 14:22:26 +00:00
|
|
|
if (!m_dpEntity) {
|
|
|
|
m_dpEntity = CreatePhysicsEntity(ComponentType);
|
|
|
|
if (!m_dpEntity) return;
|
2024-02-11 20:36:15 +00:00
|
|
|
m_dpEntity->SetScale(m_Scale);
|
|
|
|
m_dpEntity->SetRotation(m_Rotation);
|
|
|
|
m_dpEntity->SetPosition(m_Position);
|
|
|
|
dpWorld::AddEntity(m_dpEntity);
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
PhantomPhysicsComponent::~PhantomPhysicsComponent() {
|
|
|
|
if (m_dpEntity) {
|
2024-01-19 21:12:05 +00:00
|
|
|
dpWorld::RemoveEntity(m_dpEntity);
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-27 07:25:44 +00:00
|
|
|
void PhantomPhysicsComponent::Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) {
|
2023-10-09 20:19:38 +00:00
|
|
|
PhysicsComponent::Serialize(outBitStream, bIsInitialUpdate);
|
2022-07-25 02:26:51 +00:00
|
|
|
|
2024-02-27 07:25:44 +00:00
|
|
|
outBitStream.Write(m_EffectInfoDirty || bIsInitialUpdate);
|
2021-12-05 17:54:36 +00:00
|
|
|
if (m_EffectInfoDirty || bIsInitialUpdate) {
|
2024-02-27 07:25:44 +00:00
|
|
|
outBitStream.Write(m_IsPhysicsEffectActive);
|
2022-07-25 02:26:51 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
if (m_IsPhysicsEffectActive) {
|
2024-02-27 07:25:44 +00:00
|
|
|
outBitStream.Write(m_EffectType);
|
|
|
|
outBitStream.Write(m_DirectionalMultiplier);
|
2022-07-25 02:26:51 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
// forgive me father for i have sinned
|
2024-02-27 07:25:44 +00:00
|
|
|
outBitStream.Write0();
|
|
|
|
//outBitStream.Write(m_MinMax);
|
2021-12-05 17:54:36 +00:00
|
|
|
//if (m_MinMax) {
|
2024-02-27 07:25:44 +00:00
|
|
|
//outBitStream.Write(m_Min);
|
|
|
|
//outBitStream.Write(m_Max);
|
2021-12-05 17:54:36 +00:00
|
|
|
//}
|
2022-07-25 02:26:51 +00:00
|
|
|
|
2024-02-27 07:25:44 +00:00
|
|
|
outBitStream.Write(m_IsDirectional);
|
2021-12-05 17:54:36 +00:00
|
|
|
if (m_IsDirectional) {
|
2024-02-27 07:25:44 +00:00
|
|
|
outBitStream.Write(m_Direction.x);
|
|
|
|
outBitStream.Write(m_Direction.y);
|
|
|
|
outBitStream.Write(m_Direction.z);
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
m_EffectInfoDirty = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-16 12:55:57 +00:00
|
|
|
// Even if we were to implement Friction server side,
|
|
|
|
// it also defaults to 1.0f in the last argument, so we dont need two functions to do the same thing.
|
|
|
|
void ApplyCollisionEffect(const LWOOBJID& target, const ePhysicsEffectType effectType, const float effectScale) {
|
|
|
|
switch (effectType) {
|
|
|
|
case ePhysicsEffectType::GRAVITY_SCALE: {
|
|
|
|
auto* targetEntity = Game::entityManager->GetEntity(target);
|
|
|
|
if (targetEntity) {
|
|
|
|
auto* controllablePhysicsComponent = targetEntity->GetComponent<ControllablePhysicsComponent>();
|
|
|
|
// dont want to apply an effect to nothing.
|
|
|
|
if (!controllablePhysicsComponent) return;
|
|
|
|
controllablePhysicsComponent->SetGravityScale(effectScale);
|
|
|
|
GameMessages::SendSetGravityScale(target, effectScale, targetEntity->GetSystemAddress());
|
|
|
|
}
|
2024-05-10 14:22:26 +00:00
|
|
|
break;
|
2023-10-16 12:55:57 +00:00
|
|
|
}
|
2024-05-10 14:22:26 +00:00
|
|
|
|
2023-10-16 12:55:57 +00:00
|
|
|
case ePhysicsEffectType::ATTRACT:
|
|
|
|
case ePhysicsEffectType::FRICTION:
|
|
|
|
case ePhysicsEffectType::PUSH:
|
|
|
|
case ePhysicsEffectType::REPULSE:
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2024-05-10 14:22:26 +00:00
|
|
|
// The other types are not handled by the server and are here to handle all cases of the enum.
|
2023-10-16 12:55:57 +00:00
|
|
|
}
|
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
void PhantomPhysicsComponent::Update(float deltaTime) {
|
|
|
|
if (!m_dpEntity) return;
|
|
|
|
|
|
|
|
//Process enter events
|
2024-04-05 05:52:26 +00:00
|
|
|
for (const auto id : m_dpEntity->GetNewObjects()) {
|
|
|
|
ApplyCollisionEffect(id, m_EffectType, m_DirectionalMultiplier);
|
|
|
|
m_Parent->OnCollisionPhantom(id);
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
//If we are a respawn volume, inform the client:
|
|
|
|
if (m_IsRespawnVolume) {
|
2024-04-05 05:52:26 +00:00
|
|
|
auto* const entity = Game::entityManager->GetEntity(id);
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
if (entity) {
|
|
|
|
GameMessages::SendPlayerReachedRespawnCheckpoint(entity, m_RespawnPos, m_RespawnRot);
|
|
|
|
entity->SetRespawnPos(m_RespawnPos);
|
|
|
|
entity->SetRespawnRot(m_RespawnRot);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//Process exit events
|
2024-04-05 05:52:26 +00:00
|
|
|
for (const auto id : m_dpEntity->GetRemovedObjects()) {
|
|
|
|
ApplyCollisionEffect(id, m_EffectType, 1.0f);
|
|
|
|
m_Parent->OnCollisionLeavePhantom(id);
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PhantomPhysicsComponent::SetDirection(const NiPoint3& pos) {
|
|
|
|
m_Direction = pos;
|
|
|
|
m_Direction.x *= m_DirectionalMultiplier;
|
|
|
|
m_Direction.y *= m_DirectionalMultiplier;
|
|
|
|
m_Direction.z *= m_DirectionalMultiplier;
|
2022-07-25 02:26:51 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
m_EffectInfoDirty = true;
|
|
|
|
m_IsDirectional = true;
|
|
|
|
}
|
|
|
|
|
2024-05-10 14:22:26 +00:00
|
|
|
void PhantomPhysicsComponent::SpawnVertices() const {
|
|
|
|
if (!m_dpEntity) {
|
|
|
|
LOG("No dpEntity to spawn vertices for %llu:%i", m_Parent->GetObjectID(), m_Parent->GetLOT());
|
|
|
|
return;
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
2024-05-10 14:22:26 +00:00
|
|
|
PhysicsComponent::SpawnVertices(m_dpEntity);
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void PhantomPhysicsComponent::SetDirectionalMultiplier(float mul) {
|
|
|
|
m_DirectionalMultiplier = mul;
|
|
|
|
m_EffectInfoDirty = true;
|
|
|
|
}
|
|
|
|
|
2023-03-25 10:26:39 +00:00
|
|
|
void PhantomPhysicsComponent::SetEffectType(ePhysicsEffectType type) {
|
2021-12-05 17:54:36 +00:00
|
|
|
m_EffectType = type;
|
|
|
|
m_EffectInfoDirty = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PhantomPhysicsComponent::SetMin(uint32_t min) {
|
|
|
|
m_Min = min;
|
|
|
|
m_MinMax = true;
|
|
|
|
m_EffectInfoDirty = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PhantomPhysicsComponent::SetMax(uint32_t max) {
|
|
|
|
m_Max = max;
|
|
|
|
m_MinMax = true;
|
|
|
|
m_EffectInfoDirty = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PhantomPhysicsComponent::SetPosition(const NiPoint3& pos) {
|
2023-10-09 20:19:38 +00:00
|
|
|
PhysicsComponent::SetPosition(pos);
|
2021-12-05 17:54:36 +00:00
|
|
|
if (m_dpEntity) m_dpEntity->SetPosition(pos);
|
|
|
|
}
|
|
|
|
|
|
|
|
void PhantomPhysicsComponent::SetRotation(const NiQuaternion& rot) {
|
2023-10-09 20:19:38 +00:00
|
|
|
PhysicsComponent::SetRotation(rot);
|
2021-12-05 17:54:36 +00:00
|
|
|
if (m_dpEntity) m_dpEntity->SetRotation(rot);
|
|
|
|
}
|