Files
OGG/Assets/Scripts/WeaponManager.cs

198 lines
7.3 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// Attach to the Player GameObject.
/// Manages all instantiated weapon instances and switching between them.
/// Also registers any weapon already in the scene (e.g. the starting gun).
/// </summary>
public class WeaponManager : MonoBehaviour
{
[Header("References")]
[Tooltip("The transform weapons are parented to — usually the Camera or a WeaponHolder child.")]
public Transform weaponHolder;
[Header("Weapon Position")]
[Tooltip("Local position offset applied to all equipped weapons.")]
public Vector3 weaponPositionOffset = new Vector3(0.2f, -0.25f, 0.45f);
[Tooltip("Local euler rotation offset applied to all equipped weapons.")]
public Vector3 weaponRotationOffset = new Vector3(0f, 0f, 0f);
[Tooltip("Scale applied to all equipped weapons.")]
public Vector3 weaponScale = new Vector3(1f, 1f, 1f);
[Header("Switching")]
public bool allowScrollSwitch = true;
public bool allowNumberKeys = true;
// ─── internal slot ───────────────────────────────────────────────
public class WeaponSlot
{
public string itemName;
public GameObject instance; // the live GO in weaponHolder
public ItemDefinition definition; // may be null for the starting gun
}
public List<WeaponSlot> slots = new List<WeaponSlot>();
public int activeIndex { get; private set; } = -1;
// ─────────────────────────────────────────────────────────────────
void Start()
{
// Auto-find weapon holder if not set
if (weaponHolder == null)
{
Camera cam = GetComponentInChildren<Camera>();
weaponHolder = cam != null ? cam.transform : transform;
}
// Register any SimpleGun already present as children of the holder
SimpleGun[] existing = weaponHolder.GetComponentsInChildren<SimpleGun>(true);
foreach (SimpleGun gun in existing)
{
RegisterExistingGun(gun.gameObject);
}
}
private Inventory _inventory;
void Update()
{
if (slots.Count == 0) return;
// Live-update active weapon transform so Inspector tweaks take effect immediately
if (activeIndex >= 0 && activeIndex < slots.Count)
{
var vm = slots[activeIndex].instance.GetComponent<WeaponViewmodel>();
if (vm != null)
vm.Apply();
else
{
Transform t = slots[activeIndex].instance.transform;
t.localPosition = weaponPositionOffset;
t.localRotation = Quaternion.Euler(weaponRotationOffset);
t.localScale = weaponScale;
}
}
// Don't switch weapons while the inventory UI is open
if (_inventory == null) _inventory = GetComponent<Inventory>();
if (_inventory != null && _inventory.IsOpen) return;
// Scroll wheel
if (allowScrollSwitch)
{
float scroll = Input.GetAxis("Mouse ScrollWheel");
if (scroll > 0f) CycleWeapon(1);
if (scroll < 0f) CycleWeapon(-1);
}
// Number keys 19
if (allowNumberKeys)
{
for (int i = 0; i < Mathf.Min(slots.Count, 9); i++)
{
if (Input.GetKeyDown(KeyCode.Alpha1 + i))
EquipByIndex(i);
}
}
}
// ─── Public API ──────────────────────────────────────────────────
/// <summary>Register a weapon that already exists in the scene (starting gun).</summary>
public void RegisterExistingGun(GameObject gunGO, ItemDefinition def = null)
{
string name = def != null ? def.itemName : gunGO.name;
// Don't double-register
if (slots.Exists(s => s.instance == gunGO)) return;
slots.Add(new WeaponSlot { itemName = name, instance = gunGO, definition = def });
int idx = slots.Count - 1;
// Always start inactive — player must pick up / equip from inventory
gunGO.SetActive(false);
Debug.Log($"[WeaponManager] Registered existing weapon: {name} at slot {idx} (inactive)");
}
/// <summary>Add a new weapon from a definition (called by Inventory on first equip).</summary>
public int AddWeapon(ItemDefinition def)
{
if (def == null || def.weaponPrefab == null)
{
Debug.LogWarning("[WeaponManager] AddWeapon: definition or prefab is null.");
return -1;
}
// Already registered?
int existing = slots.FindIndex(s => s.definition == def);
if (existing >= 0) return existing;
GameObject instance = Instantiate(def.weaponPrefab, weaponHolder);
var vm = instance.GetComponent<WeaponViewmodel>();
if (vm != null)
vm.Apply();
else
{
instance.transform.localPosition = weaponPositionOffset;
instance.transform.localRotation = Quaternion.Euler(weaponRotationOffset);
instance.transform.localScale = weaponScale;
}
instance.SetActive(false);
// Strip colliders so they don't mess with the CharacterController
foreach (Collider col in instance.GetComponentsInChildren<Collider>())
if (!(col is CharacterController)) Destroy(col);
slots.Add(new WeaponSlot { itemName = def.itemName, instance = instance, definition = def });
int newIdx = slots.Count - 1;
Debug.Log($"[WeaponManager] Added weapon: {def.itemName} at slot {newIdx}");
return newIdx;
}
/// <summary>Equip weapon by slot index.</summary>
public void EquipByIndex(int index)
{
if (index < 0 || index >= slots.Count) return;
// Deactivate current
if (activeIndex >= 0 && activeIndex < slots.Count)
slots[activeIndex].instance.SetActive(false);
activeIndex = index;
slots[activeIndex].instance.SetActive(true);
Debug.Log($"[WeaponManager] Equipped: {slots[activeIndex].itemName}");
}
/// <summary>Equip weapon by item name.</summary>
public void EquipByName(string name)
{
int idx = slots.FindIndex(s => s.itemName == name);
if (idx >= 0)
EquipByIndex(idx);
else
Debug.LogWarning($"[WeaponManager] No slot found for: {name}");
}
/// <summary>Cycle forward (+1) or backward (-1).</summary>
public void CycleWeapon(int dir)
{
if (slots.Count == 0) return;
int next = (activeIndex + dir + slots.Count) % slots.Count;
EquipByIndex(next);
}
/// <summary>Deactivate the current weapon without switching to another.</summary>
public void Unequip()
{
if (activeIndex >= 0 && activeIndex < slots.Count)
slots[activeIndex].instance.SetActive(false);
activeIndex = -1;
Debug.Log("[WeaponManager] Unequipped all weapons.");
}
public string ActiveWeaponName =>
(activeIndex >= 0 && activeIndex < slots.Count) ? slots[activeIndex].itemName : "";
}