diff --git a/data/uking_functions.csv b/data/uking_functions.csv index 4bb3b282..34eb2f1a 100644 --- a/data/uking_functions.csv +++ b/data/uking_functions.csv @@ -82969,7 +82969,7 @@ Address,Quality,Size,Name 0x0000007100f8cc98,O,000172,_ZN4ksys4phys9RigidBody18initMotionAccessorERKNS0_22RigidBodyInstanceParamEPN4sead4HeapEb 0x0000007100f8cd44,O,000552,_ZN4ksys4phys9RigidBody12createMotionEP16hkpMaxSizeMotionNS0_10MotionTypeERKNS0_22RigidBodyInstanceParamE 0x0000007100f8cf6c,O,000052,_ZNK4ksys4phys9RigidBody13getHkBodyNameEv -0x0000007100f8cfa0,U,000424,phys::RigidBody::x_0 +0x0000007100f8cfa0,m,000424,_ZN4ksys4phys9RigidBody3x_0Ev 0x0000007100f8d148,O,000144,_ZN4ksys4phys9RigidBody13setMotionFlagENS1_10MotionFlagE 0x0000007100f8d1d8,O,000032,_ZNK4ksys4phys9RigidBody8isActiveEv 0x0000007100f8d1f8,O,000012,_ZNK4ksys4phys9RigidBody10isFlag8SetEv @@ -82987,14 +82987,14 @@ Address,Quality,Size,Name 0x0000007100f8e3fc,U,000816,phys::RigidBody::x_11 0x0000007100f8e72c,U,000136,phys::RigidBody::x_12 0x0000007100f8e7b4,O,000052,_ZN4ksys4phys9RigidBody16setContactPointsEPNS0_18RigidContactPointsE -0x0000007100f8e7e8,U,000724,phys::RigidBody::x_13 -0x0000007100f8e8f0,U,000460,phys::RigidBody::x_14 -0x0000007100f8eabc,U,000384,phys::RigidBody::x_15 +0x0000007100f8e7e8,O,000264,_ZN4ksys4phys9RigidBody26setFixedAndPreserveImpulseEbb +0x0000007100f8e8f0,O,000460,_ZN4ksys4phys9RigidBody6freezeEbbb +0x0000007100f8eabc,O,000384,_ZN4ksys4phys9RigidBody8setFixedEbb 0x0000007100f8ec3c,O,000312,_ZN4ksys4phys9RigidBody17setLinearVelocityERKN4sead7Vector3IfEEf 0x0000007100f8ed74,O,000196,_ZN4ksys4phys9RigidBody18setAngularVelocityERKN4sead7Vector3IfEEf 0x0000007100f8ee38,O,000024,_ZN4ksys4phys9RigidBody16resetFrozenStateEv 0x0000007100f8ee50,U,000048,phys::RigidBody::x_17 -0x0000007100f8ee80,U,000384,phys::RigidBody::x_2 +0x0000007100f8ee80,O,000384,_ZN4ksys4phys9RigidBody27updateCollidableQualityTypeEb 0x0000007100f8f000,U,000012,phys::RigidBody::x_18 0x0000007100f8f00c,U,000080,phys::RigidBody::x_19 0x0000007100f8f05c,U,000080,phys::RigidBody::x_20 diff --git a/lib/hkStubs/Havok/Physics2012/Collide/Agent/Collidable/hkpCollidableQualityType.h b/lib/hkStubs/Havok/Physics2012/Collide/Agent/Collidable/hkpCollidableQualityType.h index c795ffa6..035b1d32 100644 --- a/lib/hkStubs/Havok/Physics2012/Collide/Agent/Collidable/hkpCollidableQualityType.h +++ b/lib/hkStubs/Havok/Physics2012/Collide/Agent/Collidable/hkpCollidableQualityType.h @@ -1,6 +1,6 @@ #pragma once -enum hkpCollidableQualityType { +enum hkpCollidableQualityType : int { HK_COLLIDABLE_QUALITY_INVALID = -1, HK_COLLIDABLE_QUALITY_FIXED = 0, HK_COLLIDABLE_QUALITY_KEYFRAMED, diff --git a/src/KingSystem/Physics/RigidBody/physRigidBody.cpp b/src/KingSystem/Physics/RigidBody/physRigidBody.cpp index bb2b8c8c..5b1a6dbb 100644 --- a/src/KingSystem/Physics/RigidBody/physRigidBody.cpp +++ b/src/KingSystem/Physics/RigidBody/physRigidBody.cpp @@ -176,6 +176,32 @@ sead::SafeString RigidBody::getHkBodyName() const { return name; } +// NON_MATCHING: ldr w8, [x20, #0x68] should be ldr w8, [x22] (equivalent) +void RigidBody::x_0() { + // debug code that survived because mFlags is atomic + static_cast(isFlag8Set()); + + auto lock = makeScopedLock(false); + + if (mMotionAccessor) { + const bool use_system_time_factor = hasFlag(Flag::_100); + setTimeFactor(use_system_time_factor ? MemSystem::instance()->getTimeFactor() : 1.0f); + + if (isSensor()) { + auto* accessor = sead::DynamicCast(mMotionAccessor); + if (accessor->hasFlag(RigidBodyMotionSensor::Flag::_400000)) + return; + } + } + + if (isMotionFlag2Set()) { + mMotionFlags.reset(MotionFlag::_2); + mMotionFlags.set(MotionFlag::_1); + } else if (!isMotionFlag1Set()) { + setMotionFlag(MotionFlag::_1); + } +} + void RigidBody::setMotionFlag(MotionFlag flag) { auto lock = sead::makeScopedLock(mCS); @@ -288,11 +314,91 @@ void RigidBody::setContactPoints(RigidContactPoints* points) { MemSystem::instance()->registerContactPoints(points); } +void RigidBody::freeze(bool should_freeze, bool preserve_velocities, bool preserve_max_impulse) { + if (hasFlag(Flag::_80000) == should_freeze) { + if (should_freeze) { + setLinearVelocity(sead::Vector3f::zero); + setAngularVelocity(sead::Vector3f::zero); + } + return; + } + + if (!mMotionAccessor) { + mFlags.change(Flag::_80000, should_freeze); + return; + } + + if (should_freeze) { + mMotionAccessor->freeze(true, preserve_velocities, preserve_max_impulse); + mFlags.set(Flag::_80000); + } else { + mFlags.reset(Flag::_80000); + mMotionAccessor->freeze(false, preserve_velocities, preserve_max_impulse); + } +} + +void RigidBody::setFixedAndPreserveImpulse(bool fixed, bool mark_linear_vel_as_dirty) { + if (hasFlag(Flag::_20000) != fixed) { + mFlags.change(Flag::_20000, fixed); + if (!fixed && mark_linear_vel_as_dirty) { + setMotionFlag(MotionFlag::DirtyLinearVelocity); + } + } + + freeze(hasFlag(Flag::_20000) || hasFlag(Flag::_40000), true, true); +} + +void RigidBody::setFixed(bool fixed, bool preserve_velocities) { + if (hasFlag(Flag::_40000) != fixed) { + mFlags.change(Flag::_40000, fixed); + if (!fixed) { + setMotionFlag(MotionFlag::DirtyLinearVelocity); + setMotionFlag(MotionFlag::_40000); + } + } + + freeze(hasFlag(Flag::_20000) || hasFlag(Flag::_40000), preserve_velocities, false); +} + void RigidBody::resetFrozenState() { if (mMotionAccessor) mMotionAccessor->resetFrozenState(); } +void RigidBody::updateCollidableQualityType(bool high_quality) { + auto lock = makeScopedLock(isFlag8Set()); + + if (isCharacterControllerType()) { + setCollidableQualityType(HK_COLLIDABLE_QUALITY_CHARACTER); + mFlags.set(Flag::IsCharacterController); + return; + } + + switch (getMotionType()) { + case MotionType::Dynamic: + setCollidableQualityType(high_quality ? HK_COLLIDABLE_QUALITY_BULLET : + HK_COLLIDABLE_QUALITY_DEBRIS_SIMPLE_TOI); + break; + case MotionType::Fixed: + setCollidableQualityType(HK_COLLIDABLE_QUALITY_FIXED); + break; + case MotionType::Keyframed: + setCollidableQualityType(isEntity() && high_quality ? + HK_COLLIDABLE_QUALITY_MOVING : + HK_COLLIDABLE_QUALITY_KEYFRAMED_REPORTING); + break; + case MotionType::Unknown: + case MotionType::Invalid: + break; + } + + mFlags.change(Flag::IsCharacterController, high_quality); +} + +void RigidBody::setCollidableQualityType(hkpCollidableQualityType quality) { + getHkBody()->getCollidableRw()->setQualityType(quality); +} + void RigidBody::setContactMask(u32 value) { mContactMask.setDirect(value); } diff --git a/src/KingSystem/Physics/RigidBody/physRigidBody.h b/src/KingSystem/Physics/RigidBody/physRigidBody.h index 470ce470..4b5c1b22 100644 --- a/src/KingSystem/Physics/RigidBody/physRigidBody.h +++ b/src/KingSystem/Physics/RigidBody/physRigidBody.h @@ -12,6 +12,7 @@ #include "KingSystem/Physics/System/physDefines.h" #include "KingSystem/Utils/Types.h" +enum hkpCollidableQualityType : int; class hkQuaternionf; class hkVector4f; class hkpRigidBody; @@ -129,7 +130,6 @@ public: sead::SafeString getHkBodyName() const; - // 0x0000007100f8cfa0 void x_0(); bool isActive() const; @@ -175,15 +175,13 @@ public: // 0x0000007100f8e7b4 void setContactPoints(RigidContactPoints* points); - // 0x0000007100f8e7e8 - void x_13(bool a, bool b); - // 0x0000007100f8e8f0 - void x_14(bool a, bool b, bool c); - // 0x0000007100f8eabc - void x_15(bool a, bool b); - // 0x0000007100f8ee38 + void freeze(bool should_freeze, bool preserve_velocities, bool preserve_max_impulse); + void setFixedAndPreserveImpulse(bool fixed, bool mark_linear_vel_as_dirty); + void setFixed(bool fixed, bool preserve_velocities); void resetFrozenState(); + void updateCollidableQualityType(bool high_quality); + u32 addContactLayer(ContactLayer); u32 removeContactLayer(ContactLayer); void setContactMask(u32); @@ -371,6 +369,7 @@ private: void onInvalidParameter(int code = 0); void notifyUserTag(int code); void updateDeactivation(); + void setCollidableQualityType(hkpCollidableQualityType quality); sead::CriticalSection mCS; sead::TypedBitFlag> mFlags{}; diff --git a/src/KingSystem/Physics/RigidBody/physRigidBodyMotionSensor.h b/src/KingSystem/Physics/RigidBody/physRigidBodyMotionSensor.h index eb6f72fb..c9fd4a98 100644 --- a/src/KingSystem/Physics/RigidBody/physRigidBodyMotionSensor.h +++ b/src/KingSystem/Physics/RigidBody/physRigidBodyMotionSensor.h @@ -15,6 +15,7 @@ public: HasExtraTranslateForLinkedRigidBody = 1 << 19, HasExtraRotateForLinkedRigidBody = 1 << 20, HasLinkedRigidBodyWithoutFlag10 = 1 << 21, + _400000 = 1 << 22, }; explicit RigidBodyMotionSensor(RigidBody* body); @@ -61,6 +62,8 @@ public: mFrozenAngularVelocity.set(0, 0, 0); } + bool hasFlag(Flag flag) const { return mFlags.isOn(flag); } + private: void setTransformImpl(const sead::Matrix34f& mtx); diff --git a/src/KingSystem/Physics/System/physMemSystem.h b/src/KingSystem/Physics/System/physMemSystem.h index 143c9764..fecebe56 100644 --- a/src/KingSystem/Physics/System/physMemSystem.h +++ b/src/KingSystem/Physics/System/physMemSystem.h @@ -30,6 +30,7 @@ class MemSystem { virtual ~MemSystem(); public: + float getTimeFactor() const { return mTimeFactor; } GroupFilter* getGroupFilter(ContactLayerType type) const; ContactMgr* getContactMgr() const { return mContactMgr; } RigidBodyRequestMgr* getRigidBodyRequestMgr() const { return mRigidBodyRequestMgr; } @@ -57,7 +58,9 @@ public: void unlockWorld(ContactLayerType type, void* a = nullptr, int b = 0, bool c = false); private: - u8 _28[0xa8 - 0x28]; + u8 _28[0x74 - 0x28]; + float mTimeFactor{}; + u8 _78[0xa8 - 0x78]; sead::CriticalSection mCS; void* _e8{}; void* _f0{};