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

753 lines
20 KiB
C#
Raw Normal View History

2020-05-31 17:07:22 +00:00
using SanAndreasUnity.Behaviours.Vehicles;
using SanAndreasUnity.Behaviours.World;
using SanAndreasUnity.Importing.Animation;
using System.Collections;
using System.Diagnostics;
using UnityEngine;
using Debug = UnityEngine.Debug;
using SanAndreasUnity.Utilities;
using System.Collections.Generic;
using System.Linq;
2019-04-25 14:17:41 +00:00
using SanAndreasUnity.Net;
2020-05-31 17:07:22 +00:00
namespace SanAndreasUnity.Behaviours
{
2019-10-06 22:53:16 +00:00
[RequireComponent(typeof(CharacterController))]
2019-04-23 23:59:16 +00:00
public partial class Ped :
#if MIRROR
Mirror.NetworkBehaviour
#else
MonoBehaviour
#endif
2020-05-31 17:07:22 +00:00
{
2019-04-24 21:10:57 +00:00
2020-05-31 17:07:22 +00:00
private static List<Ped> s_allPeds = new List<Ped> ();
public static Ped[] AllPeds { get { return s_allPeds.ToArray (); } }
2019-05-24 22:19:15 +00:00
public static IEnumerable<Ped> AllPedsEnumerable => s_allPeds;
2019-05-25 23:51:29 +00:00
public static int NumPeds => s_allPeds.Count;
2020-05-31 17:07:22 +00:00
private WeaponHolder m_weaponHolder;
public WeaponHolder WeaponHolder { get { return m_weaponHolder; } }
private StateMachine m_stateMachine = new StateMachine ();
2019-04-24 20:27:59 +00:00
public Camera Camera { get { return this == Ped.Instance ? Camera.main : null; } }
2019-04-24 21:27:59 +00:00
public PedModel PlayerModel { get; private set; }
2020-05-31 17:07:22 +00:00
public bool shouldPlayAnims = true;
2019-04-24 21:27:59 +00:00
public CharacterController characterController { get; private set; }
2020-05-31 17:07:22 +00:00
2019-07-29 00:10:59 +00:00
public float CameraDistance { get { return PedManager.Instance.cameraDistanceFromPed; } set { PedManager.Instance.cameraDistanceFromPed = value; } }
2020-05-31 17:07:22 +00:00
2019-07-29 00:10:59 +00:00
public float CameraDistanceVehicle { get { return VehicleManager.Instance.cameraDistanceFromVehicle; } set { VehicleManager.Instance.cameraDistanceFromVehicle = value; } }
2020-05-31 17:07:22 +00:00
2019-07-29 00:10:59 +00:00
// used for clamping camera rotation
2020-05-31 17:07:22 +00:00
[SerializeField] private Vector2 m_cameraClampValue = new Vector2(60, 60);
public Vector2 CameraClampValue { get { return m_cameraClampValue; } set { m_cameraClampValue = value; } }
2021-09-19 21:29:51 +00:00
private readonly StateContainer<Peds.States.BaseScriptState> _stateContainer = new StateContainer<Peds.States.BaseScriptState>();
2021-12-18 14:55:04 +00:00
public StateContainer<Peds.States.BaseScriptState> StateContainer => _stateContainer;
public IReadOnlyList<Peds.States.IAimState> CachedAimStates { get; private set; } = System.Array.Empty<Peds.States.IAimState>();
2021-12-26 22:40:44 +00:00
public IReadOnlyList<Peds.States.BaseScriptState> CachedNonAimStates { get; private set; } = System.Array.Empty<Peds.States.BaseScriptState>();
2021-12-18 14:55:04 +00:00
2020-05-31 17:07:22 +00:00
public Peds.States.BaseScriptState CurrentState { get { return (Peds.States.BaseScriptState) m_stateMachine.CurrentState; } }
public Cell Cell { get { return Cell.Instance; } }
public UnityEngine.Animation AnimComponent { get { return PlayerModel.AnimComponent; } }
public SanAndreasUnity.Importing.Items.Definitions.PedestrianDef PedDef { get { return this.PlayerModel.Definition; } }
public static int RandomPedId {
get {
int count = Ped.SpawnablePedDefs.Count ();
if (count < 1)
throw new System.Exception ("No ped definitions found");
int index = Random.Range (0, count);
return Ped.SpawnablePedDefs.ElementAt (index).Id;
}
}
2019-06-22 20:22:30 +00:00
public static int LayerMask { get { return UnityEngine.LayerMask.GetMask ("Player"); } }
2020-05-16 20:39:04 +00:00
public static readonly string PedBoneLayerName = "PedBone";
public static int PedBoneLayerMask { get { return UnityEngine.LayerMask.GetMask(PedBoneLayerName); } }
2019-06-22 20:22:30 +00:00
2019-04-24 21:10:57 +00:00
public bool IsGrounded { get { return characterController.isGrounded; } }
2020-05-31 17:07:22 +00:00
public Vector2 MouseMoveInput { get; set; }
public Vector2 MouseScrollInput { get; set; }
public bool IsWalkOn { get; set; }
public bool IsRunOn { get; set; }
public bool IsSprintOn { get; set; }
public bool IsJumpOn { get; set; }
public Vector3 Velocity { get; private set; }
/// <summary> Current movement input. </summary>
public Vector3 Movement { get; set; }
/// <summary> Direction towards which the player turns. </summary>
public Vector3 Heading { get; set; }
public bool IsAiming { get { return m_weaponHolder.IsAiming; } }
public Weapon CurrentWeapon { get { return m_weaponHolder.CurrentWeapon; } }
public bool IsFiring { get { return m_weaponHolder.IsFiring; } }
2019-07-07 00:09:06 +00:00
public Vector3 AimDirection { get { return m_weaponHolder.AimDirection; } set => m_weaponHolder.AimDirection = value; }
public Vector3 FirePosition => this.CurrentState is Peds.States.IAimState ? ((Peds.States.IAimState) this.CurrentState).GetFirePosition() : this.transform.position;
public Vector3 FireDirection => this.CurrentState is Peds.States.IAimState ? ((Peds.States.IAimState) this.CurrentState).GetFireDirection() : this.transform.forward;
public bool IsAimOn { get ; set ; }
2020-05-31 17:07:22 +00:00
public bool IsFireOn { get ; set ; }
public bool IsHoldingWeapon { get { return m_weaponHolder.IsHoldingWeapon; } }
2019-11-21 12:13:57 +00:00
public EntranceExitMapObject CurrentCollidingEnex { get; private set; }
public Importing.Items.Placements.EntranceExit FirstEnex { get; private set; }
public Importing.Items.Placements.EntranceExit SecondEnex { get; private set; }
Importing.Items.Placements.EntranceExit m_enexToIgnoreNextCollision;
2020-05-31 17:07:22 +00:00
private Coroutine m_findGroundCoroutine;
public struct FindGroundParams
{
public bool tryFromAbove;
2019-11-22 16:21:17 +00:00
public float raycastDistance;
public FindGroundParams(bool tryFromAbove = true, float raycastDistance = 1000)
{
this.tryFromAbove = tryFromAbove;
this.raycastDistance = raycastDistance;
}
new world loading system (#110) * wip * much faster world creation * add StaticGeometryInspector * disable child/parent logic and fading * rename * (de)activate objects based on parent * set draw distance based on layers * ... * wip * wip * wip * remove unused param * prevent concurrent modification * ... * catch exceptions when notifying * ... * notify about area, not objects * limit public access to Area * ... * ... * allow public access * add public api * adapt code * pass callback to ctor * adapt focus points * fix * fix intersection check * support rectangles * adjust parameters in prefab * this should fix IsInsideOf() * ... * ... * fix getting area by index * create area if not exists * ... * ... * ... * wip for distance levels * remove constraint on generic parameter * add some validation * fix * fix draw distance per level * change time of day in which lights are visible * add todos * don't use id for UnRegisterFocusPoint() * use hash set for storing focus points * add 1 more level * mark area for update only if visibility changes * profile WorldSystem calls * add some profiling sections * limit time per frame for LoadingThread * switch custom concurrent queue * copy jobs to buffer * rename * change max draw distance setting * wait one more frame * try to remove 801 distance level to remove holes * attempt to hide interiors, but failed * delete no longer needed script * optimization * some error checking * add camera as focus point * dont add camera as focus point in headless mode * working on load priority * fix bug - load priority finished * ... * small optimizations * ... * ... * remove unneeded variable * add fading * dont do fading in headless mode * fadeRate available in inspector * change fade rate * take into account if geometry is loaded when checking if object should be visible, and if fading should be done * small optimization * cache IsInHeadlessMode * display Instance info in inspector * move interiors up in the sky * rename * adapt code to different y pos of interiors * refactor * fix finding matched enex for enexes that lead to the same interior level * display new world stats * rename * rename class * ... * ... * extract function * extract parameters into a struct * add focus point to dead body * add focus point to vehicle * add focus point to vehicle detached parts * remove OutOfRangeDestroyer from vehicle, and destroy vehicle if it falls below the map * dont use focus points on vehicle and vehicle detached parts, when not on server * add focus point for npc peds * add possibility to set timeout during which focus point keeps revealing after it's destroyed * adapt UnRegisterFocusPoint() to timeout * rename * adapt code * cleanup MapObject class * ... * converting to `lock()` * optimize method: use 1 lock instead of 3 * call OnObjectFinishedLoading() instead of AddToLoadedObjects() * ... * make sure it's main thread * AsyncLoader is no longer thread safe * convert static members to non-static in LoadingThread * fix * ... * store indexes for each area * impl GetAreaCenter() * calculate load priority based on distance to area, not objects ; limit time per frame ; sort area in Cell, not in concurrent SortedSet ; * add support for changing draw distance at runtime * delay setting the new value by 0.2 s * have a separate default max draw distance for mobile platforms * adjust y axis world params so that number of visible areas is reduced * remove "camera far clip plane" setting * rename * document flags * rename * disable shadow casting and receiving for some objects * allow casting shadows for LODs with large draw distance * remove "WorldSystem" layer * revert layer
2021-07-18 04:03:43 +00:00
public static FindGroundParams DefaultBasedOnLoadedWorld => new FindGroundParams((null == Cell.Instance || Cell.Instance.HasMainExterior));
}
2020-05-31 17:07:22 +00:00
/// <summary>Ped who is controlled by local player.</summary>
public static Ped Instance { get { return Net.Player.Local != null ? Net.Player.Local.OwnedPed : null; } }
2020-05-31 17:07:22 +00:00
2019-04-24 21:10:57 +00:00
/// <summary>Position of ped instance.</summary>
public static Vector3 InstancePos { get { return Instance.transform.position; } }
2020-05-31 17:07:22 +00:00
/// <summary>Is this ped controlled by local player ?</summary>
2019-04-25 20:18:02 +00:00
public bool IsControlledByLocalPlayer { get { return this == Ped.Instance; } }
2020-05-31 17:07:22 +00:00
public string DescriptionForLogging => "(netId = " + this.netId + ")";
2021-02-21 00:39:39 +00:00
public static event System.Action<Ped> onAwake = delegate {};
2021-02-21 00:20:20 +00:00
public static event System.Action<Ped> onStart = delegate {};
2020-05-31 17:07:22 +00:00
void Awake()
{
2019-04-24 21:27:59 +00:00
this.PlayerModel = this.GetComponentInChildren<PedModel>();
this.characterController = this.GetComponent<CharacterController>();
2020-05-31 17:07:22 +00:00
m_weaponHolder = GetComponent<WeaponHolder> ();
2021-09-19 21:29:51 +00:00
_stateContainer.AddStates(this.GetComponentsInChildren<Peds.States.BaseScriptState> ());
2020-05-31 17:07:22 +00:00
2021-12-18 14:55:04 +00:00
this.CachedAimStates = _stateContainer
.GetStatesThatInherit<Peds.States.IAimState>()
.Cast<Peds.States.IAimState>()
.ToArray();
2021-12-26 22:40:44 +00:00
this.CachedNonAimStates = _stateContainer.States
.Where(_ => !(_ is Peds.States.IAimState))
2021-12-26 22:40:44 +00:00
.ToArray();
2021-12-18 14:55:04 +00:00
2020-05-31 17:07:22 +00:00
this.AwakeForDamage ();
this.Awake_Net();
2021-02-21 00:39:39 +00:00
F.InvokeEventExceptionSafe(onAwake, this);
2020-05-31 17:07:22 +00:00
}
void Start()
{
//MySetupLocalPlayer ();
2019-05-24 21:51:39 +00:00
this.Start_Net();
2020-05-31 17:07:22 +00:00
this.StartForDamage ();
if (NetStatus.IsServer)
{
if (null == this.CurrentState)
this.SwitchState<Peds.States.StandState> ();
}
2020-05-31 17:07:22 +00:00
2019-05-21 22:58:28 +00:00
// register Cell focus point
if (this.Cell != null)
{
if (NetStatus.IsServer)
{
new world loading system (#110) * wip * much faster world creation * add StaticGeometryInspector * disable child/parent logic and fading * rename * (de)activate objects based on parent * set draw distance based on layers * ... * wip * wip * wip * remove unused param * prevent concurrent modification * ... * catch exceptions when notifying * ... * notify about area, not objects * limit public access to Area * ... * ... * allow public access * add public api * adapt code * pass callback to ctor * adapt focus points * fix * fix intersection check * support rectangles * adjust parameters in prefab * this should fix IsInsideOf() * ... * ... * fix getting area by index * create area if not exists * ... * ... * ... * wip for distance levels * remove constraint on generic parameter * add some validation * fix * fix draw distance per level * change time of day in which lights are visible * add todos * don't use id for UnRegisterFocusPoint() * use hash set for storing focus points * add 1 more level * mark area for update only if visibility changes * profile WorldSystem calls * add some profiling sections * limit time per frame for LoadingThread * switch custom concurrent queue * copy jobs to buffer * rename * change max draw distance setting * wait one more frame * try to remove 801 distance level to remove holes * attempt to hide interiors, but failed * delete no longer needed script * optimization * some error checking * add camera as focus point * dont add camera as focus point in headless mode * working on load priority * fix bug - load priority finished * ... * small optimizations * ... * ... * remove unneeded variable * add fading * dont do fading in headless mode * fadeRate available in inspector * change fade rate * take into account if geometry is loaded when checking if object should be visible, and if fading should be done * small optimization * cache IsInHeadlessMode * display Instance info in inspector * move interiors up in the sky * rename * adapt code to different y pos of interiors * refactor * fix finding matched enex for enexes that lead to the same interior level * display new world stats * rename * rename class * ... * ... * extract function * extract parameters into a struct * add focus point to dead body * add focus point to vehicle * add focus point to vehicle detached parts * remove OutOfRangeDestroyer from vehicle, and destroy vehicle if it falls below the map * dont use focus points on vehicle and vehicle detached parts, when not on server * add focus point for npc peds * add possibility to set timeout during which focus point keeps revealing after it's destroyed * adapt UnRegisterFocusPoint() to timeout * rename * adapt code * cleanup MapObject class * ... * converting to `lock()` * optimize method: use 1 lock instead of 3 * call OnObjectFinishedLoading() instead of AddToLoadedObjects() * ... * make sure it's main thread * AsyncLoader is no longer thread safe * convert static members to non-static in LoadingThread * fix * ... * store indexes for each area * impl GetAreaCenter() * calculate load priority based on distance to area, not objects ; limit time per frame ; sort area in Cell, not in concurrent SortedSet ; * add support for changing draw distance at runtime * delay setting the new value by 0.2 s * have a separate default max draw distance for mobile platforms * adjust y axis world params so that number of visible areas is reduced * remove "camera far clip plane" setting * rename * document flags * rename * disable shadow casting and receiving for some objects * allow casting shadows for LODs with large draw distance * remove "WorldSystem" layer * revert layer
2021-07-18 04:03:43 +00:00
if (this.PlayerOwner != null)
this.Cell.RegisterFocusPoint(this.transform, PedManager.Instance.playerPedFocusPointParameters);
else
this.Cell.RegisterFocusPoint(this.transform, PedManager.Instance.npcPedFocusPointParameters);
2019-05-21 22:58:28 +00:00
}
else if (NetStatus.IsClientActive())
{
new world loading system (#110) * wip * much faster world creation * add StaticGeometryInspector * disable child/parent logic and fading * rename * (de)activate objects based on parent * set draw distance based on layers * ... * wip * wip * wip * remove unused param * prevent concurrent modification * ... * catch exceptions when notifying * ... * notify about area, not objects * limit public access to Area * ... * ... * allow public access * add public api * adapt code * pass callback to ctor * adapt focus points * fix * fix intersection check * support rectangles * adjust parameters in prefab * this should fix IsInsideOf() * ... * ... * fix getting area by index * create area if not exists * ... * ... * ... * wip for distance levels * remove constraint on generic parameter * add some validation * fix * fix draw distance per level * change time of day in which lights are visible * add todos * don't use id for UnRegisterFocusPoint() * use hash set for storing focus points * add 1 more level * mark area for update only if visibility changes * profile WorldSystem calls * add some profiling sections * limit time per frame for LoadingThread * switch custom concurrent queue * copy jobs to buffer * rename * change max draw distance setting * wait one more frame * try to remove 801 distance level to remove holes * attempt to hide interiors, but failed * delete no longer needed script * optimization * some error checking * add camera as focus point * dont add camera as focus point in headless mode * working on load priority * fix bug - load priority finished * ... * small optimizations * ... * ... * remove unneeded variable * add fading * dont do fading in headless mode * fadeRate available in inspector * change fade rate * take into account if geometry is loaded when checking if object should be visible, and if fading should be done * small optimization * cache IsInHeadlessMode * display Instance info in inspector * move interiors up in the sky * rename * adapt code to different y pos of interiors * refactor * fix finding matched enex for enexes that lead to the same interior level * display new world stats * rename * rename class * ... * ... * extract function * extract parameters into a struct * add focus point to dead body * add focus point to vehicle * add focus point to vehicle detached parts * remove OutOfRangeDestroyer from vehicle, and destroy vehicle if it falls below the map * dont use focus points on vehicle and vehicle detached parts, when not on server * add focus point for npc peds * add possibility to set timeout during which focus point keeps revealing after it's destroyed * adapt UnRegisterFocusPoint() to timeout * rename * adapt code * cleanup MapObject class * ... * converting to `lock()` * optimize method: use 1 lock instead of 3 * call OnObjectFinishedLoading() instead of AddToLoadedObjects() * ... * make sure it's main thread * AsyncLoader is no longer thread safe * convert static members to non-static in LoadingThread * fix * ... * store indexes for each area * impl GetAreaCenter() * calculate load priority based on distance to area, not objects ; limit time per frame ; sort area in Cell, not in concurrent SortedSet ; * add support for changing draw distance at runtime * delay setting the new value by 0.2 s * have a separate default max draw distance for mobile platforms * adjust y axis world params so that number of visible areas is reduced * remove "camera far clip plane" setting * rename * document flags * rename * disable shadow casting and receiving for some objects * allow casting shadows for LODs with large draw distance * remove "WorldSystem" layer * revert layer
2021-07-18 04:03:43 +00:00
// no need to register on client, because camera will be used as a focus point
2019-05-21 22:58:28 +00:00
}
}
if (!NetStatus.IsServer)
{
// destroy OutOfRangeDestroyer on clients - server should handle destroying peds which are not in range
this.gameObject.DestroyComponent<OutOfRangeDestroyer>();
}
// find ground
if (NetStatus.IsServer)
{
if (!this.IsGrounded)
{
this.FindGround (FindGroundParams.DefaultBasedOnLoadedWorld);
}
}
F.InvokeEventExceptionSafe(onStart, this);
2020-05-31 17:07:22 +00:00
}
void OnEnable ()
{
s_allPeds.Add (this);
}
void OnDisable ()
{
s_allPeds.Remove (this);
}
2019-04-25 23:39:07 +00:00
public Peds.States.BaseScriptState GetState(System.Type type)
{
2021-09-19 21:29:51 +00:00
return _stateContainer.GetState(type);
2019-04-25 23:39:07 +00:00
}
2021-09-19 21:29:51 +00:00
public T GetState<T>()
where T : Peds.States.BaseScriptState
2020-05-31 17:07:22 +00:00
{
2021-09-19 21:29:51 +00:00
return _stateContainer.GetState<T>();
2020-05-31 17:07:22 +00:00
}
2019-04-25 23:39:07 +00:00
public Peds.States.BaseScriptState GetStateOrLogError(System.Type type)
2020-05-31 17:07:22 +00:00
{
2021-09-19 21:29:51 +00:00
return _stateContainer.GetStateOrLogError(type);
2020-05-31 17:07:22 +00:00
}
2021-09-19 21:29:51 +00:00
public T GetStateOrLogError<T>()
where T : Peds.States.BaseScriptState
2019-04-25 23:39:07 +00:00
{
2021-09-19 21:29:51 +00:00
return _stateContainer.GetStateOrLogError<T>();
2019-04-25 23:39:07 +00:00
}
public void SwitchState(System.Type type)
{
var state = this.GetStateOrLogError (type);
2020-05-31 17:07:22 +00:00
if (null == state)
return;
m_stateMachine.SwitchState (state);
}
2021-09-19 21:29:51 +00:00
public void SwitchState<T>()
where T : Peds.States.BaseScriptState
2019-04-25 23:39:07 +00:00
{
this.SwitchState(typeof(T));
}
2020-05-31 17:07:22 +00:00
public void Teleport(Vector3 position, Quaternion rotation, FindGroundParams parameters) {
2020-05-31 17:07:22 +00:00
2019-04-25 14:20:48 +00:00
if (!NetStatus.IsServer)
return;
2020-05-31 17:07:22 +00:00
if (this.IsInVehicle)
return;
this.transform.position = position;
this.transform.rotation = rotation;
this.Heading = rotation.TransformDirection(Vector3.forward);
2020-05-31 17:07:22 +00:00
this.FindGround (parameters);
2020-05-31 17:07:22 +00:00
}
public void Teleport(Vector3 position, Quaternion rotation)
{
this.Teleport(position, rotation, FindGroundParams.DefaultBasedOnLoadedWorld);
}
2020-05-31 17:07:22 +00:00
public void Teleport(Vector3 position) {
this.Teleport (position, this.transform.rotation);
}
public void FindGround (FindGroundParams parameters)
2020-05-31 17:07:22 +00:00
{
if (m_findGroundCoroutine != null) {
StopCoroutine (m_findGroundCoroutine);
m_findGroundCoroutine = null;
}
m_findGroundCoroutine = StartCoroutine (FindGroundCoroutine (parameters));
2020-05-31 17:07:22 +00:00
}
private IEnumerator FindGroundCoroutine(FindGroundParams parameters)
2020-05-31 17:07:22 +00:00
{
// set y pos to high value, so that higher grounds can be loaded
// this.transform.SetY (150);
2020-05-31 17:07:22 +00:00
Vector3 startingPos = this.transform.position;
yield return null;
2020-05-31 17:07:22 +00:00
// wait for loader to finish, in case he didn't
while (!Loader.HasLoaded)
yield return null;
// yield until you find ground beneath or above the player, or until timeout expires
float timeStarted = Time.time;
int numAttempts = 1;
while (true) {
if (Time.time - timeStarted > 4.0f) {
// timeout expired
2019-10-22 00:58:30 +00:00
Debug.LogWarningFormat("Failed to find ground for ped {0} - timeout expired", this.DescriptionForLogging);
2020-05-31 17:07:22 +00:00
yield break;
}
// maintain starting position
this.transform.position = startingPos;
this.Velocity = Vector3.zero;
RaycastHit hit;
float raycastDistance = parameters.raycastDistance;
int raycastLayerMask = ~ PedManager.Instance.groundFindingIgnoredLayerMask;
2020-05-31 17:07:22 +00:00
var raycastPositions = new List<Vector3>{ this.transform.position }; //transform.position - Vector3.up * characterController.height;
var raycastDirections = new List<Vector3>{ Vector3.down };
var customMessages = new List<string>{ "from center" };
2020-05-31 17:07:22 +00:00
if (parameters.tryFromAbove)
{
raycastPositions.Add (this.transform.position + Vector3.up * raycastDistance);
raycastDirections.Add (Vector3.down);
customMessages.Add ("from above");
}
for (int i = 0; i < raycastPositions.Count; i++) {
2020-05-31 17:07:22 +00:00
if (Physics.Raycast (raycastPositions[i], raycastDirections[i], out hit, raycastDistance, raycastLayerMask)) {
// ray hit the ground
// we can move there
this.OnFoundGround (hit, numAttempts, customMessages [i]);
yield break;
}
}
numAttempts++;
yield return null;
}
}
private void OnFoundGround(RaycastHit hit, int numAttempts, string customMessage) {
this.transform.position = hit.point + Vector3.up * (characterController.height * 0.5f + 0.1f);
2020-05-31 17:07:22 +00:00
this.Velocity = Vector3.zero;
//Debug.LogFormat ("Found ground at {0}, distance {1}, object name {2}, num attempts {3}, {4}, ped {5}", hit.point, hit.distance,
// hit.transform.name, numAttempts, customMessage, this.DescriptionForLogging);
2020-05-31 17:07:22 +00:00
}
private void Update()
{
if (!Loader.HasLoaded)
return;
if (this.CurrentState != null)
{
this.CurrentState.UpdateState ();
}
2019-04-25 14:35:29 +00:00
if (NetStatus.IsServer)
this.ResetIfFallingBelowTheWorld();
2020-05-31 17:07:22 +00:00
// ConstrainPosition ();
// ConstrainRotation ();
// UpdateAnims ();
//if (IsDrivingVehicle)
// UpdateWheelTurning();
this.UpdateDamageStuff ();
2019-04-24 00:50:28 +00:00
this.Update_Net();
2020-05-31 17:07:22 +00:00
if (this.CurrentState != null)
this.CurrentState.PostUpdateState();
}
void LateUpdate ()
{
if (this.CurrentState != null)
{
this.CurrentState.LateUpdateState ();
}
}
public void ConstrainPosition() {
// Constrain to stay inside map
2019-06-23 21:09:41 +00:00
/*
2020-05-31 17:07:22 +00:00
if (transform.position.x < -3000)
{
var t = transform.position;
t.x = -3000;
transform.position = t;
}
if (transform.position.x > 3000)
{
var t = transform.position;
t.x = 3000;
transform.position = t;
}
if (transform.position.z < -3000)
{
var t = transform.position;
t.z = -3000;
transform.position = t;
}
if (transform.position.z > 3000)
{
var t = transform.position;
t.z = 3000;
transform.position = t;
}
2019-06-23 21:09:41 +00:00
*/
2020-05-31 17:07:22 +00:00
}
public void ConstrainRotation ()
{
if (IsInVehicle)
return;
// ped can only rotate around Y axis
Vector3 eulers = this.transform.eulerAngles;
if (eulers.x != 0f || eulers.z != 0f) {
eulers.x = 0f;
eulers.z = 0f;
this.transform.eulerAngles = eulers;
}
}
2019-04-25 14:32:25 +00:00
void ResetIfFallingBelowTheWorld()
{
2019-04-25 14:35:29 +00:00
if (this.IsInVehicle)
return;
if (!this.IsGrounded && this.transform.position.y < -300 && this.Velocity.y < -20)
2019-04-25 14:32:25 +00:00
{
// set velocity to 0
this.Velocity = Vector3.zero;
// restore ped to higher position, and try to find ground
Vector3 t = this.transform.position;
t.y = 150;
this.transform.position = t;
2019-11-22 16:21:17 +00:00
this.FindGround(new FindGroundParams());
2019-04-25 14:32:25 +00:00
}
2019-04-25 14:32:25 +00:00
}
2020-05-31 17:07:22 +00:00
private void FixedUpdate()
{
if (!Loader.HasLoaded)
return;
if (this.CurrentState != null)
{
this.CurrentState.FixedUpdateState ();
}
2019-04-27 01:11:07 +00:00
this.FixedUpdate_Net();
2020-05-31 17:07:22 +00:00
}
public void UpdateHeading()
{
if (this.IsAiming && this.CurrentWeapon != null && !this.CurrentWeapon.CanTurnInDirectionOtherThanAiming) {
// ped heading can only be the same as ped direction
this.Heading = this.WeaponHolder.AimDirection;
}
// player can look only along X and Z axis
this.Heading = this.Heading.WithXAndZ ().normalized;
}
public void UpdateRotation()
{
// rotate player towards his heading
Vector3 forward = Vector3.RotateTowards (this.transform.forward, Heading, PedManager.Instance.pedTurnSpeed * Time.deltaTime, 0.0f);
2020-05-31 17:07:22 +00:00
this.transform.rotation = Quaternion.LookRotation(forward);
}
public void UpdateMovement()
{
// movement can only be done on X and Z axis
2021-09-11 17:14:31 +00:00
this.Movement = this.Movement.WithXAndZ().normalized;
2020-05-31 17:07:22 +00:00
// change heading to match movement input
//if (Movement.sqrMagnitude > float.Epsilon)
//{
// Heading = Vector3.Scale(Movement, new Vector3(1f, 0f, 1f)).normalized;
//}
// change velocity based on movement input and current speed extracted from anim
float modelVel = Mathf.Abs( PlayerModel.Velocity [PlayerModel.VelocityAxis] );
//Vector3 localMovement = this.transform.InverseTransformDirection (this.Movement);
//Vector3 globalMovement = this.transform.TransformDirection( Vector3.Scale( localMovement, modelVel ) );
2021-09-11 16:35:59 +00:00
// override velocity along X and Z axis, accumulate it along Y axis
Vector3 newVelocity = this.Movement * modelVel;
newVelocity.y = Velocity.y + this.Movement.y * modelVel;
2020-05-31 17:07:22 +00:00
2021-09-11 16:35:59 +00:00
if (characterController.isGrounded)
newVelocity.y = 0f;
else
newVelocity.y -= (-Physics.gravity.y) * 2f * Time.deltaTime;
2020-05-31 17:07:22 +00:00
2021-09-11 16:35:59 +00:00
Velocity = newVelocity;
2020-05-31 17:07:22 +00:00
// finally, move the character
characterController.Move(Velocity * Time.deltaTime);
2020-05-31 17:07:22 +00:00
// if(!IsLocalPlayer)
// {
// Velocity = characterController.velocity;
// }
}
public void StartFiring ()
{
if (!this.IsAiming)
return;
((Peds.States.IAimState)this.CurrentState).StartFiring();
}
public void StopFiring ()
{
if (!this.IsFiring)
return;
((Peds.States.IFireState)this.CurrentState).StopFiring();
}
public void ResetInput ()
{
this.ResetMovementInput ();
this.MouseMoveInput = Vector2.zero;
this.MouseScrollInput = Vector2.zero;
this.IsAimOn = this.IsFireOn = false;
}
public void ResetMovementInput ()
{
this.IsWalkOn = this.IsRunOn = this.IsSprintOn = false;
this.Movement = Vector3.zero;
this.IsJumpOn = false;
}
public void OnButtonPressed (string buttonName)
{
if (this.CurrentState != null)
this.CurrentState.OnButtonPressed (buttonName);
}
2020-05-31 17:07:22 +00:00
public void OnFireButtonPressed ()
{
if (this.CurrentState != null)
this.CurrentState.OnFireButtonPressed ();
}
public void OnAimButtonPressed ()
{
if (this.CurrentState != null)
this.CurrentState.OnAimButtonPressed ();
}
public void OnSubmitPressed ()
{
if (this.CurrentState != null)
{
this.CurrentState.OnSubmitPressed ();
}
}
public void OnJumpButtonPressed ()
{
if (this.CurrentState != null)
this.CurrentState.OnJumpPressed ();
}
public void OnCrouchButtonPressed ()
{
if (this.CurrentState != null)
this.CurrentState.OnCrouchButtonPressed ();
}
public void OnNextWeaponButtonPressed ()
{
if (this.CurrentState != null)
this.CurrentState.OnNextWeaponButtonPressed ();
}
public void OnPreviousWeaponButtonPressed ()
{
if (this.CurrentState != null)
this.CurrentState.OnPreviousWeaponButtonPressed ();
}
public void OnFlyButtonPressed ()
{
if (this.CurrentState != null)
this.CurrentState.OnFlyButtonPressed ();
}
public void OnFlyThroughButtonPressed ()
{
if (this.CurrentState != null)
this.CurrentState.OnFlyThroughButtonPressed ();
}
2022-01-02 20:52:31 +00:00
public void OnSurrenderButtonPressed()
{
if (this.CurrentState != null)
this.CurrentState.OnSurrenderButtonPressed();
}
2020-05-31 17:07:22 +00:00
2019-11-20 12:56:06 +00:00
internal void OnStartCollidingWithEnex(EntranceExitMapObject enex)
{
2019-11-21 12:13:57 +00:00
if (this.CurrentCollidingEnex != null && this.CurrentCollidingEnex.gameObject.activeInHierarchy) // already colliding with enex
return;
2019-11-21 12:13:57 +00:00
this.CurrentCollidingEnex = enex;
if (NetStatus.IsServer)
{
if (enex.Info == m_enexToIgnoreNextCollision)
{
// we should ignore this collision
// collision will be processed next time
m_enexToIgnoreNextCollision = null;
}
else
{
if (enex.Info == this.SecondEnex)
2019-11-21 16:54:46 +00:00
{
// we collided with second enex
2019-11-21 16:54:46 +00:00
// teleport back to first enex ; reset first and second enex
var tmpEnex = this.FirstEnex;
this.FirstEnex = null;
this.SecondEnex = null;
m_enexToIgnoreNextCollision = tmpEnex; // ignore next collision with first enex
2019-11-21 16:54:46 +00:00
this.TeleportToEnex(tmpEnex);
}
else
{
new world loading system (#110) * wip * much faster world creation * add StaticGeometryInspector * disable child/parent logic and fading * rename * (de)activate objects based on parent * set draw distance based on layers * ... * wip * wip * wip * remove unused param * prevent concurrent modification * ... * catch exceptions when notifying * ... * notify about area, not objects * limit public access to Area * ... * ... * allow public access * add public api * adapt code * pass callback to ctor * adapt focus points * fix * fix intersection check * support rectangles * adjust parameters in prefab * this should fix IsInsideOf() * ... * ... * fix getting area by index * create area if not exists * ... * ... * ... * wip for distance levels * remove constraint on generic parameter * add some validation * fix * fix draw distance per level * change time of day in which lights are visible * add todos * don't use id for UnRegisterFocusPoint() * use hash set for storing focus points * add 1 more level * mark area for update only if visibility changes * profile WorldSystem calls * add some profiling sections * limit time per frame for LoadingThread * switch custom concurrent queue * copy jobs to buffer * rename * change max draw distance setting * wait one more frame * try to remove 801 distance level to remove holes * attempt to hide interiors, but failed * delete no longer needed script * optimization * some error checking * add camera as focus point * dont add camera as focus point in headless mode * working on load priority * fix bug - load priority finished * ... * small optimizations * ... * ... * remove unneeded variable * add fading * dont do fading in headless mode * fadeRate available in inspector * change fade rate * take into account if geometry is loaded when checking if object should be visible, and if fading should be done * small optimization * cache IsInHeadlessMode * display Instance info in inspector * move interiors up in the sky * rename * adapt code to different y pos of interiors * refactor * fix finding matched enex for enexes that lead to the same interior level * display new world stats * rename * rename class * ... * ... * extract function * extract parameters into a struct * add focus point to dead body * add focus point to vehicle * add focus point to vehicle detached parts * remove OutOfRangeDestroyer from vehicle, and destroy vehicle if it falls below the map * dont use focus points on vehicle and vehicle detached parts, when not on server * add focus point for npc peds * add possibility to set timeout during which focus point keeps revealing after it's destroyed * adapt UnRegisterFocusPoint() to timeout * rename * adapt code * cleanup MapObject class * ... * converting to `lock()` * optimize method: use 1 lock instead of 3 * call OnObjectFinishedLoading() instead of AddToLoadedObjects() * ... * make sure it's main thread * AsyncLoader is no longer thread safe * convert static members to non-static in LoadingThread * fix * ... * store indexes for each area * impl GetAreaCenter() * calculate load priority based on distance to area, not objects ; limit time per frame ; sort area in Cell, not in concurrent SortedSet ; * add support for changing draw distance at runtime * delay setting the new value by 0.2 s * have a separate default max draw distance for mobile platforms * adjust y axis world params so that number of visible areas is reduced * remove "camera far clip plane" setting * rename * document flags * rename * disable shadow casting and receiving for some objects * allow casting shadows for LODs with large draw distance * remove "WorldSystem" layer * revert layer
2021-07-18 04:03:43 +00:00
var counterPart = enex.FindMatchingEnex();
if (counterPart != null)
{
// found a counterpart where we can teleport
// remember first and second enex
this.FirstEnex = enex.Info;
this.SecondEnex = counterPart;
// ignore next collision with second enex
m_enexToIgnoreNextCollision = counterPart;
// teleport to second enex
this.TeleportToEnex(counterPart);
}
}
}
}
2019-11-20 12:56:06 +00:00
}
internal void OnStopCollidingWithEnex(EntranceExitMapObject enex)
{
2019-11-21 12:13:57 +00:00
if (enex == this.CurrentCollidingEnex)
this.CurrentCollidingEnex = null;
2019-11-20 12:56:06 +00:00
}
void TeleportToEnex(Importing.Items.Placements.EntranceExit enex)
{
TransformDataStruct transformData = Cell.GetEnexExitTransform(enex);
this.Teleport(transformData.position, transformData.rotation, new FindGroundParams(false, 50));
}
2019-11-20 12:56:06 +00:00
2020-05-31 17:07:22 +00:00
void OnDrawGizmosSelected ()
{
// draw heading ray
Gizmos.color = Color.blue;
Gizmos.DrawLine (this.transform.position, this.transform.position + this.Heading);
// draw movement ray
Gizmos.color = Color.green;
Gizmos.DrawLine (this.transform.position, this.transform.position + this.Movement);
}
}
}