Files
DarkflameServer/dPhysics/dpShapeBox.h
Aaron Kimbrell 5d3c2e6f9a fix: filter physics volumes like the client's collision groups
Volumes on the server touched far more than in the client:

- An enemy's body in the physics world was a sphere the size of its aggro
  radius, so trigger and damage volumes caught enemies from far away
  (Cavalry Hill enemies taking damage on spawn). It is now the enemy's
  own radius and collision group from its physics component.
- Trigger volumes ignored their collision group and caught everything.
  dpEntity now filters with the client's collision filter
  (PeCollisionFilter, 1.10.64 0x00fb6940, group table from 0x00fcf9a0):
  POI walls ignore enemies, threat clearing walls ignore players, and
  so on. The aggro sensor keeps seeing only players.
- Rotated boxes were tested as the axis aligned box around them, which
  for a turned wall covers a big square (the AG survival boundary).
  Sphere and point tests now use the box's own axes.

Proximity monitors take an optional collision group like live's
SetProximityRadius; the AM shield generators use live's (10 finds
enemies, 1 finds players).

Fixes #1127
Refs #1971

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:30:54 -05:00

83 lines
1.9 KiB
C++

#pragma once
#include "dpShapeBase.h"
#include <vector>
#include "NiPoint3.h"
#include "NiQuaternion.h"
class dpShapeBox : public dpShapeBase {
public:
dpShapeBox(dpEntity* parentEntity, float width, float height, float depth);
~dpShapeBox();
bool IsColliding(dpShapeBase* other);
const float GetScale() const { return m_Scale; }
const float GetWidth() const { return m_Width; }
const float GetHeight() const { return m_Height; }
const float GetDepth() const { return m_Depth; }
const float GetMaxWidth();
const float GetTop();
const float GetMaxDepth();
const float GetMinWidth();
const float GetBottom();
const float GetMinDepth();
void SetScale(float scale);
void SetRotation(const NiQuaternion& rotation);
const std::vector<NiPoint3>& GetVertices() const { return m_Vertices; }
bool IsVertInBox(const NiPoint3& vert);
/**
* The squared distance from a point to the box, measured along the box's own (rotated) axes. The m_Min/m_Max
* bounds are the axis aligned box around the rotated one, which for a rotated wall is far bigger than the wall.
*/
float SquaredDistanceTo(const NiPoint3& point) const;
void InitVertices();
void SetPosition(const NiPoint3& position);
//idc atm
float m_MinX = 9999.0f;
float m_MaxX = -9999.0f;
float m_MinY = 9999.0f;
float m_MaxY = -9999.0f;
float m_MinZ = 9999.0f;
float m_MaxZ = -9999.0f;
private:
float m_Width; //X
float m_Height; //Y
float m_Depth; //Z
std::vector<NiPoint3> m_Vertices;
NiPoint3 m_TopMinLeft;
NiPoint3 m_TopMinRight;
NiPoint3 m_TopMaxLeft;
NiPoint3 m_TopMaxRight;
NiPoint3 m_BottomMinLeft;
NiPoint3 m_BottomMinRight;
NiPoint3 m_BottomMaxLeft;
NiPoint3 m_BottomMaxRight;
float m_Scale;
// Where the box was placed and how it was turned, to test against its real shape
NiPoint3 m_Origin{};
NiQuaternion m_Orientation = QuatUtils::IDENTITY;
bool m_HasBeenRotated = false;
bool isScaled = false;
bool isTransformed = false;
void InsertVertices();
};