Files
BABA_YAGA/Assets/Scripts/ThirdPersonController/Character/Abilities/ItemAbilities/ItemPullback.cs

179 lines
7.7 KiB
C#

/// ---------------------------------------------
/// Ultimate Character Controller
/// Copyright (c) Opsive. All Rights Reserved.
/// https://www.opsive.com
/// ---------------------------------------------
namespace Opsive.UltimateCharacterController.ThirdPersonController.Character.Abilities.Items
{
using Opsive.Shared.Events;
using Opsive.Shared.Game;
using Opsive.UltimateCharacterController.Character.Abilities;
using Opsive.UltimateCharacterController.Character.Abilities.Items;
using Opsive.UltimateCharacterController.Game;
using Opsive.UltimateCharacterController.Utility;
using UnityEngine;
/// <summary>
/// Pulls back the item if the character gets too close to a wall. This will prevent the item from clipping with the wall.
/// </summary>
[DefaultStopType(AbilityStopType.Automatic)]
public class ItemPullback : ItemAbility
{
[Tooltip("The collider used to detect when the character is near an object and should pull back the items.")]
[SerializeField] protected Collider m_Collider;
[Tooltip("The layers that the collider can collide with.")]
[SerializeField] protected LayerMask m_CollisionLayers = ~(1 << LayerManager.IgnoreRaycast | 1 << LayerManager.TransparentFX | 1 << LayerManager.SubCharacter |
1 << LayerManager.Overlay | 1 << LayerManager.VisualEffect | 1 << LayerManager.Water);
[Tooltip("The maximum number of collisions that should be detected by the collider.")]
[SerializeField] protected int m_MaxCollisionCount = 5;
public Collider Collider { get { return m_Collider; } set { m_Collider = value; } }
public LayerMask CollisionLayers { get { return m_CollisionLayers; } set { m_CollisionLayers = value; } }
private Transform m_ColliderTransform;
private Collider[] m_HitColliders;
/// <summary>
/// Initialize the default values.
/// </summary>
public override void Awake()
{
base.Awake();
if (m_Collider == null || (!(m_Collider is CapsuleCollider) && !(m_Collider is SphereCollider))) {
Debug.LogError("Error: Only Capsule and Sphere Colliders are supported by the Item Pullback ability.");
m_Collider = null;
Enabled = false;
return;
}
m_HitColliders = new Collider[m_MaxCollisionCount];
m_ColliderTransform = m_Collider.transform;
m_Collider.gameObject.SetActive(false);
EventHandler.RegisterEvent<bool>(m_GameObject, "OnCameraWillChangePerspectives", OnChangePerspectives);
}
/// <summary>
/// Called when the ablity is tried to be started. If false is returned then the ability will not be started.
/// </summary>
/// <returns>True if the ability can be started.</returns>
public override bool CanStartAbility()
{
return HasCollision();
}
/// <summary>
/// Is there a collision between the item pullback collider and another object?
/// </summary>
/// <returns>True if there is a collision with the item pullback collider.</returns>
private bool HasCollision()
{
int hitCount;
if (m_Collider is CapsuleCollider) {
var capsuleCollider = m_Collider as CapsuleCollider;
if (capsuleCollider.radius == 0) {
return false;
}
Vector3 startEndCap, endEndCap;
MathUtility.CapsuleColliderEndCaps(capsuleCollider, m_ColliderTransform.position, m_ColliderTransform.rotation, out startEndCap, out endEndCap);
hitCount = Physics.OverlapCapsuleNonAlloc(startEndCap, endEndCap, capsuleCollider.radius * MathUtility.ColliderRadiusMultiplier(capsuleCollider), m_HitColliders, m_CollisionLayers, QueryTriggerInteraction.Ignore);
} else { // SphereCollider.
var sphereCollider = m_Collider as SphereCollider;
if (sphereCollider.radius == 0) {
return false;
}
hitCount = Physics.OverlapSphereNonAlloc(m_ColliderTransform.position, sphereCollider.radius * MathUtility.ColliderRadiusMultiplier(sphereCollider), m_HitColliders, m_CollisionLayers, QueryTriggerInteraction.Ignore);
}
for (int i = 0; i < hitCount; ++i) {
// Objects which are children of the character aren't considered a collision.
if (m_HitColliders[i].transform.IsChildOf(m_Transform)) {
continue;
}
// Projectiles shouldn't prevent the pullback ability.
if (m_HitColliders[i].gameObject.GetCachedComponent<Objects.Projectile>() != null) {
continue;
}
// It only takes one object for the ability to be in a collision state.
return true;
}
return false;
}
/// <summary>
/// Called when another ability is attempting to start and the current ability is active.
/// Returns true or false depending on if the new ability should be blocked from starting.
/// </summary>
/// <param name="startingAbility">The ability that is starting.</param>
/// <returns>True if the ability should be blocked.</returns>
public override bool ShouldBlockAbilityStart(Ability startingAbility)
{
return CanStopAbility(startingAbility);
}
/// <summary>
/// Called when the current ability is attempting to start and another ability is active.
/// Returns true or false depending on if the active ability should be stopped.
/// </summary>
/// <param name="activeAbility">The ability that is currently active.</param>
/// <returns>True if the ability should be stopped.</returns>
public override bool ShouldStopActiveAbility(Ability activeAbility)
{
return CanStopAbility(activeAbility);
}
/// <summary>
/// Can the Item Pullback ability stop the specified ability?
/// </summary>
/// <param name="ability">The ability that may be able to be stopped.</param>
/// <returns>True if the ability can be stopped.</returns>
private bool CanStopAbility(Ability ability)
{
#if ULTIMATE_CHARACTER_CONTROLLER_SHOOTER
if (ability is Use) {
var useAbility = ability as Use;
return useAbility.UsesItemActionType(typeof(UltimateCharacterController.Items.Actions.ShootableWeapon));
}
if (ability is Reload) {
return true;
}
#endif
return false;
}
/// <summary>
/// Can the ability be stopped?
/// </summary>
/// <returns>True if the ability can be stopped.</returns>
public override bool CanStopAbility()
{
return !HasCollision();
}
/// <summary>
/// The character perspective between first and third person has changed.
/// </summary>
/// <param name="firstPersonPerspective">Is the character in a first person perspective?</param>
private void OnChangePerspectives(bool firstPersonPerspective)
{
// Item Pullback does not work in first person mode.
Enabled = !firstPersonPerspective;
}
/// <summary>
/// The character has been destroyed.
/// </summary>
public override void OnDestroy()
{
base.OnDestroy();
EventHandler.UnregisterEvent<bool>(m_GameObject, "OnCameraWillChangePerspectives", OnChangePerspectives);
}
}
}