mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-10-02 10:53:44 +00:00
fix(physics): simple-physics motion type and velocity like live
Live's simple-physics constructions (40,786 in the captures): - Motion type Fixed (5) for objects without a motionType (38,970). DLU read the level's motionType and, when there was none, sent 0, a value the client's motion-type enum does not have. - Keyframed (4) for every moving platform (1,059 of 1,059) and for models without behaviors; Dynamic (1) for models with behaviors (655 of 666 model constructions follow this; DLU only switched it when a behavior was added or removed). - No velocity for fixed objects (all 38,970); keyframed and dynamic objects have one. DLU wrote a velocity in every construction. A level-set motionType still wins. Test: ReplicaConstructionTest.SimplePhysicsConstructionLikeLive (values of a captured smashable, LOT 12266); the existing SimplePhysicsTest bytes are unchanged. Check in game: moving platforms (AG, GF, NS, NT), spinners and other simple-physics objects move and collide as before; smashables and static objects stay put; on a property, placed models with and without behaviors sit and run as before, including after picking them up and placing again. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -98,6 +98,12 @@ void ModelComponent::LoadBehaviors() {
|
||||
// add behavior at the back
|
||||
LoadBehavior(behaviorId.value(), m_Behaviors.size(), false);
|
||||
}
|
||||
|
||||
// Live constructed models with behaviors as dynamic and models without as keyframed (655 of 666 model constructions)
|
||||
auto* const simplePhysics = m_Parent->GetComponent<SimplePhysicsComponent>();
|
||||
if (simplePhysics && !m_Parent->HasVar(u"motionType")) {
|
||||
simplePhysics->SetPhysicsMotionState(m_Behaviors.empty() ? SimplePhysicsComponent::MOTION_TYPE_KEYFRAMED : SimplePhysicsComponent::MOTION_TYPE_DYNAMIC);
|
||||
}
|
||||
}
|
||||
|
||||
void ModelComponent::LoadBehavior(const LWOOBJID behaviorID, const size_t index, const bool isIndexed) {
|
||||
|
||||
@@ -65,6 +65,10 @@ MovingPlatformComponent::MovingPlatformComponent(Entity* parent, const int32_t c
|
||||
if (m_Path == nullptr) {
|
||||
LOG("Path not found: %s", pathName.c_str());
|
||||
}
|
||||
|
||||
// Live constructed every moving platform with simple physics as keyframed
|
||||
auto* const simplePhysics = m_Parent->GetComponent<SimplePhysicsComponent>();
|
||||
if (simplePhysics && !m_Parent->HasVar(u"motionType")) simplePhysics->SetPhysicsMotionState(SimplePhysicsComponent::MOTION_TYPE_KEYFRAMED);
|
||||
}
|
||||
|
||||
MovingPlatformComponent::~MovingPlatformComponent() {
|
||||
|
||||
@@ -31,7 +31,8 @@ SimplePhysicsComponent::SimplePhysicsComponent(Entity* parent, const int32_t com
|
||||
} else {
|
||||
SetClimbableType(eClimbableType::CLIMBABLE_TYPE_NOT);
|
||||
}
|
||||
m_PhysicsMotionState = m_Parent->GetVarAs<uint32_t>(u"motionType");
|
||||
// Without a motionType the object is fixed (live: Fixed on 38,970 of 40,786 constructions, never the invalid 0)
|
||||
if (m_Parent->HasVar(u"motionType")) m_PhysicsMotionState = m_Parent->GetVarAs<uint32_t>(u"motionType");
|
||||
}
|
||||
|
||||
SimplePhysicsComponent::~SimplePhysicsComponent() {
|
||||
@@ -50,13 +51,16 @@ void SimplePhysicsComponent::Serialize(RakNet::BitStream& outBitStream, bool bIs
|
||||
outBitStream.Write(m_ClimbableType);
|
||||
}
|
||||
|
||||
outBitStream.Write(m_DirtyVelocity || bIsInitialUpdate);
|
||||
if (m_DirtyVelocity || bIsInitialUpdate) {
|
||||
// Live left the velocity out of a fixed object's construction and wrote it for keyframed and dynamic ones.
|
||||
const bool writeVelocity = bIsInitialUpdate
|
||||
? m_PhysicsMotionState != MOTION_TYPE_FIXED || m_Velocity != NiPoint3Constant::ZERO || m_AngularVelocity != NiPoint3Constant::ZERO
|
||||
: m_DirtyVelocity;
|
||||
outBitStream.Write(writeVelocity);
|
||||
if (writeVelocity) {
|
||||
outBitStream.Write(m_Velocity);
|
||||
outBitStream.Write(m_AngularVelocity);
|
||||
|
||||
m_DirtyVelocity = false;
|
||||
}
|
||||
if (writeVelocity || bIsInitialUpdate) m_DirtyVelocity = false;
|
||||
|
||||
// Physics motion state
|
||||
outBitStream.Write(m_DirtyPhysicsMotionState || bIsInitialUpdate);
|
||||
|
||||
@@ -30,6 +30,11 @@ class SimplePhysicsComponent : public PhysicsComponent {
|
||||
public:
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::SIMPLE_PHYSICS;
|
||||
|
||||
// Havok motion types the client reads as the physics motion state
|
||||
static constexpr uint32_t MOTION_TYPE_DYNAMIC = 1;
|
||||
static constexpr uint32_t MOTION_TYPE_KEYFRAMED = 4;
|
||||
static constexpr uint32_t MOTION_TYPE_FIXED = 5;
|
||||
|
||||
SimplePhysicsComponent(Entity* parent, const int32_t componentID);
|
||||
~SimplePhysicsComponent() override;
|
||||
|
||||
@@ -106,7 +111,7 @@ private:
|
||||
/**
|
||||
* The current physics motion state
|
||||
*/
|
||||
uint32_t m_PhysicsMotionState = 5;
|
||||
uint32_t m_PhysicsMotionState = MOTION_TYPE_FIXED;
|
||||
|
||||
bool m_DirtyPhysicsMotionState = true;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user