Files
UltimateFishing/Assets/Scripts/Assembly-CSharp/vp_MovingPlatform.cs
2026-02-21 16:45:37 +08:00

506 lines
13 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(Rigidbody))]
[RequireComponent(typeof(AudioSource))]
public class vp_MovingPlatform : MonoBehaviour
{
protected class WaypointComparer : IComparer
{
int IComparer.Compare(object x, object y)
{
return new CaseInsensitiveComparer().Compare(((Transform)x).name, ((Transform)y).name);
}
}
public enum PathMoveType
{
PingPong = 0,
Loop = 1,
Target = 2
}
public enum Direction
{
Forward = 0,
Backwards = 1,
Direct = 2
}
public enum MovementInterpolationMode
{
EaseInOut = 0,
EaseIn = 1,
EaseOut = 2,
EaseOut2 = 3,
Slerp = 4,
Lerp = 5
}
public enum RotateInterpolationMode
{
SyncToMovement = 0,
EaseOut = 1,
CustomEaseOut = 2,
CustomRotate = 3
}
protected Transform m_Transform;
public PathMoveType PathType;
public GameObject PathWaypoints;
public Direction PathDirection;
public int MoveAutoStartTarget = 1000;
protected List<Transform> m_Waypoints = new List<Transform>();
protected int m_NextWaypoint;
protected Vector3 m_CurrentTargetPosition = Vector3.zero;
protected Vector3 m_CurrentTargetAngle = Vector3.zero;
protected int m_TargetedWayPoint;
protected float m_TravelDistance;
protected Vector3 m_OriginalAngle = Vector3.zero;
protected int m_CurrentWaypoint;
public float MoveSpeed = 0.1f;
public float MoveReturnDelay;
public float MoveCooldown;
public MovementInterpolationMode MoveInterpolationMode;
protected bool m_Moving;
protected float m_NextAllowedMoveTime;
protected float m_MoveTime;
protected vp_Timer.Handle m_ReturnDelayTimer = new vp_Timer.Handle();
protected Vector3 m_PrevPos = Vector3.zero;
protected AnimationCurve m_EaseInOutCurve = AnimationCurve.EaseInOut(0f, 0f, 1f, 1f);
protected AnimationCurve m_LinearCurve = AnimationCurve.Linear(0f, 0f, 1f, 1f);
public float RotationEaseAmount = 0.1f;
public Vector3 RotationSpeed = Vector3.zero;
public RotateInterpolationMode RotationInterpolationMode;
protected Vector3 m_PrevAngle = Vector3.zero;
public AudioClip SoundStart;
public AudioClip SoundStop;
public AudioClip SoundMove;
public AudioClip SoundWaypoint;
protected AudioSource m_Audio;
public bool PhysicsSnapPlayerToTopOnIntersect = true;
public float m_PhysicsPushForce = 2f;
protected Rigidbody m_RigidBody;
protected Collider m_Collider;
protected Collider m_PlayerCollider;
protected vp_PlayerEventHandler m_PlayerToPush;
protected float m_PhysicsCurrentMoveVelocity;
protected float m_PhysicsCurrentRotationVelocity;
protected static Dictionary<Collider, vp_PlayerEventHandler> m_KnownPlayers = new Dictionary<Collider, vp_PlayerEventHandler>();
public int TargetedWaypoint
{
get
{
return m_TargetedWayPoint;
}
}
private void Start()
{
m_Transform = base.transform;
m_Collider = GetComponentInChildren<Collider>();
m_RigidBody = GetComponent<Rigidbody>();
m_RigidBody.useGravity = false;
m_RigidBody.isKinematic = true;
m_NextWaypoint = 0;
m_Audio = GetComponent<AudioSource>();
m_Audio.loop = true;
m_Audio.clip = SoundMove;
if (PathWaypoints == null)
{
return;
}
base.gameObject.layer = 28;
foreach (Transform item in PathWaypoints.transform)
{
if (vp_Utility.IsActive(item.gameObject))
{
m_Waypoints.Add(item);
item.gameObject.layer = 28;
}
if (item.GetComponent<Renderer>() != null)
{
item.GetComponent<Renderer>().enabled = false;
}
if (item.GetComponent<Collider>() != null)
{
item.GetComponent<Collider>().enabled = false;
}
}
IComparer comparer = new WaypointComparer();
m_Waypoints.Sort(comparer.Compare);
if (m_Waypoints.Count > 0)
{
m_CurrentTargetPosition = m_Waypoints[m_NextWaypoint].position;
m_CurrentTargetAngle = m_Waypoints[m_NextWaypoint].eulerAngles;
m_Transform.position = m_CurrentTargetPosition;
m_Transform.eulerAngles = m_CurrentTargetAngle;
if (MoveAutoStartTarget > m_Waypoints.Count - 1)
{
MoveAutoStartTarget = m_Waypoints.Count - 1;
}
}
}
private void FixedUpdate()
{
UpdatePath();
UpdateMovement();
UpdateRotation();
UpdateVelocity();
}
protected void UpdatePath()
{
if (m_Waypoints.Count < 2 || !(GetDistanceLeft() < 0.01f) || !(Time.time >= m_NextAllowedMoveTime))
{
return;
}
switch (PathType)
{
case PathMoveType.Target:
if (m_NextWaypoint == m_TargetedWayPoint)
{
if (m_Moving)
{
OnStop();
}
else if (m_NextWaypoint != 0)
{
OnArriveAtDestination();
}
break;
}
if (m_Moving)
{
if (m_PhysicsCurrentMoveVelocity == 0f)
{
OnStart();
}
else
{
OnArriveAtWaypoint();
}
}
GoToNextWaypoint();
break;
case PathMoveType.Loop:
OnArriveAtWaypoint();
GoToNextWaypoint();
break;
case PathMoveType.PingPong:
if (PathDirection == Direction.Backwards)
{
if (m_NextWaypoint == 0)
{
PathDirection = Direction.Forward;
}
}
else if (m_NextWaypoint == m_Waypoints.Count - 1)
{
PathDirection = Direction.Backwards;
}
OnArriveAtWaypoint();
GoToNextWaypoint();
break;
}
}
protected void OnStart()
{
if (SoundStart != null)
{
m_Audio.PlayOneShot(SoundStart);
}
}
protected void OnArriveAtWaypoint()
{
if (SoundWaypoint != null)
{
m_Audio.PlayOneShot(SoundWaypoint);
}
}
protected void OnArriveAtDestination()
{
if (MoveReturnDelay > 0f && !m_ReturnDelayTimer.Active)
{
vp_Timer.In(MoveReturnDelay, delegate
{
GoTo(0);
}, m_ReturnDelayTimer);
}
}
protected void OnStop()
{
m_Audio.Stop();
if (SoundStop != null)
{
m_Audio.PlayOneShot(SoundStop);
}
m_Transform.position = m_CurrentTargetPosition;
m_Transform.eulerAngles = m_CurrentTargetAngle;
m_Moving = false;
if (m_NextWaypoint == 0)
{
m_NextAllowedMoveTime = Time.time + MoveCooldown;
}
}
protected void UpdateMovement()
{
if (m_Waypoints.Count >= 2)
{
switch (MoveInterpolationMode)
{
case MovementInterpolationMode.EaseInOut:
m_Transform.position = vp_MathUtility.NaNSafeVector3(Vector3.Lerp(m_Transform.position, m_CurrentTargetPosition, m_EaseInOutCurve.Evaluate(m_MoveTime)));
break;
case MovementInterpolationMode.EaseIn:
m_Transform.position = vp_MathUtility.NaNSafeVector3(Vector3.MoveTowards(m_Transform.position, m_CurrentTargetPosition, m_MoveTime));
break;
case MovementInterpolationMode.EaseOut:
m_Transform.position = vp_MathUtility.NaNSafeVector3(Vector3.Lerp(m_Transform.position, m_CurrentTargetPosition, m_LinearCurve.Evaluate(m_MoveTime)));
break;
case MovementInterpolationMode.EaseOut2:
m_Transform.position = vp_MathUtility.NaNSafeVector3(Vector3.Lerp(m_Transform.position, m_CurrentTargetPosition, MoveSpeed * 0.25f));
break;
case MovementInterpolationMode.Lerp:
m_Transform.position = vp_MathUtility.NaNSafeVector3(Vector3.MoveTowards(m_Transform.position, m_CurrentTargetPosition, MoveSpeed));
break;
case MovementInterpolationMode.Slerp:
m_Transform.position = vp_MathUtility.NaNSafeVector3(Vector3.Slerp(m_Transform.position, m_CurrentTargetPosition, m_LinearCurve.Evaluate(m_MoveTime)));
break;
}
}
}
protected void UpdateRotation()
{
switch (RotationInterpolationMode)
{
case RotateInterpolationMode.SyncToMovement:
if (m_Moving)
{
m_Transform.eulerAngles = vp_MathUtility.NaNSafeVector3(new Vector3(Mathf.LerpAngle(m_OriginalAngle.x, m_CurrentTargetAngle.x, 1f - GetDistanceLeft() / m_TravelDistance), Mathf.LerpAngle(m_OriginalAngle.y, m_CurrentTargetAngle.y, 1f - GetDistanceLeft() / m_TravelDistance), Mathf.LerpAngle(m_OriginalAngle.z, m_CurrentTargetAngle.z, 1f - GetDistanceLeft() / m_TravelDistance)));
}
break;
case RotateInterpolationMode.EaseOut:
m_Transform.eulerAngles = vp_MathUtility.NaNSafeVector3(new Vector3(Mathf.LerpAngle(m_Transform.eulerAngles.x, m_CurrentTargetAngle.x, m_LinearCurve.Evaluate(m_MoveTime)), Mathf.LerpAngle(m_Transform.eulerAngles.y, m_CurrentTargetAngle.y, m_LinearCurve.Evaluate(m_MoveTime)), Mathf.LerpAngle(m_Transform.eulerAngles.z, m_CurrentTargetAngle.z, m_LinearCurve.Evaluate(m_MoveTime))));
break;
case RotateInterpolationMode.CustomEaseOut:
m_Transform.eulerAngles = vp_MathUtility.NaNSafeVector3(new Vector3(Mathf.LerpAngle(m_Transform.eulerAngles.x, m_CurrentTargetAngle.x, RotationEaseAmount), Mathf.LerpAngle(m_Transform.eulerAngles.y, m_CurrentTargetAngle.y, RotationEaseAmount), Mathf.LerpAngle(m_Transform.eulerAngles.z, m_CurrentTargetAngle.z, RotationEaseAmount)));
break;
case RotateInterpolationMode.CustomRotate:
m_Transform.Rotate(RotationSpeed);
break;
}
}
protected void UpdateVelocity()
{
m_MoveTime += MoveSpeed * 0.01f * vp_TimeUtility.AdjustedTimeScale;
m_PhysicsCurrentMoveVelocity = (m_Transform.position - m_PrevPos).magnitude;
m_PhysicsCurrentRotationVelocity = (m_Transform.eulerAngles - m_PrevAngle).magnitude;
m_PrevPos = m_Transform.position;
m_PrevAngle = m_Transform.eulerAngles;
}
public void GoTo(int targetWayPoint)
{
if (!vp_Gameplay.isMaster || Time.time < m_NextAllowedMoveTime || PathType != PathMoveType.Target)
{
return;
}
m_TargetedWayPoint = GetValidWaypoint(targetWayPoint);
if (targetWayPoint > m_NextWaypoint)
{
if (PathDirection != Direction.Direct)
{
PathDirection = Direction.Forward;
}
}
else if (PathDirection != Direction.Direct)
{
PathDirection = Direction.Backwards;
}
m_Moving = true;
}
protected float GetDistanceLeft()
{
if (m_Waypoints.Count < 2)
{
return 0f;
}
return Vector3.Distance(m_Transform.position, m_Waypoints[m_NextWaypoint].position);
}
protected void GoToNextWaypoint()
{
if (m_Waypoints.Count >= 2)
{
m_MoveTime = 0f;
if (!m_Audio.isPlaying)
{
m_Audio.Play();
}
m_CurrentWaypoint = m_NextWaypoint;
switch (PathDirection)
{
case Direction.Forward:
m_NextWaypoint = GetValidWaypoint(m_NextWaypoint + 1);
break;
case Direction.Backwards:
m_NextWaypoint = GetValidWaypoint(m_NextWaypoint - 1);
break;
case Direction.Direct:
m_NextWaypoint = m_TargetedWayPoint;
break;
}
m_OriginalAngle = m_CurrentTargetAngle;
m_CurrentTargetPosition = m_Waypoints[m_NextWaypoint].position;
m_CurrentTargetAngle = m_Waypoints[m_NextWaypoint].eulerAngles;
m_TravelDistance = GetDistanceLeft();
m_Moving = true;
}
}
protected int GetValidWaypoint(int wayPoint)
{
if (wayPoint < 0)
{
return m_Waypoints.Count - 1;
}
if (wayPoint > m_Waypoints.Count - 1)
{
return 0;
}
return wayPoint;
}
protected void OnTriggerEnter(Collider col)
{
if (GetPlayer(col))
{
TryPushPlayer();
TryAutoStart();
}
}
protected void OnTriggerStay(Collider col)
{
if (PhysicsSnapPlayerToTopOnIntersect && GetPlayer(col))
{
TrySnapPlayerToTop();
}
}
public bool GetPlayer(Collider col)
{
if (col.gameObject.layer != 30 && col.gameObject.layer != 23)
{
return false;
}
if (!m_KnownPlayers.ContainsKey(col))
{
vp_PlayerEventHandler component = col.transform.root.GetComponent<vp_PlayerEventHandler>();
if (component == null)
{
return false;
}
m_KnownPlayers.Add(col, component);
}
if (!m_KnownPlayers.TryGetValue(col, out m_PlayerToPush))
{
return false;
}
m_PlayerCollider = col;
return true;
}
protected void TryPushPlayer()
{
if (!(m_PlayerToPush == null) && m_PlayerToPush.Platform != null && !(m_PlayerToPush.Position.Get().y > m_Collider.bounds.max.y) && !(m_PlayerToPush.Platform.Get() == m_Transform))
{
float num = m_PhysicsCurrentMoveVelocity;
if (num == 0f)
{
num = m_PhysicsCurrentRotationVelocity * 0.1f;
}
if (num > 0f)
{
m_PlayerToPush.ForceImpact.Send(vp_3DUtility.HorizontalVector(-(m_Transform.position - m_PlayerCollider.bounds.center).normalized * num * m_PhysicsPushForce));
}
}
}
protected void TrySnapPlayerToTop()
{
if (!(m_PlayerToPush == null) && m_PlayerToPush.Platform != null && !(m_PlayerToPush.Position.Get().y > m_Collider.bounds.max.y) && !(m_PlayerToPush.Platform.Get() == m_Transform) && RotationSpeed.x == 0f && RotationSpeed.z == 0f && m_CurrentTargetAngle.x == 0f && m_CurrentTargetAngle.z == 0f && !(m_Collider.bounds.max.x < m_PlayerCollider.bounds.max.x) && !(m_Collider.bounds.max.z < m_PlayerCollider.bounds.max.z) && !(m_Collider.bounds.min.x > m_PlayerCollider.bounds.min.x) && !(m_Collider.bounds.min.z > m_PlayerCollider.bounds.min.z))
{
Vector3 o = m_PlayerToPush.Position.Get();
o.y = m_Collider.bounds.max.y - 0.1f;
m_PlayerToPush.Position.Set(o);
}
}
public void TryAutoStart()
{
if (vp_Gameplay.isMaster && MoveAutoStartTarget != 0 && !(m_PhysicsCurrentMoveVelocity > 0f) && !m_Moving)
{
GoTo(MoveAutoStartTarget);
}
}
protected void OnLevelWasLoaded()
{
m_KnownPlayers.Clear();
}
}