rigid as heck

This commit is contained in:
Aaron Kimbre
2023-12-02 21:03:17 -06:00
parent 731b828c12
commit 4dce512d64
19 changed files with 675 additions and 16 deletions

View File

@@ -1,16 +1,244 @@
/*
* Darkflame Universe
* Copyright 2023
* Copyright 2018
*/
#include <sstream>
#include <iostream>
#include "RigidbodyPhantomPhysicsComponent.h"
#include "Game.h"
#include "LDFFormat.h"
#include "Logger.h"
#include "Entity.h"
#include "EntityManager.h"
#include "ControllablePhysicsComponent.h"
#include "GameMessages.h"
#include "ePhysicsEffectType.h"
#include "CDClientManager.h"
#include "CDComponentsRegistryTable.h"
#include "CDPhysicsComponentTable.h"
#include "dServer.h"
#include "EntityInfo.h"
#include "dpWorld.h"
#include "dpEntity.h"
#include "dpShapeBox.h"
#include "dpShapeSphere.h"
RigidbodyPhantomPhysicsComponent::RigidbodyPhantomPhysicsComponent(Entity* parent) : PhysicsComponent(parent) {
m_Position = m_Parent->GetDefaultPosition();
m_Rotation = m_Parent->GetDefaultRotation();
m_Scale = m_Parent->GetDefaultScale();
m_dpEntity = nullptr;
m_EffectInfoDirty = false;
m_IsPhysicsEffectActive = false;
m_EffectType = ePhysicsEffectType::PUSH;
m_DirectionalMultiplier = 0.0f;
m_MinMax = false;
m_Min = 0;
m_Max = 1;
m_IsDirectional = false;
m_Direction = NiPoint3(); // * m_DirectionalMultiplier
if (m_Parent->GetVar<bool>(u"create_physics")) {
CreatePhysics();
}
if (!m_HasCreatedPhysics) {
CDComponentsRegistryTable* compRegistryTable = CDClientManager::Instance().GetTable<CDComponentsRegistryTable>();
auto componentID = compRegistryTable->GetByIDAndType(m_Parent->GetLOT(), eReplicaComponentType::RIGID_BODY_PHANTOM_PHYSICS);
CDPhysicsComponentTable* physComp = CDClientManager::Instance().GetTable<CDPhysicsComponentTable>();
if (physComp == nullptr) return;
auto* info = physComp->GetByID(componentID);
if (info == nullptr || info->physicsAsset == "" || info->physicsAsset == "NO_PHYSICS") return;
//temp test
if (info->physicsAsset == "miscellaneous\\misc_phys_10x1x5.hkx") {
m_dpEntity = new dpEntity(m_Parent->GetObjectID(), 10.0f, 5.0f, 1.0f);
m_dpEntity->SetScale(m_Scale);
m_dpEntity->SetRotation(m_Rotation);
m_dpEntity->SetPosition(m_Position);
dpWorld::Instance().AddEntity(m_dpEntity);
} else if (info->physicsAsset == "miscellaneous\\misc_phys_640x640.hkx") {
// Move this down by 13.521004 units so it is still effectively at the same height as before
m_Position = m_Position - NiPoint3::UNIT_Y * 13.521004f;
// TODO Fix physics simulation to do simulation at high velocities due to bullet through paper problem...
m_dpEntity = new dpEntity(m_Parent->GetObjectID(), 1638.4f, 13.521004f * 2.0f, 1638.4f);
m_dpEntity->SetScale(m_Scale);
m_dpEntity->SetRotation(m_Rotation);
m_dpEntity->SetPosition(m_Position);
dpWorld::Instance().AddEntity(m_dpEntity);
} else if (info->physicsAsset == "env\\trigger_wall_tall.hkx") {
m_dpEntity = new dpEntity(m_Parent->GetObjectID(), 10.0f, 25.0f, 1.0f);
m_dpEntity->SetScale(m_Scale);
m_dpEntity->SetRotation(m_Rotation);
m_dpEntity->SetPosition(m_Position);
dpWorld::Instance().AddEntity(m_dpEntity);
} else if (info->physicsAsset == "env\\env_gen_placeholderphysics.hkx") {
m_dpEntity = new dpEntity(m_Parent->GetObjectID(), 20.0f, 20.0f, 20.0f);
m_dpEntity->SetScale(m_Scale);
m_dpEntity->SetRotation(m_Rotation);
m_dpEntity->SetPosition(m_Position);
dpWorld::Instance().AddEntity(m_dpEntity);
} else if (info->physicsAsset == "env\\POI_trigger_wall.hkx") {
m_dpEntity = new dpEntity(m_Parent->GetObjectID(), 1.0f, 12.5f, 20.0f); // Not sure what the real size is
m_dpEntity->SetScale(m_Scale);
m_dpEntity->SetRotation(m_Rotation);
m_dpEntity->SetPosition(m_Position);
dpWorld::Instance().AddEntity(m_dpEntity);
} else if (info->physicsAsset == "env\\NG_NinjaGo\\env_ng_gen_gate_chamber_puzzle_ceiling_tile_falling_phantom.hkx") {
m_dpEntity = new dpEntity(m_Parent->GetObjectID(), 18.0f, 5.0f, 15.0f);
m_dpEntity->SetScale(m_Scale);
m_dpEntity->SetRotation(m_Rotation);
m_dpEntity->SetPosition(m_Position + m_Rotation.GetForwardVector() * 7.5f);
dpWorld::Instance().AddEntity(m_dpEntity);
} else if (info->physicsAsset == "env\\NG_NinjaGo\\ng_flamejet_brick_phantom.HKX") {
m_dpEntity = new dpEntity(m_Parent->GetObjectID(), 1.0f, 1.0f, 12.0f);
m_dpEntity->SetScale(m_Scale);
m_dpEntity->SetRotation(m_Rotation);
m_dpEntity->SetPosition(m_Position + m_Rotation.GetForwardVector() * 6.0f);
dpWorld::Instance().AddEntity(m_dpEntity);
} else if (info->physicsAsset == "env\\Ring_Trigger.hkx") {
m_dpEntity = new dpEntity(m_Parent->GetObjectID(), 6.0f, 6.0f, 6.0f);
m_dpEntity->SetScale(m_Scale);
m_dpEntity->SetRotation(m_Rotation);
m_dpEntity->SetPosition(m_Position);
dpWorld::Instance().AddEntity(m_dpEntity);
} else if (info->physicsAsset == "env\\vfx_propertyImaginationBall.hkx") {
m_dpEntity = new dpEntity(m_Parent->GetObjectID(), 4.5f);
m_dpEntity->SetScale(m_Scale);
m_dpEntity->SetRotation(m_Rotation);
m_dpEntity->SetPosition(m_Position);
dpWorld::Instance().AddEntity(m_dpEntity);
} else if (info->physicsAsset == "env\\env_won_fv_gas-blocking-volume.hkx") {
m_dpEntity = new dpEntity(m_Parent->GetObjectID(), 390.496826f, 111.467964f, 600.821534f, true);
m_dpEntity->SetScale(m_Scale);
m_dpEntity->SetRotation(m_Rotation);
m_Position.y -= (111.467964f * m_Scale) / 2;
m_dpEntity->SetPosition(m_Position);
dpWorld::Instance().AddEntity(m_dpEntity);
} else {
//LOG("This one is supposed to have %s", info->physicsAsset.c_str());
//add fallback cube:
m_dpEntity = new dpEntity(m_Parent->GetObjectID(), 2.0f, 2.0f, 2.0f);
m_dpEntity->SetScale(m_Scale);
m_dpEntity->SetRotation(m_Rotation);
m_dpEntity->SetPosition(m_Position);
dpWorld::Instance().AddEntity(m_dpEntity);
}
}
}
RigidbodyPhantomPhysicsComponent::~RigidbodyPhantomPhysicsComponent() {
if (m_dpEntity) {
dpWorld::Instance().RemoveEntity(m_dpEntity);
}
}
void RigidbodyPhantomPhysicsComponent::CreatePhysics() {
unsigned char alpha;
unsigned char red;
unsigned char green;
unsigned char blue;
int type = -1;
float x = 0.0f;
float y = 0.0f;
float z = 0.0f;
float width = 0.0f; //aka "radius"
float height = 0.0f;
if (m_Parent->HasVar(u"primitiveModelType")) {
type = m_Parent->GetVar<int32_t>(u"primitiveModelType");
x = m_Parent->GetVar<float>(u"primitiveModelValueX");
y = m_Parent->GetVar<float>(u"primitiveModelValueY");
z = m_Parent->GetVar<float>(u"primitiveModelValueZ");
} else {
CDComponentsRegistryTable* compRegistryTable = CDClientManager::Instance().GetTable<CDComponentsRegistryTable>();
auto componentID = compRegistryTable->GetByIDAndType(m_Parent->GetLOT(), eReplicaComponentType::PHANTOM_PHYSICS);
CDPhysicsComponentTable* physComp = CDClientManager::Instance().GetTable<CDPhysicsComponentTable>();
if (physComp == nullptr) return;
auto info = physComp->GetByID(componentID);
if (info == nullptr) return;
type = info->pcShapeType;
width = info->playerRadius;
height = info->playerHeight;
}
switch (type) {
case 1: { //Make a new box shape
NiPoint3 boxSize(x, y, z);
if (x == 0.0f) {
//LU has some weird values, so I think it's best to scale them down a bit
if (height < 0.5f) height = 2.0f;
if (width < 0.5f) width = 2.0f;
//Scale them:
width = width * m_Scale;
height = height * m_Scale;
boxSize = NiPoint3(width, height, width);
}
m_dpEntity = new dpEntity(m_Parent->GetObjectID(), boxSize);
break;
}
}
if (!m_dpEntity) return;
m_dpEntity->SetPosition({ m_Position.x, m_Position.y - (height / 2), m_Position.z });
dpWorld::Instance().AddEntity(m_dpEntity);
m_HasCreatedPhysics = true;
}
void RigidbodyPhantomPhysicsComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) {
PhysicsComponent::Serialize(outBitStream, bIsInitialUpdate);
}
void RigidbodyPhantomPhysicsComponent::Update(float deltaTime) {
if (!m_dpEntity) return;
//Process enter events
for (auto en : m_dpEntity->GetNewObjects()) {
if (!en) continue;
m_Parent->OnCollisionPhantom(en->GetObjectID());
}
//Process exit events
for (auto en : m_dpEntity->GetRemovedObjects()) {
if (!en) continue;
m_Parent->OnCollisionLeavePhantom(en->GetObjectID());
}
}
void RigidbodyPhantomPhysicsComponent::SetPosition(const NiPoint3& pos) {
PhysicsComponent::SetPosition(pos);
if (m_dpEntity) m_dpEntity->SetPosition(pos);
}
void RigidbodyPhantomPhysicsComponent::SetRotation(const NiQuaternion& rot) {
PhysicsComponent::SetRotation(rot);
if (m_dpEntity) m_dpEntity->SetRotation(rot);
}

View File

@@ -1,29 +1,142 @@
/*
* Darkflame Universe
* Copyright 2023
* Copyright 2018
*/
#ifndef __RIGIDBODYPHANTOMPHYSICS_H__
#define __RIGIDBODYPHANTOMPHYSICS_H__
#pragma once
#include "BitStream.h"
#include "dCommonVars.h"
#include "NiPoint3.h"
#include "NiQuaternion.h"
#include "PhysicsComponent.h"
#include "BitStream.h"
#include <vector>
#include "CppScripts.h"
#include "InvalidScript.h"
#include "eReplicaComponentType.h"
#include "PhysicsComponent.h"
/**
* Component that handles rigid bodies that can be interacted with, mostly client-side rendered. An example is the
* bananas that fall from trees in GF.
*/
class LDFBaseData;
class Entity;
class dpEntity;
enum class ePhysicsEffectType : uint32_t ;
/**
* Allows the creation of phantom physics for an entity: a physics object that is generally invisible but can be
* collided with using various shapes to detect collision on certain points in the map. Generally these are used to
* trigger gameplay events, for example the bus in Avant Gardens that moves around when the player touches its physics
* body. Optionally this object can also have effects, like the fans in AG.
*/
class RigidbodyPhantomPhysicsComponent : public PhysicsComponent {
public:
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::RIGID_BODY_PHANTOM_PHYSICS;
RigidbodyPhantomPhysicsComponent(Entity* parent);
~RigidbodyPhantomPhysicsComponent() override;
void Update(float deltaTime) override;
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override;
};
#endif // __RIGIDBODYPHANTOMPHYSICS_H__
/**
* Creates the physics shape for this entity based on LDF data
*/
void CreatePhysics();
/**
* Sets the position of this physics object
* @param pos the position to set
*/
void SetPosition(const NiPoint3& pos) override;
/**
* Sets the rotation of this physics object
* @param rot the rotation to set
*/
void SetRotation(const NiQuaternion& rot) override;
/**
* Returns the effect that's currently active, defaults to 0
* @return the effect that's currently active
*/
ePhysicsEffectType GetEffectType() const { return m_EffectType; }
/**
* Sets the effect that's currently active
* @param type the effect to set
*/
void SetEffectType(ePhysicsEffectType type);
/**
* Returns the Physics entity for the component
* @return Physics entity for the component
*/
dpEntity* GetdpEntity() const { return m_dpEntity; }
/**
* Spawns an object at each of the vertices for debugging purposes
*/
void SpawnVertices();
private:
/**
* A scale to apply to the size of the physics object
*/
float m_Scale;
/**
* Whether or not the effect has changed and needs to be serialized
*/
bool m_EffectInfoDirty;
/**
* Whether or not there's currently a physics effect active
*/
bool m_IsPhysicsEffectActive;
/**
* The physics effect that's currently active, defaults to 0
*/
ePhysicsEffectType m_EffectType;
/**
* A scaling multiplier to add to the directional vector
*/
float m_DirectionalMultiplier;
bool m_MinMax;
uint32_t m_Min;
uint32_t m_Max;
/**
* Whether or not this physics object is pointed in some direction
*/
bool m_IsDirectional;
/**
* The direction this physics object is pointed in, if any
*/
NiPoint3 m_Direction;
/**
* The parent entity of this component
*/
dpEntity* m_dpEntity;
/**
* Whether or not the physics object has been created yet
*/
bool m_HasCreatedPhysics = false;
/**
* Whether or not this physics object represents an object that updates the respawn pos of an entity that crosses it
*/
bool m_IsRespawnVolume = false;
/**
* If this is a respawn volume, the exact position an entity will respawn
*/
NiPoint3 m_RespawnPos;
/**
* If this is a respawn volume, the exact rotation an entity will respawn
*/
NiQuaternion m_RespawnRot;
};