feat(vfx): port retail hidden and teleport presentation
Preserve canonical live-object ownership across Hidden transitions and remote teleport placement so effects, collision, streaming, and targeting remain synchronized.
This commit is contained in:
parent
a51ebc66e9
commit
1e98d81448
46 changed files with 4883 additions and 127 deletions
|
|
@ -145,4 +145,62 @@ public class HandleAllCollisionsTests
|
|||
// dot = -5 < 0 → k = -(-5*1.05) = 5.25 → v.z = -5 + 5.25 = 0.25 (tiny bounce)
|
||||
Assert.Equal(0.25f, b.Velocity.Z, precision: 3);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SetPositionTransition_HiddenLandingCallbackRunsBeforeCollisionResponse()
|
||||
{
|
||||
var body = Airborne(Vector3.Zero);
|
||||
int hitGroundCalls = 0;
|
||||
|
||||
PhysicsObjUpdate.CommitSetPositionTransition(
|
||||
body,
|
||||
inContact: true,
|
||||
onWalkable: true,
|
||||
collisionNormalValid: true,
|
||||
collisionNormal: Vector3.UnitZ,
|
||||
previousContact: false,
|
||||
previousOnWalkable: false,
|
||||
hitGround: () =>
|
||||
{
|
||||
hitGroundCalls++;
|
||||
body.Velocity = new Vector3(0f, 0f, -4f);
|
||||
});
|
||||
|
||||
Assert.Equal(1, hitGroundCalls);
|
||||
Assert.True(body.InContact);
|
||||
Assert.True(body.OnWalkable);
|
||||
// Callback -4 then retail elasticity 0.05 reflection => +0.2.
|
||||
// Running the callback after collision response would leave -4.
|
||||
Assert.Equal(0.2f, body.Velocity.Z, precision: 3);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SetPositionTransition_HiddenWalkOffCallbackRunsBeforeCollisionResponse()
|
||||
{
|
||||
var body = Airborne(Vector3.Zero);
|
||||
body.TransientState = TransientStateFlags.Contact
|
||||
| TransientStateFlags.OnWalkable;
|
||||
int leaveGroundCalls = 0;
|
||||
|
||||
PhysicsObjUpdate.CommitSetPositionTransition(
|
||||
body,
|
||||
inContact: false,
|
||||
onWalkable: false,
|
||||
collisionNormalValid: true,
|
||||
collisionNormal: -Vector3.UnitX,
|
||||
previousContact: true,
|
||||
previousOnWalkable: true,
|
||||
leaveGround: () =>
|
||||
{
|
||||
leaveGroundCalls++;
|
||||
body.Velocity = new Vector3(3f, 0f, 0f);
|
||||
});
|
||||
|
||||
Assert.Equal(1, leaveGroundCalls);
|
||||
Assert.False(body.InContact);
|
||||
Assert.False(body.OnWalkable);
|
||||
// Callback +3 into a -X normal then reflection => -0.15.
|
||||
// Running the callback after response would leave +3.
|
||||
Assert.Equal(-0.15f, body.Velocity.X, precision: 3);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,6 +50,9 @@ public sealed class InitialPlacementOverlapTests
|
|||
movingEntityId: PlayerId);
|
||||
|
||||
Assert.True(result.Ok);
|
||||
Assert.True(result.InContact);
|
||||
Assert.True(result.OnWalkable);
|
||||
Assert.Equal(Cell, result.ContactPlaneCellId);
|
||||
Assert.NotEqual(savedFeet, result.Position);
|
||||
float centerDistance = Vector3.Distance(
|
||||
result.Position + new Vector3(0f, 0f, Radius),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,77 @@
|
|||
using AcDream.Core.Physics;
|
||||
|
||||
namespace AcDream.Core.Tests.Physics;
|
||||
|
||||
public sealed class RetailPhysicsStateTransitionTests
|
||||
{
|
||||
[Fact]
|
||||
public void ConstructorState_MatchesRetailAndIsNotHidden()
|
||||
{
|
||||
Assert.Equal(0x00400C08u, (uint)RetailPhysicsStateTransitions.ConstructorState);
|
||||
Assert.Equal(
|
||||
PhysicsStateFlags.None,
|
||||
RetailPhysicsStateTransitions.ConstructorState & PhysicsStateFlags.Hidden);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VisibleToHidden_PlaysHiddenShapeAndRewritesCollisionBits()
|
||||
{
|
||||
PhysicsStateFlags requested = PhysicsStateFlags.Hidden
|
||||
| PhysicsStateFlags.ReportCollisions
|
||||
| PhysicsStateFlags.Lighting;
|
||||
|
||||
RetailPhysicsStateTransition result = RetailPhysicsStateTransitions.Apply(
|
||||
RetailPhysicsStateTransitions.ConstructorState,
|
||||
requested);
|
||||
|
||||
Assert.Equal(RetailHiddenTransition.BecameHidden, result.HiddenTransition);
|
||||
Assert.False(result.LightingChanged);
|
||||
Assert.Equal(PhysicsStateFlags.None, result.FinalState & PhysicsStateFlags.ReportCollisions);
|
||||
Assert.NotEqual(PhysicsStateFlags.None, result.FinalState & PhysicsStateFlags.IgnoreCollisions);
|
||||
Assert.NotEqual(PhysicsStateFlags.None, result.FinalState & PhysicsStateFlags.Hidden);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HiddenToVisible_RestoresReportCollisionsEvenWhenWireOmitsIt()
|
||||
{
|
||||
PhysicsStateFlags hidden = PhysicsStateFlags.Hidden
|
||||
| PhysicsStateFlags.IgnoreCollisions;
|
||||
|
||||
RetailPhysicsStateTransition result = RetailPhysicsStateTransitions.Apply(
|
||||
hidden,
|
||||
PhysicsStateFlags.None);
|
||||
|
||||
Assert.Equal(RetailHiddenTransition.BecameVisible, result.HiddenTransition);
|
||||
Assert.Equal(PhysicsStateFlags.None, result.FinalState & PhysicsStateFlags.Hidden);
|
||||
Assert.Equal(PhysicsStateFlags.None, result.FinalState & PhysicsStateFlags.IgnoreCollisions);
|
||||
Assert.NotEqual(PhysicsStateFlags.None, result.FinalState & PhysicsStateFlags.ReportCollisions);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IdenticalHiddenState_DoesNotReplayTransition()
|
||||
{
|
||||
PhysicsStateFlags state = PhysicsStateFlags.Hidden
|
||||
| PhysicsStateFlags.IgnoreCollisions;
|
||||
|
||||
RetailPhysicsStateTransition result = RetailPhysicsStateTransitions.Apply(state, state);
|
||||
|
||||
Assert.Equal(RetailHiddenTransition.None, result.HiddenTransition);
|
||||
Assert.False(result.LightingChanged);
|
||||
Assert.False(result.NoDrawChanged);
|
||||
Assert.Equal(state, result.FinalState);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LightingNoDrawAndHiddenChangeFlags_AreDerivedFromLowWord()
|
||||
{
|
||||
RetailPhysicsStateTransition result = RetailPhysicsStateTransitions.Apply(
|
||||
PhysicsStateFlags.None,
|
||||
PhysicsStateFlags.Lighting
|
||||
| PhysicsStateFlags.NoDraw
|
||||
| PhysicsStateFlags.Hidden);
|
||||
|
||||
Assert.True(result.LightingChanged);
|
||||
Assert.True(result.NoDrawChanged);
|
||||
Assert.Equal(RetailHiddenTransition.BecameHidden, result.HiddenTransition);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue