fix(ui): select and examine favorite spells like retail

This commit is contained in:
Erik 2026-07-24 06:47:54 +02:00
parent 043ab10b3c
commit 3e31b0ac70
23 changed files with 974 additions and 34 deletions

View file

@ -17,6 +17,12 @@ public sealed record SpellComponentDescriptor(
uint Category,
uint IconId);
/// <summary>One resolved formula cell in retail's spell examination subview.</summary>
public readonly record struct SpellExamineComponent(
uint SpellComponentId,
SpellComponentDescriptor Descriptor,
bool Owned);
/// <summary>
/// App-layer projection of retail's spell, component, and school-focus DAT tables.
/// Keeping this catalog outside <c>GameWindow</c> makes the SCID/WCID boundary and
@ -52,6 +58,20 @@ public sealed class MagicCatalog
public CoreSpellTable SpellTable { get; }
public IReadOnlyDictionary<uint, SpellComponentDescriptor> Components { get; }
public bool TryGetComponentBySpellComponentId(
uint spellComponentId,
out SpellComponentDescriptor descriptor)
{
if (_wcidByScid.TryGetValue(spellComponentId, out uint weenieClassId)
&& Components.TryGetValue(weenieClassId, out SpellComponentDescriptor? found))
{
descriptor = found;
return true;
}
descriptor = null!;
return false;
}
public bool IsComponentPack(uint weenieClassId)
=> Components.ContainsKey(weenieClassId);
@ -143,15 +163,43 @@ public sealed class MagicCatalog
/// </summary>
public sealed class MagicRuntime
{
private MagicRuntime(MagicCatalog catalog, SpellCastingController casting)
private readonly SpellComponentRequirementService _requirements;
private MagicRuntime(
MagicCatalog catalog,
SpellCastingController casting,
SpellComponentRequirementService requirements)
{
Catalog = catalog;
Casting = casting;
_requirements = requirements;
}
public MagicCatalog Catalog { get; }
public SpellCastingController Casting { get; }
public IReadOnlyList<SpellExamineComponent> GetExamineComponents(uint spellId)
{
IReadOnlyList<uint> formula = _requirements.GetAppropriateFormula(spellId);
if (formula.Count == 0)
return [];
var result = new List<SpellExamineComponent>(formula.Count);
foreach (uint spellComponentId in formula)
{
if (spellComponentId == 0u
|| !Catalog.TryGetComponentBySpellComponentId(
spellComponentId,
out SpellComponentDescriptor descriptor))
continue;
result.Add(new SpellExamineComponent(
spellComponentId,
descriptor,
_requirements.IsComponentOwned(spellComponentId)));
}
return result;
}
public static MagicRuntime Create(
MagicCatalog catalog,
Spellbook spellbook,
@ -198,7 +246,7 @@ public sealed class MagicRuntime
incrementBusy: incrementBusy,
canSend: canSend,
targetCompatibleSilent: (target, spell) => TargetCompatible(target, spell, false));
return new MagicRuntime(catalog, casting);
return new MagicRuntime(catalog, casting, requirements);
}
public void Reset() => Casting.Reset();