231 lines
5.8 KiB
C#
231 lines
5.8 KiB
C#
using System;
|
|
using UnityEngine;
|
|
|
|
/// <summary>
|
|
/// Types of equipment slots available.
|
|
/// </summary>
|
|
public enum EquipmentSlotType
|
|
{
|
|
MainHand,
|
|
OffHand,
|
|
Head,
|
|
Body,
|
|
Back,
|
|
Accessory
|
|
}
|
|
|
|
/// <summary>
|
|
/// Represents a single equipment slot that can hold an equipped item.
|
|
/// </summary>
|
|
[Serializable]
|
|
public class EquipmentSlot
|
|
{
|
|
/// <summary>
|
|
/// Type of this equipment slot.
|
|
/// </summary>
|
|
public EquipmentSlotType SlotType;
|
|
|
|
/// <summary>
|
|
/// Transform where equipment is attached.
|
|
/// </summary>
|
|
public Transform AttachPoint;
|
|
|
|
/// <summary>
|
|
/// Currently spawned equipment instance.
|
|
/// </summary>
|
|
[NonSerialized]
|
|
public GameObject CurrentEquipment;
|
|
|
|
/// <summary>
|
|
/// Currently equipped item data.
|
|
/// </summary>
|
|
[NonSerialized]
|
|
public ItemData EquippedItem;
|
|
|
|
/// <summary>
|
|
/// Event fired when equipment changes.
|
|
/// </summary>
|
|
public event Action<EquipmentSlot, ItemData> OnEquipmentChanged;
|
|
|
|
/// <summary>
|
|
/// Equip an item to this slot.
|
|
/// </summary>
|
|
/// <param name="item">Item to equip (or null to unequip)</param>
|
|
public void Equip(ItemData item)
|
|
{
|
|
// Remove current equipment
|
|
Unequip();
|
|
|
|
if (item == null) return;
|
|
|
|
// Check if item can be equipped
|
|
if (!item.CanBeEquipped) return;
|
|
|
|
EquippedItem = item;
|
|
|
|
// Spawn equipment visual
|
|
var prefab = item.GetEquipmentPrefab();
|
|
if (prefab != null && AttachPoint != null)
|
|
{
|
|
CurrentEquipment = UnityEngine.Object.Instantiate(prefab, AttachPoint);
|
|
CurrentEquipment.transform.localPosition = item.GetPositionOffset();
|
|
CurrentEquipment.transform.localRotation = Quaternion.Euler(item.GetRotationOffset());
|
|
}
|
|
|
|
OnEquipmentChanged?.Invoke(this, item);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Equip using IEquippableItem interface (more generic).
|
|
/// </summary>
|
|
/// <param name="equippable">Equippable item</param>
|
|
/// <param name="user">The user equipping the item</param>
|
|
public void Equip(IEquippableItem equippable, GameObject user)
|
|
{
|
|
Unequip();
|
|
|
|
if (equippable == null) return;
|
|
|
|
var prefab = equippable.GetEquipmentPrefab();
|
|
if (prefab == null) return;
|
|
|
|
// Find or use the configured attach point
|
|
Transform attachTo = AttachPoint;
|
|
if (attachTo == null && user != null)
|
|
{
|
|
attachTo = equippable.FindAttachmentPoint(user);
|
|
}
|
|
|
|
if (attachTo != null)
|
|
{
|
|
CurrentEquipment = UnityEngine.Object.Instantiate(prefab, attachTo);
|
|
CurrentEquipment.transform.localPosition = equippable.GetPositionOffset();
|
|
CurrentEquipment.transform.localRotation = Quaternion.Euler(equippable.GetRotationOffset());
|
|
}
|
|
|
|
OnEquipmentChanged?.Invoke(this, EquippedItem);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Unequip the current item.
|
|
/// </summary>
|
|
public void Unequip()
|
|
{
|
|
if (CurrentEquipment != null)
|
|
{
|
|
UnityEngine.Object.Destroy(CurrentEquipment);
|
|
CurrentEquipment = null;
|
|
}
|
|
|
|
var previousItem = EquippedItem;
|
|
EquippedItem = null;
|
|
|
|
if (previousItem != null)
|
|
{
|
|
OnEquipmentChanged?.Invoke(this, null);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Check if this slot has equipment.
|
|
/// </summary>
|
|
public bool HasEquipment => CurrentEquipment != null || EquippedItem != null;
|
|
|
|
/// <summary>
|
|
/// Check if a specific item can be equipped in this slot.
|
|
/// </summary>
|
|
public bool CanEquip(ItemData item)
|
|
{
|
|
if (item == null) return true; // Can always "unequip"
|
|
return item.CanBeEquipped;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Manages multiple equipment slots for a character.
|
|
/// </summary>
|
|
[Serializable]
|
|
public class EquipmentManager
|
|
{
|
|
[SerializeField]
|
|
private EquipmentSlot[] _slots;
|
|
|
|
/// <summary>
|
|
/// All equipment slots.
|
|
/// </summary>
|
|
public EquipmentSlot[] Slots => _slots;
|
|
|
|
/// <summary>
|
|
/// Get a slot by type.
|
|
/// </summary>
|
|
public EquipmentSlot GetSlot(EquipmentSlotType type)
|
|
{
|
|
if (_slots == null) return null;
|
|
|
|
foreach (var slot in _slots)
|
|
{
|
|
if (slot.SlotType == type)
|
|
return slot;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Equip an item to the appropriate slot.
|
|
/// </summary>
|
|
public bool TryEquip(ItemData item, EquipmentSlotType preferredSlot = EquipmentSlotType.MainHand)
|
|
{
|
|
var slot = GetSlot(preferredSlot);
|
|
if (slot != null && slot.CanEquip(item))
|
|
{
|
|
slot.Equip(item);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Unequip all slots.
|
|
/// </summary>
|
|
public void UnequipAll()
|
|
{
|
|
if (_slots == null) return;
|
|
|
|
foreach (var slot in _slots)
|
|
{
|
|
slot.Unequip();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Initialize slots with attach points found on the character.
|
|
/// </summary>
|
|
public void Initialize(GameObject character, params (EquipmentSlotType type, string attachPointName)[] slotConfigs)
|
|
{
|
|
_slots = new EquipmentSlot[slotConfigs.Length];
|
|
|
|
for (int i = 0; i < slotConfigs.Length; i++)
|
|
{
|
|
var config = slotConfigs[i];
|
|
Transform attachPoint = null;
|
|
|
|
// Find attach point
|
|
var transforms = character.GetComponentsInChildren<Transform>();
|
|
foreach (var t in transforms)
|
|
{
|
|
if (t.name == config.attachPointName)
|
|
{
|
|
attachPoint = t;
|
|
break;
|
|
}
|
|
}
|
|
|
|
_slots[i] = new EquipmentSlot
|
|
{
|
|
SlotType = config.type,
|
|
AttachPoint = attachPoint
|
|
};
|
|
}
|
|
}
|
|
}
|