mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-11-14 15:57:13 +00:00
LWOPlatform moves its object with SetPosition and SetRotation ignoring the dirty flags (ProcessStateChange 0x00cce380), turned between the two waypoints' rotations, and live serialized a moving platform's mover data without its physics. The server's object stayed where it spawned, so anything that asks where a platform is (the lightning orbs' knockback of issue 1352, phantoms riding a platform) had the start of its path. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
103 lines
3.9 KiB
C++
103 lines
3.9 KiB
C++
#ifndef __PHYSICSCOMPONENT__H__
|
|
#define __PHYSICSCOMPONENT__H__
|
|
|
|
#include "Component.h"
|
|
#include "NiPoint3.h"
|
|
#include "NiQuaternion.h"
|
|
#include "dCommonVars.h"
|
|
|
|
struct LwoNameValue;
|
|
|
|
namespace GameMessages {
|
|
struct GetObjectReportInfo;
|
|
struct GetPosition;
|
|
};
|
|
|
|
namespace Raknet {
|
|
class BitStream;
|
|
};
|
|
|
|
enum class eReplicaComponentType : uint32_t;
|
|
|
|
class dpEntity;
|
|
|
|
class PhysicsComponent : public Component {
|
|
public:
|
|
PhysicsComponent(Entity* parent, const int32_t componentID);
|
|
|
|
void LoadDataFromTemplate() override;
|
|
void LoadConfigData() override;
|
|
virtual ~PhysicsComponent();
|
|
|
|
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
|
|
|
|
const NiPoint3& GetPosition() const noexcept { return m_Position; }
|
|
virtual void SetPosition(const NiPoint3& pos) { if (m_Position == pos) return; m_Position = pos; m_DirtyPosition = true; }
|
|
|
|
const NiQuaternion& GetRotation() const { return m_Rotation; }
|
|
virtual void SetRotation(const NiQuaternion& rot) { if (m_Rotation == rot) return; m_Rotation = rot; m_DirtyPosition = true; }
|
|
|
|
// As the client's SetPosition and SetRotation with bIgnoreDirtyFlags: moved without being serialized for it
|
|
void SetPositionAndRotationIgnoringDirtyFlags(const NiPoint3& pos, const NiQuaternion& rot) {
|
|
const bool dirty = m_DirtyPosition;
|
|
SetPosition(pos);
|
|
SetRotation(rot);
|
|
m_DirtyPosition = dirty;
|
|
}
|
|
|
|
int32_t GetCollisionGroup() const noexcept { return m_CollisionGroup; }
|
|
void SetCollisionGroup(int32_t group) noexcept { m_CollisionGroup = group; }
|
|
|
|
/**
|
|
* Whether a level object is carver_only, which the client never loads (LWOResMgr2Interface::Run skips its load
|
|
* when its config has carver_only set; LWOBasePhysComponent::LoadConfigData 0x00c495c9 reads it next to
|
|
* navmesh_carver). Live never sent one.
|
|
*/
|
|
[[nodiscard]] static bool IsCarverOnly(const LwoNameValue& settings);
|
|
|
|
/**
|
|
* For a level object the server doesn't spawn (carver_only): adds its shape to the world's movement blockers, the
|
|
* way its physics component would have (RegisterMovementBlocker), owned by the world.
|
|
* @return whether it blocks movement (its data makes it a wall and the server knows its shape)
|
|
*/
|
|
static bool AddLevelMovementBlocker(LWOOBJID id, LOT lot, const LwoNameValue& settings, const NiPoint3& position, const NiQuaternion& rotation, float scale);
|
|
protected:
|
|
bool OnGetObjectReportInfo(GameMessages::GetObjectReportInfo& msg);
|
|
|
|
// isFallback, when given, says whether the asset had no known shape and got a stand in cube
|
|
dpEntity* CreatePhysicsEntity(eReplicaComponentType type, bool* isFallback = nullptr);
|
|
|
|
/**
|
|
* The shape of the physics asset of a LOT's physics component of the given type, for an object placed with this
|
|
* scale and rotation, or nullptr when it has none. Some shapes move position (in and out) to line up with the
|
|
* client's. isFallback, when given, says whether the asset had no known shape and got a stand in cube.
|
|
*/
|
|
static dpEntity* CreateAssetShape(LWOOBJID id, LOT lot, eReplicaComponentType type, int32_t collisionGroup, float scale, const NiQuaternion& rotation, NiPoint3& position, bool* isFallback = nullptr);
|
|
|
|
/**
|
|
* Makes this object a wall the server's movers can't walk through when its data says it is one
|
|
* (dpMovementBlockers::BlockingFilter: a navmesh carver, or a solid object only enemies collide with). Only
|
|
* shapes the server knows are used; a stand in cube would be a guess.
|
|
*/
|
|
void RegisterMovementBlocker(eReplicaComponentType type, bool solid, float scale);
|
|
|
|
dpEntity* CreatePhysicsLnv(const float scale, const eReplicaComponentType type) const;
|
|
|
|
void SpawnVertices(dpEntity* entity) const;
|
|
|
|
bool OnGetPosition(GameMessages::GetPosition& msg);
|
|
|
|
NiPoint3 m_Position;
|
|
|
|
NiQuaternion m_Rotation = QuatUtils::IDENTITY;
|
|
|
|
bool m_DirtyPosition;
|
|
|
|
int32_t m_CollisionGroup{};
|
|
|
|
// This object's shape as a movement blocker, owned here and not stepped with the physics world
|
|
dpEntity* m_MovementBlocker{};
|
|
};
|
|
|
|
#endif //!__PHYSICSCOMPONENT__H__
|