first commit

This commit is contained in:
2026-06-04 23:22:13 +03:00
commit d329f501be
310 changed files with 36395 additions and 0 deletions
+181
View File
@@ -0,0 +1,181 @@
using System;
using System.Collections.Generic;
using OTGIntegrated.Core;
using OTGIntegrated.Player;
using OTGIntegrated.Stats;
using UnityEngine;
namespace OTGIntegrated.Abilities
{
public sealed class AbilityManager : MonoBehaviour
{
public List<AbilityData> learnedAbilities = new List<AbilityData>();
public Transform castOrigin;
private readonly List<float> cooldownRemaining = new List<float>();
private PlayerStats playerStats;
private PlayerController playerController;
public event Action OnAbilitiesChanged;
public IReadOnlyList<AbilityData> LearnedAbilities => learnedAbilities;
public void Initialize(PlayerStats stats)
{
playerStats = stats != null ? stats : GetComponent<PlayerStats>();
playerController = GetComponent<PlayerController>();
if (castOrigin == null)
{
castOrigin = transform;
}
EnsureCooldownSlots();
OnAbilitiesChanged?.Invoke();
}
private void Awake()
{
if (playerStats == null)
{
playerStats = GetComponent<PlayerStats>();
}
playerController = GetComponent<PlayerController>();
EnsureCooldownSlots();
}
private void Update()
{
TickCooldowns();
if (playerController != null && !playerController.InputEnabled)
{
return;
}
if (Input.GetKeyDown(KeyCode.Alpha1)) TryUseAbility(0);
if (Input.GetKeyDown(KeyCode.Alpha2)) TryUseAbility(1);
if (Input.GetKeyDown(KeyCode.Alpha3)) TryUseAbility(2);
}
public bool TryUseAbility(int index)
{
EnsureCooldownSlots();
if (index < 0 || index >= learnedAbilities.Count)
{
return false;
}
AbilityData ability = learnedAbilities[index];
if (ability == null || playerStats == null)
{
return false;
}
if (cooldownRemaining[index] > 0f)
{
GameEvents.RaiseNotification("Способность на перезарядке");
return false;
}
if (!playerStats.SpendMana(ability.manaCost))
{
return false;
}
if (ability.effectPrefab == null)
{
playerStats.RestoreMana(ability.manaCost);
Debug.LogWarning($"Ability has no effect prefab: {ability.displayName}", ability);
return false;
}
Vector3 forward = GetCastForward();
Vector3 origin = castOrigin != null ? castOrigin.position : transform.position + Vector3.up;
GameObject effectObject = Instantiate(ability.effectPrefab, origin, Quaternion.LookRotation(forward, Vector3.up));
AbilityEffect effect = effectObject.GetComponent<AbilityEffect>();
if (effect == null)
{
playerStats.RestoreMana(ability.manaCost);
Destroy(effectObject);
Debug.LogWarning($"Ability effect prefab misses AbilityEffect: {ability.effectPrefab.name}", ability.effectPrefab);
return false;
}
effect.Activate(new AbilityContext(ability, transform, playerStats, origin, forward));
cooldownRemaining[index] = GetEffectiveCooldown(ability);
GameEvents.RaiseAbilityUsed(ability);
GameEvents.RaiseNotification($"Способность: {ability.displayName}");
OnAbilitiesChanged?.Invoke();
return true;
}
public float GetCooldownRemaining(int index)
{
EnsureCooldownSlots();
return index >= 0 && index < cooldownRemaining.Count ? cooldownRemaining[index] : 0f;
}
public float GetCooldownNormalized(int index)
{
if (index < 0 || index >= learnedAbilities.Count || learnedAbilities[index] == null)
{
return 0f;
}
float cooldown = GetEffectiveCooldown(learnedAbilities[index]);
return cooldown <= 0f ? 0f : Mathf.Clamp01(GetCooldownRemaining(index) / cooldown);
}
private float GetEffectiveCooldown(AbilityData ability)
{
float reduction = playerStats != null ? playerStats.CooldownReduction : 0f;
return Mathf.Max(0f, ability.cooldown * (1f - Mathf.Clamp(reduction, 0f, 0.9f)));
}
private void TickCooldowns()
{
EnsureCooldownSlots();
bool changed = false;
for (int i = 0; i < cooldownRemaining.Count; i++)
{
if (cooldownRemaining[i] <= 0f)
{
continue;
}
cooldownRemaining[i] = Mathf.Max(0f, cooldownRemaining[i] - Time.deltaTime);
changed = true;
}
if (changed)
{
OnAbilitiesChanged?.Invoke();
}
}
private void EnsureCooldownSlots()
{
while (cooldownRemaining.Count < learnedAbilities.Count)
{
cooldownRemaining.Add(0f);
}
while (cooldownRemaining.Count > learnedAbilities.Count)
{
cooldownRemaining.RemoveAt(cooldownRemaining.Count - 1);
}
}
private Vector3 GetCastForward()
{
if (playerController != null)
{
return playerController.GetAimForward();
}
Vector3 forward = transform.forward;
forward.y = 0f;
return forward.sqrMagnitude > 0.001f ? forward.normalized : Vector3.forward;
}
}
}