feat(physics): port canonical retail set-position core
This commit is contained in:
parent
6b28ff999c
commit
e84a388e6f
6 changed files with 1952 additions and 21 deletions
155
src/AcDream.Core/Physics/PhysicsSetPosition.cs
Normal file
155
src/AcDream.Core/Physics/PhysicsSetPosition.cs
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
using System.Collections.Immutable;
|
||||
using System.Numerics;
|
||||
|
||||
namespace AcDream.Core.Physics;
|
||||
|
||||
/// <summary>
|
||||
/// Retail <c>SetPositionError</c> (<c>acclient.h</c>, enum 491). This is
|
||||
/// deliberately independent of <see cref="PhysicsResidenceDisposition"/>:
|
||||
/// losing the destination cell is a successful SetPosition operation whose
|
||||
/// residence is deferred, not a placement error.
|
||||
/// </summary>
|
||||
internal enum PhysicsSetPositionError
|
||||
{
|
||||
Ok = 0,
|
||||
GeneralFailure = 1,
|
||||
NoValidPosition = 2,
|
||||
NoCell = 3,
|
||||
Collided = 4,
|
||||
InvalidArguments = 0x100,
|
||||
}
|
||||
|
||||
internal enum PhysicsResidenceDisposition
|
||||
{
|
||||
Committed,
|
||||
DeferredCell,
|
||||
Unchanged,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shadow-list operation performed by retail's SetPosition commit tail.
|
||||
/// Recalculate delegates to the canonical live shadow-shape owner (the
|
||||
/// PhysicsBSP/bounding-box path cannot be reconstructed from placement
|
||||
/// spheres); Replace consumes <see cref="PhysicsSetPositionResult.CrossCellIds"/>;
|
||||
/// Preserve intentionally leaves the existing list untouched.
|
||||
/// </summary>
|
||||
internal enum PhysicsShadowCommitAction
|
||||
{
|
||||
None,
|
||||
Recalculate,
|
||||
Replace,
|
||||
Preserve,
|
||||
}
|
||||
|
||||
internal readonly record struct PhysicsSetPositionCollisionReport(
|
||||
bool ContactPlaneValid,
|
||||
Plane ContactPlane,
|
||||
uint ContactPlaneCellId,
|
||||
bool ContactPlaneIsWater,
|
||||
bool LastKnownContactPlaneValid,
|
||||
Plane LastKnownContactPlane,
|
||||
uint LastKnownContactPlaneCellId,
|
||||
bool LastKnownContactPlaneIsWater,
|
||||
bool SlidingNormalValid,
|
||||
Vector3 SlidingNormal,
|
||||
bool CollisionNormalValid,
|
||||
Vector3 CollisionNormal,
|
||||
bool CollidedWithEnvironment,
|
||||
int FramesStationaryFall,
|
||||
Vector3 AdjustOffset,
|
||||
uint? LastCollidedObjectId,
|
||||
ImmutableArray<uint> CollidedObjectIds);
|
||||
|
||||
[Flags]
|
||||
internal enum PhysicsSetPositionFlags : uint
|
||||
{
|
||||
None = 0,
|
||||
Placement = 0x001,
|
||||
Teleport = 0x002,
|
||||
Restore = 0x004,
|
||||
Slide = 0x010,
|
||||
DoNotCreateCells = 0x020,
|
||||
Scatter = 0x100,
|
||||
RandomScatter = 0x200,
|
||||
Line = 0x400,
|
||||
SendPositionEvent = 0x1000,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The three retail weenie classifications which bypass placement collision
|
||||
/// in <c>CPhysicsObj::SetPositionInternal</c> after AdjustPosition succeeds.
|
||||
/// Runtime derives this from the canonical object record; callers cannot use a
|
||||
/// free boolean to force ordinary objects through geometry.
|
||||
/// </summary>
|
||||
internal enum PhysicsPlacementClass
|
||||
{
|
||||
Ordinary,
|
||||
Hook,
|
||||
Storage,
|
||||
Corpse,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Complete immutable input to retail <c>CPhysicsObj::SetPosition</c>. World
|
||||
/// position feeds acdream's flat collision representation; cell-local position
|
||||
/// is retail's <c>Position.frame.origin</c> and is the only input to
|
||||
/// <c>LandDefs::adjust_to_outside</c>.
|
||||
/// </summary>
|
||||
internal readonly record struct PhysicsSetPositionRequest(
|
||||
Vector3 Position,
|
||||
Quaternion Orientation,
|
||||
uint CellId,
|
||||
Vector3 CellLocalPosition,
|
||||
ImmutableArray<FlatCollisionSphere> Spheres,
|
||||
float Scale,
|
||||
float StepUpHeight,
|
||||
float StepDownHeight,
|
||||
PhysicsStateFlags MoverPhysicsState = PhysicsStateFlags.None,
|
||||
ObjectInfoState MoverFlags = ObjectInfoState.None,
|
||||
uint MovingEntityId = 0u,
|
||||
PhysicsPlacementClass PlacementClass = PhysicsPlacementClass.Ordinary,
|
||||
PhysicsSetPositionFlags Flags = PhysicsSetPositionFlags.Placement,
|
||||
Vector3 Line = default,
|
||||
float ScatterRadiusX = 0f,
|
||||
float ScatterRadiusY = 0f,
|
||||
uint ScatterAttempts = 0u,
|
||||
// Null models retail's distinct `this->cell == nullptr` state. The
|
||||
// retained Position cell id may equal the destination while the object is
|
||||
// still in the lost-cell list; that wake must change_cell and reflood.
|
||||
uint? CurrentCellId = null);
|
||||
|
||||
/// <summary>
|
||||
/// Immutable commit packet produced by the pure placement transaction. Runtime
|
||||
/// installs this packet atomically into the canonical body/spatial owner before
|
||||
/// publishing one presentation delta.
|
||||
/// </summary>
|
||||
internal readonly record struct PhysicsSetPositionResult(
|
||||
PhysicsSetPositionError Error,
|
||||
PhysicsResidenceDisposition Residence,
|
||||
Vector3 Position,
|
||||
Quaternion Orientation,
|
||||
uint CellId,
|
||||
Vector3 CellLocalPosition,
|
||||
bool InContact = false,
|
||||
bool OnWalkable = false,
|
||||
Plane ContactPlane = default,
|
||||
uint ContactPlaneCellId = 0u,
|
||||
bool ContactPlaneIsWater = false,
|
||||
bool SlidingNormalValid = false,
|
||||
Vector3 SlidingNormal = default,
|
||||
bool CollisionNormalValid = false,
|
||||
Vector3 CollisionNormal = default,
|
||||
int FramesStationaryFall = 0,
|
||||
bool CollidedWithEnvironment = false,
|
||||
bool CollisionHandlerResult = false,
|
||||
bool CellChanged = false,
|
||||
PhysicsShadowCommitAction ShadowAction = PhysicsShadowCommitAction.None,
|
||||
ImmutableArray<uint> CrossCellIds = default,
|
||||
ImmutableArray<uint> CollidedObjectIds = default)
|
||||
{
|
||||
internal bool IsSuccessful => Error == PhysicsSetPositionError.Ok;
|
||||
internal bool IsCommitted =>
|
||||
IsSuccessful && Residence == PhysicsResidenceDisposition.Committed;
|
||||
internal bool IsDeferred =>
|
||||
IsSuccessful && Residence == PhysicsResidenceDisposition.DeferredCell;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue