472 lines
12 KiB
C#
472 lines
12 KiB
C#
using System;
|
|
using NitroxClient.GameLogic;
|
|
using UnityEngine;
|
|
using static PlayerCinematicController;
|
|
|
|
namespace NitroxClient.MonoBehaviours.CinematicController;
|
|
|
|
/// <summary>
|
|
/// Override for <see cref="PlayerCinematicController"/>
|
|
/// </summary>
|
|
public class RemotePlayerCinematicController : MonoBehaviour, IManagedUpdateBehaviour, IManagedLateUpdateBehaviour
|
|
{
|
|
[AssertNotNull] public Transform animatedTransform;
|
|
|
|
public GameObject informGameObject;
|
|
|
|
public Transform endTransform;
|
|
|
|
public bool onlyUseEndTransformInVr;
|
|
|
|
public bool playInVr;
|
|
|
|
public string playerViewAnimationName = "";
|
|
|
|
public string playerViewInterpolateAnimParam = "";
|
|
|
|
public string animParam = "cinematicMode";
|
|
|
|
public string interpolateAnimParam = "";
|
|
|
|
public float interpolationTime = 0.25f;
|
|
|
|
public float interpolationTimeOut = 0.25f;
|
|
|
|
public string receiversAnimParam = "";
|
|
|
|
public GameObject[] animParamReceivers;
|
|
|
|
public bool interpolateDuringAnimation;
|
|
|
|
public bool debug;
|
|
|
|
public Animator animator;
|
|
|
|
[NonSerialized] public bool cinematicModeActive;
|
|
|
|
private Vector3 playerFromPosition = Vector3.zero;
|
|
|
|
private Quaternion playerFromRotation = Quaternion.identity;
|
|
|
|
private bool onCinematicModeEndCall;
|
|
|
|
private float timeStateChanged;
|
|
|
|
private State _state;
|
|
|
|
private RemotePlayer player;
|
|
|
|
private bool subscribed;
|
|
|
|
private bool _animState;
|
|
|
|
public static int cinematicModeCount { get; private set; }
|
|
|
|
public static float cinematicActivityStart { get; private set; }
|
|
|
|
private State state
|
|
{
|
|
get => _state;
|
|
set
|
|
{
|
|
timeStateChanged = Time.time;
|
|
_state = value;
|
|
}
|
|
}
|
|
|
|
public bool animState
|
|
{
|
|
get => _animState;
|
|
private set
|
|
{
|
|
if (value == _animState)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (debug)
|
|
{
|
|
Debug.Log($"setting cinematic controller {gameObject.name} to: {value}");
|
|
}
|
|
|
|
_animState = value;
|
|
if (animParam.Length > 0)
|
|
{
|
|
SafeAnimator.SetBool(animator, animParam, value);
|
|
}
|
|
|
|
if (receiversAnimParam.Length > 0)
|
|
{
|
|
for (int i = 0; i < animParamReceivers.Length; i++)
|
|
{
|
|
animParamReceivers[i].GetComponent<IAnimParamReceiver>()?.ForwardAnimationParameterBool(receiversAnimParam, value);
|
|
}
|
|
}
|
|
|
|
if (playerViewAnimationName.Length > 0 && player != null)
|
|
{
|
|
Animator componentInChildren = player.Body.GetComponentInChildren<Animator>();
|
|
if (componentInChildren != null && componentInChildren.gameObject.activeInHierarchy)
|
|
{
|
|
SafeAnimator.SetBool(componentInChildren, playerViewAnimationName, value);
|
|
}
|
|
}
|
|
|
|
SetVrActiveParam();
|
|
}
|
|
}
|
|
|
|
public int managedUpdateIndex { get; set; }
|
|
|
|
public int managedLateUpdateIndex { get; set; }
|
|
|
|
public string GetProfileTag()
|
|
{
|
|
return nameof(RemotePlayerCinematicController);
|
|
}
|
|
|
|
public void SetPlayer(RemotePlayer setplayer)
|
|
{
|
|
if (subscribed && player != setplayer)
|
|
{
|
|
Subscribe(player, false);
|
|
Subscribe(setplayer, true);
|
|
}
|
|
|
|
player = setplayer;
|
|
}
|
|
|
|
public RemotePlayer GetPlayer()
|
|
{
|
|
return player;
|
|
}
|
|
|
|
private void AddToUpdateManager()
|
|
{
|
|
BehaviourUpdateUtils.Register((IManagedUpdateBehaviour)this);
|
|
BehaviourUpdateUtils.Register((IManagedLateUpdateBehaviour)this);
|
|
}
|
|
|
|
private void RemoveFromUpdateManager()
|
|
{
|
|
BehaviourUpdateUtils.Deregister((IManagedUpdateBehaviour)this);
|
|
BehaviourUpdateUtils.Deregister((IManagedLateUpdateBehaviour)this);
|
|
}
|
|
|
|
private void OnEnable()
|
|
{
|
|
AddToUpdateManager();
|
|
}
|
|
|
|
private void OnDestroy()
|
|
{
|
|
RemoveFromUpdateManager();
|
|
}
|
|
|
|
private void Start()
|
|
{
|
|
SetVrActiveParam();
|
|
}
|
|
|
|
private void SetVrActiveParam()
|
|
{
|
|
string paramaterName = "vr_active";
|
|
bool vrAnimationMode = GameOptions.GetVrAnimationMode();
|
|
if (animator != null)
|
|
{
|
|
animator.SetBool(paramaterName, vrAnimationMode);
|
|
}
|
|
|
|
foreach (GameObject animatedObject in animParamReceivers)
|
|
{
|
|
animatedObject.GetComponent<IAnimParamReceiver>()?.ForwardAnimationParameterBool(paramaterName, vrAnimationMode);
|
|
}
|
|
}
|
|
|
|
private bool UseEndTransform()
|
|
{
|
|
if (endTransform == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (onlyUseEndTransformInVr)
|
|
{
|
|
return GameOptions.GetVrAnimationMode();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
private void SkipCinematic(RemotePlayer player)
|
|
{
|
|
this.player = player;
|
|
if (player != null)
|
|
{
|
|
Transform component = player.Body.GetComponent<Transform>();
|
|
if (UseEndTransform())
|
|
{
|
|
component.position = endTransform.position;
|
|
component.rotation = endTransform.rotation;
|
|
}
|
|
}
|
|
|
|
if (informGameObject != null)
|
|
{
|
|
informGameObject.SendMessage(nameof(CinematicModeTriggerBase.OnPlayerCinematicModeEnd), this, SendMessageOptions.DontRequireReceiver);
|
|
}
|
|
}
|
|
|
|
public void StartCinematicMode(RemotePlayer setplayer)
|
|
{
|
|
if (debug)
|
|
{
|
|
Debug.Log($"{gameObject.name}.StartCinematicMode");
|
|
}
|
|
|
|
if (!cinematicModeActive)
|
|
{
|
|
player = null;
|
|
if (!playInVr && GameOptions.GetVrAnimationMode())
|
|
{
|
|
if (debug)
|
|
{
|
|
Debug.Log($"{gameObject.name} skip cinematic");
|
|
}
|
|
|
|
SkipCinematic(setplayer);
|
|
return;
|
|
}
|
|
|
|
animator.cullingMode = AnimatorCullingMode.AlwaysAnimate;
|
|
cinematicModeActive = true;
|
|
if (setplayer != null)
|
|
{
|
|
SetPlayer(setplayer);
|
|
Subscribe(player, true);
|
|
}
|
|
|
|
state = State.In;
|
|
if (informGameObject != null)
|
|
{
|
|
informGameObject.SendMessage(nameof(DockedVehicleHandTarget.OnPlayerCinematicModeStart), this, SendMessageOptions.DontRequireReceiver);
|
|
}
|
|
|
|
if (player != null)
|
|
{
|
|
Transform component = player.Body.GetComponent<Transform>();
|
|
playerFromPosition = component.position;
|
|
playerFromRotation = component.rotation;
|
|
if (playerViewInterpolateAnimParam.Length > 0)
|
|
{
|
|
SafeAnimator.SetBool(player.Body.GetComponentInChildren<Animator>(), playerViewInterpolateAnimParam, true);
|
|
}
|
|
}
|
|
|
|
if (interpolateAnimParam.Length > 0)
|
|
{
|
|
SafeAnimator.SetBool(animator, interpolateAnimParam, true);
|
|
}
|
|
|
|
if (interpolateDuringAnimation)
|
|
{
|
|
animState = true;
|
|
}
|
|
|
|
if (debug)
|
|
{
|
|
Debug.Log($"{gameObject.name} successfully started cinematic");
|
|
}
|
|
|
|
if (cinematicModeCount == 0)
|
|
{
|
|
cinematicActivityStart = Time.time;
|
|
}
|
|
|
|
cinematicModeCount++;
|
|
}
|
|
else if (debug)
|
|
{
|
|
Debug.Log($"{gameObject.name} cinematic already active!");
|
|
}
|
|
}
|
|
|
|
public void EndCinematicMode(bool reset = false)
|
|
{
|
|
if (cinematicModeActive)
|
|
{
|
|
if (reset) // Added by us
|
|
{
|
|
animator.Rebind();
|
|
animator.Update(0f);
|
|
}
|
|
|
|
animator.cullingMode = AnimatorCullingMode.CullCompletely;
|
|
animState = false;
|
|
state = State.None;
|
|
cinematicModeActive = false;
|
|
cinematicModeCount--;
|
|
}
|
|
}
|
|
|
|
public void OnPlayerCinematicModeEnd()
|
|
{
|
|
if (!cinematicModeActive || onCinematicModeEndCall)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (player != null)
|
|
{
|
|
UpdatePlayerPosition();
|
|
}
|
|
|
|
animState = false;
|
|
if (UseEndTransform())
|
|
{
|
|
state = State.Out;
|
|
if (player != null)
|
|
{
|
|
Transform component = player.Body.GetComponent<Transform>();
|
|
playerFromPosition = component.position;
|
|
playerFromRotation = component.rotation;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
EndCinematicMode();
|
|
}
|
|
|
|
if (informGameObject != null)
|
|
{
|
|
onCinematicModeEndCall = true;
|
|
informGameObject.SendMessage(nameof(DockedVehicleHandTarget.OnPlayerCinematicModeEnd), this, SendMessageOptions.DontRequireReceiver);
|
|
onCinematicModeEndCall = false;
|
|
}
|
|
}
|
|
|
|
private void UpdatePlayerPosition()
|
|
{
|
|
Transform component = player.Body.GetComponent<Transform>();
|
|
component.position = animatedTransform.position;
|
|
component.rotation = animatedTransform.rotation;
|
|
}
|
|
|
|
public void ManagedLateUpdate()
|
|
{
|
|
if (!cinematicModeActive)
|
|
{
|
|
return;
|
|
}
|
|
|
|
float num = Time.time - timeStateChanged;
|
|
float timedOutScalar;
|
|
Transform transform = null;
|
|
if (player != null && player.Body)
|
|
{
|
|
transform = player.Body.GetComponent<Transform>();
|
|
}
|
|
|
|
bool isVrAnimationMode = !GameOptions.GetVrAnimationMode();
|
|
switch (state)
|
|
{
|
|
case State.In:
|
|
timedOutScalar = interpolationTime != 0f && isVrAnimationMode ? Mathf.Clamp01(num / interpolationTime) : 1f;
|
|
if (player != null && transform)
|
|
{
|
|
transform.position = Vector3.Lerp(playerFromPosition, animatedTransform.position, timedOutScalar);
|
|
transform.rotation = Quaternion.Slerp(playerFromRotation, animatedTransform.rotation, timedOutScalar);
|
|
}
|
|
|
|
if (timedOutScalar == 1f)
|
|
{
|
|
state = State.Update;
|
|
animState = true;
|
|
if (interpolateAnimParam.Length > 0)
|
|
{
|
|
SafeAnimator.SetBool(animator, interpolateAnimParam, false);
|
|
}
|
|
|
|
if (playerViewInterpolateAnimParam.Length > 0 && player != null)
|
|
{
|
|
SafeAnimator.SetBool(player.Body.GetComponentInChildren<Animator>(), playerViewInterpolateAnimParam, false);
|
|
}
|
|
}
|
|
|
|
break;
|
|
case State.Update:
|
|
if (player != null)
|
|
{
|
|
UpdatePlayerPosition();
|
|
}
|
|
|
|
break;
|
|
case State.Out:
|
|
timedOutScalar = interpolationTimeOut != 0f && isVrAnimationMode ? Mathf.Clamp01(num / interpolationTimeOut) : 1f;
|
|
if (player != null && transform)
|
|
{
|
|
transform.position = Vector3.Lerp(playerFromPosition, endTransform.position, timedOutScalar);
|
|
transform.rotation = Quaternion.Slerp(playerFromRotation, endTransform.rotation, timedOutScalar);
|
|
}
|
|
|
|
if (timedOutScalar == 1f)
|
|
{
|
|
EndCinematicMode();
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
public bool IsCinematicModeActive()
|
|
{
|
|
return cinematicModeActive;
|
|
}
|
|
|
|
private void OnDisable()
|
|
{
|
|
RemoveFromUpdateManager();
|
|
if (subscribed)
|
|
{
|
|
Subscribe(player, false);
|
|
}
|
|
|
|
EndCinematicMode();
|
|
}
|
|
|
|
private void OnPlayerDeath(RemotePlayer player)
|
|
{
|
|
EndCinematicMode();
|
|
animator.Rebind();
|
|
}
|
|
|
|
private void Subscribe(RemotePlayer player, bool state)
|
|
{
|
|
if (player == null)
|
|
{
|
|
subscribed = false;
|
|
}
|
|
else if (subscribed != state)
|
|
{
|
|
if (state)
|
|
{
|
|
player.PlayerDeathEvent.AddHandler(gameObject, OnPlayerDeath);
|
|
}
|
|
else
|
|
{
|
|
player.PlayerDeathEvent.RemoveHandler(gameObject, OnPlayerDeath);
|
|
}
|
|
|
|
subscribed = state;
|
|
}
|
|
}
|
|
|
|
public void ManagedUpdate()
|
|
{
|
|
if (!cinematicModeActive && subscribed)
|
|
{
|
|
Subscribe(player, false);
|
|
}
|
|
}
|
|
}
|