Files
jakub 6a667d8deb Capture current mission, AI, map and administration development
Include the current addon, terrain integrations, tools, regression tests and recorded development evidence.
2026-10-13 22:52:53 +02:00

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)