Batch 1 - Scripts

This commit is contained in:
Rohan
2026-07-21 08:58:18 +05:30
parent 604c0c786a
commit 1dcd8bf80b
41 changed files with 655 additions and 13 deletions

View File

@@ -0,0 +1,47 @@
using System.Collections;
using UnityEngine;
public class CharacterCombat : MonoBehaviour, IDamageReceiver
{
private Animator animator;
void Awake()
{
animator = GetComponentInChildren<Animator>();
}
public void OnDamageTaken(string bodyPart)
{
switch (bodyPart)
{
case "Head":
animator.SetTrigger("HitHead");
break;
case "Body":
animator.SetTrigger("HitBody");
break;
case "Legs":
StartCoroutine(KnockdownRoutine());
break;
}
}
IEnumerator KnockdownRoutine()
{
// Step 1: play leg hit
animator.SetTrigger("HitLegs");
// wait for hit animation
yield return new WaitForSeconds(0.6f);
// Step 2: fall happens automatically via Exit Time
// stay on ground
yield return new WaitForSeconds(2f);
// Step 3: stand up
animator.SetTrigger("StandUp");
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: d38a973115a2f284d8e799d031d8779b

View File

@@ -0,0 +1,213 @@
using Cinemachine;
using System;
using System.Collections;
using UnityEngine;
using UnityEngine.AI;
public class Health : MonoBehaviour
{
public float currentHealth;
public float maxHealth = 100f;
// Event used by UI or other systems to react to health changes
public event Action<float, float> OnHealthChanged;
private CharacterController controller;
public bool isHit;
public bool isDead;
[SerializeField] private float knockbackForce = 4f;
[SerializeField] private float knockbackDuration = 0.2f;
private Vector3 knockbackVelocity;
private float knockbackTimer;
private NavMeshAgent agent;
//[SerializeField] private float knockbackForce = 6f;
//[SerializeField] private float knockbackDuration = 0.2f;
//private Vector3 knockbackVelocity;
//private float knockbackTimer;
void Awake()
{
controller = GetComponent<CharacterController>();
agent = GetComponent<NavMeshAgent>();
}
void Start()
{
currentHealth = maxHealth;
OnHealthChanged?.Invoke(currentHealth, maxHealth);
}
void Update()
{
if (isDead) return;
if (knockbackTimer > 0)
{
knockbackTimer -= Time.deltaTime;
// ONLY move via CharacterController if it is still enabled
if (controller != null && controller.enabled)
{
controller.Move(knockbackVelocity * Time.deltaTime);
}
// TEMP stop agent movement only if agent is enabled and active
if (agent != null && agent.enabled && agent.isOnNavMesh)
{
agent.isStopped = true;
}
}
else
{
// Resume AI movement only if agent is enabled and active
if (agent != null && agent.enabled && agent.isOnNavMesh)
{
agent.isStopped = false;
}
}
}
public void TakeDamage(float amount, string bodyPart)
{
if (isDead) return;
currentHealth = Mathf.Clamp(currentHealth - amount, 0, maxHealth);
OnHealthChanged?.Invoke(currentHealth, maxHealth);
// PLAY ENEMY GRUNT SOUND
if (AudioManager.Instance != null)
{
AudioManager.Instance.PlayEnemyHit();
}
PlayerControllerNewRohan player = GetComponent<PlayerControllerNewRohan>();
if (player != null)
{
player.CancelAttack();
}
//SimpleEnemyAI enemy = GetComponent<SimpleEnemyAI>();
//if (enemy != null)
//{
// enemy.CancelAttackAndHit(bodyPart);
//}
var receiver = GetComponent<IDamageReceiver>();
receiver?.OnDamageTaken(bodyPart);
// DEATH CHECK
if (currentHealth <= 0)
{
Die();
}
}
void Die()
{
if (isDead) return;
isDead = true;
DisableAfterDeath();
CashManager cashManager = GetComponent<CashManager>();
if (cashManager != null)
{
cashManager.DropAllCash();
}
Animator anim = GetComponent<Animator>();
if (anim != null)
{
anim.SetTrigger("Death");
}
// STOP NAVMESH
// STOP NAVMESH
if (agent != null && agent.enabled)
{
if (agent.isOnNavMesh)
{
agent.isStopped = true;
agent.ResetPath();
agent.velocity = Vector3.zero;
}
agent.enabled = false;
}
// DISABLE PLAYER CONTROLLER
PlayerControllerNewRohan player = GetComponent<PlayerControllerNewRohan>();
if (player != null)
{
player.enabled = false;
}
// DISABLE ENEMY AI
//SimpleEnemyAI enemy = GetComponent<SimpleEnemyAI>();
//if (enemy != null)
//{
// enemy.enabled = false;
//}
// OPTIONAL
CharacterController cc = GetComponent<CharacterController>();
if (cc != null)
{
cc.enabled = false;
}
// Destroy after animation
Destroy(gameObject, 2f);
}
public void ApplyKnockback(Vector3 direction, float forceMultiplier = 1f)
{
if (knockbackTimer > 0) return; // prevent stacking
direction.Normalize();
// Add slight upward push (optional but feels better)
Vector3 finalDir = direction;
knockbackVelocity = finalDir * knockbackForce * forceMultiplier;
knockbackTimer = knockbackDuration;
}
void DisableAfterDeath()
{
gameObject.tag = "Untagged";
Collider[] colliders = GetComponentsInChildren<Collider>();
foreach (Collider col in colliders)
{
col.enabled = false;
}
SimpleTeamAI ai = GetComponent<SimpleTeamAI>();
if (ai != null)
ai.enabled = false;
MonoBehaviour[] scripts = GetComponentsInChildren<MonoBehaviour>();
foreach (MonoBehaviour script in scripts)
{
if (script != this && script.GetType() != typeof(Animator))
script.enabled = false;
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 2899f8d69deca1647aa65e10360c8629

View File

@@ -0,0 +1,592 @@
using Cinemachine;
using System.Collections;
using TMPro;
using UnityEngine;
using UnityEngine.InputSystem;
[RequireComponent(typeof(CharacterController))]
public class PlayerControllerNewRohan : MonoBehaviour
{
[Header("Movement")]
[SerializeField] private float walkSpeed = 3f;
[SerializeField] private float runSpeed = 6f;
[SerializeField] private float rotationSpeed = 10f;
private Stamina stamina;
[Header("References")]
private CharacterController controller;
private Animator animator;
[Header("State")]
private bool isAttacking;
private bool canMove = true;
[Header("Gravity")]
[SerializeField] private float gravity = -9.81f;
[SerializeField] private float groundCheckDistance = 0.2f;
[Header("Combat")]
public float attackRange = 3f; // adjust in inspector
private float verticalVelocity;
// Input
private Vector2 moveInput;
private bool sprintInput;
private float currentSpeed;
public Joystick joystick;
public GameObject rightHandPunchHitbox;
public GameObject leftHandPunchHitbox;
public GameObject rightFootKickHitbox;
public GameObject leftFootKickHitbox;
public TrailRenderer rightHandTrail;
public TrailRenderer leftHandTrail;
public TrailRenderer rightFootTrail;
public TrailRenderer leftFootTrail;
public Transform target; // assign enemy in inspector
[Header("Camera FOV")]
[SerializeField] private CinemachineFreeLook freeLookCam;
[SerializeField] private float normalFOV = 60f;
[SerializeField] private float sprintFOV = 75f;
[SerializeField] private float fovSpeed = 5f;
[SerializeField] private float walkStepInterval = 0.5f;
[SerializeField] private float runStepInterval = 0.3f;
private float footstepTimer;
private Coroutine attackRoutine;
private bool isDepositing;
private Coroutine depositRoutine;
private bool isOpeningVault;
[Header("Deposit Effect")]
[SerializeField] private ParticleSystem depositAura;
void Awake()
{
controller = GetComponent<CharacterController>();
animator = GetComponent<Animator>();
stamina = GetComponent<Stamina>();
//StopDepositEffect();
}
private void Start()
{
//Cursor.lockState = CursorLockMode.Locked;
//Cursor.visible = false;
}
void Update()
{
HandleMovement();
}
// ---------------- MOVEMENT ----------------
void HandleMovement()
{
if (!canMove || isAttacking) return;
// -------- CAMERA RELATIVE MOVE --------
Vector3 camForward = Camera.main.transform.forward;
Vector3 camRight = Camera.main.transform.right;
camForward.y = 0;
camRight.y = 0;
camForward.Normalize();
camRight.Normalize();
Vector3 move = camForward * moveInput.y + camRight * moveInput.x;
bool isMoving = move.magnitude > 0.1f;
if (isMoving)
SetTrails(true);
else if (!isAttacking)
SetTrails(false);
// Sprint only if moving
bool isRunning = sprintInput && isMoving && stamina.currentStamina > 0f;
if (isRunning)
{
stamina.UseStamina(20f * Time.deltaTime);
}
else if (!isAttacking && !sprintInput) // key fix
{
stamina.RecoverStamina(10f * Time.deltaTime);
}
HandleFootsteps(isMoving, isRunning);
if (freeLookCam != null)
{
float targetFOV = isRunning ? sprintFOV : normalFOV;
// Apply to all rigs (top, middle, bottom)
freeLookCam.m_Lens.FieldOfView = Mathf.Lerp(
freeLookCam.m_Lens.FieldOfView,
targetFOV,
Time.deltaTime * fovSpeed
);
}
currentSpeed = isRunning ? runSpeed : walkSpeed;
// -------- GRAVITY --------
if (controller.isGrounded && verticalVelocity < 0)
{
verticalVelocity = -2f; // keeps player grounded
}
verticalVelocity += gravity * Time.deltaTime;
// -------- FINAL MOVE --------
Vector3 finalMove = move * currentSpeed;
finalMove.y = verticalVelocity;
controller.Move(finalMove * Time.deltaTime);
// -------- ROTATION --------
if (isMoving)
{
Quaternion targetRotation = Quaternion.LookRotation(move);
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, rotationSpeed * Time.deltaTime);
}
// -------- ANIMATION --------
float targetSpeed = move.magnitude * (isRunning ? 2f : 1f);
animator.SetFloat("Speed", targetSpeed, 0.1f, Time.deltaTime);
}
// ---------------- INPUT CALLBACKS ----------------
public void OnMove(InputAction.CallbackContext context)
{
moveInput = context.ReadValue<Vector2>();
}
public void OnSprint(InputAction.CallbackContext context)
{
sprintInput = context.ReadValueAsButton();
}
// ---------------- ATTACKS ----------------
public void OnAttack1(InputAction.CallbackContext ctx)
{
if (ctx.performed)
{
attackRoutine = StartCoroutine(PlayAttack("Haymaker", 1f));
}
}
public void OnAttack2(InputAction.CallbackContext ctx)
{
if (ctx.performed)
{
if (ctx.performed) StartCoroutine(PlayAttack("LeftKick", 1.5f));
}
}
public void OnAttack3(InputAction.CallbackContext ctx)
{
if (ctx.performed)
{
if (ctx.performed) StartCoroutine(PlayAttack("LowKick", 1.5f));
}
}
public void OnAttack4(InputAction.CallbackContext ctx)
{
if (ctx.performed)
{
if (ctx.performed) StartCoroutine(PlayAttack("ElbowSmash", 0.6f));
}
}
public void OnAttack5(InputAction.CallbackContext ctx)
{
if (ctx.performed)
{
if (ctx.performed) StartCoroutine(PlayAttack("SpinningBackFist", 1f));
}
}
public void OnAttack6(InputAction.CallbackContext ctx)
{
if (ctx.performed)
{
if (ctx.performed) StartCoroutine(PlayAttack("BicycleKick", 1f));
}
}
public void PunchTap()
{
StartCoroutine(PlayAttack("Haymaker", 1f));
}
public void PunchHold()
{
StartCoroutine(PlayAttack("ElbowSmash", 0.6f));
}
public void KickTap()
{
StartCoroutine(PlayAttack("LeftKick", 1.5f));
}
public void KickHold()
{
StartCoroutine(PlayAttack("LowKick", 1.5f));
}
public void SpecialTap()
{
StartCoroutine(PlayAttack("SpinningBackFist", 1f));
}
public void SpecialHold()
{
StartCoroutine(PlayAttack("BicycleKick", 1f));
}
IEnumerator PlayAttack(string trigger, float distance)
{
CancelVaultOpening();
if (isAttacking) yield break;
if (!stamina.UseStamina(15f)) yield break;
isAttacking = true;
canMove = false;
FindClosestEnemy();
FaceTarget();
SetTrails(true);
if (IsTargetInRange())
{
SetAttackDistance(distance);
}
animator.SetTrigger(trigger);
yield return new WaitForSeconds(1f);
SetTrails(false);
canMove = true;
isAttacking = false;
}
public void CancelAttack()
{
if (!isAttacking) return;
if (attackRoutine != null)
{
StopCoroutine(attackRoutine);
attackRoutine = null;
}
isAttacking = false;
canMove = true;
SetTrails(false);
// reset attack triggers
animator.ResetTrigger("Haymaker");
animator.ResetTrigger("LeftKick");
animator.ResetTrigger("LowKick");
animator.ResetTrigger("ElbowSmash");
animator.ResetTrigger("SpinningBackFist");
animator.ResetTrigger("BicycleKick");
// NO animator.SetTrigger("Hit") here
}
public void PlayWhoosh()
{
AudioManager.Instance.PlaySFX("PunchWhoosh");
}
bool IsTargetInRange()
{
if (target == null) return false;
float dist = Vector3.Distance(transform.position, target.position);
return dist <= attackRange;
}
void SetAttackDistance(float distance)
{
if (target == null) return;
// direction from enemy player
Vector3 dir = (transform.position - target.position).normalized;
dir.y = 0;
// place player at fixed distance
Vector3 newPos = target.position + dir * distance;
transform.position = newPos;
}
public void StartDeposit(float depositTime)
{
if (isDepositing)
return;
StartDepositEffect();
depositRoutine = StartCoroutine(DepositRoutine(depositTime));
}
IEnumerator DepositRoutine(float depositTime)
{
isDepositing = true;
float timer = depositTime;
while (timer > 0)
{
UI_Manager.Instance?.UpdateDepositTimer(timer);
timer -= Time.deltaTime;
yield return null;
}
UI_Manager.Instance?.HideDepositTimer();
CashManager cash = GetComponent<CashManager>();
if (cash != null)
{
int depositedAmount = cash.DepositAllCash();
TeamMember teamMember = GetComponent<TeamMember>();
DepositStationManager.Instance.AddCash(
depositedAmount,
teamMember.CurrentTeam
);
}
StopDepositEffect();
canMove = true;
isDepositing = false;
}
public void CancelDeposit()
{
if (!isDepositing)
return;
if (depositRoutine != null)
{
StopCoroutine(depositRoutine);
depositRoutine = null;
}
UI_Manager.Instance?.HideDepositTimer();
StopDepositEffect();
isDepositing = false;
}
void FaceTarget()
{
if (target == null)
return;
Vector3 dir = target.position - transform.position;
dir.y = 0;
if (dir.sqrMagnitude > 0.01f)
{
transform.rotation = Quaternion.LookRotation(dir);
}
}
private void FindClosestEnemy()
{
TeamMember myTeam = GetComponent<TeamMember>();
float closestDistance = Mathf.Infinity;
Transform closestEnemy = null;
TeamMember[] allCharacters = FindObjectsOfType<TeamMember>();
foreach (TeamMember character in allCharacters)
{
if (character == myTeam)
continue;
if (character.CurrentTeam == myTeam.CurrentTeam)
continue;
float distance = Vector3.Distance(transform.position, character.transform.position);
if (distance < closestDistance)
{
closestDistance = distance;
closestEnemy = character.transform;
}
}
target = closestEnemy;
}
public void PlayVaultOpen(System.Action onComplete)
{
StartCoroutine(VaultRoutine(onComplete));
}
IEnumerator VaultRoutine(System.Action onComplete)
{
canMove = false;
isOpeningVault = true;
animator.SetTrigger("OpenVault");
float timer = 6f;
while (timer > 0)
{
if (!isOpeningVault)
{
UI_Manager.Instance?.HideActionTimer();
canMove = true;
yield break;
}
UI_Manager.Instance?.UpdateActionTimer(
"Opening Vault",
timer);
timer -= Time.deltaTime;
yield return null;
}
UI_Manager.Instance?.HideActionTimer();
canMove = true;
isOpeningVault = false;
onComplete?.Invoke();
}
public void CancelVaultOpening()
{
if (!isOpeningVault)
return;
isOpeningVault = false;
animator.ResetTrigger("OpenVault");
canMove = true;
UI_Manager.Instance?.HideActionTimer();
}
public void PlayPickupAnimation()
{
if (animator != null)
{
animator.SetTrigger("Pickup");
}
}
void SetTrails(bool state)
{
rightHandTrail.emitting = state;
leftHandTrail.emitting = state;
rightFootTrail.emitting = state;
leftFootTrail.emitting = state;
}
public void StartDepositEffect()
{
if (depositAura != null)
depositAura.Play();
}
public void StopDepositEffect()
{
if (depositAura != null)
depositAura.Stop();
}
// Disable player movement (call at animation start)
public void DisableMovement()
{
canMove = false;
}
// Enable player movement (call at animation end)
public void EnableMovement()
{
canMove = true;
}
void HandleFootsteps(bool isMoving, bool isRunning)
{
if (!controller.isGrounded)
{
footstepTimer = 0f;
return;
}
if (!isMoving)
{
footstepTimer = 0f;
return;
}
float interval = isRunning ? runStepInterval : walkStepInterval;
footstepTimer += Time.deltaTime;
if (footstepTimer >= interval)
{
footstepTimer = 0f;
AudioManager.Instance.PlayFootstep(isRunning);
}
}
public void EnableRightHandPunchHitbox() => rightHandPunchHitbox.SetActive(true);
public void DisableRightHandPunchHitbox() => rightHandPunchHitbox.SetActive(false);
public void EnableLeftHandPunchHitbox() => leftHandPunchHitbox.SetActive(true);
public void DisableLeftHandPunchHitbox() => leftHandPunchHitbox.SetActive(false);
public void EnableLeftFootKickHitbox() => leftFootKickHitbox.SetActive(true);
public void DisableLeftFootKickHitbox() => leftFootKickHitbox.SetActive(false);
public void EnableRightFootKickHitbox() => rightFootKickHitbox.SetActive(true);
public void DisableRightFootKickHitbox() => rightFootKickHitbox.SetActive(false);
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 4a194c2231515bb40abb28d049fdea9d

View File

@@ -0,0 +1,37 @@
using System;
using UnityEngine;
public class Stamina : MonoBehaviour
{
public float currentStamina;
public float maxStamina = 100f;
public event Action<float, float> OnStaminaChanged;
void Start()
{
currentStamina = maxStamina;
OnStaminaChanged?.Invoke(currentStamina, maxStamina);
}
public bool UseStamina(float amount)
{
if (currentStamina <= 0f)
return false;
currentStamina -= amount;
if (currentStamina < 0f)
currentStamina = 0f;
OnStaminaChanged?.Invoke(currentStamina, maxStamina);
return currentStamina > 0f;
}
public void RecoverStamina(float amount)
{
currentStamina = Mathf.Clamp(currentStamina + amount, 0, maxStamina);
OnStaminaChanged?.Invoke(currentStamina, maxStamina);
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 89358a0a4e498554d936f78fcdd4de7f