using System; using System.Collections.Generic; using Grid; using UnityEngine; namespace Actions { public class ShootAction : BaseAction { private enum State { Aiming, Shooting, Cooloff, } private State state; private float stateTimer; public Unit TargetUnit { get; private set; } private bool canShootBullet; private const float rotationSpeed = 10f; private const int maxShootDistance = 7; private const float shootingStateTime = .1f; private const float coolOffStateTime = .5f; private const float aimingStateTime = 1.2f; public event EventHandler OnShoot; public class OnShootEventArgs : EventArgs { public Unit TargetUnit; public Unit ShootingUnit; } private void Update() { if (!IsActive) return; stateTimer -= Time.deltaTime; switch (state) { case State.Aiming: Vector3 aimDirection = (TargetUnit.GetWorldPosition() - Unit.GetWorldPosition()).normalized; transform.forward = Vector3.Lerp(transform.forward, aimDirection, rotationSpeed * Time.deltaTime); break; case State.Shooting: if (canShootBullet) { Shoot(); canShootBullet = false; } break; case State.Cooloff: break; } if (stateTimer <= 0f) NextState(); } private void Shoot() { OnShoot?.Invoke(this,new(){TargetUnit = TargetUnit, ShootingUnit = Unit}); TargetUnit.Damage(40); } private void NextState() { switch (state) { case State.Aiming: state = State.Shooting; stateTimer = shootingStateTime; break; case State.Shooting: state = State.Cooloff; stateTimer = coolOffStateTime; break; case State.Cooloff: ActionComplete(); break; } } public override string GetActionName() => "Shoot"; public override void TakeAction(GridPosition gridPosition, Action onActionComplete) { IsActive = true; TargetUnit = LevelGrid.Instance.GetUnitAtGridPosition(gridPosition); canShootBullet = true; state = State.Aiming; stateTimer = aimingStateTime; ActionStart(onActionComplete); } public override List GetValidActionGridPositionList() { List validGridPositionList = new(); GridPosition unitGridPosition = Unit.GridPosition; for (int x = -maxShootDistance; x <= maxShootDistance; x++) { for (int z = -maxShootDistance; z <= maxShootDistance; z++) { GridPosition offsetGridPosition = new(x, z); GridPosition testGridPosition = unitGridPosition + offsetGridPosition; if (!LevelGrid.Instance.IsValidGridPosition(testGridPosition)) continue; //Only return valid grid positions if (Mathf.Abs(x) + Mathf.Abs(z) > maxShootDistance) continue; //Out of Range if (!LevelGrid.Instance.HasAnyUnitOnGridPosition(testGridPosition)) continue; //Grid position is empty, no unit Unit unitAtGridPosition = LevelGrid.Instance.GetUnitAtGridPosition(testGridPosition); if (unitAtGridPosition.IsEnemy == Unit.IsEnemy) continue; //Both units are on the same 'team' validGridPositionList.Add(testGridPosition); } } return validGridPositionList; } } }