Files
DarkflameServer/dPhysics/dpShapeBox.h
Aaron Kimbrell 425b913848 feat(physics): movement blockers the server's movers can't walk through
Enemies are moved along navmesh paths without collision, so a wall only stops
them if their path stops at it. dpWorld now keeps a list of such walls, each
with the collision filter it blocks with, and cuts a path where it first walks
into one (a little short of the wall; a mover inside one can walk out).

Which objects block comes from data (dpMovementBlockers::BlockingFilter):
- navmesh carvers (navmesh_carver in the level config, which the client reads
  with add_to_navmesh and carver_only) block every mover;
- solid objects whose collision group touches enemies and not players (group 18,
  e.g. "FV - Enemy Blocking Volume", "PR - Pet Blocker") block what that group
  touches.

dpShapeBox gains SegmentEntry, a segment test against the rotated box.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 17:52:02 -05:00

91 lines
2.3 KiB
C++

#pragma once
#include "dpShapeBase.h"
#include <optional>
#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;
/**
* Where the segment from a to b first goes into the box, as a fraction of the way from a to b (0 to 1), tested
* against the box's real (rotated) shape. Empty when the segment misses the box, or starts inside it (so
* something already in the box can always leave it).
*/
std::optional<float> SegmentEntry(const NiPoint3& a, const NiPoint3& b) 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();
};