Files
VOIDRPG/Assets/92 - UserInterface/Generic/Game/ActionBarTurnInfoUI.cs
T
2026-07-09 21:33:33 +02:00

258 lines
9.4 KiB
C#

using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UIElements;
using VOID.Generic.Dict;
using VOID.Generic.Objects.Abstract.Events;
using VOID.Generic.Objects.Unit;
using VOID.Generic.Objects.Unit.Actions;
using VOID.Generic.Objects.Unit.Actions.Exceptions;
using VOID.Generic.Objects.Unit.Events;
using VOID.Generic.Player;
using VOID.Generic.Turn;
namespace VOID.UserInterface.Game
{
/// <summary>
/// Manages ActionBar's Turn elements for current player only:<br/>
/// - Turn resources of <see cref="UnitObject"/><br/>
/// - Button to start new <see cref="TurnManager"/><br/>
/// - Buttons to <see cref="LeaveTurnAction"/> and <see cref="EndTurnAction"/> when in combat
/// </summary>
public class ActionBarTurnInfoUI : MonoBehaviour
{
public static ActionBarTurnInfoUI current { get; private set; }
// ActionBar for this unit
private UnitObject _unit;
private UnitObjectActionBar _actionBar;
// Visual Elements - Turn Info
private VisualElement _turnInfoElement;
private VisualElement _actionPointsElement;
private readonly List<VisualElement> _actionPointsElements = new();
private ProgressBar _moveBar;
private Button _nextTurnButton;
private Button _startTurnButton;
private Button _endTurnButton;
// References
private PlayerController _playerController;
private void Awake()
{
current = this;
var uiDocument = gameObject.GetComponent<UIDocument>();
var templateElement = uiDocument.rootVisualElement;
// Find all important elements
_turnInfoElement = templateElement.Q("turn-info");
_actionPointsElement = templateElement.Q("action-points");
_moveBar = templateElement.Q<ProgressBar>("move-bar");
_nextTurnButton = templateElement.Q<Button>("next-turn");
_startTurnButton = templateElement.Q<Button>("start-turn");
_endTurnButton = templateElement.Q<Button>("end-turn");
// Remove placeholders from action points
_actionPointsElement.Clear();
_turnInfoElement.dataSource = this;
_turnInfoElement.pickingMode = PickingMode.Position;
}
private void Start()
{
_playerController = PlayerController.current;
_playerController.OnActiveUnitChange += OnActiveUnitChange;
_nextTurnButton.clicked += NextTurn;
_startTurnButton.clicked += StartTurn;
_endTurnButton.clicked += EndTurn;
}
/// <summary>
/// Player order active unit to end its turn.
/// </summary>
private void NextTurn()
{
if (!_unit) return;
_unit.OrderStop();
_unit.Order(new EndTurnAction(_unit));
}
/// <summary>
/// Starts new turn manager - also nearby units will also join
/// </summary>
private void StartTurn()
{
if (!_unit) return;
if (_unit.basicState.turnManager) return;
TurnManager.BuildGameObject(_unit);
}
/// <summary>
/// Player order active unit to try end turn.<br/>
/// - If combat is FORCED then try to escape (if possible)
/// - If combat is NOT FORCED then end whole turn manager
/// </summary>
private void EndTurn()
{
if (!_unit) return;
if (!_unit.basicState.turnManager) return;
// if fight is forced when try leave with current unit
// else end whole turn combat
if (_unit.basicState.turnManager.isForcedFight)
_unit.OrderInstantly(new LeaveTurnAction(_unit));
else
_unit.basicState.turnManager.EndTurnManager();
}
/// <summary>
/// Depending on unit turn state it hide or show player's buttons for turn.
/// </summary>
private void UpdateTurnButtonsVisibility()
{
if (_unit.basicState.turnManager)
{
_nextTurnButton.style.display = DisplayStyle.Flex;
_endTurnButton.style.display = DisplayStyle.Flex;
_startTurnButton.style.display = DisplayStyle.None;
}
else
{
_nextTurnButton.style.display = DisplayStyle.None;
_endTurnButton.style.display = DisplayStyle.None;
_startTurnButton.style.display = DisplayStyle.Flex;
}
}
/// <summary>
/// 1. Stops listening to changes for previous unit
/// 2. Start listening to changes in new active unit
/// 3. Updates whole UI
/// </summary>
private void OnActiveUnitChange(UnitObject unit)
{
if (_unit)
{
_unit.basicEvents.onTurnQueueEnter.RemoveListener(OnTurnEnter);
_unit.basicEvents.onTurnQueueLeave.RemoveListener(OnTurnLeave);
_unit.basicEvents.onTurnSelfStart.RemoveListener(OnTurnSelfStart);
_unit.basicEvents.onTurnSelfEnd.RemoveListener(OnTurnSelfEnd);
_unit.unitEvents.onCurrentResourceChange.RemoveListener(OnResourceChange);
_unit.unitEvents.onMaxResourceChange.RemoveListener(OnResourceChange);
}
_unit = unit;
UpdateActionPoints();
UpdateMovePoints();
UpdateTurnButtonsVisibility();
UpdateWaitingForTurn();
_unit.basicEvents.onTurnQueueEnter.AddListener(OnTurnEnter);
_unit.basicEvents.onTurnQueueLeave.AddListener(OnTurnLeave);
_unit.basicEvents.onTurnSelfStart.AddListener(OnTurnSelfStart);
_unit.basicEvents.onTurnSelfEnd.AddListener(OnTurnSelfEnd);
_unit.unitEvents.onCurrentResourceChange.AddListener(OnResourceChange);
_unit.unitEvents.onMaxResourceChange.AddListener(OnResourceChange);
}
private void OnTurnEnter(TurnEvent turnEvent)
{
UpdateTurnButtonsVisibility();
UpdateWaitingForTurn();
}
private void OnTurnLeave(TurnEvent turnEvent)
{
UpdateTurnButtonsVisibility();
UpdateWaitingForTurn();
}
private void OnTurnSelfStart(TurnEvent turnEvent)
{
UpdateWaitingForTurn();
}
private void OnTurnSelfEnd(TurnEvent turnEvent)
{
UpdateWaitingForTurn();
}
/// <summary>
/// Makes ActionBar's turn elements inactive if currently active unit is waiting for its turn.
/// </summary>
private void UpdateWaitingForTurn()
{
var isWaiting = _unit.basicState.turnManager && _unit.basicState.turnManager.currentUnitTurn != _unit;
_turnInfoElement.EnableInClassList("inactive", isWaiting);
}
private void OnResourceChange(UnitResourceChangeEvent resourceChangeEvent)
{
switch (resourceChangeEvent.type)
{
case UnitResourceType.ActionPoints:
UpdateActionPoints();
break;
case UnitResourceType.MovePoints:
UpdateMovePoints();
break;
default: return;
}
}
/// <summary>
/// Updates current and max action points to correspond these from UnitData.
/// </summary>
private void UpdateActionPoints()
{
var maxActionPoints = (int)_unit.unitData.maxResources.actionPoints;
var currentActionPoints = (int)_unit.unitData.currentResources.actionPoints;
// Add/Remove visual elements if needed
for (var i = 0; i < maxActionPoints - _actionPointsElements.Count;) AddActionPointElement();
for (var i = 0; i < _actionPointsElements.Count - maxActionPoints;) RemoveActionPointElement();
// Activate/Disable action points
for (var i = 0; i < _actionPointsElements.Count; i++)
{
var actionPointElement = _actionPointsElements[i];
actionPointElement.EnableInClassList("active-action-point", i < currentActionPoints);
}
}
/// <summary>
/// Adds new action point element to UI.
/// </summary>
private void AddActionPointElement()
{
var actionPointElement = new VisualElement();
actionPointElement.AddToClassList("action-point");
_actionPointsElement.Add(actionPointElement);
_actionPointsElements.Add(actionPointElement);
}
/// <summary>
/// Removes one action point element from UI.
/// </summary>
private void RemoveActionPointElement()
{
_actionPointsElement.Remove(_actionPointsElements.Last());
_actionPointsElements.Remove(_actionPointsElements.Last());
}
/// <summary>
/// Updates current and max move points to correspond these from UnitData.
/// </summary>
private void UpdateMovePoints()
{
_moveBar.highValue = _unit.unitData.maxResources.movePoints;
_moveBar.value = _unit.unitData.currentResources.movePoints;
_moveBar.title = $"{_moveBar.value:F1} / {_moveBar.highValue:F1}";
}
}
}