TurnBasedStrategyCourse/Assets/Scripts/Actions/ShootAction.cs

113 lines
4.0 KiB
C#

using System;
using System.Collections.Generic;
using Grid;
using UnityEngine;
namespace Actions {
public class ShootAction : BaseAction
{
private enum State {
Aiming,
Shooting,
Cooloff,
}
public Unit TargetUnit { get; private set; }
public int MaxShootDistance { get; private set; } = 7;
private State state;
private float stateTimer;
private bool canShootBullet;
private const float rotationSpeed = 10f;
private const float shootingStateTime = .1f;
private const float coolOffStateTime = .5f;
private const float aimingStateTime = 1.2f;
public event EventHandler<OnShootEventArgs> 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<GridPosition> GetValidActionGridPositionList() {
List<GridPosition> 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;
}
}
}