Files
crystall-punk-14/Content.Client/_CP14/ResearchTable/CP14ResearchTableWindow.xaml.cs
Ed be495f274c Skill progression system (#1263)
* delete skill trees

* Revert "delete skill trees"

This reverts commit 9d7fae73c4.

* learning refactor

* UI tweaks

* sword mastery skill

* telegraphy

* rapier mastery

* research table ui

* finish studing

* polish UI researching

* pyrokinetic

* more skill tree working

* heat adapt

* alchemist and metamagic update

* skill multiple effects support + metamagic bugg manapool

* impossible 😢

* skimitar gaming

* skimidi

* blacksmithing branch

* remove research restrictions

* remove species magic buff

* fix loc

* Update thaumaturgy.yml

* pip

* Delete skill_tree.yml
2025-05-14 12:43:43 +03:00

236 lines
7.1 KiB
C#

using Content.Client._CP14.Workbench;
using Content.Shared._CP14.Skill;
using Content.Shared._CP14.Skill.Prototypes;
using Content.Shared._CP14.Skill.Restrictions;
using Robust.Client.AutoGenerated;
using Robust.Client.GameObjects;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Prototypes;
namespace Content.Client._CP14.ResearchTable;
[GenerateTypedNameReferences]
public sealed partial class CP14ResearchTableWindow : DefaultWindow
{
private const int AllCategoryId = -1;
[Dependency] private readonly IPrototypeManager _prototype = default!;
[Dependency] private readonly ILogManager _log = default!;
[Dependency] private readonly IEntityManager _entity = default!;
private readonly SpriteSystem _sprite;
private readonly CP14SharedSkillSystem _skillSystem;
public event Action<CP14ResearchUiEntry>? OnResearch;
private readonly Dictionary<int, LocId> _categories = new();
private CP14ResearchTableUiState? _cachedState;
private CP14ResearchUiEntry? _selectedEntry;
private string _searchFilter = string.Empty;
private ISawmill Sawmill { get; init; }
public CP14ResearchTableWindow()
{
RobustXamlLoader.Load(this);
IoCManager.InjectDependencies(this);
_sprite = _entity.System<SpriteSystem>();
_skillSystem = _entity.System<CP14SharedSkillSystem>();
Sawmill = _log.GetSawmill("cp14_research_table_window");
SearchBar.OnTextChanged += OnSearchChanged;
CraftButton.OnPressed += OnCraftPressed;
OptionCategories.OnItemSelected += OnCategoryItemSelected;
}
public void UpdateRecipesVisibility()
{
if (_cachedState is null)
return;
CraftsContainer.RemoveAllChildren();
var recipes = new List<CP14ResearchUiEntry>();
foreach (var entry in _cachedState.Skills)
{
if (!_prototype.TryIndex(entry.ProtoId, out var indexedEntry))
{
Sawmill.Error($"No recipe prototype {entry.ProtoId} retrieved from cache found");
continue;
}
if (!ProcessSearchFilter(indexedEntry))
continue;
if (!ProcessSearchCategoryFilter(indexedEntry))
continue;
recipes.Add(entry);
}
recipes.Sort(CP14ResearchUiEntry.CompareTo);
foreach (var recipe in recipes)
{
var control = new CP14ResearchRecipeControl(recipe);
control.OnResearch += RecipeSelect;
CraftsContainer.AddChild(control);
}
if (_selectedEntry is not null && !recipes.Contains(_selectedEntry.Value))
RecipeSelectNull();
}
public void UpdateState(CP14ResearchTableUiState recipesState)
{
_cachedState = recipesState;
_categories.Clear();
OptionCategories.Clear();
OptionCategories.AddItem(Loc.GetString("cp14-recipe-category-all"), AllCategoryId);
var categories = new List<LocId>();
var count = 0;
foreach (var skill in recipesState.Skills)
{
if (!_prototype.TryIndex(skill.ProtoId, out var indexedSkill))
continue;
if (!_prototype.TryIndex(indexedSkill.Tree, out var indexedTree))
continue;
if (categories.Contains(indexedTree.Name))
continue;
categories.Add(indexedTree.Name);
}
categories.Sort((a, b) => string.Compare(Loc.GetString(a), Loc.GetString(b), StringComparison.Ordinal));
foreach (var category in categories)
{
OptionCategories.AddItem(Loc.GetString(category), count);
_categories.Add(count, category);
count++;
}
UpdateRecipesVisibility();
}
private void OnSearchChanged(LineEdit.LineEditEventArgs _)
{
_searchFilter = SearchBar.Text.Trim().ToLowerInvariant();
UpdateRecipesVisibility();
}
private void OnCraftPressed(BaseButton.ButtonEventArgs _)
{
if (_selectedEntry is null)
return;
OnResearch?.Invoke(_selectedEntry.Value);
}
private void OnCategoryItemSelected(OptionButton.ItemSelectedEventArgs obj)
{
OptionCategories.SelectId(obj.Id);
UpdateRecipesVisibility();
}
private bool ProcessSearchFilter(CP14SkillPrototype indexedEntry)
{
if (_searchFilter == string.Empty)
return true;
return Loc.GetString(_skillSystem.GetSkillName(indexedEntry)).Contains(_searchFilter);
}
private bool ProcessSearchCategoryFilter(CP14SkillPrototype indexedEntry)
{
// If we are searching through all categories, we simply skip the current filter
if (OptionCategories.SelectedId == AllCategoryId)
return true;
if (!_categories.TryGetValue(OptionCategories.SelectedId, out var selectedCategory))
{
Sawmill.Error($"Non-existent {OptionCategories.SelectedId} category id selected. Filter skipped");
return true;
}
if (!_prototype.TryIndex(indexedEntry.Tree, out var indexedTree))
{
Sawmill.Error($"Non-existent {indexedEntry.Tree} category prototype id. Filter skipped");
return true;
}
return indexedTree.Name == selectedCategory;
}
private void RecipeSelect(CP14ResearchTableUiState recipesState)
{
foreach (var skill in recipesState.Skills)
{
RecipeSelect(skill, _prototype.Index(skill.ProtoId));
break;
}
}
private void RecipeSelect(CP14ResearchUiEntry cachedEntry)
{
if (_cachedState is null)
return;
if (_cachedState.Skills.Contains(cachedEntry))
{
Sawmill.Warning($"The selected cache option {cachedEntry} isn't found in recipes");
return;
}
RecipeSelect(cachedEntry, _prototype.Index(cachedEntry.ProtoId));
}
private void RecipeSelect(CP14ResearchUiEntry entry, CP14SkillPrototype skill)
{
_selectedEntry = entry;
ItemView.Texture = _sprite.Frame0(skill.Icon);
ItemName.Text = _skillSystem.GetSkillName(skill);
ItemDescription.Text = _skillSystem.GetSkillDescription(skill);
ItemRequirements.RemoveAllChildren();
foreach (var restriction in skill.Restrictions)
{
switch (restriction)
{
case Researched researched:
foreach (var requirement in researched.Requirements)
{
ItemRequirements.AddChild(new CP14WorkbenchRequirementControl(requirement));
}
break;
}
}
CraftButton.Disabled = !entry.Craftable;
}
private void RecipeSelectNull()
{
_selectedEntry = null;
ItemView.Texture = null;
ItemName.Text = string.Empty;
ItemDescription.Text = string.Empty;
ItemRequirements.RemoveAllChildren();
CraftButton.Disabled = true;
}
}