SanAndreasUnity/Assets/Scripts/Behaviours/Ped/PlayerController.cs

263 lines
No EOL
7 KiB
C#

using SanAndreasUnity.Behaviours.Vehicles;
using SanAndreasUnity.Importing.Animation;
using SanAndreasUnity.Utilities;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using SanAndreasUnity.Net;
namespace SanAndreasUnity.Behaviours
{
[RequireComponent(typeof(Ped))]
public class PlayerController : MonoBehaviour
{
public static PlayerController Instance { get { return Ped.Instance != null ? Ped.Instance.GetComponent<PlayerController>() : null; } }
private Ped m_ped;
// Alpha speedometer
private const float velTimer = 1 / 4f;
private float m_velCounter = velTimer;
private Vector3 m_lastPos = Vector3.zero,
m_deltaPos = Vector3.zero;
private Vector2 _mouseAbsolute;
private Vector2 _smoothMouse = Vector2.zero;
public Vector2 clampInDegrees = new Vector2(90, 60);
public float EnterVehicleRadius { get { return m_ped.EnterVehicleRadius; } }
public Vector2 smoothing = new Vector2(10, 10);
[SerializeField] private bool m_doSmooth = true;
[SerializeField] private bool m_smoothMovement = false;
public float CurVelocity { get { return m_deltaPos.magnitude * 3.6f / velTimer; } }
private void Awake()
{
m_ped = GetComponent<Ped>();
}
private void FixedUpdate()
{
m_velCounter -= Time.deltaTime;
if (m_velCounter <= 0)
{
Vector3 t = new Vector3(transform.position.x, 0, transform.position.z);
m_deltaPos = t - m_lastPos;
m_lastPos = t;
m_velCounter = velTimer;
}
}
private void Update()
{
if (!m_ped.IsControlledByLocalPlayer)
return;
if (!Loader.HasLoaded)
return;
// reset ped input
m_ped.ResetMovementInput ();
m_ped.MouseMoveInput = Vector2.zero;
m_ped.MouseScrollInput = Vector2.zero;
if (!GameManager.CanPlayerReadInput()) return;
// states must be read before events, otherwise callback functions for events will not have access
// to states (they will always be unpressed/reset, because we did a reset above)
this.ReadStates ();
this.ReadEvents ();
}
void ReadStates()
{
CustomInput customInput = CustomInput.Instance;
this.ReadCameraInput ();
m_ped.MouseScrollInput = Input.mouseScrollDelta;
m_ped.IsAimOn = customInput.GetButton ("RightClick");
m_ped.IsFireOn = customInput.GetButton ("LeftClick");
m_ped.IsJumpOn = customInput.GetButton ("Jump");
Vector3 inputMove = Vector3.zero;
if (m_smoothMovement)
inputMove = new Vector3 (customInput.GetAxis ("Horizontal"), 0f, customInput.GetAxis ("Vertical"));
else
inputMove = new Vector3 (customInput.GetAxisRaw ("Horizontal"), 0f, customInput.GetAxisRaw ("Vertical"));
if (inputMove.sqrMagnitude > 0f)
{
inputMove.Normalize();
if (customInput.GetButton ("Walk"))
m_ped.IsWalkOn = true;
else if (customInput.GetButton ("Sprint"))
m_ped.IsSprintOn = true;
else
m_ped.IsRunOn = true;
}
if (m_ped.Camera != null)
m_ped.Movement = m_ped.Camera.transform.TransformVector (inputMove).normalized;
else
m_ped.Movement = inputMove.normalized;
if (m_ped.Movement.sqrMagnitude > float.Epsilon) {
// only assign heading if there is any movement - we don't want the heading to be zero vector
m_ped.Heading = m_ped.Movement;
}
}
void ReadEvents()
{
CustomInput customInput = CustomInput.Instance;
if (customInput.GetButtonDown ("LeftClick"))
m_ped.OnFireButtonPressed ();
if (customInput.GetButtonDown ("RightClick"))
m_ped.OnAimButtonPressed ();
if (customInput.GetKeyDown (KeyCode.Q))
m_ped.OnPreviousWeaponButtonPressed();
else if (customInput.GetKeyDown (KeyCode.E))
m_ped.OnNextWeaponButtonPressed();
if (customInput.GetButtonDown("Use"))
m_ped.OnSubmitPressed ();
if (customInput.GetButtonDown("Jump"))
m_ped.OnJumpButtonPressed ();
if (customInput.GetKeyDown(KeyCode.C))
m_ped.OnCrouchButtonPressed ();
if (customInput.GetKeyDown(KeyCode.G))
m_ped.OnButtonPressed ("G");
if (customInput.GetKeyDown(KeyCode.H))
m_ped.OnButtonPressed ("H");
if (customInput.GetKeyDown (KeyCode.T))
m_ped.OnFlyButtonPressed();
if (customInput.GetKeyDown (KeyCode.R))
m_ped.OnFlyThroughButtonPressed();
}
private void ReadCameraInput ()
{
CustomInput customInput = CustomInput.Instance;
if (GameManager.CanPlayerReadInput())
{
// rotate camera
// FIXME: Camera rotation should be done by ped's current state. We should only assign mouse move input.
var mouseDelta = new Vector2(customInput.GetAxisRaw("Mouse X"), customInput.GetAxisRaw("Mouse Y"));
var rightAnalogDelta = new Vector2(customInput.GetAxisRaw("Joystick X"), customInput.GetAxisRaw("Joystick Y"));
Vector2 totalMouseDelta = mouseDelta + rightAnalogDelta;
totalMouseDelta = Vector2.Scale (totalMouseDelta, GameManager.Instance.cursorSensitivity);
m_ped.MouseMoveInput = totalMouseDelta;
if (m_doSmooth)
{
_smoothMouse.x = Mathf.Lerp (_smoothMouse.x, totalMouseDelta.x, 1f / smoothing.x);
_smoothMouse.y = Mathf.Lerp (_smoothMouse.y, totalMouseDelta.y, 1f / smoothing.y);
_mouseAbsolute += _smoothMouse;
}
else
{
_mouseAbsolute += totalMouseDelta;
}
if (clampInDegrees.y > 0)
_mouseAbsolute.y = Mathf.Clamp(_mouseAbsolute.y, -clampInDegrees.y, clampInDegrees.y);
}
}
private void OnDrawGizmosSelected()
{
if (null == m_ped)
return;
Gizmos.color = Color.white;
// draw enter vehicle radius
Gizmos.DrawWireSphere(transform.position, EnterVehicleRadius);
// find closest vehicle in entering range
var vehicles = FindObjectsOfType<Vehicle>()
.Where(x => Vector3.Distance(transform.position, x.FindClosestSeatTransform(transform.position).position) < EnterVehicleRadius)
.OrderBy(x => Vector3.Distance(transform.position, x.FindClosestSeatTransform(transform.position).position)).ToArray();
foreach (var vehicle in vehicles)
{
// draw all seats
foreach (var seat in vehicle.Seats)
{
Gizmos.color = Color.red;
Gizmos.DrawWireSphere(seat.Parent.position, 0.1f);
}
// draw closest seat
var closestSeat = vehicle.GetSeatAlignmentOfClosestSeat(transform.position);
if (closestSeat != Vehicle.SeatAlignment.None)
{
var closestSeatTransform = vehicle.GetSeatTransform(closestSeat);
Gizmos.color = Color.green;
Gizmos.DrawWireSphere(closestSeatTransform.position, 0.1f);
Gizmos.DrawLine(transform.position, closestSeatTransform.position);
}
break;
}
}
}
}