first commit

This commit is contained in:
2026-06-04 21:37:43 +03:00
commit a6ea987b0d
152 changed files with 34059 additions and 0 deletions
+83
View File
@@ -0,0 +1,83 @@
using System.Collections.Generic;
using OTG.Lab06.Abilities;
using UnityEngine;
namespace OTG.Lab06.UI
{
public sealed class AbilityBarUI : MonoBehaviour
{
[SerializeField] private AbilityManager abilityManager;
[SerializeField] private AbilitySlotUI slotPrefab;
[SerializeField] private Transform slotRoot;
[SerializeField] private TooltipUI tooltip;
private readonly List<AbilitySlotUI> slots = new List<AbilitySlotUI>();
private void OnEnable()
{
if (abilityManager != null)
{
abilityManager.AbilitiesChanged += RebuildOrRefresh;
}
}
private void OnDisable()
{
if (abilityManager != null)
{
abilityManager.AbilitiesChanged -= RebuildOrRefresh;
}
}
private void Start()
{
if (abilityManager != null)
{
RebuildOrRefresh(abilityManager.Abilities);
}
}
public void Bind(AbilityManager manager, AbilitySlotUI prefab, Transform root, TooltipUI tooltipUI)
{
if (abilityManager != null)
{
abilityManager.AbilitiesChanged -= RebuildOrRefresh;
}
abilityManager = manager;
slotPrefab = prefab;
slotRoot = root;
tooltip = tooltipUI;
if (isActiveAndEnabled && abilityManager != null)
{
abilityManager.AbilitiesChanged += RebuildOrRefresh;
RebuildOrRefresh(abilityManager.Abilities);
}
}
private void RebuildOrRefresh(IReadOnlyList<AbilityRuntime> abilities)
{
if (slotPrefab == null || slotRoot == null)
{
return;
}
while (slots.Count < abilities.Count)
{
AbilitySlotUI slot = Instantiate(slotPrefab, slotRoot);
slots.Add(slot);
}
for (int i = 0; i < slots.Count; i++)
{
bool active = i < abilities.Count;
slots[i].gameObject.SetActive(active);
if (active)
{
slots[i].Bind(abilities[i], i, tooltip);
}
}
}
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f1b8660e98f014b3880af4c5b70f2dc6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+103
View File
@@ -0,0 +1,103 @@
using OTG.Lab06.Abilities;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
namespace OTG.Lab06.UI
{
public sealed class AbilitySlotUI : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler
{
[SerializeField] private Image icon;
[SerializeField] private Image cooldownOverlay;
[SerializeField] private Text hotkeyLabel;
[SerializeField] private Text nameLabel;
[SerializeField] private Text manaLabel;
[SerializeField] private Text cooldownLabel;
private AbilityRuntime runtime;
private TooltipUI tooltip;
public void Bind(AbilityRuntime abilityRuntime, int index, TooltipUI tooltipUI)
{
runtime = abilityRuntime;
tooltip = tooltipUI;
if (icon != null)
{
icon.sprite = runtime.Data.icon;
icon.color = runtime.Data.icon == null ? new Color(0.35f, 0.35f, 0.35f, 1f) : Color.white;
}
if (hotkeyLabel != null)
{
hotkeyLabel.text = (index + 1).ToString();
}
if (manaLabel != null)
{
manaLabel.text = Mathf.RoundToInt(runtime.Data.manaCost).ToString();
}
if (nameLabel != null)
{
nameLabel.text = GetShortName(runtime.Data.abilityName);
}
Refresh();
}
private static string GetShortName(string abilityName)
{
if (string.IsNullOrWhiteSpace(abilityName))
{
return string.Empty;
}
return abilityName.Length <= 9 ? abilityName : abilityName.Substring(0, 9);
}
private void Update()
{
Refresh();
}
private void Refresh()
{
if (runtime == null)
{
return;
}
if (cooldownOverlay != null)
{
cooldownOverlay.fillAmount = runtime.CooldownNormalized;
}
if (cooldownLabel != null)
{
bool show = runtime.CooldownRemaining > 0.05f;
cooldownLabel.gameObject.SetActive(show);
if (show)
{
cooldownLabel.text = runtime.CooldownRemaining.ToString("0.0");
}
}
}
public void OnPointerEnter(PointerEventData eventData)
{
if (tooltip != null && runtime != null)
{
tooltip.Show(runtime.Data, transform as RectTransform);
}
}
public void OnPointerExit(PointerEventData eventData)
{
if (tooltip != null)
{
tooltip.Hide();
}
}
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d80b838b44dd63b8a83685aa2df02f15
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+89
View File
@@ -0,0 +1,89 @@
using OTG.Lab06.Characters;
using UnityEngine;
using UnityEngine.UI;
namespace OTG.Lab06.UI
{
public sealed class ResourceBarUI : MonoBehaviour
{
[SerializeField] private PlayerStats playerStats;
[SerializeField] private Image fill;
[SerializeField] private Text valueLabel;
[SerializeField] private bool useMana;
private void OnEnable()
{
Subscribe();
Refresh();
}
private void OnDisable()
{
Unsubscribe();
}
public void Bind(PlayerStats stats, bool mana)
{
Unsubscribe();
playerStats = stats;
useMana = mana;
Subscribe();
Refresh();
}
private void Subscribe()
{
if (playerStats == null)
{
return;
}
if (useMana)
{
playerStats.ManaChanged += OnChanged;
}
else
{
playerStats.HealthChanged += OnChanged;
}
}
private void Unsubscribe()
{
if (playerStats == null)
{
return;
}
playerStats.ManaChanged -= OnChanged;
playerStats.HealthChanged -= OnChanged;
}
private void Refresh()
{
if (playerStats == null)
{
return;
}
OnChanged(useMana ? playerStats.Mana : playerStats.Health, useMana ? playerStats.MaxMana : playerStats.MaxHealth);
}
private void OnChanged(float current, float max)
{
float normalized = max <= 0f ? 0f : Mathf.Clamp01(current / max);
if (fill != null)
{
fill.type = Image.Type.Filled;
fill.fillMethod = Image.FillMethod.Horizontal;
fill.fillOrigin = (int)Image.OriginHorizontal.Left;
fill.fillAmount = normalized;
}
if (valueLabel != null)
{
valueLabel.text = $"{Mathf.RoundToInt(current)} / {Mathf.RoundToInt(max)}";
}
}
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9b1633c268542d115823df8771e20b9b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+49
View File
@@ -0,0 +1,49 @@
using OTG.Lab06.Abilities;
using UnityEngine;
using UnityEngine.UI;
namespace OTG.Lab06.UI
{
public sealed class TooltipUI : MonoBehaviour
{
[SerializeField] private Text titleLabel;
[SerializeField] private Text descriptionLabel;
[SerializeField] private Text statsLabel;
private RectTransform rectTransform;
private void Awake()
{
rectTransform = transform as RectTransform;
Hide();
}
public void Show(AbilityData data, RectTransform anchor)
{
if (data == null)
{
return;
}
if (rectTransform == null)
{
rectTransform = transform as RectTransform;
}
titleLabel.text = data.abilityName;
descriptionLabel.text = data.description;
statsLabel.text = $"Damage: {Mathf.RoundToInt(data.damage)}\nMana: {Mathf.RoundToInt(data.manaCost)}\nCooldown: {data.cooldown:0.#}s";
gameObject.SetActive(true);
if (rectTransform != null && anchor != null)
{
rectTransform.position = anchor.position + new Vector3(0f, 142f, 0f);
}
}
public void Hide()
{
gameObject.SetActive(false);
}
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 13ea93e0504244d82b04abc14e512442
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: