using System.Collections.Generic; using Pathfinding; using Pathfinding.RVO; using UnityEngine; [RequireComponent(typeof(Seeker))] public class PathfindMovementPlayerunit : PathfindMovement, DayNightCycle.IDaytimeSensitive { public List targetPriorities = new List(); public float keepDistanceOf = 2f; public float maximumDistanceFromHome = 100000f; public float movementSpeed = 2f; public float recalculatePathInterval = 1f; public string backupMovementGraph = ""; public float agroTimeWhenAttackedByPlayer = 5f; public float speedBoostDuringDaytime = 1.5f; private TaggedObject agroPlayerTarget; private Seeker seeker; private RVOController rvo; private Vector3 seekToTargetPosSnappedtoNavmesh = Vector3.zero; private Vector3 seekToTargetPos = Vector3.zero; private TaggedObject seekToTaggedObj; private List path = new List(); private int nextPathPointIndex; private float recalculatePathCooldown; private Vector3 homePosition; private Vector3 homePositionOriginal; private bool currentlyWalkingHome = true; private TargetPriority targetPrio; private NNConstraint nearestConstraint = new NNConstraint(); private GraphMask graphMaskOriginal; private Vector3 nextPathPoint; private SettingsManager settingsManager; private bool followingPlayer; [SerializeField] private GameObject holdPositionMarker; private Transform holdPositionMarkerTransform; private float slowedFor; private bool day = true; private bool holdPosition; private Vector3 storeRequestedTargetPos; public override RVOController RVO => rvo; public Vector3 HopePositionOriginal => homePositionOriginal; public Vector3 HomePosition { get { return homePosition; } set { homePosition = value; } } public Vector3 NextPathPoint => nextPathPoint; public override bool IsSlowed => slowedFor > 0f; public bool HoldPosition { get { return holdPosition; } set { holdPosition = value; holdPositionMarker.SetActive(value); if ((bool)holdPositionMarkerTransform) { holdPositionMarkerTransform.position = homePosition + 0.05f * Vector3.up; } } } public void FollowPlayer(bool _follow) { followingPlayer = _follow; HoldPosition = false; } public override void GetAgroFromObject(TaggedObject _agroTarget) { } private void OnDisable() { if ((bool)holdPositionMarker) { holdPositionMarker.SetActive(value: false); } } private void OnEnable() { HoldPosition = HoldPosition; } public void OnDusk() { day = false; } public void OnDawn_AfterSunrise() { day = true; } public void OnDawn_BeforeSunrise() { if (settingsManager.ResetUnitFormationEveryMorning) { homePosition = homePositionOriginal; HoldPosition = false; } } private void Start() { settingsManager = SettingsManager.Instance; holdPositionMarkerTransform = holdPositionMarker.transform; holdPositionMarkerTransform.SetParent(null); HoldPosition = false; seeker = GetComponent(); rvo = GetComponent(); recalculatePathCooldown = recalculatePathInterval * Random.value; homePosition = base.transform.position; homePositionOriginal = base.transform.position; nearestConstraint.graphMask = seeker.graphMask; graphMaskOriginal = seeker.graphMask; DayNightCycle.Instance.RegisterDaytimeSensitiveObject(this); } private void OriginalPathRequest() { seekToTargetPos = FindMoveToTarget(); seekToTargetPosSnappedtoNavmesh = AstarPath.active.GetNearest(seekToTargetPos, nearestConstraint).position; storeRequestedTargetPos = seekToTargetPosSnappedtoNavmesh; seeker.StartPath(base.transform.position, seekToTargetPosSnappedtoNavmesh, OriginalOnPathComplete, graphMaskOriginal); } private void OriginalOnPathComplete(Path _p) { if (backupMovementGraph != "") { if (_p.error) { BackupPathRequest(); return; } if ((storeRequestedTargetPos - _p.vectorPath[_p.vectorPath.Count - 1]).magnitude > 0.1f) { BackupPathRequest(); return; } } else if (_p.error) { return; } path = _p.vectorPath; nextPathPointIndex = 0; } private void BackupPathRequest() { seekToTargetPos = FindMoveToTarget(); seekToTargetPosSnappedtoNavmesh = AstarPath.active.GetNearest(seekToTargetPos, nearestConstraint).position; storeRequestedTargetPos = seekToTargetPosSnappedtoNavmesh; seeker.StartPath(base.transform.position, seekToTargetPosSnappedtoNavmesh, BackupOnPathComplete, GraphMask.FromGraphName(backupMovementGraph)); } private void BackupOnPathComplete(Path _p) { if (!_p.error) { path = _p.vectorPath; nextPathPointIndex = 0; } } private Vector3 FindMoveToTarget() { if (followingPlayer) { seekToTaggedObj = null; targetPrio = null; currentlyWalkingHome = true; return homePosition; } if (holdPosition) { seekToTaggedObj = null; targetPrio = null; currentlyWalkingHome = true; return homePosition; } currentlyWalkingHome = false; for (int i = 0; i < targetPriorities.Count; i++) { targetPrio = targetPriorities[i]; seekToTaggedObj = targetPrio.FindTaggedObjectCloseToHome(base.transform.position, homePosition, maximumDistanceFromHome, out var _outPosition); if (!(seekToTaggedObj == null)) { return _outPosition; } } seekToTaggedObj = null; targetPrio = null; currentlyWalkingHome = true; return homePosition; } private void Update() { recalculatePathCooldown -= Time.deltaTime; if (recalculatePathCooldown <= 0f) { recalculatePathCooldown = recalculatePathInterval; OriginalPathRequest(); } if (followingPlayer) { if (path.Count > 0) { path[path.Count - 1] = homePosition; } seekToTargetPos = homePosition; } FollowPathUpdate(); } public override void Slow(float _duration) { slowedFor = Mathf.Max(_duration, slowedFor); } private void FollowPathUpdate() { if (path.Count <= nextPathPointIndex) { if (!followingPlayer || path.Count <= 0) { return; } nextPathPointIndex = path.Count - 1; } nextPathPoint = path[nextPathPointIndex]; Vector3 vector; if ((base.transform.position - seekToTargetPos).magnitude < keepDistanceOf && !currentlyWalkingHome) { vector = Vector3.zero; nextPathPoint = base.transform.position; } else { vector = nextPathPoint - base.transform.position; if (vector.magnitude <= 1f) { nextPathPointIndex++; nextPathPointIndex = Mathf.Clamp(nextPathPointIndex, 0, path.Count - 1); nextPathPoint = path[nextPathPointIndex]; vector = nextPathPoint - base.transform.position; } } rvo.priority = vector.magnitude; float num = (day ? (movementSpeed * speedBoostDuringDaytime) : movementSpeed); if (slowedFor > 0f) { rvo.SetTarget(nextPathPoint, vector.magnitude * 3f, num * 0.33f); slowedFor -= Time.deltaTime; } else { rvo.SetTarget(nextPathPoint, vector.magnitude * 3f, num); } Vector3 position = base.transform.position + rvo.CalculateMovementDelta(Time.deltaTime); Vector3 position2 = AstarPath.active.GetNearest(position, nearestConstraint).position; base.transform.position = position2; } public void SnapToNavmesh() { base.transform.position = AstarPath.active.GetNearest(base.transform.position, nearestConstraint).position; } public override void ClearCurrentPath() { path.Clear(); } }