Files
FutureMen/Assets/Scripts/Player/PlayerHands.cs

211 lines
4.9 KiB
C#
Raw 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 DragonLi.Core;
using Knife.Effects.SimpleController;
using UnityEngine;
/// <summary>
/// PlayerHands永远不会空手版
/// </summary>
public class PlayerHands : MonoBehaviour
{
[Header("所有武器预制体0 号为初始武器)")]
public GameObject[] WeaponsObjects;
[SerializeField] private Player player;
public WeaponSelector weaponSelector;
public int[] Indices;
private IWeapon[] weapons;
/// <summary>
/// 当前已拥有的武器(存数组下标,永远至少包含 0
/// </summary>
private readonly List<int> available = new List<int>();
/// <summary>
/// available 列表中的当前位置
/// </summary>
private int currentIdx = 0;
#region Unity
private void Start()
{
int count = WeaponsObjects.Length;
weapons = new IWeapon[count];
for (int i = 0; i < count; i++)
{
weapons[i] = WeaponsObjects[i].GetComponent<IWeapon>();
var w = WeaponsObjects[i].GetComponent<Weapon>();
if (w != null)
w.weaponId = i + 1;
WeaponsObjects[i].SetActive(false);
}
// 🔒 初始化:永远拥有 0 号武器
available.Clear();
available.Add(0);
currentIdx = 0;
ActivateWeapon(0);
Weapon.OnAmmoDepleted += OnAmmoDepleted;
if (weaponSelector != null)
weaponSelector.OnSelectedEvent += OnWeaponSelected;
}
private void OnDestroy()
{
Weapon.OnAmmoDepleted -= OnAmmoDepleted;
if (weaponSelector != null)
weaponSelector.OnSelectedEvent -= OnWeaponSelected;
foreach (var w in weapons)
if (w != null)
w.OnFire -= OnFire;
}
#endregion
#region / / UI
public void SwitchNext()
{
if (available.Count <= 1) return;
int next = (currentIdx + 1) % available.Count;
SwitchByListIndex(next);
}
public void SwitchPrev()
{
if (available.Count <= 1) return;
int prev = (currentIdx - 1 + available.Count) % available.Count;
SwitchByListIndex(prev);
}
public void OnWeaponSelected(int selectorIndex)
{
if (Indices == null) return;
for (int i = 0; i < Indices.Length; i++)
{
if (Indices[i] == selectorIndex)
{
int listPos = available.IndexOf(i);
if (listPos >= 0)
SwitchByListIndex(listPos);
return;
}
}
}
#endregion
#region
public void PickUpAndSwitchTo(int weaponIndex, int ammo)
{
weaponIndex -= 1;
if (weaponIndex <= 0 || weaponIndex >= WeaponsObjects.Length)
return;
if (!available.Contains(weaponIndex))
available.Add(weaponIndex);
var w = WeaponsObjects[weaponIndex].GetComponent<Weapon>();
if (w != null)
w.PickUpWeapon(w.weaponId, ammo);
SwitchByListIndex(available.IndexOf(weaponIndex));
}
#endregion
#region
private void SwitchByListIndex(int listIdx)
{
if (listIdx < 0 || listIdx >= available.Count)
return;
int newIndex = available[listIdx];
int oldIndex = available[currentIdx];
if (newIndex == oldIndex)
return;
DeactivateWeapon(oldIndex);
currentIdx = listIdx;
ActivateWeapon(newIndex);
}
private void ActivateWeapon(int index)
{
weapons[index].OnFire += OnFire;
WeaponsObjects[index].SetActive(true);
var w = WeaponsObjects[index].GetComponent<Weapon>();
EventDispatcher.TriggerEvent(
"ChangeWeaponIcon",
(PlayerWeaponType)index,
w != null ? w.bulletsLeft : 0
);
}
private void DeactivateWeapon(int index)
{
weapons[index].OnFire -= OnFire;
WeaponsObjects[index].SetActive(false);
}
#endregion
#region
private void OnAmmoDepleted(int weaponId)
{
int index = weaponId - 1;
// 🔒 初始武器永不移除
if (index <= 0)
return;
int listPos = available.IndexOf(index);
if (listPos < 0)
return;
bool wasCurrent = (listPos == currentIdx);
available.RemoveAt(listPos);
DeactivateWeapon(index);
if (wasCurrent)
{
// 优先切到前一把,否则切 0
int nextListPos = Mathf.Clamp(listPos - 1, 0, available.Count - 1);
currentIdx = nextListPos;
ActivateWeapon(available[currentIdx]);
}
else if (listPos < currentIdx)
{
currentIdx--;
}
}
#endregion
#region
private void OnFire(Vector2 recoil)
{
player?.ApplyRecoil(recoil);
}
#endregion
}