Batch 1 - Scripts
This commit is contained in:
47
Assets/New Lowpoly Models/Scripts/Player/CombatAnimations.cs
Normal file
47
Assets/New Lowpoly Models/Scripts/Player/CombatAnimations.cs
Normal 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");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d38a973115a2f284d8e799d031d8779b
|
||||
213
Assets/New Lowpoly Models/Scripts/Player/Health.cs
Normal file
213
Assets/New Lowpoly Models/Scripts/Player/Health.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/New Lowpoly Models/Scripts/Player/Health.cs.meta
Normal file
2
Assets/New Lowpoly Models/Scripts/Player/Health.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2899f8d69deca1647aa65e10360c8629
|
||||
@@ -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);
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4a194c2231515bb40abb28d049fdea9d
|
||||
37
Assets/New Lowpoly Models/Scripts/Player/Stamina.cs
Normal file
37
Assets/New Lowpoly Models/Scripts/Player/Stamina.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
2
Assets/New Lowpoly Models/Scripts/Player/Stamina.cs.meta
Normal file
2
Assets/New Lowpoly Models/Scripts/Player/Stamina.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 89358a0a4e498554d936f78fcdd4de7f
|
||||
Reference in New Issue
Block a user