using System; using System.Collections.Generic; using Reset.Core.Tools; using Reset.Units; using Unity.Netcode; using UnityEngine; using Random = UnityEngine.Random; public class UnitCombat : UnitComponent { // public List draggedUnits = new List(); public Dictionary draggedColliders = new Dictionary(); private UnitMovementHandler movement; private Vector3 lastPosition; private Vector3 positionDelta; private float lastSpeed; private float speedDelta; private float sinAmplitude; private float sinOffset; private List activelyDraggedColliders; private List expiredColliders; void Awake(){ movement = GetComponent(); activelyDraggedColliders = new List(); expiredColliders = new List(); } void Start(){ lastPosition = transform.position; sinOffset = Random.value; sinAmplitude = 1 + Random.value / 4f; } // Update is called once per frame void Update(){ // Calculate movement for dragged units DragAttackedUnits(); // Check timers to make sure an object doesn't stay dragged CheckUnitTimers(); } // dragTime is set as a maximum. If no time is provided then it defaults to two seconds. public void AddDragCollider(Collider newCollider, float dragTime = 2f){ if (draggedColliders.ContainsKey(newCollider)) { draggedColliders[newCollider] = dragTime; } else { draggedColliders.Add(newCollider, dragTime); activelyDraggedColliders.Add(newCollider); } } public void RemoveDragCollider(Collider colliderToRemove){ draggedColliders.Remove(colliderToRemove); activelyDraggedColliders.Remove(colliderToRemove); } public void CallAttack(){ Debug.Log("Attacked!"); Unit.Graph.SendEvent("Call Attack"); } void CheckUnitTimers(){ // Decrease the timer of the dragged colliders foreach (Collider thisCollider in activelyDraggedColliders) { draggedColliders[thisCollider] -= 1f * Time.deltaTime; // Pend them for removal when ready if (draggedColliders[thisCollider] < 0f) { expiredColliders.Add(thisCollider); } } // Remove expired colliders for (int i = 0; i < expiredColliders.Count; i++) { RemoveDragCollider(expiredColliders[i]); } // Clear list if not empty if (expiredColliders.Count > 0f) { expiredColliders.Clear(); } } void DragAttackedUnits(){ // Get the original difference in position for speed and direction positionDelta = Vector3.Lerp(positionDelta, lastPosition.DirectionTo(transform.position), 5f * Time.deltaTime); speedDelta = Vector3.Distance(lastPosition, transform.position) / Time.deltaTime; // Add some randomness to the movements based on small offsets float sinVal = Mathf.Sin(2f + sinOffset) * sinAmplitude; speedDelta += sinVal; // Set a floor to prevent them from not moving enough speedDelta = Mathf.Max(3f, speedDelta); // Multiply the speed to be lower when further, and faster when close float speedDiff = Mathf.Lerp(.2f, 1.4f, speedDelta); speedDelta *= speedDiff; // Debug DebugOverlayDrawer.ChangeValue($"Combat - {name}", "Position Delta", positionDelta); DebugOverlayDrawer.ChangeValue($"Combat - {name}", "Speed Delta", speedDelta); // Update last known position lastPosition = transform.position; // Apply the speed, direction, and rotation to each unit foreach (Collider draggedUnit in activelyDraggedColliders) { UnitMovementHandler draggedUnitMovement = draggedUnit.GetComponent(); if (!draggedUnitMovement) { Debug.LogError($"No available UnitMovement on {draggedUnit.name}. Aborting drag on this unit."); continue; } // Prevent units from entering a runaway situation where they constantly pull each other at high speeds across the map speedDelta = Mathf.Min(speedDelta, draggedUnitMovement.data.moveSpeed.Value); draggedUnitMovement.SetNewRotation(-transform.position.DirectionTo(draggedUnit.transform.position), 1f, true); draggedUnitMovement.SetNewDirection(positionDelta.ToVector2(), 1f, true); draggedUnitMovement.SetNewSpeed(speedDelta, 1f, true); } } }