upgrades working; fix a small bug in which a base spell could be re-offered after picking an upgrade

This commit is contained in:
Ian Woods 2026-07-25 23:46:45 -07:00
parent 2de6d85b2f
commit a26d0acbfb
8 changed files with 88 additions and 3 deletions

View file

@ -15,7 +15,9 @@ namespace TD.Gameplay.Draft
/// <see cref="PlayerSpellLoadout"/> and <see cref="BuilderSpellPool"/> already key off of.
/// <see cref="IsValidFor"/> also checks slot capacity — once
/// <see cref="PlayerSpellLoadout.MaxSpellSlots"/> is reached, no further spell options are
/// offered.
/// offered. Gates on <see cref="PlayerSpellLoadout.PlayerHasEverGranted"/> rather than
/// current possession, so a base spell already upgraded past (see
/// <see cref="BuilderSpellUpgradeDraftOption"/>) is never re-offered.
/// </remarks>
[CreateAssetMenu(fileName = "BuilderSpellOption", menuName = "TD/Draft/Builder Spell Option")]
public class BuilderSpellDraftOption : DraftOption
@ -29,7 +31,7 @@ namespace TD.Gameplay.Draft
var loadout = PlayerSpellLoadout.GetForClient(clientId);
if (loadout == null) return false;
if (loadout.SlotCount >= PlayerSpellLoadout.MaxSpellSlots) return false;
return !loadout.PlayerHasSpell(Kind);
return !loadout.PlayerHasEverGranted(Kind);
}
public override bool ServerApply(ulong clientId)

View file

@ -60,6 +60,10 @@ namespace TD.Gameplay
private readonly NetworkList<SpellSlot> spells = new NetworkList<SpellSlot>();
// Every kind ever granted this match, including ones since upgraded away. Unlike
// `spells`, entries here are never removed — see PlayerHasEverGranted.
private readonly NetworkList<byte> everGrantedKinds = new NetworkList<byte>();
/// <summary>Fired on every peer when a spell is granted or a cooldown changes.</summary>
public event System.Action OnLoadoutChanged;
@ -100,6 +104,14 @@ namespace TD.Gameplay
public BuilderSpellKind? GetKind(int slot)
=> (slot >= 0 && slot < spells.Count) ? spells[slot].Kind : (BuilderSpellKind?)null;
/// <summary>
/// True if this player has ever been granted the given spell this match, whether or
/// not it's still occupying a slot (e.g. it may have since been upgraded away). Used
/// by <see cref="TD.Gameplay.Draft.BuilderSpellDraftOption"/> so a base spell already
/// upgraded past is never re-offered.
/// </summary>
public bool PlayerHasEverGranted(BuilderSpellKind kind) => everGrantedKinds.Contains((byte)kind);
/// <summary>True if <paramref name="slot"/> is out of range, empty, or still cooling down.</summary>
public bool IsSlotOnCooldown(int slot)
{
@ -136,6 +148,7 @@ namespace TD.Gameplay
if (PlayerHasSpell(kind)) return false;
spells.Add(SpellSlot.CreateReady(kind));
if (!everGrantedKinds.Contains((byte)kind)) everGrantedKinds.Add((byte)kind);
return true;
}
@ -155,6 +168,7 @@ namespace TD.Gameplay
if (spells[i].Kind == oldKind)
{
spells[i] = SpellSlot.CreateReady(newKind);
if (!everGrantedKinds.Contains((byte)newKind)) everGrantedKinds.Add((byte)newKind);
return true;
}
}