|
|
|
|
@@ -0,0 +1,832 @@
|
|
|
|
|
using System.Collections;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
using Cinemachine;
|
|
|
|
|
using FirstGearGames.SmoothCameraShaker;
|
|
|
|
|
|
|
|
|
|
public class CharacterCollisionManager : MonoBehaviour
|
|
|
|
|
{
|
|
|
|
|
public ShakeData punchKickShakeData;
|
|
|
|
|
public GameObject lefthandcollider;
|
|
|
|
|
public GameObject righthandcollider;
|
|
|
|
|
public GameObject leftfootcollider;
|
|
|
|
|
public GameObject rightfootcollider;
|
|
|
|
|
public GameManager gameManager;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public UltimateParentFinder finder;
|
|
|
|
|
public GroundCheck groundCheck;
|
|
|
|
|
Animator anim;
|
|
|
|
|
private CharacterVFXManager vfxScript;
|
|
|
|
|
private HealthNew healthScript;
|
|
|
|
|
private CharacterSoundFXManager soundScript;
|
|
|
|
|
|
|
|
|
|
public float nextAnimationTime;
|
|
|
|
|
public float animationInterval;
|
|
|
|
|
public bool jump = false;
|
|
|
|
|
|
|
|
|
|
public float slowdownFactor = 0.5f;
|
|
|
|
|
private SlowMotionManager slowMotionManager;
|
|
|
|
|
public DamageDisplay damageDisplay;
|
|
|
|
|
bool calculatingDamage;
|
|
|
|
|
private bool isColliding;
|
|
|
|
|
|
|
|
|
|
//private StaminaSystem staminaScript;
|
|
|
|
|
public PlayerScript playerScript;
|
|
|
|
|
|
|
|
|
|
MissionHandler mission_handler;
|
|
|
|
|
public CinemachineImpulseSource impulseSource;
|
|
|
|
|
|
|
|
|
|
void OnEnable(){
|
|
|
|
|
GameObject gamestatsmanager_go = GameObject.Find("GameStatsManager");
|
|
|
|
|
mission_handler = gamestatsmanager_go.GetComponent<MissionHandler>();
|
|
|
|
|
|
|
|
|
|
if (mission_handler != null){
|
|
|
|
|
//Debug.Log("Mission Handler Found");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// mission_handler.test();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Start is called before the first frame update
|
|
|
|
|
void Start()
|
|
|
|
|
{
|
|
|
|
|
damageDisplay = GetComponent<DamageDisplay>();
|
|
|
|
|
anim = GetComponent<Animator>();
|
|
|
|
|
groundCheck = GetComponent<GroundCheck>();
|
|
|
|
|
finder = GameObject.FindObjectOfType<UltimateParentFinder>();
|
|
|
|
|
vfxScript = GetComponent<CharacterVFXManager>();
|
|
|
|
|
gameManager = GameObject.FindObjectOfType<GameManager>();
|
|
|
|
|
healthScript = GetComponent<HealthNew>();
|
|
|
|
|
soundScript = GetComponent<CharacterSoundFXManager>();
|
|
|
|
|
slowMotionManager = FindObjectOfType<SlowMotionManager>();
|
|
|
|
|
calculatingDamage = false;
|
|
|
|
|
//playerScript = GetComponent<PlayerScript>();
|
|
|
|
|
//staminaScript = GetComponent<StaminaSystem>();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Checks if the given animation clip name is a valid attack animation.
|
|
|
|
|
/// This prevents damage from being dealt when characters simply walk into each other.
|
|
|
|
|
/// </summary>
|
|
|
|
|
private bool IsValidAttackAnimation(string clipName)
|
|
|
|
|
{
|
|
|
|
|
if (string.IsNullOrEmpty(clipName)) return false;
|
|
|
|
|
|
|
|
|
|
// Punch animations
|
|
|
|
|
return clipName == AnimationNames.Jab ||
|
|
|
|
|
clipName == AnimationNames.RightBody ||
|
|
|
|
|
clipName == AnimationNames.SupermanPunch ||
|
|
|
|
|
clipName == AnimationNames.SpecialBackfist ||
|
|
|
|
|
clipName == AnimationNames.Right ||
|
|
|
|
|
clipName == AnimationNames.LeftHook ||
|
|
|
|
|
clipName == AnimationNames.RightHook ||
|
|
|
|
|
clipName == AnimationNames.LeftElbow ||
|
|
|
|
|
clipName == AnimationNames.RightElbow ||
|
|
|
|
|
clipName == AnimationNames.PowerPunchLeft ||
|
|
|
|
|
clipName == AnimationNames.Haymaker ||
|
|
|
|
|
clipName == AnimationNames.SpinningBackfist ||
|
|
|
|
|
clipName == AnimationNames.ElbowSmash ||
|
|
|
|
|
clipName == AnimationNames.AirPunch ||
|
|
|
|
|
clipName == AnimationNames.SumoSlap ||
|
|
|
|
|
clipName == AnimationNames.ChargedPunch ||
|
|
|
|
|
// Kick animations
|
|
|
|
|
clipName == AnimationNames.FrontKickRight ||
|
|
|
|
|
clipName == AnimationNames.BodyKickRight ||
|
|
|
|
|
clipName == AnimationNames.LegPowerKickRight ||
|
|
|
|
|
clipName == AnimationNames.BackSideKick ||
|
|
|
|
|
clipName == AnimationNames.LegKickRight ||
|
|
|
|
|
clipName == AnimationNames.LowKick ||
|
|
|
|
|
clipName == AnimationNames.BasicKick ||
|
|
|
|
|
clipName == AnimationNames.DropKick ||
|
|
|
|
|
clipName == AnimationNames.AirKick ||
|
|
|
|
|
// Weapon animations
|
|
|
|
|
clipName == AnimationNames.BatOne ||
|
|
|
|
|
clipName == AnimationNames.BatTwo ||
|
|
|
|
|
clipName == AnimationNames.HammerOne ||
|
|
|
|
|
clipName == AnimationNames.HammerTwo;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//Updates the character's rotation to face the specified targetCharacter. Ensures the character stays upright.
|
|
|
|
|
void updateCharacterDirection(GameObject targetCharacter)
|
|
|
|
|
{
|
|
|
|
|
// follow player
|
|
|
|
|
Vector3 relativePos = targetCharacter.transform.position - transform.position;
|
|
|
|
|
Quaternion rotation;
|
|
|
|
|
float closeness = Vector3.Distance(targetCharacter.transform.position, transform.position);
|
|
|
|
|
// Calculate the angle between the character's forward vector and the relative position
|
|
|
|
|
|
|
|
|
|
// the second argument, upwards, defaults to Vector3.up
|
|
|
|
|
if (relativePos.y < 0.1)
|
|
|
|
|
{
|
|
|
|
|
rotation = Quaternion.LookRotation(relativePos, Vector3.left);
|
|
|
|
|
//print(rotation.z);
|
|
|
|
|
if(rotation.z < 2)
|
|
|
|
|
{
|
|
|
|
|
// Use Slerp for smoother rotation
|
|
|
|
|
transform.rotation = Quaternion.Slerp(transform.rotation, rotation, 10f * Time.deltaTime);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Ensure the character always stays upright
|
|
|
|
|
Vector3 currentEulerAngles = transform.rotation.eulerAngles;
|
|
|
|
|
float maxRotationAngle = 2f; // Adjust this value as needed
|
|
|
|
|
|
|
|
|
|
if (Mathf.Abs(currentEulerAngles.x) > maxRotationAngle || Mathf.Abs(currentEulerAngles.z) > maxRotationAngle)
|
|
|
|
|
{
|
|
|
|
|
Quaternion uprightRotation = Quaternion.Euler(0f, currentEulerAngles.y, 0f);
|
|
|
|
|
transform.rotation = Quaternion.Lerp(transform.rotation, uprightRotation, 50.0f * Time.deltaTime);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Activates the corresponding colliders for the character's hands and feet
|
|
|
|
|
#region
|
|
|
|
|
void lefthandcolliderOn()
|
|
|
|
|
{
|
|
|
|
|
lefthandcollider.SetActive(true);
|
|
|
|
|
}
|
|
|
|
|
void righthandcolliderOn()
|
|
|
|
|
{
|
|
|
|
|
righthandcollider.SetActive(true);
|
|
|
|
|
}
|
|
|
|
|
void leftfootcolliderOn()
|
|
|
|
|
{
|
|
|
|
|
leftfootcollider.SetActive(true);
|
|
|
|
|
}
|
|
|
|
|
void rightfootcolliderOn()
|
|
|
|
|
{
|
|
|
|
|
rightfootcollider.SetActive(true);
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Deactivates the corresponding colliders for the character's hands and feet.
|
|
|
|
|
#region
|
|
|
|
|
void lefthandcolliderOff()
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
lefthandcollider.SetActive(false);
|
|
|
|
|
}
|
|
|
|
|
void righthandcolliderOff()
|
|
|
|
|
{
|
|
|
|
|
righthandcollider.SetActive(false);
|
|
|
|
|
}
|
|
|
|
|
void leftfootcolliderOff()
|
|
|
|
|
{
|
|
|
|
|
leftfootcollider.SetActive(false);
|
|
|
|
|
}
|
|
|
|
|
void rightfootcolliderOff()
|
|
|
|
|
{
|
|
|
|
|
rightfootcollider.SetActive(false);
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Get the action_type (punch or kick) based on the collision
|
|
|
|
|
// Get the source of the action, from the player or the enemy
|
|
|
|
|
public void collision_occured(string action_type, string action_source){
|
|
|
|
|
|
|
|
|
|
//Check if the source of the action is from the player character
|
|
|
|
|
if (action_source == "Player"){
|
|
|
|
|
int enemyendHealth = GameObject.FindGameObjectWithTag("Enemy").GetComponent<HealthNew>().currentHealth;
|
|
|
|
|
mission_handler.PlayerHasHitEnemy(action_type, action_source, enemyendHealth);
|
|
|
|
|
//Debug.LogWarning("PlayerCharacter || Src = " + action_source);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//Not Player character
|
|
|
|
|
if (action_source != "Enemy"){
|
|
|
|
|
// int enemyendHealth = GameObject.FindGameObjectWithTag("Enemy").GetComponent<HealthNew>().currentHealth;
|
|
|
|
|
mission_handler.EnemyHasHitPlayer(action_type, action_source);
|
|
|
|
|
Debug.LogWarning("Not PlayerCharacter || Src = " + action_source);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Handles collision events when the character collides with other objects.
|
|
|
|
|
// Determines the type of collider that was triggered (left/right hand or left/right foot).
|
|
|
|
|
// Calculates damage, plays corresponding visual and audio effects, and triggers animations based on the collision.
|
|
|
|
|
// Checks the type of animation currently playing and adjusts the character's direction accordingly.
|
|
|
|
|
// Initiates slow-motion for specific animations and stops it after a short delay.
|
|
|
|
|
private void OnTriggerEnter(Collider other)
|
|
|
|
|
{
|
|
|
|
|
GameObject ultimateParent = finder.GetUltimateParent(other.gameObject);
|
|
|
|
|
//ultimateParent.tag = "Enemy" | "Player"
|
|
|
|
|
// Debug.LogError(ultimateParent.name + " Character XL");
|
|
|
|
|
|
|
|
|
|
if (ultimateParent == null)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
// FRIENDLY FIRE PREVENTION: Skip damage if attacker and target are on the same team
|
|
|
|
|
// In Cash System mode, all player team members have "Player" tag, enemies have "Enemy" tag
|
|
|
|
|
if (ultimateParent.tag == gameObject.tag)
|
|
|
|
|
{
|
|
|
|
|
// Same team - no friendly fire allowed
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(gameObject.CompareTag("Player"))
|
|
|
|
|
{
|
|
|
|
|
if (gameObject.GetComponent<PlayerScript>().block && IsInBodyReactionAnimation())
|
|
|
|
|
{
|
|
|
|
|
PlayBlockReactions(other.gameObject);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
else if (gameObject.GetComponent<PlayerScript>().dodge)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int remainingHealth = 1;
|
|
|
|
|
|
|
|
|
|
if (calculatingDamage == false)
|
|
|
|
|
{
|
|
|
|
|
healthScript.StartCoroutine(CheckAndDisplayDamage());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (other.gameObject.CompareTag("rightfootcollider"))
|
|
|
|
|
{
|
|
|
|
|
// CRITICAL FIX: Validate attacker is actually in an attack animation
|
|
|
|
|
AnimatorClipInfo[] attackerClipInfo = ultimateParent.GetComponent<Animator>().GetCurrentAnimatorClipInfo(0);
|
|
|
|
|
if (attackerClipInfo.Length == 0) return;
|
|
|
|
|
string attackerClip = attackerClipInfo[0].clip.name;
|
|
|
|
|
if (!IsValidAttackAnimation(attackerClip))
|
|
|
|
|
{
|
|
|
|
|
// Not attacking - ignore collision
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
collision_occured("kick", ultimateParent.tag);
|
|
|
|
|
// Debug.LogError("Right Foot Collider");
|
|
|
|
|
|
|
|
|
|
//staminaScript.UseStamina(1);
|
|
|
|
|
vfxScript.playKickEffect(other.gameObject);
|
|
|
|
|
soundScript.PlayKickSound();
|
|
|
|
|
|
|
|
|
|
Collider[] characterColliders = ultimateParent.GetComponentsInChildren<Collider>();
|
|
|
|
|
foreach (Collider characterCollider in characterColliders)
|
|
|
|
|
{
|
|
|
|
|
if (Physics.ComputePenetration(
|
|
|
|
|
characterCollider, characterCollider.transform.position,
|
|
|
|
|
characterCollider.transform.rotation,
|
|
|
|
|
other, other.transform.position, other.transform.rotation,
|
|
|
|
|
out Vector3 direction, out float distance))
|
|
|
|
|
{
|
|
|
|
|
if (!healthScript.isDead)
|
|
|
|
|
{
|
|
|
|
|
remainingHealth = healthScript.TakeDamage(healthScript.CalculateDamage(characterCollider, other), ultimateParent);
|
|
|
|
|
break; // Exit the loop since we found the colliding collider
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
AnimatorClipInfo[] m_CurrentClipInfo;
|
|
|
|
|
string clipname;
|
|
|
|
|
m_CurrentClipInfo = ultimateParent.GetComponent<Animator>().GetCurrentAnimatorClipInfo(0);
|
|
|
|
|
clipname = m_CurrentClipInfo[0].clip.name;
|
|
|
|
|
|
|
|
|
|
//Checks if the character's remaining health is less than or equal to 0. If true, it triggers a death animation and sets the next animation time.
|
|
|
|
|
if (remainingHealth <= 0)
|
|
|
|
|
{
|
|
|
|
|
updateCharacterDirection(ultimateParent);
|
|
|
|
|
anim.Play("BodyKickHitReaction");
|
|
|
|
|
nextAnimationTime = Time.time + animationInterval + 2;
|
|
|
|
|
vfxScript.playKickEffect(other.gameObject);
|
|
|
|
|
soundScript.PlayKickSound();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
string reaction = AnimationNames.GetReactionForAttack(clipname);
|
|
|
|
|
if (!string.IsNullOrEmpty(reaction) && groundCheck.isGrounded)
|
|
|
|
|
{
|
|
|
|
|
// Face the attacker before reacting
|
|
|
|
|
updateCharacterDirection(ultimateParent);
|
|
|
|
|
|
|
|
|
|
// Get or add AnimationManager
|
|
|
|
|
AnimationManager animManager = GetComponent<AnimationManager>();
|
|
|
|
|
if (animManager != null)
|
|
|
|
|
{
|
|
|
|
|
// Use specialized reaction method for better timing
|
|
|
|
|
animManager.PlayReactionAnimation(reaction);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Fallback to direct animation
|
|
|
|
|
anim.Play(reaction);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Visual and sound effects
|
|
|
|
|
vfxScript.playKickEffect(other.gameObject);
|
|
|
|
|
soundScript.PlayKickSound();
|
|
|
|
|
|
|
|
|
|
// Damage calculation
|
|
|
|
|
if (calculatingDamage == false)
|
|
|
|
|
{
|
|
|
|
|
healthScript.StartCoroutine(CheckAndDisplayDamage());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Special handling for certain moves
|
|
|
|
|
if (clipname == "BackSideKick")
|
|
|
|
|
{
|
|
|
|
|
slowMotionManager.StartSlowMotion(slowdownFactor);
|
|
|
|
|
StartCoroutine(EndSlowMotion());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (other.gameObject.CompareTag("leftfootcollider"))
|
|
|
|
|
{
|
|
|
|
|
// CRITICAL FIX: Validate attacker is actually in an attack animation
|
|
|
|
|
AnimatorClipInfo[] attackerClipInfo = ultimateParent.GetComponent<Animator>().GetCurrentAnimatorClipInfo(0);
|
|
|
|
|
if (attackerClipInfo.Length == 0) return;
|
|
|
|
|
string attackerClip = attackerClipInfo[0].clip.name;
|
|
|
|
|
if (!IsValidAttackAnimation(attackerClip))
|
|
|
|
|
{
|
|
|
|
|
// Not attacking - ignore collision
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
collision_occured("kick", ultimateParent.tag);
|
|
|
|
|
// Debug.LogError("Left Foot Collider");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//staminaScript.UseStamina(1);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Collider[] characterColliders = ultimateParent.GetComponentsInChildren<Collider>();
|
|
|
|
|
foreach (Collider characterCollider in characterColliders)
|
|
|
|
|
{
|
|
|
|
|
if (Physics.ComputePenetration(
|
|
|
|
|
characterCollider, characterCollider.transform.position,
|
|
|
|
|
characterCollider.transform.rotation,
|
|
|
|
|
other, other.transform.position, other.transform.rotation,
|
|
|
|
|
out Vector3 direction, out float distance))
|
|
|
|
|
{
|
|
|
|
|
if (!healthScript.isDead)
|
|
|
|
|
{
|
|
|
|
|
remainingHealth = healthScript.TakeDamage(healthScript.CalculateDamage(characterCollider, other), ultimateParent);
|
|
|
|
|
break; // Exit the loop since we found the colliding collider
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AnimatorClipInfo[] m_CurrentClipInfo;
|
|
|
|
|
string clipname;
|
|
|
|
|
m_CurrentClipInfo = ultimateParent.GetComponent<Animator>().GetCurrentAnimatorClipInfo(0);
|
|
|
|
|
|
|
|
|
|
clipname = m_CurrentClipInfo[0].clip.name;
|
|
|
|
|
if (remainingHealth <= 0)
|
|
|
|
|
{
|
|
|
|
|
updateCharacterDirection(ultimateParent);
|
|
|
|
|
anim.Play("HookHitReaction");
|
|
|
|
|
nextAnimationTime = Time.time + animationInterval + 2;
|
|
|
|
|
if (calculatingDamage == false)
|
|
|
|
|
{
|
|
|
|
|
healthScript.StartCoroutine(CheckAndDisplayDamage());
|
|
|
|
|
}
|
|
|
|
|
vfxScript.playKickEffect(other.gameObject);
|
|
|
|
|
soundScript.PlayKickSound();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
string reaction = AnimationNames.GetReactionForAttack(clipname);
|
|
|
|
|
if (!string.IsNullOrEmpty(reaction) && groundCheck.isGrounded)
|
|
|
|
|
{
|
|
|
|
|
// Face the attacker before reacting
|
|
|
|
|
updateCharacterDirection(ultimateParent);
|
|
|
|
|
|
|
|
|
|
// Get or add AnimationManager
|
|
|
|
|
AnimationManager animManager = GetComponent<AnimationManager>();
|
|
|
|
|
if (animManager != null)
|
|
|
|
|
{
|
|
|
|
|
// Use specialized reaction method for better timing
|
|
|
|
|
animManager.PlayReactionAnimation(reaction);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Fallback to direct animation
|
|
|
|
|
anim.Play(reaction);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Visual and sound effects
|
|
|
|
|
vfxScript.playKickEffect(other.gameObject);
|
|
|
|
|
soundScript.PlayKickSound();
|
|
|
|
|
|
|
|
|
|
// Damage calculation
|
|
|
|
|
if (calculatingDamage == false)
|
|
|
|
|
{
|
|
|
|
|
healthScript.StartCoroutine(CheckAndDisplayDamage());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else if (other.gameObject.CompareTag("righthandcollider"))
|
|
|
|
|
{
|
|
|
|
|
// CRITICAL FIX: Validate attacker is actually in an attack animation
|
|
|
|
|
AnimatorClipInfo[] attackerClipInfo = ultimateParent.GetComponent<Animator>().GetCurrentAnimatorClipInfo(0);
|
|
|
|
|
if (attackerClipInfo.Length == 0) return;
|
|
|
|
|
string attackerClip = attackerClipInfo[0].clip.name;
|
|
|
|
|
if (!IsValidAttackAnimation(attackerClip))
|
|
|
|
|
{
|
|
|
|
|
// Not attacking - ignore collision
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
collision_occured("punch", ultimateParent.tag);
|
|
|
|
|
// Debug.LogError("Right Hand Collider");
|
|
|
|
|
|
|
|
|
|
//staminaScript.UseStamina(1);
|
|
|
|
|
|
|
|
|
|
Collider[] characterColliders = ultimateParent.GetComponentsInChildren<Collider>();
|
|
|
|
|
foreach (Collider characterCollider in characterColliders)
|
|
|
|
|
{
|
|
|
|
|
if (Physics.ComputePenetration(
|
|
|
|
|
characterCollider, characterCollider.transform.position,
|
|
|
|
|
characterCollider.transform.rotation,
|
|
|
|
|
other, other.transform.position, other.transform.rotation,
|
|
|
|
|
out Vector3 direction, out float distance))
|
|
|
|
|
{
|
|
|
|
|
if (!healthScript.isDead)
|
|
|
|
|
{
|
|
|
|
|
remainingHealth = healthScript.TakeDamage(healthScript.CalculateDamage(characterCollider, other), ultimateParent);
|
|
|
|
|
break; // Exit the loop since we found the colliding collider
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AnimatorClipInfo[] m_CurrentClipInfo;
|
|
|
|
|
string clipname;
|
|
|
|
|
m_CurrentClipInfo = ultimateParent.GetComponent<Animator>().GetCurrentAnimatorClipInfo(0);
|
|
|
|
|
|
|
|
|
|
clipname = m_CurrentClipInfo[0].clip.name;
|
|
|
|
|
if (remainingHealth <= 0)
|
|
|
|
|
{
|
|
|
|
|
updateCharacterDirection(ultimateParent);
|
|
|
|
|
anim.Play("HookHitReaction");
|
|
|
|
|
nextAnimationTime = Time.time + animationInterval + 2;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
string reaction = AnimationNames.GetReactionForAttack(clipname);
|
|
|
|
|
if (!string.IsNullOrEmpty(reaction) && groundCheck.isGrounded)
|
|
|
|
|
{
|
|
|
|
|
// Face the attacker before reacting
|
|
|
|
|
updateCharacterDirection(ultimateParent);
|
|
|
|
|
|
|
|
|
|
// Get or add AnimationManager
|
|
|
|
|
AnimationManager animManager = GetComponent<AnimationManager>();
|
|
|
|
|
if (animManager != null)
|
|
|
|
|
{
|
|
|
|
|
// Use specialized reaction method for better timing
|
|
|
|
|
animManager.PlayReactionAnimation(reaction);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Fallback to direct animation
|
|
|
|
|
anim.Play(reaction);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Visual and sound effects
|
|
|
|
|
vfxScript.playPunchEffect(other.gameObject);
|
|
|
|
|
soundScript.PlayPunchFaceHitSound();
|
|
|
|
|
|
|
|
|
|
// Damage calculation
|
|
|
|
|
if (calculatingDamage == false)
|
|
|
|
|
{
|
|
|
|
|
healthScript.StartCoroutine(CheckAndDisplayDamage());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (other.gameObject.CompareTag("lefthandcollider"))
|
|
|
|
|
{
|
|
|
|
|
// CRITICAL FIX: Validate attacker is actually in an attack animation
|
|
|
|
|
AnimatorClipInfo[] attackerClipInfo = ultimateParent.GetComponent<Animator>().GetCurrentAnimatorClipInfo(0);
|
|
|
|
|
if (attackerClipInfo.Length == 0) return;
|
|
|
|
|
string attackerClip = attackerClipInfo[0].clip.name;
|
|
|
|
|
if (!IsValidAttackAnimation(attackerClip))
|
|
|
|
|
{
|
|
|
|
|
// Not attacking - ignore collision
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
collision_occured("punch", ultimateParent.tag);
|
|
|
|
|
// Debug.LogError("Left Hand Collider");
|
|
|
|
|
|
|
|
|
|
//staminaScript.UseStamina(1);
|
|
|
|
|
Collider[] characterColliders = ultimateParent.GetComponentsInChildren<Collider>();
|
|
|
|
|
foreach (Collider characterCollider in characterColliders)
|
|
|
|
|
{
|
|
|
|
|
if (Physics.ComputePenetration(
|
|
|
|
|
characterCollider, characterCollider.transform.position,
|
|
|
|
|
characterCollider.transform.rotation,
|
|
|
|
|
other, other.transform.position, other.transform.rotation,
|
|
|
|
|
out Vector3 direction, out float distance))
|
|
|
|
|
{
|
|
|
|
|
if (!healthScript.isDead)
|
|
|
|
|
{
|
|
|
|
|
remainingHealth = healthScript.TakeDamage(healthScript.CalculateDamage(characterCollider, other), ultimateParent);
|
|
|
|
|
break; // Exit the loop since we found the colliding collider
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
AnimatorClipInfo[] m_CurrentClipInfo;
|
|
|
|
|
string clipname;
|
|
|
|
|
m_CurrentClipInfo = ultimateParent.GetComponent<Animator>().GetCurrentAnimatorClipInfo(0);
|
|
|
|
|
|
|
|
|
|
clipname = m_CurrentClipInfo[0].clip.name;
|
|
|
|
|
if (remainingHealth <= 0)
|
|
|
|
|
{
|
|
|
|
|
updateCharacterDirection(ultimateParent);
|
|
|
|
|
anim.Play("HookHitReaction");
|
|
|
|
|
nextAnimationTime = Time.time + animationInterval + 2;
|
|
|
|
|
vfxScript.playPunchEffect(other.gameObject);
|
|
|
|
|
soundScript.PlayPunchLightHitSound();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
string reaction = AnimationNames.GetReactionForAttack(clipname);
|
|
|
|
|
if (!string.IsNullOrEmpty(reaction) && groundCheck.isGrounded)
|
|
|
|
|
{
|
|
|
|
|
// Face the attacker before reacting
|
|
|
|
|
updateCharacterDirection(ultimateParent);
|
|
|
|
|
|
|
|
|
|
// Get or add AnimationManager
|
|
|
|
|
AnimationManager animManager = GetComponent<AnimationManager>();
|
|
|
|
|
if (animManager != null)
|
|
|
|
|
{
|
|
|
|
|
// Use specialized reaction method for better timing
|
|
|
|
|
animManager.PlayReactionAnimation(reaction);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Fallback to direct animation
|
|
|
|
|
anim.Play(reaction);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Visual and sound effects
|
|
|
|
|
vfxScript.playPunchEffect(other.gameObject);
|
|
|
|
|
soundScript.PlayPunchFaceHitSound();
|
|
|
|
|
|
|
|
|
|
// Damage calculation
|
|
|
|
|
if (calculatingDamage == false)
|
|
|
|
|
{
|
|
|
|
|
healthScript.StartCoroutine(CheckAndDisplayDamage());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (other.gameObject.CompareTag("headcollider"))
|
|
|
|
|
{
|
|
|
|
|
// CRITICAL FIX: Validate attacker is actually in an attack animation
|
|
|
|
|
AnimatorClipInfo[] attackerClipInfo = ultimateParent.GetComponent<Animator>().GetCurrentAnimatorClipInfo(0);
|
|
|
|
|
if (attackerClipInfo.Length == 0) return;
|
|
|
|
|
string attackerClip = attackerClipInfo[0].clip.name;
|
|
|
|
|
if (!IsValidAttackAnimation(attackerClip))
|
|
|
|
|
{
|
|
|
|
|
// Not attacking - ignore collision
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//staminaScript.UseStamina(1);
|
|
|
|
|
Collider[] characterColliders = ultimateParent.GetComponentsInChildren<Collider>();
|
|
|
|
|
foreach (Collider characterCollider in characterColliders)
|
|
|
|
|
{
|
|
|
|
|
if (Physics.ComputePenetration(
|
|
|
|
|
characterCollider, characterCollider.transform.position,
|
|
|
|
|
characterCollider.transform.rotation,
|
|
|
|
|
other, other.transform.position, other.transform.rotation,
|
|
|
|
|
out Vector3 direction, out float distance))
|
|
|
|
|
{
|
|
|
|
|
if (!healthScript.isDead)
|
|
|
|
|
{
|
|
|
|
|
remainingHealth = healthScript.TakeDamage(healthScript.CalculateDamage(characterCollider, other), ultimateParent);
|
|
|
|
|
break; // Exit the loop since we found the colliding collider
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AnimatorClipInfo[] m_CurrentClipInfo;
|
|
|
|
|
string clipname = null;
|
|
|
|
|
m_CurrentClipInfo = ultimateParent.GetComponent<Animator>().GetCurrentAnimatorClipInfo(0);
|
|
|
|
|
clipname = m_CurrentClipInfo[0].clip.name;
|
|
|
|
|
|
|
|
|
|
if (remainingHealth <= 0)
|
|
|
|
|
{
|
|
|
|
|
updateCharacterDirection(ultimateParent);
|
|
|
|
|
anim.Play("HookHitReaction");
|
|
|
|
|
nextAnimationTime = Time.time + animationInterval + 2;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
string reaction = AnimationNames.GetReactionForAttack(clipname);
|
|
|
|
|
if (!string.IsNullOrEmpty(reaction) && groundCheck.isGrounded)
|
|
|
|
|
{
|
|
|
|
|
// Face the attacker before reacting
|
|
|
|
|
updateCharacterDirection(ultimateParent);
|
|
|
|
|
|
|
|
|
|
// Get or add AnimationManager
|
|
|
|
|
AnimationManager animManager = GetComponent<AnimationManager>();
|
|
|
|
|
if (animManager != null)
|
|
|
|
|
{
|
|
|
|
|
// Use specialized reaction method for better timing
|
|
|
|
|
animManager.PlayReactionAnimation(reaction);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Fallback to direct animation
|
|
|
|
|
anim.Play(reaction);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Visual and sound effects
|
|
|
|
|
vfxScript.playPunchEffect(other.gameObject);
|
|
|
|
|
soundScript.PlayPunchFaceHitSound();
|
|
|
|
|
|
|
|
|
|
// Damage calculation
|
|
|
|
|
if (calculatingDamage == false)
|
|
|
|
|
{
|
|
|
|
|
healthScript.StartCoroutine(CheckAndDisplayDamage());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (other.gameObject.CompareTag("weaponcollider"))
|
|
|
|
|
{
|
|
|
|
|
// Treat weapon as a punch-type hit for missions and effects
|
|
|
|
|
collision_occured("punch", ultimateParent.tag);
|
|
|
|
|
|
|
|
|
|
// Optional VFX/SFX: reuse punch visuals
|
|
|
|
|
vfxScript.playPunchEffect(other.gameObject);
|
|
|
|
|
soundScript.PlayPunchFaceHitSound();
|
|
|
|
|
|
|
|
|
|
// Only allow damage during weapon swing animations to avoid idle bumps
|
|
|
|
|
string clipname = null;
|
|
|
|
|
AnimatorClipInfo[] m_CurrentClipInfo = ultimateParent.GetComponent<Animator>().GetCurrentAnimatorClipInfo(0);
|
|
|
|
|
if (m_CurrentClipInfo.Length > 0)
|
|
|
|
|
clipname = m_CurrentClipInfo[0].clip.name;
|
|
|
|
|
|
|
|
|
|
bool isWeaponSwing = clipname == AnimationNames.BatOne ||
|
|
|
|
|
clipname == AnimationNames.BatTwo ||
|
|
|
|
|
clipname == AnimationNames.HammerOne ||
|
|
|
|
|
clipname == AnimationNames.HammerTwo;
|
|
|
|
|
if (!isWeaponSwing)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
// Compute contact and apply damage
|
|
|
|
|
Collider[] characterColliders = ultimateParent.GetComponentsInChildren<Collider>();
|
|
|
|
|
foreach (Collider characterCollider in characterColliders)
|
|
|
|
|
{
|
|
|
|
|
if (Physics.ComputePenetration(
|
|
|
|
|
characterCollider, characterCollider.transform.position,
|
|
|
|
|
characterCollider.transform.rotation,
|
|
|
|
|
other, other.transform.position, other.transform.rotation,
|
|
|
|
|
out Vector3 direction, out float distance))
|
|
|
|
|
{
|
|
|
|
|
if (!healthScript.isDead)
|
|
|
|
|
{
|
|
|
|
|
remainingHealth = healthScript.TakeDamage(healthScript.CalculateDamage(characterCollider, other), ultimateParent);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (remainingHealth <= 0)
|
|
|
|
|
{
|
|
|
|
|
updateCharacterDirection(ultimateParent);
|
|
|
|
|
anim.Play("HookHitReaction");
|
|
|
|
|
nextAnimationTime = Time.time + animationInterval + 2;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
string reaction = AnimationNames.GetReactionForAttack(clipname);
|
|
|
|
|
if (!string.IsNullOrEmpty(reaction) && groundCheck.isGrounded)
|
|
|
|
|
{
|
|
|
|
|
updateCharacterDirection(ultimateParent);
|
|
|
|
|
|
|
|
|
|
AnimationManager animManager = GetComponent<AnimationManager>();
|
|
|
|
|
if (animManager != null)
|
|
|
|
|
animManager.PlayReactionAnimation(reaction);
|
|
|
|
|
else
|
|
|
|
|
anim.Play(reaction);
|
|
|
|
|
|
|
|
|
|
if (calculatingDamage == false)
|
|
|
|
|
{
|
|
|
|
|
healthScript.StartCoroutine(CheckAndDisplayDamage());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Shake camera for impacts
|
|
|
|
|
CameraShakerHandler.Shake(punchKickShakeData);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void PlayBlockReactions(GameObject fxLocation)
|
|
|
|
|
{
|
|
|
|
|
vfxScript.playBlockEffect(fxLocation);
|
|
|
|
|
soundScript.PlayBlockSound();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Ends the slow-motion effect after a specified delay.
|
|
|
|
|
private IEnumerator EndSlowMotion()
|
|
|
|
|
{
|
|
|
|
|
yield return new WaitForSeconds(1); // Adjust as needed
|
|
|
|
|
slowMotionManager.StopSlowMotion();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Coroutine to continuously check for changes in the character's health.
|
|
|
|
|
// Compares the current health with the previous health after a delay.
|
|
|
|
|
public IEnumerator CheckAndDisplayDamage()
|
|
|
|
|
{
|
|
|
|
|
calculatingDamage = true;
|
|
|
|
|
while (true)
|
|
|
|
|
{
|
|
|
|
|
// Store the current damage
|
|
|
|
|
healthScript.previousHealth = healthScript.currentHealth;
|
|
|
|
|
|
|
|
|
|
// Wait for 1 second
|
|
|
|
|
yield return new WaitForSeconds(1.0f);
|
|
|
|
|
|
|
|
|
|
// Compare the damage after 1 second
|
|
|
|
|
int damageDifference = healthScript.previousHealth - healthScript.currentHealth;
|
|
|
|
|
//print(damageDifference);
|
|
|
|
|
|
|
|
|
|
// Check if the damage difference exceeds the threshold
|
|
|
|
|
if (damageDifference >= healthScript.damageDisplayThreshold && healthScript.currentHealth > 2)
|
|
|
|
|
{
|
|
|
|
|
// Display the damage text using the DamageDisplay script
|
|
|
|
|
StartCoroutine(damageDisplay.ShowFloatDamageText(damageDifference));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
StopCoroutine(damageDisplay.ShowFloatDamageText(damageDifference));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
calculatingDamage = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private bool IsInBodyReactionAnimation()
|
|
|
|
|
{
|
|
|
|
|
AnimatorClipInfo[] m_CurrentClipInfo;
|
|
|
|
|
m_CurrentClipInfo = gameObject.GetComponent<Animator>().GetCurrentAnimatorClipInfo(0);
|
|
|
|
|
string m_ClipName;
|
|
|
|
|
|
|
|
|
|
if (m_CurrentClipInfo.Length == 0)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
m_ClipName = m_CurrentClipInfo[0].clip.name;
|
|
|
|
|
|
|
|
|
|
// Focus on reactions for our active animations only
|
|
|
|
|
return m_ClipName == AnimationNames.BlockBodyLeft ||
|
|
|
|
|
m_ClipName == AnimationNames.BlockStepBack ||
|
|
|
|
|
m_ClipName == AnimationNames.BlockLeg ||
|
|
|
|
|
|
|
|
|
|
// Active animation reactions
|
|
|
|
|
m_ClipName == AnimationNames.JabReaction ||
|
|
|
|
|
m_ClipName == AnimationNames.HaymakerReaction ||
|
|
|
|
|
m_ClipName == AnimationNames.SpinningBackfistReaction ||
|
|
|
|
|
m_ClipName == AnimationNames.ElbowSmashReaction ||
|
|
|
|
|
m_ClipName == AnimationNames.ChargedPunchReaction ||
|
|
|
|
|
m_ClipName == AnimationNames.AirPunchReaction ||
|
|
|
|
|
m_ClipName == AnimationNames.DropKickReaction ||
|
|
|
|
|
m_ClipName == AnimationNames.LowKickReaction;
|
|
|
|
|
|
|
|
|
|
/* Commented out other reactions for future use
|
|
|
|
|
m_ClipName == AnimationNames.ChopReaction ||
|
|
|
|
|
m_ClipName == AnimationNames.GroundPoundReaction ||
|
|
|
|
|
m_ClipName == AnimationNames.AirKickReaction ||
|
|
|
|
|
m_ClipName == AnimationNames.RightHookHitReaction ||
|
|
|
|
|
m_ClipName == AnimationNames.BodyKickHitReaction ||
|
|
|
|
|
m_ClipName == AnimationNames.HookHitReaction ||
|
|
|
|
|
m_ClipName == AnimationNames.JabHitReaction ||
|
|
|
|
|
m_ClipName == AnimationNames.LegKickHitReaction ||
|
|
|
|
|
m_ClipName == AnimationNames.UppercutPowerHitReaction ||
|
|
|
|
|
m_ClipName == AnimationNames.OverhandHitReaction;
|
|
|
|
|
*/
|
|
|
|
|
}
|
|
|
|
|
}
|