Files
BABA_YAGA/Assets/Third Parties/Opsive/UltimateCharacterController/Scripts/FirstPersonController/Items/FirstPersonShootableWeaponProperties.cs
Scove 3e39117acc Consolidate third-party plugins into Assets/Plugins
Move and consolidate many third-party plugin files and metadata from various locations (notably Assets/Third Parties/Plugins 1 and scattered Opsive/Photon folders) into a unified Assets/Plugins directory. Includes DOTween, PrimeTween, Native/BackroomsNoise, Sirenix/Odin Inspector, and Opsive UltimateCharacterController/shared libs, plus updates to several .meta files and removal of obsolete installer/legacy files. This standardizes plugin layout and cleans up duplicate/obsolete assets.
2026-06-16 18:41:44 +07:00

193 lines
12 KiB
C#

/// ---------------------------------------------
/// Ultimate Character Controller
/// Copyright (c) Opsive. All Rights Reserved.
/// https://www.opsive.com
/// ---------------------------------------------
namespace Opsive.UltimateCharacterController.FirstPersonController.Items
{
using UnityEngine;
using Opsive.Shared.Events;
using Opsive.Shared.Utility;
using Opsive.UltimateCharacterController.Character;
using Opsive.UltimateCharacterController.Items;
using Opsive.UltimateCharacterController.Items.Actions.PerspectiveProperties;
using Opsive.UltimateCharacterController.Utility;
/// <summary>
/// Describes any first person perspective dependent properties for the ShootableWeapon.
/// </summary>
public class FirstPersonShootableWeaponProperties : FirstPersonWeaponProperties, IShootableWeaponPerspectiveProperties
{
[Tooltip("The sensitivity amount for how much the weapon must be looking in the look source direction (-1 is least sensitive and 1 is most).")]
[Range(-1, 1)] [SerializeField] protected float m_LookSensitivity = 0.97f;
[Tooltip("The location that the weapon is fired at.")]
[SerializeField] protected Transform m_FirePointLocation;
[Tooltip("The transform that the fire point should be attached to.")]
[SerializeField] protected Transform m_FirePointAttachmentLocation;
[Tooltip("The ID of the transform that the fire point should be attached to. This field will be used if the value is not -1 and the attachment is null.")]
[SerializeField] protected int m_FirePointAttachmentLocationID = -1;
[Tooltip("The location that the muzzle flash is spawned at.")]
[SerializeField] protected Transform m_MuzzleFlashLocation;
[Tooltip("The location that the shell is ejected at.")]
[SerializeField] protected Transform m_ShellLocation;
[Tooltip("The location that the smoke is spawned at.")]
[SerializeField] protected Transform m_SmokeLocation;
[Tooltip("The location that the tracer is spawned at.")]
[SerializeField] protected Transform m_TracerLocation;
[Tooltip("A reference to the weapon's clip that can be reloaded.")]
[SerializeField] protected Transform m_ReloadableClip;
[Tooltip("A reference to the reloadable clip attachment transform.")]
[SerializeField] protected Transform m_ReloadableClipAttachment;
[Tooltip("The ID of the reloadable clip attachment transform. This field will be used if the value is not -1 and the attachment is null.")]
[SerializeField] protected int m_ReloadableClipAttachmentID = -1;
[Tooltip("A reference to the attachment transform that the projectile should be parented to when reloading.")]
[SerializeField] protected Transform m_ReloadProjectileAttachment;
[Tooltip("The ID of the attachment transform that hte projectile should be parented to when reloading. This field will be used if the value is not -1 and the attachment is null.")]
[SerializeField] protected int m_ReloadProjectileAttachmentID = -1;
[Tooltip("Optionally specify if the weapon has a camera for the scope.")]
[SerializeField] protected GameObject m_ScopeCamera;
[NonSerialized] public Transform FirePointLocation { get { return m_FirePointLocation; } set { m_FirePointLocation = value; } }
[NonSerialized] public Transform MuzzleFlashLocation { get { return m_MuzzleFlashLocation; } set { m_MuzzleFlashLocation = value; } }
[NonSerialized] public Transform ShellLocation { get { return m_ShellLocation; } set { m_ShellLocation = value; } }
[NonSerialized] public Transform SmokeLocation { get { return m_SmokeLocation; } set { m_SmokeLocation = value; } }
[NonSerialized] public Transform TracerLocation { get { return m_TracerLocation; } set { m_TracerLocation = value; } }
[NonSerialized] public Transform ReloadableClip { get { return m_ReloadableClip; } set { m_ReloadableClip = value; } }
[NonSerialized] public Transform ReloadableClipAttachment { get { return m_ReloadableClipAttachment; } set { m_ReloadableClipAttachment = value; } }
[NonSerialized] public int ReloadableClipAttachmentID { get { return m_ReloadableClipAttachmentID; } set { m_ReloadableClipAttachmentID = value; } }
[NonSerialized] public Transform ReloadProjectileAttachment { get { return m_ReloadProjectileAttachment; } set { m_ReloadProjectileAttachment = value; } }
[NonSerialized] public int ReloadProjectileAttachmentID { get { return m_ReloadProjectileAttachmentID; } set { m_ReloadProjectileAttachmentID = value; } }
[NonSerialized] public GameObject ScopeCamera { get { return m_ScopeCamera; } set { m_ScopeCamera = value; } }
private Transform m_VisibleTransform;
private ILookSource m_LookSource;
#if UNITY_EDITOR
private float m_LastLookSensitivity;
private int m_ConsistantLookSensitivityCount;
#endif
/// <summary>
/// Initialize the default values.
/// </summary>
protected override void Awake()
{
base.Awake();
var perspectiveItems = GetComponents<PerspectiveItem>();
for (int i = 0; i < perspectiveItems.Length; ++i) {
if (perspectiveItems[i].FirstPersonItem) {
// A Visible Item may not exist.
var visibleItem = (perspectiveItems[i] as FirstPersonPerspectiveItem).VisibleItem;
m_VisibleTransform = visibleItem != null ? visibleItem.transform : m_Object.transform;
}
}
// The look source is used to determine if the item is facing in the forward direction.
m_LookSource = m_CharacterLocomotion.LookSource;
// The item may be added at runtime while the attachment transform is located on the character.
if (m_FirePointAttachmentLocationID != -1 || (m_ReloadableClipAttachment == null && m_ReloadableClip != null) || m_ReloadProjectileAttachmentID != -1) {
var firstPersonObject = GetComponent<FirstPersonPerspectiveItem>().Object;
if (firstPersonObject != null) {
var objectIdentifiers = firstPersonObject.GetComponentsInChildren<Objects.ObjectIdentifier>();
if (objectIdentifiers.Length > 0) {
for (int i = 0; i < objectIdentifiers.Length; ++i) {
if (objectIdentifiers[i].ID == m_FirePointAttachmentLocationID) {
m_FirePointAttachmentLocation = objectIdentifiers[i].transform;
} else if (objectIdentifiers[i].ID == m_ReloadableClipAttachmentID) {
m_ReloadableClipAttachment = objectIdentifiers[i].transform;
} else if (objectIdentifiers[i].ID == m_ReloadProjectileAttachmentID) {
m_ReloadProjectileAttachment = objectIdentifiers[i].transform;
}
// If the references are found then the loop can end early.
if ((m_ReloadableClip == null || m_ReloadableClipAttachmentID == -1 || m_ReloadableClipAttachment != null) &&
(m_FirePointAttachmentLocationID == -1 || m_FirePointAttachmentLocation != null) &&
(m_ReloadProjectileAttachmentID == -1 || m_ReloadProjectileAttachment != null)) {
break;
}
}
// If no IDs match then log a warning.
if (m_FirePointAttachmentLocation == null && m_FirePointAttachmentLocationID != -1) {
Debug.LogWarning("Warning: Unable to find the third person fire point attachment ObjectIdentifier with the ID " + m_FirePointAttachmentLocationID + " for item " + name + ".");
}
if (m_ReloadableClipAttachment == null && m_ReloadableClip != null && m_ReloadableClipAttachmentID != -1) {
Debug.LogWarning("Warning: Unable to find the third person reload attachment ObjectIdentifier with the ID " + m_ReloadableClipAttachmentID + " for item " + name + ".");
}
if (m_ReloadProjectileAttachment == null && m_ReloadProjectileAttachmentID != -1) {
Debug.LogWarning("Warning: Unable to find the third person reload projectile ObjectIdentifier with the ID " + m_ReloadProjectileAttachmentID + " for item " + name + ".");
}
}
}
}
if (m_FirePointAttachmentLocation != null) {
// If the fire point is null then the found attachment transform becomes the firepoint. If it is not null then the parent is set.
if (m_FirePointLocation == null) {
m_FirePointLocation = m_FirePointAttachmentLocation;
} else {
m_FirePointLocation.SetParentOrigin(m_FirePointAttachmentLocation);
}
}
EventHandler.RegisterEvent<ILookSource>(m_Character, "OnCharacterAttachLookSource", OnAttachLookSource);
}
/// <summary>
/// A new ILookSource object has been attached to the character.
/// </summary>
/// <param name="lookSource">The ILookSource object attached to the character.</param>
private void OnAttachLookSource(ILookSource lookSource)
{
m_LookSource = lookSource;
}
/// <summary>
/// Can the weapon be fired?
/// </summary>
/// <param name="fireInLookSourceDirection">Should the weapon fire in the LookSource direction?</param>
/// <param name="abilityActive">Is the Use ability active?</param>
/// <returns>True if the item can be fired.</returns>
public bool CanFire(bool abilityActive, bool fireInLookSourceDirection)
{
#if UNITY_EDITOR
if (!abilityActive) {
m_LastLookSensitivity = -1;
m_ConsistantLookSensitivityCount = 0;
}
#endif
// The object has to be facing in the same general direction as the character. When the ability is not active the direction shouldn't prevent
// the ability from starting. This will allow the weapon to move to the correct direction while the ability is active.
if (abilityActive && fireInLookSourceDirection) {
var lookSensitivity = Vector3.Dot(m_VisibleTransform.forward, m_LookSource.LookDirection(false));
#if UNITY_EDITOR
// A common cause for the weapon not being able to fire is because of the look sensitivity. Add a check to display a warning if the look sensitivity is blocking the firing.
if (lookSensitivity <= m_LookSensitivity && m_ConsistantLookSensitivityCount != -1) {
if (Mathf.Abs(m_LastLookSensitivity - lookSensitivity) < 0.05f) {
m_ConsistantLookSensitivityCount++;
if (m_ConsistantLookSensitivityCount > 10) {
Debug.LogWarning("Warning: The ShootableWeapon is unable to fire because of the Look Sensitivity on the ShootableWeaponProperties. See this page for more info: " +
"https://opsive.com/support/documentation/ultimate-character-controller/items/actions/usable/shootable-weapon/", this);
m_ConsistantLookSensitivityCount = -1;
}
} else {
m_ConsistantLookSensitivityCount = 0;
}
m_LastLookSensitivity = lookSensitivity;
}
#endif
return lookSensitivity > m_LookSensitivity;
}
return true;
}
/// <summary>
/// The object has been destroyed.
/// </summary>
private void OnDestroy()
{
EventHandler.UnregisterEvent<ILookSource>(m_Character, "OnCharacterAttachLookSource", OnAttachLookSource);
}
}
}