using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using UnityEngine;
public class SwordAction : BaseAction
{
public static event EventHandler onAnySwordHit;
public event EventHandler onSwordActionStarted;
public event EventHandler onSwordActionCompleted;
private State state;
private float stateTimer;
private float beforeHitStateTime = 0.7f;
private float afterHitStateTime = 0.5f;
private Vector3 swingStartDirectionVector;
private Vector3 swingEndDirectionVector;
private enum State {
Idle,
SwingingSwordBeforeHit,
SwingingSwordAfterHit,
}
private Unit targetUnit;
public override string GetActionName()
{
return "Sword";
}
private void Start() {
actionCost = 1;
maxDistance = (Range)1;
}
private void Update() {
if (!IsActive()) {
return;
}
stateTimer -= Time.deltaTime;
switch (state) {
case State.SwingingSwordBeforeHit:
float rotateSpeed = 2;
float timeElapsed = (beforeHitStateTime - stateTimer) * rotateSpeed;
if (timeElapsed > beforeHitStateTime) {
timeElapsed = beforeHitStateTime;
}
transform.forward = Vector3.Lerp(swingStartDirectionVector
,swingEndDirectionVector
,timeElapsed / beforeHitStateTime) ;
break;
case State.SwingingSwordAfterHit:
break;
}
if (IsStateTimerElapsed()) {
NextState();
}
}
private bool IsStateTimerElapsed() => (stateTimer <= 0f);
private void NextState() {
switch (state) {
case State.Idle:
swingStartDirectionVector = transform.forward;
swingEndDirectionVector = ( targetUnit.GetWorldPosition() - transform.position).normalized;
state = State.SwingingSwordBeforeHit;
SetTimer(beforeHitStateTime);
break;
case State.SwingingSwordBeforeHit:
state = State.SwingingSwordAfterHit;
SetTimer(afterHitStateTime);
SwordSlash();
break;
case State.SwingingSwordAfterHit:
onAnySwordHit?.Invoke(this, EventArgs.Empty);
targetUnit.Damage(100);
StopAction();
break;
}
}
private void SwordSlash() {
onSwordActionStarted?.Invoke(this, EventArgs.Empty);
}
private void SetTimer(float time) {
stateTimer = time;
}
public override EnemyAIAction GetEnemyAIAction(GridPosition gridPosition)
{
return new EnemyAIAction {
gridPosition = gridPosition,
actionValue = 200,
};
}
public override CancellationToken TakeAction(in GridPosition gridPosition, out CancellationToken cancellationToken)
{
targetUnit = LevelGrid.Instance.GetUnitAtGridPosition(gridPosition);
NextState();
StartAction(out cancellationToken).Register(() => {
state = State.Idle;
onSwordActionCompleted?.Invoke(this, EventArgs.Empty);
});
return cancellationToken;
}
protected override bool IsValidTargetPositionSpecific(in GridPosition unitGridPosition, in GridPosition testGridPosition)
{
return (LevelGrid.Instance.HasAnyUnitOnGridPosition(testGridPosition)
&& (LevelGrid.Instance.GetUnitAtGridPosition(testGridPosition).IsEnemy() != unit.IsEnemy())
);
}
}