using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Threading;
using System.Threading.Tasks;
using System.Linq;
public class EnemyAI : MonoBehaviour
{
[SerializeField] private TurnSystem turnSystem;
[SerializeField] private UnitManager unitManager;
private enum State {
WaitingForEnemyTurn,
TakingTurn,
Busy,
}
private State state;
private float timer;
private void Awake() {
state = State.WaitingForEnemyTurn;
}
private void Start() {
turnSystem.OnTurnChanged += TurnSystem_OnTurnChanged;
}
private void Update() {
if (turnSystem.IsPlayerTurn()) {
return;
}
switch (state) {
case State.WaitingForEnemyTurn:
break;
case State.TakingTurn:
timer -= Time.deltaTime;
if (timer <= 0f) {
if (TryTakeEnemyAIAction(SetStateTakingTurn)) {
state = State.Busy;
} else {
turnSystem.EndTurn();
}
}
break;
case State.Busy:
break;
}
}
private void SetStateTakingTurn() {
timer = 0.5f;
state = State.TakingTurn;
}
private void TurnSystem_OnTurnChanged(object sender, EventArgs empty) {
if (!turnSystem.IsPlayerTurn()) {
state = State.TakingTurn;
timer = 0.5f;
}
}
private bool TryTakeEnemyAIAction(Action onEnemyAIActionComplete) {
return unitManager.GetEnemyUnitList().Any(enemyUnit => TryTakeEnemyAIAction(enemyUnit, onEnemyAIActionComplete));
}
private bool TryTakeEnemyAIAction(Unit enemyUnit, Action onEnemyAIActionComplete) {
BaseAction bestBaseAction = null;
EnemyAIAction bestEnemyAIAction = null;
foreach ((BaseAction baseAction, EnemyAIAction enemyAIAction) in enemyUnit.GetBaseActionArray()
.Where(baseAction => enemyUnit.CanSpendActionPointToTakeAction(baseAction))
.SelectMany(baseAction => baseAction.GetPossibleEnemyAIAction())
.Where(action => action.enemyAIAction.actionValue > 0)) {
if (bestBaseAction == null) {
bestBaseAction = baseAction;
bestEnemyAIAction = enemyAIAction;
} else {
if (enemyAIAction.actionValue > bestEnemyAIAction.actionValue) {
bestBaseAction = baseAction;
bestEnemyAIAction = enemyAIAction;
}
}
}
bool spentActionPoint = false;
if (bestBaseAction != null) {
spentActionPoint = enemyUnit.TrySpendActionPointToTakeAction(bestBaseAction);
}
if (spentActionPoint) {
bestBaseAction.TakeAction(bestEnemyAIAction.gridPosition, out CancellationToken cancellationToken);
cancellationToken.Register(onEnemyAIActionComplete);
}
return spentActionPoint;
}
}