160 lines
8.0 KiB
C#
160 lines
8.0 KiB
C#
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using Sirenix.OdinInspector;
|
|
using UnityEngine;
|
|
using UnityEngine.UIElements;
|
|
using VOID.Generic.Objects.Abstract.Events;
|
|
using VOID.Generic.Objects.Item.Events;
|
|
using VOID.Generic.Objects.Unit;
|
|
using VOID.Generic.Objects.Unit.Actions.Exceptions;
|
|
using VOID.Generic.Objects.Unit.Events;
|
|
using VOID.Generic.Objects.Usable.Events;
|
|
using VOID.Generic.Objects.Wearable.Events;
|
|
using VOID.Generic.Player;
|
|
|
|
namespace VOID.UserInterface.Game.GameLog
|
|
{
|
|
public class GameLogUI : MonoBehaviour
|
|
{
|
|
public static GameLogUI current { get; private set; }
|
|
|
|
// Configuration
|
|
[SerializeField, MinValue(10)] private int _messageLimit = 100;
|
|
[SerializeField] private string SENDER_PREFIX = "<b>{0}:<b> ";
|
|
[SerializeField] private string STATUS_START_MESSAGE = "Got status <u>{0}</u> for <u>{1} turns</u>.";
|
|
[SerializeField] private string STATUS_END_MESSAGE = "Status <u>{0}</u> ended.";
|
|
[SerializeField] private string DEATH_MESSAGE = "Died!";
|
|
[SerializeField] private string DAMAGED_MESSAGE = "Received <u>{0} {1}</u> damage from <u>{2}</u>.";
|
|
[SerializeField] private string DAMAGE_MESSAGE = "Dealt <u>{0} {1}</u> damage to <u>{2}</u>.";
|
|
[SerializeField] private string ABILITY_CAST_MESSAGE = "Casted <u>{0}</u>.";
|
|
[SerializeField] private string TAKE_MESSAGE = "Took <u>{0}</u>.";
|
|
[SerializeField] private string DROP_MESSAGE = "Dropped <u>{0}</u>.";
|
|
[SerializeField] private string EQUIP_MESSAGE = "Equipped <u>{0}</u>.";
|
|
[SerializeField] private string UNEQUIP_MESSAGE = "Unequipped <u>{0}</u>.";
|
|
[SerializeField] private string USE_MESSAGE = "Used <u>{0}</u>.";
|
|
[SerializeField] private string ACTION_ERROR_MESSAGE = "Action prevented: <u>{0}</u>.";
|
|
|
|
// Message template
|
|
public VisualTreeAsset messageTemplate => _messageTemplate;
|
|
[SerializeField, Required] private VisualTreeAsset _messageTemplate;
|
|
|
|
// Visual Elements
|
|
private VisualElement _messageWrapper;
|
|
private Scroller _scroller;
|
|
private readonly List<GameLogMessageUI> _messages = new();
|
|
|
|
// Units which we listen to
|
|
private UnitObject _mainUnit;
|
|
private UnitObject _subUnit;
|
|
|
|
private void Awake()
|
|
{
|
|
current = this;
|
|
|
|
var uiDocument = gameObject.GetComponent<UIDocument>();
|
|
var templateElement = uiDocument.rootVisualElement;
|
|
_messageWrapper = templateElement.Q("message-wrapper");
|
|
_messageWrapper.Clear();
|
|
}
|
|
|
|
private void Start()
|
|
{
|
|
PlayerController.current.OnMainUnitChange += OnMainUnitChange;
|
|
PlayerController.current.OnSubUnitChange += OnSubUnitChange;
|
|
}
|
|
|
|
private void OnMainUnitChange(UnitObject unit)
|
|
{
|
|
if (_mainUnit) StopListenFor(_mainUnit);
|
|
_mainUnit = unit;
|
|
if (unit) ListenFor(unit);
|
|
}
|
|
|
|
private void OnSubUnitChange(UnitObject unit)
|
|
{
|
|
if (_subUnit) StopListenFor(_subUnit);
|
|
_subUnit = unit;
|
|
if (unit) ListenFor(unit);
|
|
}
|
|
|
|
private void ListenFor(UnitObject unit)
|
|
{
|
|
unit.basicEvents.onStatusStart.AddListener(OnStatusStart);
|
|
unit.basicEvents.onStatusEnd.AddListener(OnStatusEnd);
|
|
unit.basicEvents.onDeathAfter.AddListener(OnDeathAfter);
|
|
unit.basicEvents.onDamagedAfter.AddListener(OnDamagedAfter);
|
|
unit.unitEvents.onDamageAfter.AddListener(OnDamageAfter);
|
|
unit.unitEvents.onStartAbilityAfter.AddListener(OnAbilityCastAfter);
|
|
unit.unitEvents.onTakeAfter.AddListener(OnTakeAfter);
|
|
unit.unitEvents.onDropAfter.AddListener(OnDropAfter);
|
|
unit.unitEvents.onEquipAfter.AddListener(OnEquipAfter);
|
|
unit.unitEvents.onUnEquipAfter.AddListener(OnUnEquipAfter);
|
|
unit.unitEvents.onUseAfter.AddListener(OnUseAfter);
|
|
unit.unitEvents.onActionError.AddListener(OnActionError);
|
|
}
|
|
|
|
private void StopListenFor(UnitObject unit)
|
|
{
|
|
unit.basicEvents.onStatusStart.RemoveListener(OnStatusStart);
|
|
unit.basicEvents.onStatusEnd.RemoveListener(OnStatusEnd);
|
|
unit.basicEvents.onDeathAfter.RemoveListener(OnDeathAfter);
|
|
unit.basicEvents.onDamagedAfter.RemoveListener(OnDamagedAfter);
|
|
unit.unitEvents.onDamageAfter.RemoveListener(OnDamageAfter);
|
|
unit.unitEvents.onStartAbilityAfter.RemoveListener(OnAbilityCastAfter);
|
|
unit.unitEvents.onTakeAfter.RemoveListener(OnTakeAfter);
|
|
unit.unitEvents.onDropAfter.RemoveListener(OnDropAfter);
|
|
unit.unitEvents.onEquipAfter.RemoveListener(OnEquipAfter);
|
|
unit.unitEvents.onUnEquipAfter.RemoveListener(OnUnEquipAfter);
|
|
unit.unitEvents.onUseAfter.RemoveListener(OnUseAfter);
|
|
unit.unitEvents.onActionError.RemoveListener(OnActionError);
|
|
}
|
|
|
|
private void AddError(string richText)
|
|
{
|
|
AddMessage($"<color=#D33>{richText}</color>");
|
|
}
|
|
|
|
private void AddMessage(string richText)
|
|
{
|
|
var message = new GameLogMessageUI();
|
|
message.InitNew(_messageWrapper, richText);
|
|
_messages.Add(message);
|
|
|
|
if (_messages.Count > _messageLimit) RemoveLastMessage();
|
|
}
|
|
|
|
private void RemoveLastMessage()
|
|
{
|
|
var lastMessage = _messages.Last();
|
|
lastMessage.Destroy();
|
|
_messages.RemoveAt(_messages.Count-1);
|
|
}
|
|
|
|
/* EVENTS BELOW */
|
|
/* for register and unregister */
|
|
|
|
private void OnStatusStart(StatusEvent e)
|
|
{
|
|
if (e.status.hidden) return;
|
|
AddMessage(string.Format(SENDER_PREFIX, e.obj.basicData.finalName) + string.Format(STATUS_START_MESSAGE, e.status.displayName, e.status.durationInTurns));
|
|
}
|
|
|
|
private void OnStatusEnd(StatusEvent e)
|
|
{
|
|
if (e.status.hidden) return;
|
|
AddMessage(string.Format(SENDER_PREFIX, e.obj.basicData.finalName) + string.Format(STATUS_END_MESSAGE, e.status.displayName));
|
|
}
|
|
|
|
private void OnDeathAfter(DeathEvent e) => AddMessage(string.Format(SENDER_PREFIX, e.obj.basicData.finalName) + string.Format(DEATH_MESSAGE));
|
|
private void OnDamagedAfter(DamageEvent e) => AddMessage(string.Format(SENDER_PREFIX, e.target.basicData.finalName) + string.Format(DAMAGED_MESSAGE, e.amount, e.damageType, e.attacker?.basicData.finalName ?? "unknown"));
|
|
private void OnDamageAfter(DamageEvent e) => AddMessage(string.Format(SENDER_PREFIX, e.attacker.basicData.finalName) + string.Format(DAMAGE_MESSAGE, e.amount, e.damageType, e.target.basicData.finalName));
|
|
private void OnAbilityCastAfter(AbilityCastEvent e) => AddMessage(string.Format(SENDER_PREFIX, e.caster.basicData.finalName) + string.Format(ABILITY_CAST_MESSAGE, e.ability.displayName));
|
|
private void OnTakeAfter(PickEvent e) => AddMessage(string.Format(SENDER_PREFIX, e.unit.basicData.finalName) + string.Format(TAKE_MESSAGE, e.item.basicData.finalName));
|
|
private void OnDropAfter(DropEvent e) => AddMessage(string.Format(SENDER_PREFIX, e.unit.basicData.finalName) + string.Format(DROP_MESSAGE, e.item.basicData.finalName));
|
|
private void OnEquipAfter(EquipEvent e) => AddMessage(string.Format(SENDER_PREFIX, e.unit.basicData.finalName) + string.Format(EQUIP_MESSAGE, e.wearable.basicData.finalName));
|
|
private void OnUnEquipAfter(UnEquipEvent e) => AddMessage(string.Format(SENDER_PREFIX, e.unit.basicData.finalName) + string.Format(UNEQUIP_MESSAGE, e.wearable.basicData.finalName));
|
|
private void OnUseAfter(UseEvent e) => AddMessage(string.Format(SENDER_PREFIX, e.usedBy.basicData.finalName) + string.Format(USE_MESSAGE, e.usedObject.basicData.finalName));
|
|
private void OnActionError(ActionErrorEvent e) => AddError(string.Format(SENDER_PREFIX, e.unit.basicData.finalName) + string.Format(ACTION_ERROR_MESSAGE, UnitActionErrorMessage.Get(e.cause)));
|
|
}
|
|
}
|