stabilize dead air camera reconciliation
All checks were successful
build / image (push) Successful in 27s
All checks were successful
build / image (push) Successful in 27s
This commit is contained in:
@@ -172,7 +172,7 @@ function updateRuntime(
|
||||
const local = world.players.find((player) => player.id === playerId);
|
||||
const fractionalSeconds = frame.interpolationAlpha / DEAD_AIR_TICK_RATE;
|
||||
if (local) {
|
||||
const correctionLife = Math.max(0, 1 - (time - frame.localCorrection.updatedAt) / 130);
|
||||
const correctionLife = Math.exp(-(time - frame.localCorrection.updatedAt) / 115);
|
||||
runtime.camera.position.set(
|
||||
local.x + local.velocityX * fractionalSeconds + frame.localCorrection.x * correctionLife,
|
||||
1.62,
|
||||
|
||||
@@ -203,11 +203,36 @@ export function useDeadAirClient(): DeadAirClientView {
|
||||
const localAfter = (engine.currentState as DeadAirClientState).players.find(
|
||||
(player) => player.id === engine.localPlayerId,
|
||||
);
|
||||
if (localBefore && localAfter && decoded.snapshot.state.round === renderSource.current.state.round) {
|
||||
if (
|
||||
localBefore &&
|
||||
localAfter &&
|
||||
localBefore.alive === localAfter.alive &&
|
||||
decoded.snapshot.state.round === renderSource.current.state.round
|
||||
) {
|
||||
const now = performance.now();
|
||||
const correction = renderSource.current.localCorrection;
|
||||
correction.x += localBefore.x - localAfter.x;
|
||||
correction.z += localBefore.z - localAfter.z;
|
||||
correction.updatedAt = performance.now();
|
||||
const decay = Math.exp(-(now - correction.updatedAt) / 115);
|
||||
const leadSeconds = clock.interpolationAlpha / deadAirGame.tickRateHz;
|
||||
const deltaX =
|
||||
localBefore.x + localBefore.velocityX * leadSeconds -
|
||||
localAfter.x - localAfter.velocityX * leadSeconds;
|
||||
const deltaZ =
|
||||
localBefore.z + localBefore.velocityZ * leadSeconds -
|
||||
localAfter.z - localAfter.velocityZ * leadSeconds;
|
||||
if (Math.hypot(deltaX, deltaZ) < 3) {
|
||||
correction.x = correction.x * decay + deltaX;
|
||||
correction.z = correction.z * decay + deltaZ;
|
||||
} else {
|
||||
correction.x = 0;
|
||||
correction.z = 0;
|
||||
}
|
||||
correction.updatedAt = now;
|
||||
} else {
|
||||
renderSource.current.localCorrection = {
|
||||
x: 0,
|
||||
z: 0,
|
||||
updatedAt: performance.now(),
|
||||
};
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -67,6 +67,20 @@ const baseDeadAirGame = defineMultiplayerGame<DeadAirGameContract>({
|
||||
applyInput(state, input, { playerId, emit }) {
|
||||
const player = findPlayer(state, playerId);
|
||||
if (!player || player.bot || !player.alive || state.resetTicks > 0) return;
|
||||
if (
|
||||
Math.abs(input.forward) > 0.01 ||
|
||||
Math.abs(input.strafe) > 0.01 ||
|
||||
input.fire ||
|
||||
input.sprint ||
|
||||
input.reload ||
|
||||
input.interact ||
|
||||
input.toggleFlashlight ||
|
||||
input.throwDecoy ||
|
||||
angleDifference(input.yaw, player.yaw) > 0.003 ||
|
||||
Math.abs(input.pitch - player.pitch) > 0.003
|
||||
) {
|
||||
player.engaged = true;
|
||||
}
|
||||
applyCommand(player, input);
|
||||
if (input.reload) beginReload(player);
|
||||
if (input.toggleFlashlight) player.flashlight = !player.flashlight;
|
||||
@@ -370,6 +384,7 @@ function createPlayer(id: number, bot: boolean, round: number): DeadAirAuthority
|
||||
return {
|
||||
id,
|
||||
bot,
|
||||
engaged: bot,
|
||||
alive: true,
|
||||
x: spawn.x,
|
||||
z: spawn.z,
|
||||
@@ -517,7 +532,12 @@ function fire(
|
||||
let hit: DeadAirAuthorityPlayer | null = null;
|
||||
let hitDistance = shotRange;
|
||||
for (const target of state.players) {
|
||||
if (!target.alive || target.id === shooter.id || target.bot === shooter.bot) continue;
|
||||
if (
|
||||
!target.alive ||
|
||||
target.id === shooter.id ||
|
||||
target.bot === shooter.bot ||
|
||||
(!target.bot && !target.engaged)
|
||||
) continue;
|
||||
const offsetX = target.x - shooter.x;
|
||||
const offsetZ = target.z - shooter.z;
|
||||
const forwardDistance = offsetX * directionX + offsetZ * directionZ;
|
||||
@@ -673,7 +693,7 @@ function updateWarden(
|
||||
tick: number,
|
||||
): void {
|
||||
const visibleTargets = state.players.filter(
|
||||
(target) => !target.bot && target.alive && canSeePlayer(state, warden, target),
|
||||
(target) => !target.bot && target.engaged && target.alive && canSeePlayer(state, warden, target),
|
||||
);
|
||||
visibleTargets.sort(
|
||||
(left, right) =>
|
||||
|
||||
@@ -31,6 +31,8 @@ export interface DeadAirBotState {
|
||||
export interface DeadAirAuthorityPlayer {
|
||||
id: number;
|
||||
bot: boolean;
|
||||
/** Humans remain untargetable until they produce deliberate play input. */
|
||||
engaged: boolean;
|
||||
alive: boolean;
|
||||
x: number;
|
||||
z: number;
|
||||
|
||||
Reference in New Issue
Block a user