222 lines
6.8 KiB
C#
222 lines
6.8 KiB
C#
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEngine.InputSystem;
|
|
|
|
/// <summary>
|
|
/// Manages equipping/unequipping weapons on the player and overrides attack animations
|
|
/// so that only the equipped weapon's animations are used.
|
|
/// Assumes weapon models (bat/hammer) are already attached to the player's hand and hidden.
|
|
/// </summary>
|
|
public class WeaponManager : MonoBehaviour
|
|
{
|
|
public enum WeaponType { None, Bat, Hammer }
|
|
|
|
[Header("In-hand weapon objects (already attached to player hand)")]
|
|
[SerializeField] private GameObject batInHand;
|
|
[SerializeField] private GameObject hammerInHand;
|
|
|
|
[Header("Optional: disable base attack inputs while a weapon is equipped")]
|
|
[SerializeField] private bool blockBaseAttacksWhenEquipped = true;
|
|
|
|
[Header("Input System")]
|
|
[SerializeField] private string pickupActionName = "WeaponPickup";
|
|
|
|
[Header("Pickup/Drop Settings")]
|
|
[SerializeField] private float dropReequipBlockSeconds = 0.2f;
|
|
|
|
// Tracks the current equipped weapon
|
|
public WeaponType CurrentWeapon { get; private set; } = WeaponType.None;
|
|
public bool IsWeaponEquipped => CurrentWeapon != WeaponType.None;
|
|
|
|
// Internal state for alternating swings (e.g., BatOne/BatTwo)
|
|
private int swingIndex = 0;
|
|
|
|
// Base attacks to override when a weapon is equipped
|
|
private static readonly HashSet<string> baseAttackNames = new HashSet<string>
|
|
{
|
|
AnimationNames.Jab,
|
|
AnimationNames.Haymaker,
|
|
AnimationNames.BasicKick,
|
|
AnimationNames.SumoSlap,
|
|
AnimationNames.SpinningBackfist,
|
|
AnimationNames.ElbowSmash,
|
|
AnimationNames.AirPunch,
|
|
AnimationNames.LowKick,
|
|
// common fallbacks
|
|
"Punch", "Kick", "Strike"
|
|
};
|
|
|
|
private PlayerInput _playerInput;
|
|
private InputAction _pickupAction;
|
|
private float _pickupCooldownUntil = 0f;
|
|
|
|
private void Awake()
|
|
{
|
|
_playerInput = GetComponent<PlayerInput>();
|
|
if (_playerInput != null)
|
|
{
|
|
_pickupAction = _playerInput.actions?.FindAction(pickupActionName, false);
|
|
if (_pickupAction != null && !_pickupAction.enabled)
|
|
_pickupAction.SafeEnable();
|
|
}
|
|
}
|
|
|
|
private void OnEnable()
|
|
{
|
|
if (_pickupAction != null)
|
|
_pickupAction.performed += OnPickupOrDrop;
|
|
}
|
|
|
|
private void OnDisable()
|
|
{
|
|
if (_pickupAction != null)
|
|
_pickupAction.performed -= OnPickupOrDrop;
|
|
}
|
|
|
|
private void Start()
|
|
{
|
|
// Ensure correct visibility at start
|
|
ApplyVisibility();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Equip a specific weapon and reveal it on the player's hand.
|
|
/// </summary>
|
|
public void EquipWeapon(WeaponType weapon)
|
|
{
|
|
if (CurrentWeapon == weapon) return;
|
|
|
|
CurrentWeapon = weapon;
|
|
swingIndex = 0; // reset combo index on equip
|
|
ApplyVisibility();
|
|
Debug.Log($"Equipped weapon: {CurrentWeapon}");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Unequip any weapon and restore default (unarmed) state.
|
|
/// </summary>
|
|
public void UnequipWeapon()
|
|
{
|
|
if (CurrentWeapon == WeaponType.None) return;
|
|
CurrentWeapon = WeaponType.None;
|
|
swingIndex = 0;
|
|
ApplyVisibility();
|
|
Debug.Log("Unequipped weapon");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Resolves an incoming requested animation to a weapon-specific animation if a weapon is equipped.
|
|
/// Non-attack animations are passed through unchanged.
|
|
/// </summary>
|
|
public string ResolveAnimation(string requested)
|
|
{
|
|
if (!IsWeaponEquipped)
|
|
return requested;
|
|
|
|
// Allow reactions, blocks, locomotion and non-attack anims
|
|
if (!baseAttackNames.Contains(requested))
|
|
return requested;
|
|
|
|
switch (CurrentWeapon)
|
|
{
|
|
case WeaponType.Bat:
|
|
return NextBatAnimation();
|
|
case WeaponType.Hammer:
|
|
return NextHammerAnimation();
|
|
default:
|
|
return requested;
|
|
}
|
|
}
|
|
|
|
private string NextBatAnimation()
|
|
{
|
|
// Alternate between two bat swings
|
|
swingIndex = (swingIndex + 1) % 2;
|
|
return swingIndex == 0 ? AnimationNames.BatOne : AnimationNames.BatTwo;
|
|
}
|
|
|
|
private string NextHammerAnimation()
|
|
{
|
|
swingIndex = (swingIndex + 1) % 2;
|
|
return swingIndex == 0 ? AnimationNames.HammerOne : AnimationNames.HammerTwo;
|
|
}
|
|
|
|
private void ApplyVisibility()
|
|
{
|
|
// Toggle in-hand models based on current weapon
|
|
if (batInHand != null)
|
|
{
|
|
batInHand.SetActive(CurrentWeapon == WeaponType.Bat);
|
|
Debug.Log($"[WeaponManager] batInHand active={batInHand.activeSelf} (weapon={CurrentWeapon})");
|
|
}
|
|
else
|
|
{
|
|
Debug.LogWarning("[WeaponManager] 'batInHand' is not assigned in inspector.");
|
|
}
|
|
|
|
if (hammerInHand != null)
|
|
{
|
|
hammerInHand.SetActive(CurrentWeapon == WeaponType.Hammer);
|
|
Debug.Log($"[WeaponManager] hammerInHand active={hammerInHand.activeSelf} (weapon={CurrentWeapon})");
|
|
}
|
|
else
|
|
{
|
|
Debug.LogWarning("[WeaponManager] 'hammerInHand' is not assigned in inspector.");
|
|
}
|
|
}
|
|
|
|
// Keep the last pickup object used so we can re-enable it on drop (optional)
|
|
private WeaponPickup lastPickupSource;
|
|
|
|
public void EquipWeaponFromPickup(WeaponType weapon, WeaponPickup pickup)
|
|
{
|
|
lastPickupSource = pickup;
|
|
EquipWeapon(weapon);
|
|
}
|
|
|
|
public void DropWeapon()
|
|
{
|
|
if (!IsWeaponEquipped) return;
|
|
|
|
// Play the pickup animation even when dropping
|
|
var anim = GetComponent<AnimationManager>();
|
|
if (anim != null)
|
|
{
|
|
anim.PlayAnimation(AnimationNames.WeaponPickup);
|
|
}
|
|
|
|
if (lastPickupSource != null)
|
|
{
|
|
// Let the pickup place itself and avoid instant trigger
|
|
lastPickupSource.PlaceAsDropped(transform);
|
|
lastPickupSource = null;
|
|
}
|
|
|
|
// Block immediate re-equip for a short time
|
|
_pickupCooldownUntil = Time.time + dropReequipBlockSeconds;
|
|
|
|
UnequipWeapon();
|
|
}
|
|
|
|
private void OnPickupOrDrop(InputAction.CallbackContext ctx)
|
|
{
|
|
// Ignore if within cooldown window
|
|
if (Time.time < _pickupCooldownUntil)
|
|
return;
|
|
|
|
// Requirement 3: If the character has a weapon in hand, pressing the same button drops it (and plays pickup anim)
|
|
if (IsWeaponEquipped)
|
|
{
|
|
DropWeapon();
|
|
return;
|
|
}
|
|
|
|
// Requirement 1 & 2: Only when in range and no weapon equipped, allow pickup and play pickup anim
|
|
if (WeaponPickup.currentPickupInRange != null)
|
|
{
|
|
WeaponPickup.currentPickupInRange.TryEquip();
|
|
}
|
|
// Otherwise do nothing (no animation out of range)
|
|
}
|
|
}
|