first commit
This commit is contained in:
@@ -0,0 +1,268 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using OTGIntegrated.Core;
|
||||
using OTGIntegrated.Stats;
|
||||
using UnityEngine;
|
||||
|
||||
namespace OTGIntegrated.Talents
|
||||
{
|
||||
public sealed class TalentManager : MonoBehaviour
|
||||
{
|
||||
private const string TalentSourcePrefix = "Talent:";
|
||||
|
||||
public List<TalentData> allTalents = new List<TalentData>();
|
||||
public int availableTalentPoints;
|
||||
|
||||
[SerializeField] private List<string> learnedTalentIds = new List<string>();
|
||||
|
||||
private PlayerStats playerStats;
|
||||
private readonly Dictionary<string, TalentData> talentLookup = new Dictionary<string, TalentData>(StringComparer.Ordinal);
|
||||
|
||||
public event Action OnTalentStateChanged;
|
||||
public IReadOnlyList<string> LearnedTalentIds => learnedTalentIds;
|
||||
|
||||
public void Initialize(PlayerStats stats)
|
||||
{
|
||||
playerStats = stats;
|
||||
BuildLookup();
|
||||
RebuildAllModifiers();
|
||||
RaiseChanged();
|
||||
}
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (playerStats == null)
|
||||
{
|
||||
playerStats = GetComponent<PlayerStats>();
|
||||
}
|
||||
|
||||
BuildLookup();
|
||||
}
|
||||
|
||||
public bool IsLearned(TalentData talent)
|
||||
{
|
||||
return IsValidTalent(talent) && learnedTalentIds.Contains(talent.talentId);
|
||||
}
|
||||
|
||||
public bool CanLearn(TalentData talent)
|
||||
{
|
||||
return IsValidTalent(talent) &&
|
||||
!IsLearned(talent) &&
|
||||
availableTalentPoints >= Mathf.Max(0, talent.cost) &&
|
||||
ArePrerequisitesLearned(talent);
|
||||
}
|
||||
|
||||
public bool ArePrerequisitesLearned(TalentData talent)
|
||||
{
|
||||
if (!IsValidTalent(talent))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (talent.prerequisites == null || talent.prerequisites.Length == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
for (int i = 0; i < talent.prerequisites.Length; i++)
|
||||
{
|
||||
TalentData prerequisite = talent.prerequisites[i];
|
||||
if (!IsValidTalent(prerequisite) || !IsLearned(prerequisite))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool LearnTalent(TalentData talent)
|
||||
{
|
||||
if (!IsValidTalent(talent))
|
||||
{
|
||||
GameEvents.RaiseNotification("Некорректный талант");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CanLearn(talent))
|
||||
{
|
||||
GameEvents.RaiseNotification(GetBlockingReason(talent));
|
||||
return false;
|
||||
}
|
||||
|
||||
availableTalentPoints -= Mathf.Max(0, talent.cost);
|
||||
learnedTalentIds.Add(talent.talentId);
|
||||
ApplyTalentModifiers(talent);
|
||||
GameEvents.RaiseTalentLearned(talent);
|
||||
GameEvents.RaiseNotification($"Изучен талант: {talent.displayName}");
|
||||
RaiseChanged();
|
||||
return true;
|
||||
}
|
||||
|
||||
public void AddTalentPoints(int amount)
|
||||
{
|
||||
if (amount <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
availableTalentPoints = Mathf.Max(0, availableTalentPoints + amount);
|
||||
GameEvents.RaiseNotification(amount == 1 ? "Получено очко талантов" : $"Получено очков талантов: {amount}");
|
||||
RaiseChanged();
|
||||
}
|
||||
|
||||
public void SetTalentPoints(int points)
|
||||
{
|
||||
availableTalentPoints = Mathf.Max(0, points);
|
||||
RaiseChanged();
|
||||
}
|
||||
|
||||
public TalentData GetTalentById(string talentId)
|
||||
{
|
||||
BuildLookup();
|
||||
if (string.IsNullOrWhiteSpace(talentId))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
talentLookup.TryGetValue(talentId, out TalentData talent);
|
||||
return talent;
|
||||
}
|
||||
|
||||
public string GetBlockingReason(TalentData talent)
|
||||
{
|
||||
if (!IsValidTalent(talent))
|
||||
{
|
||||
return "Некорректные данные таланта";
|
||||
}
|
||||
|
||||
if (IsLearned(talent))
|
||||
{
|
||||
return "Талант уже изучен";
|
||||
}
|
||||
|
||||
if (!ArePrerequisitesLearned(talent))
|
||||
{
|
||||
return GetMissingPrerequisiteText(talent);
|
||||
}
|
||||
|
||||
if (availableTalentPoints < Mathf.Max(0, talent.cost))
|
||||
{
|
||||
return "Недостаточно очков талантов";
|
||||
}
|
||||
|
||||
return "Доступно";
|
||||
}
|
||||
|
||||
public void LoadProgress(int points, List<string> learnedIds)
|
||||
{
|
||||
BuildLookup();
|
||||
availableTalentPoints = Mathf.Max(0, points);
|
||||
learnedTalentIds.Clear();
|
||||
|
||||
if (learnedIds != null)
|
||||
{
|
||||
for (int i = 0; i < learnedIds.Count; i++)
|
||||
{
|
||||
string id = learnedIds[i];
|
||||
if (!string.IsNullOrWhiteSpace(id) && talentLookup.ContainsKey(id) && !learnedTalentIds.Contains(id))
|
||||
{
|
||||
learnedTalentIds.Add(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RebuildAllModifiers();
|
||||
RaiseChanged();
|
||||
}
|
||||
|
||||
public void ResetTalents()
|
||||
{
|
||||
learnedTalentIds.Clear();
|
||||
availableTalentPoints = 0;
|
||||
RebuildAllModifiers();
|
||||
RaiseChanged();
|
||||
}
|
||||
|
||||
public void RebuildAllModifiers()
|
||||
{
|
||||
if (playerStats == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
playerStats.RemoveModifiersBySourcePrefix(TalentSourcePrefix);
|
||||
|
||||
for (int i = 0; i < allTalents.Count; i++)
|
||||
{
|
||||
TalentData talent = allTalents[i];
|
||||
if (IsLearned(talent))
|
||||
{
|
||||
ApplyTalentModifiers(talent);
|
||||
}
|
||||
}
|
||||
|
||||
playerStats.RecalculateStats();
|
||||
}
|
||||
|
||||
private void ApplyTalentModifiers(TalentData talent)
|
||||
{
|
||||
if (!IsValidTalent(talent) || playerStats == null || talent.modifiers == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string sourceId = TalentSourcePrefix + talent.talentId;
|
||||
playerStats.RemoveModifiersBySource(sourceId);
|
||||
for (int i = 0; i < talent.modifiers.Length; i++)
|
||||
{
|
||||
StatModifier modifier = talent.modifiers[i];
|
||||
modifier.sourceId = sourceId;
|
||||
playerStats.AddModifier(modifier);
|
||||
}
|
||||
}
|
||||
|
||||
private void BuildLookup()
|
||||
{
|
||||
talentLookup.Clear();
|
||||
for (int i = 0; i < allTalents.Count; i++)
|
||||
{
|
||||
TalentData talent = allTalents[i];
|
||||
if (IsValidTalent(talent))
|
||||
{
|
||||
talentLookup[talent.talentId] = talent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsValidTalent(TalentData talent)
|
||||
{
|
||||
return talent != null && !string.IsNullOrWhiteSpace(talent.talentId);
|
||||
}
|
||||
|
||||
private string GetMissingPrerequisiteText(TalentData talent)
|
||||
{
|
||||
if (talent.prerequisites == null)
|
||||
{
|
||||
return "Требования не выполнены";
|
||||
}
|
||||
|
||||
for (int i = 0; i < talent.prerequisites.Length; i++)
|
||||
{
|
||||
TalentData prerequisite = talent.prerequisites[i];
|
||||
if (!IsValidTalent(prerequisite) || !IsLearned(prerequisite))
|
||||
{
|
||||
return prerequisite != null ? $"Требуется: {prerequisite.displayName}" : "Требуется другой талант";
|
||||
}
|
||||
}
|
||||
|
||||
return "Требования не выполнены";
|
||||
}
|
||||
|
||||
private void RaiseChanged()
|
||||
{
|
||||
GameEvents.RaiseTalentPointChanged(availableTalentPoints);
|
||||
OnTalentStateChanged?.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user