add wiring for offensive buffs
This commit is contained in:
parent
04ead32846
commit
3737ad517c
12 changed files with 338 additions and 3 deletions
156
Assets/_Project/Scripts/Gameplay/PlayerBuffManager.cs
Normal file
156
Assets/_Project/Scripts/Gameplay/PlayerBuffManager.cs
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
// Assets/_Project/Scripts/Gameplay/PlayerBuffManager.cs
|
||||
using Unity.Collections;
|
||||
using Unity.Netcode;
|
||||
using UnityEngine;
|
||||
using TD.Core;
|
||||
|
||||
namespace TD.Gameplay
|
||||
{
|
||||
/// <summary>
|
||||
/// Holds all buffs currently owned by one player. Lives on the Player prefab
|
||||
/// alongside <see cref="PlayerGoldManager"/> and <see cref="PlayerMatchState"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para><b>Purchase flow.</b> The owning client calls
|
||||
/// <see cref="RequestPurchaseBuffRpc"/> with a category index. The server
|
||||
/// validates gold, deducts the cost, picks a random
|
||||
/// <see cref="BuffDefinition"/> from the category's pool, and appends an
|
||||
/// <see cref="ActiveBuff"/> to the replicated <see cref="buffs"/> list.</para>
|
||||
///
|
||||
/// <para><b>Multiplier query.</b> <see cref="GetMultiplier"/> is called by
|
||||
/// <see cref="TD.Combat.TowerCombat"/> on the server each time a tower fires.
|
||||
/// It multiplies all active buffs for the requested stat together.</para>
|
||||
///
|
||||
/// <para><b>Enable / disable.</b> Enemies can call <see cref="ServerDisableBuff"/>
|
||||
/// and <see cref="ServerEnableBuff"/> by index to temporarily suppress buffs
|
||||
/// without removing them from the list.</para>
|
||||
/// </remarks>
|
||||
public class PlayerBuffManager : NetworkBehaviour
|
||||
{
|
||||
[Tooltip("Purchasable buff categories shown in the buff menu. Index in this " +
|
||||
"array is the categoryIndex passed to RequestPurchaseBuffRpc.")]
|
||||
[SerializeField] private BuffCategory[] categories;
|
||||
|
||||
private NetworkList<ActiveBuff> buffs;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
buffs = new NetworkList<ActiveBuff>();
|
||||
}
|
||||
|
||||
// ----- Public API -------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Returns the combined multiplier for <paramref name="stat"/> across all
|
||||
/// active buffs owned by this player. Returns 1.0 if no matching buffs
|
||||
/// are active. Safe to call from any peer.
|
||||
/// </summary>
|
||||
public float GetMultiplier(BuffStat stat)
|
||||
{
|
||||
float result = 1f;
|
||||
for (int i = 0; i < buffs.Count; i++)
|
||||
{
|
||||
var buff = buffs[i];
|
||||
if (buff.Stat == stat && buff.IsActive)
|
||||
result *= buff.Multiplier;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the number of buff categories available, for building the UI.
|
||||
/// </summary>
|
||||
public int CategoryCount => categories?.Length ?? 0;
|
||||
|
||||
/// <summary>Returns the category at the given index, or null.</summary>
|
||||
public BuffCategory GetCategory(int index)
|
||||
=> (categories != null && index >= 0 && index < categories.Length)
|
||||
? categories[index]
|
||||
: null;
|
||||
|
||||
/// <summary>Read-only access to the buff list for UI rendering.</summary>
|
||||
public NetworkList<ActiveBuff> Buffs => buffs;
|
||||
|
||||
// ----- Server helpers ---------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Server-only: disables the buff at <paramref name="index"/>.
|
||||
/// The buff remains in the list and can be re-enabled.
|
||||
/// </summary>
|
||||
public void ServerDisableBuff(int index)
|
||||
{
|
||||
if (!IsServer) return;
|
||||
if (index < 0 || index >= buffs.Count) return;
|
||||
|
||||
var b = buffs[index];
|
||||
if (!b.IsActive) return;
|
||||
b.IsActive = false;
|
||||
buffs[index] = b;
|
||||
}
|
||||
|
||||
/// <summary>Server-only: re-enables the buff at <paramref name="index"/>.</summary>
|
||||
public void ServerEnableBuff(int index)
|
||||
{
|
||||
if (!IsServer) return;
|
||||
if (index < 0 || index >= buffs.Count) return;
|
||||
|
||||
var b = buffs[index];
|
||||
if (b.IsActive) return;
|
||||
b.IsActive = true;
|
||||
buffs[index] = b;
|
||||
}
|
||||
|
||||
// ----- Purchase RPC -----------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Owning-client entry point. Sends a request to the server to purchase
|
||||
/// a random buff from the category at <paramref name="categoryIndex"/>.
|
||||
/// The server validates gold and adds the buff if the purchase succeeds.
|
||||
/// </summary>
|
||||
[Rpc(SendTo.Server, RequireOwnership = true)]
|
||||
public void RequestPurchaseBuffRpc(int categoryIndex)
|
||||
{
|
||||
if (categories == null || categoryIndex < 0 || categoryIndex >= categories.Length)
|
||||
{
|
||||
Debug.LogWarning("[PlayerBuffManager] RequestPurchaseBuff: invalid category index.");
|
||||
return;
|
||||
}
|
||||
|
||||
var category = categories[categoryIndex];
|
||||
if (category == null || category.Pool == null || category.Pool.Length == 0)
|
||||
{
|
||||
Debug.LogWarning("[PlayerBuffManager] RequestPurchaseBuff: category has no buffs.");
|
||||
return;
|
||||
}
|
||||
|
||||
var goldManager = PlayerGoldManager.GetForClient(OwnerClientId);
|
||||
if (goldManager == null)
|
||||
{
|
||||
Debug.LogError("[PlayerBuffManager] RequestPurchaseBuff: no PlayerGoldManager found.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (goldManager.CurrentGold < category.Cost)
|
||||
{
|
||||
Debug.Log($"[PlayerBuffManager] Client {OwnerClientId} cannot afford " +
|
||||
$"'{category.DisplayName}' (cost {category.Cost}, " +
|
||||
$"gold {goldManager.CurrentGold}).");
|
||||
return;
|
||||
}
|
||||
|
||||
goldManager.DeductGold(category.Cost);
|
||||
|
||||
var def = category.Pool[Random.Range(0, category.Pool.Length)];
|
||||
buffs.Add(new ActiveBuff
|
||||
{
|
||||
Stat = def.Stat,
|
||||
Multiplier = def.Multiplier,
|
||||
IsActive = true,
|
||||
DisplayName = new FixedString64Bytes(def.DisplayName ?? string.Empty),
|
||||
});
|
||||
|
||||
Debug.Log($"[PlayerBuffManager] Client {OwnerClientId} purchased buff " +
|
||||
$"'{def.DisplayName}' ({def.Stat} ×{def.Multiplier}).");
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue