clickthrough: cascade raycast with custom CanTargetEntity filter bits

Replace the re-raycast approach with a priority cascade: loot > GO > NPC
> normal. Each pass uses custom flag bits (0x01/02/04 in upper byte) that
our CanTargetEntity hook reads to exclude non-matching objects at the
raycast level. Terrain/WMO occlusion applies per pass.

Hook CanTargetEntity (0x480610) for per-object filtering: strips custom
bits before calling original, then checks lootable/interactable/NPC
based on which pass is active. Objects that don't match the current pass
return NULL (invisible to raycast, ray continues through them).

Fix isLootable: UNIT_DYNAMIC_FLAGS was at wrong descriptor offset
(0x96*4=0x258, should be 0x8F*4=0x23C per server UpdateFields index 143).
Also add UNIT_DYNFLAG_TAPPED and UNIT_DYNFLAG_TAPPED_BY_PLAYER offsets.
Fix isLootable base pointer: use getDescriptor (obj+0x08) not
getUnitDescriptor (obj+0x110), consistent with getNpcFlags and all
other descriptor reads in the project.
This commit is contained in:
MarcelineVQ
2026-03-25 01:30:16 -07:00
parent e78ebfd74d
commit 28514c029c
3 changed files with 114 additions and 93 deletions
+1 -1
View File
@@ -124,7 +124,7 @@ pub fn getNpcFlags(obj: u32) u32 {
pub fn isLootable(obj: u32) bool {
const desc = getDescriptor(obj);
if (!isValidPtr(desc)) return 0 != 0;
if (!isValidPtr(desc)) return false;
return (hook.readMem(u32, desc + o.DESC_UNIT_DYNAMIC_FLAGS) & o.UNIT_DYNFLAG_LOOTABLE) != 0;
}