mirror of https://github.com/zeldaret/botw.git
				
				
				
			ksys/phys: Add more EntityGroupFilter functions
This commit is contained in:
		
							parent
							
								
									b3b97a93aa
								
							
						
					
					
						commit
						c32557b793
					
				| 
						 | 
				
			
			@ -83797,17 +83797,17 @@ Address,Quality,Size,Name
 | 
			
		|||
0x0000007100fb503c,O,000096,_ZThn32_N4ksys4phys17EntityGroupFilterD0Ev
 | 
			
		||||
0x0000007100fb509c,O,000096,_ZThn40_N4ksys4phys17EntityGroupFilterD0Ev
 | 
			
		||||
0x0000007100fb50fc,O,000032,_ZN4ksys4phys17EntityGroupFilter7doInit_EPN4sead4HeapE
 | 
			
		||||
0x0000007100fb511c,U,001440,phys::EntityGroupFilter::isCollisionEnabled
 | 
			
		||||
0x0000007100fb511c,m,001440,_ZNK4ksys4phys17EntityGroupFilter24testCollisionForEntitiesEjj
 | 
			
		||||
0x0000007100fb56bc,O,000268,_ZNK4ksys4phys17EntityGroupFilter18isCollisionEnabledERK13hkpCollidableS4_
 | 
			
		||||
0x0000007100fb57c8,O,000028,_ZThn16_NK4ksys4phys17EntityGroupFilter18isCollisionEnabledERK13hkpCollidableS4_
 | 
			
		||||
0x0000007100fb57e4,O,000176,_ZNK4ksys4phys17EntityGroupFilter18isCollisionEnabledERK17hkpCollisionInputRK9hkpCdBodyS7_RK17hkpShapeContainerSA_jj
 | 
			
		||||
0x0000007100fb5894,O,000176,_ZThn24_NK4ksys4phys17EntityGroupFilter18isCollisionEnabledERK17hkpCollisionInputRK9hkpCdBodyS7_RK17hkpShapeContainerSA_jj
 | 
			
		||||
0x0000007100fb5944,O,000304,_ZNK4ksys4phys17EntityGroupFilter18isCollisionEnabledERK17hkpCollisionInputRK9hkpCdBodyS7_RK17hkpShapeContainerj
 | 
			
		||||
0x0000007100fb5a74,O,000028,_ZThn24_NK4ksys4phys17EntityGroupFilter18isCollisionEnabledERK17hkpCollisionInputRK9hkpCdBodyS7_RK17hkpShapeContainerj
 | 
			
		||||
0x0000007100fb5a90,U,000284,phys::EntityGroupFilter::isCollisionEnabled__3
 | 
			
		||||
0x0000007100fb5bac,U,000284,
 | 
			
		||||
0x0000007100fb5cc8,U,000256,phys::EntityGroupFilter::isCollisionEnabled__4
 | 
			
		||||
0x0000007100fb5dc8,U,000028,
 | 
			
		||||
0x0000007100fb5a90,O,000284,_ZNK4ksys4phys17EntityGroupFilter18isCollisionEnabledERK20hkpShapeRayCastInputRK17hkpShapeContainerj
 | 
			
		||||
0x0000007100fb5bac,O,000284,_ZThn32_NK4ksys4phys17EntityGroupFilter18isCollisionEnabledERK20hkpShapeRayCastInputRK17hkpShapeContainerj
 | 
			
		||||
0x0000007100fb5cc8,O,000256,_ZNK4ksys4phys17EntityGroupFilter18isCollisionEnabledERK20hkpWorldRayCastInputRK13hkpCollidable
 | 
			
		||||
0x0000007100fb5dc8,O,000028,_ZThn40_NK4ksys4phys17EntityGroupFilter18isCollisionEnabledERK20hkpWorldRayCastInputRK13hkpCollidable
 | 
			
		||||
0x0000007100fb5de4,O,000192,_ZN4ksys4phys17EntityGroupFilter30doInitSystemGroupHandlerLists_EPN4sead4HeapE
 | 
			
		||||
0x0000007100fb5ea4,O,000016,_ZN4ksys4phys17EntityGroupFilter16getFreeListIndexEPKNS0_18SystemGroupHandlerE
 | 
			
		||||
0x0000007100fb5eb4,O,000036,_ZN4ksys4phys21orEntityGroundHitMaskEjNS0_9GroundHitE
 | 
			
		||||
| 
						 | 
				
			
			@ -83815,29 +83815,29 @@ Address,Quality,Size,Name
 | 
			
		|||
0x0000007100fb5f14,O,000032,_ZN4ksys4phys23makeEntityGroundHitMaskENS0_12ContactLayerEj
 | 
			
		||||
0x0000007100fb5f34,O,000068,_ZN4ksys4phys23makeEntityCollisionMaskENS0_12ContactLayerEj
 | 
			
		||||
0x0000007100fb5f78,O,000036,_ZN4ksys4phys31setEntityCollisionMaskGroundHitENS0_9GroundHitEj
 | 
			
		||||
0x0000007100fb5f9c,U,000084,EntitySystemGroupHandler::m5
 | 
			
		||||
0x0000007100fb5ff0,U,000048,EntitySystemGroupHandler::m6
 | 
			
		||||
0x0000007100fb6020,U,000040,EntitySystemGroupHandler::m7
 | 
			
		||||
0x0000007100fb6048,U,000020,EntitySystemGroupHandler::m8
 | 
			
		||||
0x0000007100fb5f9c,O,000084,_ZN4ksys4phys24EntitySystemGroupHandler23makeCollisionFilterInfoEjNS0_12ContactLayerENS0_9GroundHitE
 | 
			
		||||
0x0000007100fb5ff0,O,000048,_ZN4ksys4phys24EntitySystemGroupHandler22makeQueryCollisionMaskEjNS0_9GroundHitEb
 | 
			
		||||
0x0000007100fb6020,O,000040,_ZN4ksys4phys24EntitySystemGroupHandler30makeRagdollCollisionFilterInfoENS0_9GroundHitE
 | 
			
		||||
0x0000007100fb6048,O,000020,_ZN4ksys4phys24EntitySystemGroupHandler2m8Ev
 | 
			
		||||
0x0000007100fb605c,O,000112,_ZNK4ksys4phys18SystemGroupHandler27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE
 | 
			
		||||
0x0000007100fb60cc,O,000092,_ZNK4ksys4phys18SystemGroupHandler18getRuntimeTypeInfoEv
 | 
			
		||||
0x0000007100fb6128,O,000004,_ZN4ksys4phys18SystemGroupHandlerD2Ev
 | 
			
		||||
0x0000007100fb612c,O,000004,_ZN4ksys4phys18SystemGroupHandlerD0Ev
 | 
			
		||||
0x0000007100fb612c,O,000004,_ZN4ksys4phys24EntitySystemGroupHandlerD0Ev
 | 
			
		||||
0x0000007100fb6130,O,000004,_ZN18hkpCollisionFilter4initEP8hkpWorld
 | 
			
		||||
0x0000007100fb6134,O,000008,_ZN14hkpGroupFilter11dummyUnusedEv
 | 
			
		||||
0x0000007100fb613c,O,000204,_ZNK4ksys4phys17EntityGroupFilter27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE
 | 
			
		||||
0x0000007100fb6208,O,000092,_ZNK4ksys4phys17EntityGroupFilter18getRuntimeTypeInfoEv
 | 
			
		||||
0x0000007100fb6264,U,000044,phys::EntityGroupFilter::m2
 | 
			
		||||
0x0000007100fb6290,U,000028,phys::EntityGroupFilter::m3
 | 
			
		||||
0x0000007100fb62ac,U,000020,phys::EntityGroupFilter::m4
 | 
			
		||||
0x0000007100fb62c0,U,000028,phys::EntityGroupFilter::m5
 | 
			
		||||
0x0000007100fb62dc,U,000008,phys::EntityGroupFilter::m6
 | 
			
		||||
0x0000007100fb62e4,U,000040,phys::EntityGroupFilter::m7
 | 
			
		||||
0x0000007100fb630c,U,000048,phys::EntityGroupFilter::m8_GetStringGroundHitMaskModeOrSensorText
 | 
			
		||||
0x0000007100fb6264,O,000044,_ZN4ksys4phys17EntityGroupFilter2m2ENS0_12ContactLayerES2_
 | 
			
		||||
0x0000007100fb6290,O,000028,_ZN4ksys4phys17EntityGroupFilter23makeCollisionFilterInfoENS0_12ContactLayerENS0_9GroundHitE
 | 
			
		||||
0x0000007100fb62ac,O,000020,_ZN4ksys4phys17EntityGroupFilter27getCollisionFilterInfoLayerEj
 | 
			
		||||
0x0000007100fb62c0,O,000028,_ZN4ksys4phys17EntityGroupFilter22makeQueryCollisionMaskEjNS0_9GroundHitEb
 | 
			
		||||
0x0000007100fb62dc,O,000008,_ZN4ksys4phys17EntityGroupFilter30getQueryCollisionMaskGroundHitEj
 | 
			
		||||
0x0000007100fb62e4,O,000040,_ZN4ksys4phys17EntityGroupFilter39getCollisionFilterInfoLayerAndGroundHitEjPNS0_12ContactLayerEPNS0_9GroundHitE
 | 
			
		||||
0x0000007100fb630c,O,000048,_ZN4ksys4phys17EntityGroupFilter31getCollisionFilterInfoLayerTextEj
 | 
			
		||||
0x0000007100fb633c,O,000036,_ZN4ksys4phys17EntityGroupFilter18setLayerCustomMaskENS0_12ContactLayerEj
 | 
			
		||||
0x0000007100fb6360,U,000008,phys::EntityGroupFilter::m10
 | 
			
		||||
0x0000007100fb6368,U,000044,phys::EntityGroupFilter::m14
 | 
			
		||||
0x0000007100fb6394,U,000028,phys::EntityGroupFilter::m15
 | 
			
		||||
0x0000007100fb6360,O,000008,_ZN4ksys4phys17EntityGroupFilter37getCollisionFilterInfoGroupHandlerIdxEj
 | 
			
		||||
0x0000007100fb6368,O,000044,_ZN4ksys4phys17EntityGroupFilter23makeCollisionFilterInfoENS0_12ContactLayerENS0_9GroundHitEjj
 | 
			
		||||
0x0000007100fb6394,O,000028,_ZN4ksys4phys17EntityGroupFilter34setEntityLayerCollisionEnabledMaskENS0_12ContactLayerEj
 | 
			
		||||
0x0000007100fb63b0,O,000140,_ZNK4sead15RuntimeTypeInfo6DeriveIN4ksys4phys11GroupFilterEE9isDerivedEPKNS0_9InterfaceE
 | 
			
		||||
0x0000007100fb643c,U,000108,phys::makeEntityContactListener
 | 
			
		||||
0x0000007100fb64a8,U,000004,j_ksys::phys::ContactListener::dtor
 | 
			
		||||
| 
						 | 
				
			
			@ -93391,7 +93391,7 @@ Address,Quality,Size,Name
 | 
			
		|||
0x0000007101213c68,O,000148,_ZN4ksys4phys11GroupFilter7destroyEv
 | 
			
		||||
0x0000007101213cfc,O,000160,_ZN4ksys4phys11GroupFilter21addSystemGroupHandlerEi
 | 
			
		||||
0x0000007101213d9c,O,000148,_ZN4ksys4phys11GroupFilter24removeSystemGroupHandlerEPNS0_18SystemGroupHandlerE
 | 
			
		||||
0x0000007101213e30,O,000008,_ZN4ksys4phys18SystemGroupHandler2m7Ev
 | 
			
		||||
0x0000007101213e30,O,000008,_ZN4ksys4phys18SystemGroupHandler30makeRagdollCollisionFilterInfoENS0_9GroundHitE
 | 
			
		||||
0x0000007101213e38,O,000024,_ZN4ksys4phys18SystemGroupHandler10removeThisEv
 | 
			
		||||
0x0000007101213e50,O,000112,_ZNK4ksys4phys11GroupFilter27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE
 | 
			
		||||
0x0000007101213ec0,O,000092,_ZNK4ksys4phys11GroupFilter18getRuntimeTypeInfoEv
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
		
		
			 Can't render this file because it is too large. 
		
	 | 
| 
						 | 
				
			
			@ -63,6 +63,7 @@ public:
 | 
			
		|||
    inline hkUint32 getCollisionFilterInfo() const;
 | 
			
		||||
    inline void setCollisionFilterInfo(hkUint32 info);
 | 
			
		||||
 | 
			
		||||
    /// @see hkpWorldObject::BroadPhaseType
 | 
			
		||||
    inline int getType() const;
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,8 +2,8 @@
 | 
			
		|||
 | 
			
		||||
#include <Havok/Common/Base/Types/hkBaseTypes.h>
 | 
			
		||||
 | 
			
		||||
class hkpWorldRayCastInput;
 | 
			
		||||
class hkpCollidable;
 | 
			
		||||
struct hkpWorldRayCastInput;
 | 
			
		||||
 | 
			
		||||
class hkpRayCollidableFilter {
 | 
			
		||||
public:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -602,8 +602,8 @@ void RigidBody::enableGroundCollision(bool enabled) {
 | 
			
		|||
 | 
			
		||||
    const auto current_info = getEntityCollisionFilterInfo();
 | 
			
		||||
    auto info = current_info;
 | 
			
		||||
    info.unk5 = false;
 | 
			
		||||
    info.no_ground_collision.SetBit(!enabled);
 | 
			
		||||
    info.ground_col_mode =
 | 
			
		||||
        enabled ? GroundCollisionMode::Normal : GroundCollisionMode::IgnoreGround;
 | 
			
		||||
    if (current_info != info)
 | 
			
		||||
        setCollisionFilterInfo(info.raw);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -615,9 +615,8 @@ bool RigidBody::isGroundCollisionEnabled() const {
 | 
			
		|||
    const auto info = getEntityCollisionFilterInfo();
 | 
			
		||||
 | 
			
		||||
    bool enabled = false;
 | 
			
		||||
    enabled |= info.unk5;
 | 
			
		||||
    enabled |= info.ground_col_mode != GroundCollisionMode::IgnoreGround;
 | 
			
		||||
    enabled |= info.unk30;
 | 
			
		||||
    enabled |= !info.no_ground_collision;
 | 
			
		||||
    return enabled;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -630,7 +629,7 @@ void RigidBody::enableWaterCollision(bool enabled) {
 | 
			
		|||
 | 
			
		||||
    const auto current_info = getEntityCollisionFilterInfo();
 | 
			
		||||
    auto info = current_info;
 | 
			
		||||
    info.no_water_collision = !enabled;
 | 
			
		||||
    info.water_col_mode = enabled ? WaterCollisionMode::Normal : WaterCollisionMode::IgnoreWater;
 | 
			
		||||
    if (current_info != info)
 | 
			
		||||
        setCollisionFilterInfo(info.raw);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -644,7 +643,7 @@ bool RigidBody::isWaterCollisionEnabled() const {
 | 
			
		|||
    bool enabled = false;
 | 
			
		||||
    // unk30 enables all collisions?
 | 
			
		||||
    enabled |= info.unk30;
 | 
			
		||||
    enabled |= !info.no_water_collision;
 | 
			
		||||
    enabled |= info.water_col_mode != WaterCollisionMode::IgnoreWater;
 | 
			
		||||
    return enabled;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,11 +2,15 @@
 | 
			
		|||
#include <Havok/Physics2012/Collide/Agent/Collidable/hkpCollidable.h>
 | 
			
		||||
#include <Havok/Physics2012/Collide/Agent/hkpCollisionInput.h>
 | 
			
		||||
#include <Havok/Physics2012/Collide/Dispatch/hkpCollisionDispatcher.h>
 | 
			
		||||
#include <Havok/Physics2012/Collide/Query/CastUtil/hkpWorldRayCastInput.h>
 | 
			
		||||
#include <Havok/Physics2012/Collide/Shape/Compound/Collection/hkpShapeCollection.h>
 | 
			
		||||
#include <Havok/Physics2012/Collide/Shape/Compound/Tree/hkpBvTreeShape.h>
 | 
			
		||||
#include <Havok/Physics2012/Collide/Shape/Query/hkpShapeRayCastInput.h>
 | 
			
		||||
#include <Havok/Physics2012/Collide/Shape/hkpShapeContainer.h>
 | 
			
		||||
#include <Havok/Physics2012/Dynamics/World/hkpWorldObject.h>
 | 
			
		||||
#include <heap/seadHeap.h>
 | 
			
		||||
#include "Havok/Physics2012/Dynamics/Entity/hkpEntity.h"
 | 
			
		||||
#include "KingSystem/Physics/RigidBody/physRigidBody.h"
 | 
			
		||||
#include "KingSystem/Physics/System/physContactMgr.h"
 | 
			
		||||
#include "KingSystem/Physics/System/physSystem.h"
 | 
			
		||||
#include "KingSystem/Utils/BitField.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -49,16 +53,170 @@ void EntityGroupFilter::doInit_(sead::Heap* heap) {
 | 
			
		|||
    mMasks.fill(0xffffffff);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
hkBool EntityGroupFilter::isCollisionEnabledPhantom(u32 infoPhantom, u32 infoB) const {
 | 
			
		||||
hkBool EntityGroupFilter::shouldHandleGroundCollision(u32 infoA, u32 infoB,
 | 
			
		||||
                                                      ContactLayer::ValueType layerA,
 | 
			
		||||
                                                      ContactLayer::ValueType layerB) const {
 | 
			
		||||
    const EntityCollisionFilterInfo a{infoA};
 | 
			
		||||
    const EntityCollisionFilterInfo b{infoB};
 | 
			
		||||
 | 
			
		||||
    if (EntityCollisionFilterInfo(infoA | infoB).ground_col_mode != GroundCollisionMode::Normal) {
 | 
			
		||||
        if (a.ground_col_mode != GroundCollisionMode::Normal) {
 | 
			
		||||
            bool ground = isEntityGroundLayer(layerB);
 | 
			
		||||
            if (a.ground_col_mode == GroundCollisionMode::IgnoreNonGround && !ground)
 | 
			
		||||
                return false;
 | 
			
		||||
            if (a.ground_col_mode == GroundCollisionMode::IgnoreGround && ground)
 | 
			
		||||
                return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (b.ground_col_mode != GroundCollisionMode::Normal) {
 | 
			
		||||
            bool ground = isEntityGroundLayer(layerA);
 | 
			
		||||
            if (b.ground_col_mode == GroundCollisionMode::IgnoreNonGround && !ground)
 | 
			
		||||
                return false;
 | 
			
		||||
            if (b.ground_col_mode == GroundCollisionMode::IgnoreGround && ground)
 | 
			
		||||
                return false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
hkBool EntityGroupFilter::shouldHandleWaterCollision(u32 infoA, u32 infoB,
 | 
			
		||||
                                                     ContactLayer::ValueType layerA,
 | 
			
		||||
                                                     ContactLayer::ValueType layerB) const {
 | 
			
		||||
    const EntityCollisionFilterInfo a{infoA};
 | 
			
		||||
    const EntityCollisionFilterInfo b{infoB};
 | 
			
		||||
 | 
			
		||||
    if (EntityCollisionFilterInfo(infoA | infoB).water_col_mode != WaterCollisionMode::Normal) {
 | 
			
		||||
        if (a.water_col_mode == WaterCollisionMode::IgnoreWater &&
 | 
			
		||||
            layerB == ContactLayer::EntityWater) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        if (b.water_col_mode == WaterCollisionMode::IgnoreWater &&
 | 
			
		||||
            layerA == ContactLayer::EntityWater) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// XXX: find a better name
 | 
			
		||||
static bool testHandler(u32 idx) {
 | 
			
		||||
    return idx != 0 && idx <= 15;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NON_MATCHING: deduplicated branch: `return a.data.query_custom_receiver_layer_mask & (1 << ...)`
 | 
			
		||||
hkBool EntityGroupFilter::testCollisionForEntities(u32 infoA, u32 infoB) const {
 | 
			
		||||
    if (mInhibitCollisions)
 | 
			
		||||
        return false;
 | 
			
		||||
 | 
			
		||||
    // TODO: figure out what kind of mask infoPhantom is. Receiver/sensor mask?
 | 
			
		||||
    // RigidBodyParam::getParams and ContactInfoTable seem to manipulate similar looking masks.
 | 
			
		||||
    const EntityCollisionFilterInfo a{infoA};
 | 
			
		||||
    const EntityCollisionFilterInfo b{infoB};
 | 
			
		||||
 | 
			
		||||
    constexpr auto GroupHandlerIdxMask = decltype(a.group_handler_index)::GetMask();
 | 
			
		||||
    constexpr auto GroupHandlerIdxShift = decltype(a.group_handler_index)::StartBit();
 | 
			
		||||
 | 
			
		||||
    if (!EntityCollisionFilterInfo(infoA | infoB).is_ground_hit_mask) {
 | 
			
		||||
        if (a.unk30 && b.unk30) {
 | 
			
		||||
            if (((infoA ^ infoB) & GroupHandlerIdxMask) != 0) {
 | 
			
		||||
                if (testHandler(a.group_handler_index) || testHandler(b.group_handler_index))
 | 
			
		||||
                    return false;
 | 
			
		||||
            } else if ((infoA & GroupHandlerIdxMask) >> GroupHandlerIdxShift != 0) {
 | 
			
		||||
                if (a.data.unk5 == b.data.unk10 || b.data.unk5 == a.data.unk10)
 | 
			
		||||
                    return false;
 | 
			
		||||
            }
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const auto layerA = static_cast<ContactLayer::ValueType>(a.data.layer.Value());
 | 
			
		||||
        const auto layerB = static_cast<ContactLayer::ValueType>(b.data.layer.Value());
 | 
			
		||||
 | 
			
		||||
        if (layerA != ContactLayer::EntityQueryCustomReceiver &&
 | 
			
		||||
            layerB != ContactLayer::EntityQueryCustomReceiver) {
 | 
			
		||||
            if (!a.unk30 && !b.unk30) {
 | 
			
		||||
                if (!shouldHandleGroundCollision(infoA, infoB, layerA, layerB))
 | 
			
		||||
                    return false;
 | 
			
		||||
                if (!shouldHandleWaterCollision(infoA, infoB, layerA, layerB))
 | 
			
		||||
                    return false;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (((infoA ^ infoB) & GroupHandlerIdxMask) != 0) {
 | 
			
		||||
                if (testHandler(a.group_handler_index) || testHandler(b.group_handler_index))
 | 
			
		||||
                    return false;
 | 
			
		||||
            } else if (((infoA & GroupHandlerIdxMask) >> GroupHandlerIdxShift) > 15) {
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
            return testLayerCollision(layerA, layerB);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (layerA == ContactLayer::EntityQueryCustomReceiver &&
 | 
			
		||||
            layerB == ContactLayer::EntityQueryCustomReceiver) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (layerA == ContactLayer::EntityQueryCustomReceiver)
 | 
			
		||||
            return a.data.query_custom_receiver_layer_mask & (1 << layerB);
 | 
			
		||||
        else
 | 
			
		||||
            return b.data.query_custom_receiver_layer_mask & (1 << layerA);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (a.is_ground_hit_mask && b.is_ground_hit_mask) {
 | 
			
		||||
        const auto layerA = static_cast<ContactLayer::ValueType>(a.ground_hit.layer.Value());
 | 
			
		||||
        const auto layerB = static_cast<ContactLayer::ValueType>(b.ground_hit.layer.Value());
 | 
			
		||||
 | 
			
		||||
        if (!shouldHandleGroundCollision(infoA, infoB, layerA, layerB))
 | 
			
		||||
            return false;
 | 
			
		||||
        if (!shouldHandleWaterCollision(infoA, infoB, layerA, layerB))
 | 
			
		||||
            return false;
 | 
			
		||||
        if (!testLayerCollision(layerA, layerB))
 | 
			
		||||
            return false;
 | 
			
		||||
        return !a.ground_hit.unk23 && !b.ground_hit.unk23;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    EntityCollisionFilterInfo entity_mask, ground_hit_mask;
 | 
			
		||||
 | 
			
		||||
    if (a.is_ground_hit_mask && !b.is_ground_hit_mask) {
 | 
			
		||||
        const auto layerA = static_cast<ContactLayer::ValueType>(a.ground_hit.layer.Value());
 | 
			
		||||
        const auto layerB = static_cast<ContactLayer::ValueType>(b.data.layer.Value());
 | 
			
		||||
        entity_mask = b;
 | 
			
		||||
        ground_hit_mask = a;
 | 
			
		||||
 | 
			
		||||
        if (layerB == ContactLayer::EntityQueryCustomReceiver)
 | 
			
		||||
            return b.data.query_custom_receiver_layer_mask & (1 << layerA);
 | 
			
		||||
 | 
			
		||||
        if (!b.unk30 && !shouldHandleGroundCollision(infoA, infoB, layerA, layerB))
 | 
			
		||||
            return false;
 | 
			
		||||
        if (!b.unk30 && !shouldHandleWaterCollision(infoA, infoB, layerA, layerB))
 | 
			
		||||
            return false;
 | 
			
		||||
        if (!testLayerCollision(layerA, layerB))
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
    } else /* A entity, B ground hit */ {
 | 
			
		||||
        const auto layerA = static_cast<ContactLayer::ValueType>(a.data.layer.Value());
 | 
			
		||||
        const auto layerB = static_cast<ContactLayer::ValueType>(b.ground_hit.layer.Value());
 | 
			
		||||
        entity_mask = a;
 | 
			
		||||
        ground_hit_mask = b;
 | 
			
		||||
 | 
			
		||||
        if (layerA == ContactLayer::EntityQueryCustomReceiver)
 | 
			
		||||
            return a.data.query_custom_receiver_layer_mask & (1 << layerB);
 | 
			
		||||
 | 
			
		||||
        if (!a.unk30 && !shouldHandleGroundCollision(infoA, infoB, layerA, layerB))
 | 
			
		||||
            return false;
 | 
			
		||||
        if (!a.unk30 && !shouldHandleWaterCollision(infoA, infoB, layerA, layerB))
 | 
			
		||||
            return false;
 | 
			
		||||
        if (!testLayerCollision(layerB, layerA))
 | 
			
		||||
            return false;
 | 
			
		||||
    }
 | 
			
		||||
    return !(ground_hit_mask.ground_hit.ground_hit_types & (1 << entity_mask.data.ground_hit));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
hkBool EntityGroupFilter::testCollisionForPhantom(u32 infoPhantom, u32 infoB) const {
 | 
			
		||||
    if (mInhibitCollisions)
 | 
			
		||||
        return false;
 | 
			
		||||
 | 
			
		||||
    RayCastCollisionMask infoPhantomData{infoPhantom};
 | 
			
		||||
    const EntityCollisionFilterInfo info{infoB};
 | 
			
		||||
    if (info.is_ground_hit_mask)
 | 
			
		||||
        return infoPhantom & (1 << info.ground_hit.getLayer());
 | 
			
		||||
    return (infoPhantom & (1 << info.data.layer)) & 0x1ffff;
 | 
			
		||||
        return infoPhantomData.raw & (1 << info.ground_hit.getLayer());
 | 
			
		||||
    return infoPhantomData.layer_mask & (1 << info.data.layer);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
hkBool EntityGroupFilter::isCollisionEnabled(const hkpCollidable& a, const hkpCollidable& b) const {
 | 
			
		||||
| 
						 | 
				
			
			@ -69,19 +227,19 @@ hkBool EntityGroupFilter::isCollisionEnabled(const hkpCollidable& a, const hkpCo
 | 
			
		|||
 | 
			
		||||
    if (a.getType() == hkpWorldObject::BROAD_PHASE_PHANTOM) {
 | 
			
		||||
        if (a.getShape() != nullptr)
 | 
			
		||||
            return isCollisionEnabled(a.getCollisionFilterInfo(), b.getCollisionFilterInfo());
 | 
			
		||||
            return testCollisionForEntities(a.getCollisionFilterInfo(), b.getCollisionFilterInfo());
 | 
			
		||||
 | 
			
		||||
        return isCollisionEnabledPhantom(a.getCollisionFilterInfo(), b.getCollisionFilterInfo());
 | 
			
		||||
        return testCollisionForPhantom(a.getCollisionFilterInfo(), b.getCollisionFilterInfo());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (b.getType() == hkpWorldObject::BROAD_PHASE_PHANTOM) {
 | 
			
		||||
        if (b.getShape() != nullptr)
 | 
			
		||||
            return isCollisionEnabled(a.getCollisionFilterInfo(), b.getCollisionFilterInfo());
 | 
			
		||||
            return testCollisionForEntities(a.getCollisionFilterInfo(), b.getCollisionFilterInfo());
 | 
			
		||||
 | 
			
		||||
        return isCollisionEnabledPhantom(b.getCollisionFilterInfo(), a.getCollisionFilterInfo());
 | 
			
		||||
        return testCollisionForPhantom(b.getCollisionFilterInfo(), a.getCollisionFilterInfo());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return isCollisionEnabled(a.getCollisionFilterInfo(), b.getCollisionFilterInfo());
 | 
			
		||||
    return testCollisionForEntities(a.getCollisionFilterInfo(), b.getCollisionFilterInfo());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
hkBool EntityGroupFilter::isCollisionEnabled(const hkpCollisionInput& input,
 | 
			
		||||
| 
						 | 
				
			
			@ -98,7 +256,7 @@ hkBool EntityGroupFilter::isCollisionEnabled(const hkpCollisionInput& input,
 | 
			
		|||
    if (infoB == 0xffffffff)
 | 
			
		||||
        infoB = collectionBodyB.getRootCollidable()->getCollisionFilterInfo();
 | 
			
		||||
 | 
			
		||||
    return isCollisionEnabled(infoA, infoB);
 | 
			
		||||
    return testCollisionForEntities(infoA, infoB);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
hkBool EntityGroupFilter::isCollisionEnabled(const hkpCollisionInput& input, const hkpCdBody& a,
 | 
			
		||||
| 
						 | 
				
			
			@ -150,7 +308,72 @@ hkBool EntityGroupFilter::isCollisionEnabled(const hkpCollisionInput& input, con
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
end:
 | 
			
		||||
    return isCollisionEnabled(infoA, infoB);
 | 
			
		||||
    return testCollisionForEntities(infoA, infoB);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static hkBool
 | 
			
		||||
checkCollisionWithGroundHitMask(EntityCollisionFilterInfo::GroundHitMask ground_hit_mask,
 | 
			
		||||
                                RayCastCollisionMask ray_cast) {
 | 
			
		||||
    if (!(ray_cast.layer_mask & (1 << ground_hit_mask.getLayer())))
 | 
			
		||||
        return false;
 | 
			
		||||
 | 
			
		||||
    if (ground_hit_mask.unk & ray_cast.unk)
 | 
			
		||||
        return false;
 | 
			
		||||
 | 
			
		||||
    if (ground_hit_mask.ground_hit_types & (1 << ray_cast.ground_hit_type))
 | 
			
		||||
        return false;
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
hkBool EntityGroupFilter::testCollisionForRayCasting(u32 infoRayCast, u32 info) const {
 | 
			
		||||
    if (mInhibitCollisions)
 | 
			
		||||
        return false;
 | 
			
		||||
 | 
			
		||||
    RayCastCollisionMask a{infoRayCast};
 | 
			
		||||
    EntityCollisionFilterInfo b{info};
 | 
			
		||||
 | 
			
		||||
    if (b.is_ground_hit_mask)
 | 
			
		||||
        return checkCollisionWithGroundHitMask(b.ground_hit, a);
 | 
			
		||||
 | 
			
		||||
    const u32 bHandlerIdx = b.group_handler_index;
 | 
			
		||||
    const u32 aHandlerIdx = a.group_handler_index;
 | 
			
		||||
 | 
			
		||||
    if (aHandlerIdx == bHandlerIdx) {
 | 
			
		||||
        if (bHandlerIdx > 15)
 | 
			
		||||
            return false;
 | 
			
		||||
        return a.layer_mask & (1 << b.data.layer);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (testHandler(aHandlerIdx) || testHandler(bHandlerIdx))
 | 
			
		||||
        return false;
 | 
			
		||||
 | 
			
		||||
    return a.layer_mask & (1 << b.data.layer);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
KSYS_ALWAYS_INLINE hkBool EntityGroupFilter::isCollisionEnabled(const hkpShapeRayCastInput& aInput,
 | 
			
		||||
                                                                const hkpShapeContainer& bContainer,
 | 
			
		||||
                                                                hkpShapeKey bKey) const {
 | 
			
		||||
    u32 bInfo = bContainer.getCollisionFilterInfo(bKey);
 | 
			
		||||
    if (bInfo == 0)
 | 
			
		||||
        return true;
 | 
			
		||||
 | 
			
		||||
    if (bInfo == 0xffffffff)
 | 
			
		||||
        bInfo = aInput.m_collidable->getCollisionFilterInfo();
 | 
			
		||||
 | 
			
		||||
    return testCollisionForRayCasting(aInput.m_filterInfo, bInfo);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
hkBool EntityGroupFilter::isCollisionEnabled(const hkpWorldRayCastInput& inputA,
 | 
			
		||||
                                             const hkpCollidable& collidableB) const {
 | 
			
		||||
    if (collidableB.getType() == hkpWorldObject::BROAD_PHASE_ENTITY) {
 | 
			
		||||
        auto* entity = static_cast<const hkpEntity*>(collidableB.getOwner());
 | 
			
		||||
        auto* body = entity ? reinterpret_cast<RigidBody*>(entity->getUserData()) : nullptr;
 | 
			
		||||
        if (body && body->hasFlag(RigidBody::Flag::_200))
 | 
			
		||||
            return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return testCollisionForRayCasting(inputA.m_filterInfo, collidableB.getCollisionFilterInfo());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void EntityGroupFilter::doInitSystemGroupHandlerLists_(sead::Heap* heap) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,7 +13,8 @@ public:
 | 
			
		|||
    explicit EntitySystemGroupHandler(int i) : SystemGroupHandler(i, ContactLayerType::Entity) {}
 | 
			
		||||
 | 
			
		||||
    u32 makeCollisionFilterInfo(u32 info, ContactLayer layer, GroundHit ground_hit) override;
 | 
			
		||||
    u32 m6() override;
 | 
			
		||||
    u32 makeQueryCollisionMask(u32 layer_mask, GroundHit ground_hit, bool unk) override;
 | 
			
		||||
    u32 makeRagdollCollisionFilterInfo(GroundHit ground_hit) override;
 | 
			
		||||
    bool m8() override;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -40,27 +41,42 @@ public:
 | 
			
		|||
    hkBool isCollisionEnabled(const hkpWorldRayCastInput& inputA,
 | 
			
		||||
                              const hkpCollidable& collidableB) const override;
 | 
			
		||||
 | 
			
		||||
    bool m2() override { return GroupFilter::m2(); }
 | 
			
		||||
    void m3() override {}
 | 
			
		||||
    void m4() override {}
 | 
			
		||||
    void m5() override {}
 | 
			
		||||
    void m6() override {}
 | 
			
		||||
    void m7() override {}
 | 
			
		||||
    void m8() override {}
 | 
			
		||||
    bool m2(ContactLayer layerA, ContactLayer layerB) override;
 | 
			
		||||
    u32 makeCollisionFilterInfo(ContactLayer layer, GroundHit ground_hit) override;
 | 
			
		||||
    ContactLayer getCollisionFilterInfoLayer(u32 info) override;
 | 
			
		||||
    u32 makeQueryCollisionMask(u32 layer_mask, GroundHit ground_hit, bool unk) override;
 | 
			
		||||
    GroundHit getQueryCollisionMaskGroundHit(u32 info) override;
 | 
			
		||||
    void getCollisionFilterInfoLayerAndGroundHit(u32 info, ContactLayer* layer,
 | 
			
		||||
                                                 GroundHit* ground_hit) override;
 | 
			
		||||
    const char* getCollisionFilterInfoLayerText(u32 info) override;
 | 
			
		||||
    void setLayerCustomMask(ContactLayer layer, u32 mask) override;
 | 
			
		||||
    u32 getCollisionFilterInfoGroupHandlerIdx(u32 info) override;
 | 
			
		||||
 | 
			
		||||
    void setLayerCustomMask(ContactLayer layer, u32 mask) override { mMasks[layer] = mask; }
 | 
			
		||||
 | 
			
		||||
    void m10() override {}
 | 
			
		||||
    virtual u32 makeCollisionFilterInfo(ContactLayer layer, GroundHit ground_hit, u32 unk5,
 | 
			
		||||
                                        u32 unk10);
 | 
			
		||||
    /// @param layer An entity layer
 | 
			
		||||
    virtual void setEntityLayerCollisionEnabledMask(ContactLayer layer, u32 mask);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    hkBool isCollisionEnabled(u32 infoA, u32 infoB) const;
 | 
			
		||||
    hkBool isCollisionEnabledPhantom(u32 infoPhantom, u32 infoB) const;
 | 
			
		||||
    /// Checks whether two entities are colliding.
 | 
			
		||||
    hkBool testCollisionForEntities(u32 infoA, u32 gh_mask) const;
 | 
			
		||||
    /// Checks whether a phantom and an entity are colliding with each other.
 | 
			
		||||
    hkBool testCollisionForPhantom(u32 infoPhantom, u32 infoB) const;
 | 
			
		||||
    /// Checks whether a ray cast and an entity are colliding with each other.
 | 
			
		||||
    hkBool testCollisionForRayCasting(u32 infoRayCast, u32 info) const;
 | 
			
		||||
 | 
			
		||||
    hkBool shouldHandleGroundCollision(u32 infoA, u32 infoB, ContactLayer::ValueType layerA,
 | 
			
		||||
                                       ContactLayer::ValueType layerB) const;
 | 
			
		||||
    hkBool shouldHandleWaterCollision(u32 infoA, u32 infoB, ContactLayer::ValueType layerA,
 | 
			
		||||
                                      ContactLayer::ValueType layerB) const;
 | 
			
		||||
 | 
			
		||||
    hkBool testLayerCollision(ContactLayer::ValueType a, ContactLayer::ValueType b) const {
 | 
			
		||||
        return m_collisionLookupTable[a] & (1 << b);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void doInitSystemGroupHandlerLists_(sead::Heap* heap) override;
 | 
			
		||||
    int getFreeListIndex(const SystemGroupHandler* handler) override;
 | 
			
		||||
    void doInit_(sead::Heap* heap) override;
 | 
			
		||||
    virtual void m14();
 | 
			
		||||
    virtual void m15();
 | 
			
		||||
 | 
			
		||||
    sead::SafeArray<u32, ContactLayer::size()> mMasks;
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -84,4 +100,111 @@ u32 makeEntityCollisionMask(ContactLayer layer, u32 mask);
 | 
			
		|||
/// Updates the collision mask with the specified ground hit type (*not* mask).
 | 
			
		||||
u32 setEntityCollisionMaskGroundHit(GroundHit ground_hit, u32 mask);
 | 
			
		||||
 | 
			
		||||
inline u32 EntitySystemGroupHandler::makeCollisionFilterInfo(u32 info, ContactLayer layer,
 | 
			
		||||
                                                             GroundHit ground_hit) {
 | 
			
		||||
    const EntityCollisionFilterInfo current_info{info};
 | 
			
		||||
    EntityCollisionFilterInfo result;
 | 
			
		||||
 | 
			
		||||
    if (layer == ContactLayer::EntityRagdoll) {
 | 
			
		||||
        result.data.layer.Init(layer);
 | 
			
		||||
        result.data.unk5.Init(current_info.data.unk5);
 | 
			
		||||
        result.data.unk10.Init(current_info.data.unk10);
 | 
			
		||||
        result.group_handler_index.Init(getIndex());
 | 
			
		||||
        result.data.ground_hit.Init(ground_hit);
 | 
			
		||||
        result.unk30 = true;
 | 
			
		||||
    } else {
 | 
			
		||||
        result.data.layer.Init(layer);
 | 
			
		||||
        result.ground_col_mode.Init(current_info.ground_col_mode);
 | 
			
		||||
        result.group_handler_index.Init(getIndex());
 | 
			
		||||
        result.data.ground_hit.Init(ground_hit);
 | 
			
		||||
    }
 | 
			
		||||
    return result.raw;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline u32 EntitySystemGroupHandler::makeQueryCollisionMask(u32 layer_mask, GroundHit ground_hit,
 | 
			
		||||
                                                            bool unk) {
 | 
			
		||||
    RayCastCollisionMask mask;
 | 
			
		||||
    mask.layer_mask = layer_mask;
 | 
			
		||||
    mask.group_handler_index.Init(getIndex());
 | 
			
		||||
    mask.ground_hit_type.Init(static_cast<GroundHit::ValueType>(int(ground_hit)));
 | 
			
		||||
    mask.unk.SetBit(unk);
 | 
			
		||||
    return mask.raw;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline u32 EntitySystemGroupHandler::makeRagdollCollisionFilterInfo(GroundHit ground_hit) {
 | 
			
		||||
    EntityCollisionFilterInfo info;
 | 
			
		||||
    info.data.layer.Init(ContactLayer::EntityRagdoll);
 | 
			
		||||
    info.group_handler_index.Init(getIndex());
 | 
			
		||||
    info.data.ground_hit.Init(ground_hit);
 | 
			
		||||
    return info.raw;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline bool EntitySystemGroupHandler::m8() {
 | 
			
		||||
    return getIndex() > 0 && getIndex() < 0x400;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline bool EntityGroupFilter::m2(ContactLayer layerA, ContactLayer layerB) {
 | 
			
		||||
    return (mMasks[layerA.value()] & (1 << layerB.value())) == 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline u32 EntityGroupFilter::makeCollisionFilterInfo(ContactLayer layer, GroundHit ground_hit) {
 | 
			
		||||
    return EntityCollisionFilterInfo::make(layer, ground_hit).raw;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline ContactLayer EntityGroupFilter::getCollisionFilterInfoLayer(u32 info) {
 | 
			
		||||
    return EntityCollisionFilterInfo(info).getLayer();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline u32 EntityGroupFilter::makeQueryCollisionMask(u32 layer_mask, GroundHit ground_hit,
 | 
			
		||||
                                                     bool unk) {
 | 
			
		||||
    RayCastCollisionMask mask;
 | 
			
		||||
    mask.layer_mask = layer_mask;
 | 
			
		||||
    mask.ground_hit_type = ground_hit.value();
 | 
			
		||||
    mask.unk.SetBit(unk);
 | 
			
		||||
    return mask.raw;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline GroundHit EntityGroupFilter::getQueryCollisionMaskGroundHit(u32 info) {
 | 
			
		||||
    return RayCastCollisionMask(info).ground_hit_type.Value();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void EntityGroupFilter::getCollisionFilterInfoLayerAndGroundHit(u32 info,
 | 
			
		||||
                                                                       ContactLayer* layer,
 | 
			
		||||
                                                                       GroundHit* ground_hit) {
 | 
			
		||||
    EntityCollisionFilterInfo info_{info};
 | 
			
		||||
    *layer = info_.getLayer();
 | 
			
		||||
    *ground_hit = info_.getGroundHit();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline const char* EntityGroupFilter::getCollisionFilterInfoLayerText(u32 info) {
 | 
			
		||||
    EntityCollisionFilterInfo info_{info};
 | 
			
		||||
    if (info_.is_ground_hit_mask) {
 | 
			
		||||
        return "GroundHitMaskMode";
 | 
			
		||||
    }
 | 
			
		||||
    return contactLayerToText(getCollisionFilterInfoLayer(info));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void EntityGroupFilter::setLayerCustomMask(ContactLayer layer, u32 mask) {
 | 
			
		||||
    mMasks[layer] = mask;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline u32 EntityGroupFilter::getCollisionFilterInfoGroupHandlerIdx(u32 info) {
 | 
			
		||||
    return EntityCollisionFilterInfo(info).group_handler_index;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline u32 EntityGroupFilter::makeCollisionFilterInfo(ContactLayer layer, GroundHit ground_hit,
 | 
			
		||||
                                                      u32 unk5, u32 unk10) {
 | 
			
		||||
    EntityCollisionFilterInfo info;
 | 
			
		||||
    info.data.layer.Init(layer);
 | 
			
		||||
    info.data.unk5.Init(unk5);
 | 
			
		||||
    info.data.unk10.Init(unk10);
 | 
			
		||||
    info.data.ground_hit.Init(ground_hit);
 | 
			
		||||
    info.unk30 = true;
 | 
			
		||||
    return info.raw;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void EntityGroupFilter::setEntityLayerCollisionEnabledMask(ContactLayer layer, u32 mask) {
 | 
			
		||||
    m_collisionLookupTable[layer] = mask;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace ksys::phys
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -50,7 +50,7 @@ void GroupFilter::removeSystemGroupHandler(SystemGroupHandler* handler) {
 | 
			
		|||
    mUsedList.erase(handler);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
u32 SystemGroupHandler::m7() {
 | 
			
		||||
u32 SystemGroupHandler::makeRagdollCollisionFilterInfo(GroundHit ground_hit) {
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,8 +18,8 @@ public:
 | 
			
		|||
 | 
			
		||||
    virtual ~SystemGroupHandler() = default;
 | 
			
		||||
    virtual u32 makeCollisionFilterInfo(u32 info, ContactLayer layer, GroundHit ground_hit) = 0;
 | 
			
		||||
    virtual u32 m6() = 0;
 | 
			
		||||
    virtual u32 m7();
 | 
			
		||||
    virtual u32 makeQueryCollisionMask(u32 layer_mask, GroundHit ground_hit, bool unk) = 0;
 | 
			
		||||
    virtual u32 makeRagdollCollisionFilterInfo(GroundHit ground_hit);
 | 
			
		||||
    virtual bool m8() = 0;
 | 
			
		||||
 | 
			
		||||
    int getIndex() const { return mIndex; }
 | 
			
		||||
| 
						 | 
				
			
			@ -75,15 +75,31 @@ public:
 | 
			
		|||
        m_collisionLookupTable[layer - getLayerFirst()] = mask;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual bool m2() { return true; }
 | 
			
		||||
    virtual void m3() = 0;
 | 
			
		||||
    virtual void m4() = 0;
 | 
			
		||||
    virtual void m5() = 0;
 | 
			
		||||
    virtual void m6() = 0;
 | 
			
		||||
    virtual void m7() = 0;
 | 
			
		||||
    virtual void m8() = 0;
 | 
			
		||||
    virtual bool m2(ContactLayer layerA, ContactLayer layerB) { return true; }
 | 
			
		||||
 | 
			
		||||
    /// Make a collision filter mask with the specified layer and ground hit type.
 | 
			
		||||
    virtual u32 makeCollisionFilterInfo(ContactLayer layer, GroundHit ground_hit) = 0;
 | 
			
		||||
 | 
			
		||||
    /// Get the layer from a collision filter mask.
 | 
			
		||||
    virtual ContactLayer getCollisionFilterInfoLayer(u32 info) = 0;
 | 
			
		||||
 | 
			
		||||
    /// Make a query collision mask with the specified layer mask, ground hit type and flag.
 | 
			
		||||
    virtual u32 makeQueryCollisionMask(u32 layer_mask, GroundHit ground_hit, bool unk) = 0;
 | 
			
		||||
 | 
			
		||||
    /// Get the ground hit type from a query collision mask.
 | 
			
		||||
    virtual GroundHit getQueryCollisionMaskGroundHit(u32 info) = 0;
 | 
			
		||||
 | 
			
		||||
    /// Get the layer and ground hit type from a collision filter mask.
 | 
			
		||||
    virtual void getCollisionFilterInfoLayerAndGroundHit(u32 info, ContactLayer* layer,
 | 
			
		||||
                                                         GroundHit* ground_hit) = 0;
 | 
			
		||||
 | 
			
		||||
    /// Get the layer from a collision filter mask.
 | 
			
		||||
    virtual const char* getCollisionFilterInfoLayerText(u32 info) = 0;
 | 
			
		||||
 | 
			
		||||
    virtual void setLayerCustomMask(ContactLayer layer, u32 mask) {}
 | 
			
		||||
    virtual void m10() = 0;
 | 
			
		||||
 | 
			
		||||
    /// Get the group handler index from a collision filter mask.
 | 
			
		||||
    virtual u32 getCollisionFilterInfoGroupHandlerIdx(u32 info) = 0;
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    virtual void doInitSystemGroupHandlerLists_(sead::Heap* heap) = 0;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -80,6 +80,11 @@ constexpr auto LastEntity = ContactLayer::EntityMeshVisualizer;
 | 
			
		|||
constexpr auto FirstSensor = ContactLayer::SensorObject;
 | 
			
		||||
constexpr auto LastSensor = ContactLayer::SensorCustomReceiver;
 | 
			
		||||
 | 
			
		||||
constexpr bool isEntityGroundLayer(ContactLayer::ValueType layer) {
 | 
			
		||||
    return layer == ContactLayer::EntityGround || layer == ContactLayer::EntityGroundSmooth ||
 | 
			
		||||
           layer == ContactLayer::EntityGroundRough;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SEAD_ENUM(Material,
 | 
			
		||||
Undefined,\
 | 
			
		||||
Soil,\
 | 
			
		||||
| 
						 | 
				
			
			@ -180,6 +185,22 @@ enum class MotionType {
 | 
			
		|||
    Invalid = -1,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum class GroundCollisionMode {
 | 
			
		||||
    /// Ground collision is not handled in any special way.
 | 
			
		||||
    Normal = 0,
 | 
			
		||||
    /// Any collision with a non-ground layer is ignored.
 | 
			
		||||
    IgnoreNonGround = 1,
 | 
			
		||||
    /// Any collision with a ground layer is ignored.
 | 
			
		||||
    IgnoreGround = 2,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum class WaterCollisionMode {
 | 
			
		||||
    /// Water collision is not handled in any special way.
 | 
			
		||||
    Normal = 0,
 | 
			
		||||
    /// Any collision with a water layer is ignored.
 | 
			
		||||
    IgnoreWater = 1,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
union ReceiverMask {
 | 
			
		||||
    union Data {
 | 
			
		||||
        util::BitField<0, 5, u32> layer;
 | 
			
		||||
| 
						 | 
				
			
			@ -229,6 +250,12 @@ union EntityCollisionFilterInfo {
 | 
			
		|||
 | 
			
		||||
        u32 raw;
 | 
			
		||||
        util::BitField<0, 5, u32> layer;
 | 
			
		||||
        // TODO: figure out what this is
 | 
			
		||||
        util::BitField<5, 5, u32> unk5;
 | 
			
		||||
        util::BitField<10, 5, u32> unk10;
 | 
			
		||||
        /// Layers to collide with for EntityQueryCustomReceiver entities.
 | 
			
		||||
        // XXX: was 17 chosen because ContactLayer::EntityQueryCustomReceiver = 17?
 | 
			
		||||
        util::BitField<5, 17, u32> query_custom_receiver_layer_mask;
 | 
			
		||||
        util::BitField<24, 1, u32> unk24;
 | 
			
		||||
        util::BitField<25, 1, u32> unk25;
 | 
			
		||||
        util::BitField<26, 4, u32> ground_hit;
 | 
			
		||||
| 
						 | 
				
			
			@ -244,7 +271,7 @@ union EntityCollisionFilterInfo {
 | 
			
		|||
        u32 raw;
 | 
			
		||||
        util::BitField<0, 1, u32> unk;
 | 
			
		||||
        util::BitField<8, 16, u32> ground_hit_types;
 | 
			
		||||
        util::BitField<24, 1, u32> unk24;
 | 
			
		||||
        util::BitField<23, 1, u32> unk23;
 | 
			
		||||
        util::BitField<25, 5, u32> layer;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -281,17 +308,35 @@ union EntityCollisionFilterInfo {
 | 
			
		|||
    u32 raw;
 | 
			
		||||
    Data data;
 | 
			
		||||
    GroundHitMask ground_hit;
 | 
			
		||||
    util::BitField<5, 1, bool, u32> unk5;
 | 
			
		||||
    /// Whether ground collision is disabled.
 | 
			
		||||
    util::BitField<6, 1, bool, u32> no_ground_collision;
 | 
			
		||||
    /// Whether water collision is disabled.
 | 
			
		||||
    util::BitField<7, 1, bool, u32> no_water_collision;
 | 
			
		||||
    util::BitField<5, 2, GroundCollisionMode, u32> ground_col_mode;
 | 
			
		||||
    util::BitField<7, 1, WaterCollisionMode, u32> water_col_mode;
 | 
			
		||||
    util::BitField<16, 10, u32> group_handler_index;
 | 
			
		||||
    /// If this flag is set, then this entity will always collide with ground or water,
 | 
			
		||||
    /// regardless of the configured GroundCollisionMode or WaterCollisionMode modes.
 | 
			
		||||
    // TODO: is this "is_ragdoll"? See EntitySystemGroupHandler::makeCollisionFilterInfo.
 | 
			
		||||
    util::BitField<30, 1, bool, u32> unk30;
 | 
			
		||||
    util::BitField<31, 1, bool, u32> is_ground_hit_mask;
 | 
			
		||||
};
 | 
			
		||||
static_assert(sizeof(EntityCollisionFilterInfo) == sizeof(u32));
 | 
			
		||||
 | 
			
		||||
/// Collision mask that is used for raycast-based queries.
 | 
			
		||||
union RayCastCollisionMask {
 | 
			
		||||
    constexpr explicit RayCastCollisionMask(u32 raw_ = 0) : raw(raw_) {}
 | 
			
		||||
    constexpr RayCastCollisionMask(const RayCastCollisionMask&) = default;
 | 
			
		||||
    constexpr RayCastCollisionMask& operator=(const RayCastCollisionMask& m) {
 | 
			
		||||
        raw = m.raw;
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
    constexpr bool operator==(RayCastCollisionMask rhs) const { return raw == rhs.raw; }
 | 
			
		||||
    constexpr bool operator!=(RayCastCollisionMask rhs) const { return raw != rhs.raw; }
 | 
			
		||||
 | 
			
		||||
    util::BitField<0, 17, u32> layer_mask;
 | 
			
		||||
    util::BitField<17, 1, u32> unk;
 | 
			
		||||
    util::BitField<18, 10, u32> group_handler_index;
 | 
			
		||||
    util::BitField<28, 4, GroundHit::ValueType, u32> ground_hit_type;
 | 
			
		||||
    u32 raw;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
ContactLayerType getContactLayerType(ContactLayer layer);
 | 
			
		||||
u32 makeContactLayerMask(ContactLayer layer);
 | 
			
		||||
u32 getContactLayerBase(ContactLayerType type);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -132,8 +132,7 @@ struct BitField {
 | 
			
		|||
 | 
			
		||||
    template <auto bits_ = bits, typename = std::enable_if_t<bits_ == 1>>
 | 
			
		||||
    inline constexpr void SetBit(bool set) {
 | 
			
		||||
        const auto mask = set ? ((static_cast<StorageType>(1) << position) & GetMask()) : 0;
 | 
			
		||||
        storage = (storage & ~GetMask()) | mask;
 | 
			
		||||
        storage = (storage & ~GetMask()) | (set ? GetMask() : 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @warning This does *not* check whether the value fits within the mask,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue