using System; using System.Collections.Generic; using FlaxEngine; using Console = Cabrito.Console; namespace Game { public class WeaponSway : Script { public float swaySpeed = 3000f; private Actor rootActor; private Actor cameraHolder; public override void OnStart() { rootActor = Actor.Parent.GetChild("RootActor"); cameraHolder = rootActor.GetChild("CameraHolder"); Actor.LocalOrientation = GetRotation(); } private Quaternion GetRotation() { Quaternion pitch = cameraHolder.LocalOrientation; Quaternion yawRoll = rootActor.LocalOrientation; return yawRoll * pitch; } private float timeRemainder = 0f; public override void OnLateUpdate() { Quaternion rotation = GetRotation(); Vector3 targetAngles = rotation.EulerAngles; Vector3 angles = Actor.LocalOrientation.EulerAngles; // Ensure the swaying is smooth when framerate fluctuates slightly float remaining = Time.DeltaTime + timeRemainder; const float minTime = 1f / 120f; do { float stepTime = Mathf.Min(Time.DeltaTime, minTime); remaining -= stepTime; float swaySpeedScaled = swaySpeed * stepTime; float deltaX = Mathf.DeltaAngle(angles.X, targetAngles.X); float deltaY = Mathf.DeltaAngle(angles.Y, targetAngles.Y); float deltaZ = Mathf.DeltaAngle(angles.Z, targetAngles.Z); const float maxAngle = 30f; if (deltaX > maxAngle) angles.X -= maxAngle - deltaX; else if (deltaX < -maxAngle) angles.X += maxAngle + deltaX; if (deltaY > maxAngle) angles.Y -= maxAngle - deltaY; else if (deltaY < -maxAngle) angles.Y += maxAngle + deltaY; if (deltaZ > maxAngle) angles.Z -= maxAngle - deltaZ; else if (deltaZ < -maxAngle) angles.Z += maxAngle + deltaZ; float percX = Mathf.Abs(deltaX) / maxAngle; float percY = Mathf.Abs(deltaY) / maxAngle; float percZ = Mathf.Abs(deltaZ) / maxAngle; float minSpeed = swaySpeedScaled * 0.00001f * 0f; Func fun = (f) => Mathf.Pow(f, 1.3f); angles.X = Mathf.MoveTowardsAngle(angles.X, targetAngles.X, Math.Max(swaySpeedScaled * fun(percX), minSpeed)); angles.Y = Mathf.MoveTowardsAngle(angles.Y, targetAngles.Y, Math.Max(swaySpeedScaled * fun(percY), minSpeed)); angles.Z = Mathf.MoveTowardsAngle(angles.Z, targetAngles.Z, Math.Max(swaySpeedScaled * fun(percZ), minSpeed)); } while (remaining > minTime); timeRemainder -= remaining; Actor.LocalOrientation = Quaternion.Euler(angles); } } }