Equipment: weapon-granted abilities + gear mods (DR-027 Phase 1)
Equipment slots reusing the AbilityRef/StatModifier machinery: EquipmentSlot [GhostField] buffer (index=slot), server-only event-driven EquipSystem (RPC). Weapon -> AbilityRef.Id swaps the attack (prefab + base stats, prediction-correct); gear -> StatModifiers tagged a reserved per-slot EquipSourceId, stripped target-agnostically via RemoveBySourceId. Item mods are INLINE on ItemDefBlob (a nested BlobArray reads empty under the by-value TryGetItem copy). Atomic equip-over swap (no item loss); DefaultAbility restores the unarmed ability on weapon-unequip. Client keys + build-safe hooks; HUD equipment panel + click-to-equip. 4 catalog weapon/gear items wired + re-baked. Play-validated host+client: weapon equip swaps AbilityRef on both worlds, gear folds into EffectiveCharacterStats, unequip reverses + restores DefaultAbility, all replicated to the owner. See DR-027. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
using Unity.Entities;
|
||||
using Unity.NetCode;
|
||||
|
||||
namespace ProjectM.Simulation
|
||||
{
|
||||
/// <summary>
|
||||
/// One equipment slot on the player. The per-player buffer holds exactly <see cref="EquipSlotId.Count"/>
|
||||
/// rows in fixed slot order (the buffer INDEX is the slot — Weapon=0/Armor=1/Trinket=2/Tool=3), so only the
|
||||
/// equipped item id needs to replicate; there is no separate Slot field to desync. A [GhostField]
|
||||
/// <see cref="SendToOwnerType.All"/> buffer (a <see cref="StatModifier"/>/<see cref="InventorySlot"/> twin)
|
||||
/// so the owning client's HUD can show its loadout; the server is the SOLE writer (EquipSystem).
|
||||
///
|
||||
/// The actual effects — AbilityRef.Id from the Weapon slot + StatModifiers per slot — are applied
|
||||
/// EVENT-DRIVEN by EquipSystem (once per equip/unequip), NOT re-derived from this buffer each tick; this
|
||||
/// buffer is the replicated record of WHAT is equipped (HUD-facing + persistence-ready), not the effect.
|
||||
/// NOTE: adding this [GhostField] buffer changes the player ghost serialization hash → the player
|
||||
/// prefab/subscene MUST be re-baked consistently in both worlds (see <see cref="InventorySlot"/>).
|
||||
/// </summary>
|
||||
[GhostComponent(OwnerSendType = SendToOwnerType.All)]
|
||||
[InternalBufferCapacity(4)]
|
||||
public struct EquipmentSlot : IBufferElementData
|
||||
{
|
||||
/// <summary>Item equipped in this slot (0 = empty). The buffer INDEX is the <see cref="EquipSlotId"/>.</summary>
|
||||
[GhostField] public ushort ItemId;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user