using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
using UnityEngine.EventSystems;
using System.Threading;
using System.Threading.Tasks;
public class BusyArgs : EventArgs {
public bool busy {get;}
public BusyArgs(bool isBusy) {
this.busy = isBusy;
}
}
public class UnitActionSystem : MonoBehaviour
{
public static UnitActionSystem Instance {get; private set;}
public event EventHandler OnSelectedUnitChanged;
public event EventHandler OnSelectedActionChanged;
public event EventHandler OnActionStarted;
public event EventHandler<BusyArgs> OnBusyChanged;
[SerializeField] private Unit selectedUnit;
[SerializeField] private LayerMask unitMask;
[SerializeField] private TurnSystem turnSystem;
[SerializeField] private UnitManager unitManager;
private BaseAction selectedAction;
private bool isBusy = false;
private void Awake()
{
if (Instance != null)
{
Debug.LogError("There's more than one UnitActionSystem" + transform + " - " + Instance);
Destroy(gameObject);
return;
}
Instance = this;
}
private void Start() {
Unit.OnAnyUnitDead += Unit_OnAnyUnitDead;
SetSelectedUnit(selectedUnit);
}
private void Update()
{
if (isBusy) {
return;
}
if (!turnSystem.IsPlayerTurn()) {
return;
}
if (EventSystem.current.IsPointerOverGameObject()) {
return;
}
if (TryHandleUnitSelection()) {
return;
}
HandleSelectedAction();
}
private void HandleSelectedAction() {
if (!InputManager.Instance.IsMouseButtonDownThisFrame()) return;
GridPosition targetGridPosition = LevelGrid.Instance.GetGridPosition(MouseWorld.GetPosition());
if (!selectedAction.IsValidActionGridPosition(targetGridPosition)) {
Debug.Log("Invalid Grid Position");
return;
}
if (!selectedUnit.TrySpendActionPointToTakeAction(selectedAction)) {
Debug.Log("Cannot Spend Action Points");
return;
}
SetBusy();
OnActionStarted?.Invoke(this, EventArgs.Empty);
selectedAction.TakeAction(targetGridPosition, out CancellationToken cancellationToken);
cancellationToken.Register(ClearBusy);
}
private void SetBusy() {
isBusy = true;
OnBusyChanged?.Invoke(this, new BusyArgs(isBusy));
}
private void ClearBusy() {
isBusy = false;
OnBusyChanged?.Invoke(this, new BusyArgs(isBusy));
}
private bool TryHandleUnitSelection()
{
if (!InputManager.Instance.IsMouseButtonDownThisFrame()) {
return false;
}
Ray ray = Camera.main.ScreenPointToRay(InputManager.Instance.GetMouseScreenPosition());
if (!Physics.Raycast(ray, out RaycastHit raycastHit, float.MaxValue, unitMask)) {
return false;
}
if (!raycastHit.transform.TryGetComponent<Unit>(out Unit unit)) {
return false;
}
if (selectedUnit == unit) {
return false;
}
if (unit.IsEnemy()) {
return false;
}
SetSelectedUnit(unit);
return true;
}
private void SetSelectedUnit(Unit selectedUnit)
{
this.selectedUnit = selectedUnit;
SetSelectedAction(selectedUnit.GetDefaultAction());
OnSelectedUnitChanged?.Invoke(this, EventArgs.Empty);
}
public void SetSelectedAction(BaseAction baseAction) {
selectedAction = baseAction;
OnSelectedActionChanged?.Invoke(this, EventArgs.Empty);
}
public Unit GetSelectedUnit()
{
return selectedUnit;
}
public BaseAction GetSelectedAction() {
return selectedAction;
}
public void Unit_OnAnyUnitDead (object sender, EventArgs empty) {
Unit unit = sender as Unit;
if (unit == selectedUnit) {
var friendlyUnitList = unitManager.GetFriendlyUnitList();
if (friendlyUnitList.Count > 0) {
SetSelectedUnit(friendlyUnitList[0]);
}
}
}
}