Include the current addon, terrain integrations, tools, regression tests and recorded development evidence.
61 lines
3.2 KiB
Diff
61 lines
3.2 KiB
Diff
--- before/addons/core/Scripts/Game/ERR/00_Core/ERR_ObserverPlayerView.c
|
|
+++ after/addons/core/Scripts/Game/ERR/00_Core/ERR_ObserverPlayerView.c
|
|
@@ -2,6 +2,20 @@
|
|
// spectators of that body. No client-supplied position affects gameplay.
|
|
class ERR_ObserverViewRules
|
|
{
|
|
+ // The body and camera arrive through independently timed replication streams.
|
|
+ // Keep the sampled world axes and world-axis eye offset together. Applying
|
|
+ // the proxy body's rotation to delayed body-local aim adds its yaw error to
|
|
+ // both aim and eye position, even when the owner's camera is steady.
|
|
+ static void Encode(vector body[4], vector view[4], out vector pose[4])
|
|
+ {
|
|
+ for (int axis = 0; axis < 3; axis++) pose[axis] = view[axis];
|
|
+ pose[3] = view[3] - body[3];
|
|
+ }
|
|
+ static void Decode(vector body[4], vector pose[4], out vector view[4])
|
|
+ {
|
|
+ for (int axis = 0; axis < 3; axis++) view[axis] = pose[axis];
|
|
+ view[3] = body[3] + pose[3];
|
|
+ }
|
|
static bool Sample(vector position, vector forward, vector up, float fov, float nearPlane)
|
|
{
|
|
// Negated bounded comparisons also reject NaN/infinity before matrix math.
|
|
@@ -105,13 +119,13 @@
|
|
float now = GetGame().GetWorld().GetWorldTime();
|
|
if (now - m_ERRViewRequestAt >= 500)
|
|
{ m_ERRViewRequestAt = now; Rpc(ERR_RequestPlayerView); }
|
|
- vector local[4], world[4];
|
|
- if (!m_ERRViewBuffer.Read(m_ERRObservedId, now, seconds, local, fov, nearPlane)) return false;
|
|
+ vector pose[4], world[4];
|
|
+ if (!m_ERRViewBuffer.Read(m_ERRObservedId, now, seconds, pose, fov, nearPlane)) return false;
|
|
RplId scopeWeapon; vector scopeData;
|
|
m_ERRViewBuffer.Scope(scopeWeapon, scopeData);
|
|
if (scopeWeapon != RplId.Invalid() && !ERR_ObserverScope.Resolve(target, scopeWeapon, scopeData)) return false;
|
|
target.GetWorldTransform(world);
|
|
- Math3D.MatrixMultiply4(world, local, transform);
|
|
+ ERR_ObserverViewRules.Decode(world, pose, transform);
|
|
return true;
|
|
}
|
|
[RplRpc(RplChannel.Reliable, RplRcver.Server)]
|
|
@@ -157,15 +171,15 @@
|
|
PlayerCamera camera = GetPlayerCamera();
|
|
CameraManager manager = GetGame().GetCameraManager();
|
|
if (!mode || !mode.Active() || !ERR_Actors.CanFight(actor) || !camera || !manager || manager.CurrentCamera() != camera) return;
|
|
- vector world[4], view[4], local[4];
|
|
+ vector world[4], view[4], pose[4];
|
|
actor.GetWorldTransform(world);
|
|
camera.GetWorldCameraTransform(view);
|
|
float fov = camera.GetVerticalFOV(), nearPlane = camera.GetNearPlane();
|
|
RplId scopeWeapon; vector scopeData;
|
|
ERR_ObserverScope.Sample(actor, view, fov, scopeWeapon, scopeData);
|
|
- Math3D.MatrixInvMultiply4(world, view, local);
|
|
- if (!ERR_ObserverViewRules.Sample(local[3], local[2], local[1], fov, nearPlane)) return;
|
|
- Rpc(ERR_SubmitPlayerView, ++m_ERRViewSequence, local[3], local[2], local[1], fov, nearPlane, scopeWeapon, scopeData);
|
|
+ ERR_ObserverViewRules.Encode(world, view, pose);
|
|
+ if (!ERR_ObserverViewRules.Sample(pose[3], pose[2], pose[1], fov, nearPlane)) return;
|
|
+ Rpc(ERR_SubmitPlayerView, ++m_ERRViewSequence, pose[3], pose[2], pose[1], fov, nearPlane, scopeWeapon, scopeData);
|
|
}
|
|
[RplRpc(RplChannel.Unreliable, RplRcver.Server)]
|
|
protected void ERR_SubmitPlayerView(int sequence, vector position, vector forward, vector up, float fov, float nearPlane, RplId scopeWeapon, vector scopeData)
|