Update
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
@@ -20,6 +20,7 @@ public class EnemyAI : MonoBehaviour
|
||||
private NavMeshAgent agent;
|
||||
private Rigidbody rb;
|
||||
private FieldOfView fov;
|
||||
private Collider mainCollider;
|
||||
|
||||
[Header("Movement Settings")]
|
||||
public float moveSpeed = 3f;
|
||||
@@ -53,7 +54,7 @@ public class EnemyAI : MonoBehaviour
|
||||
public float maxStrafeDuration = 2.2f;
|
||||
public float maxSpreadAngle = 6f;
|
||||
public float burstInterval = 0.12f;
|
||||
|
||||
|
||||
public float approachWeight = 0.35f;
|
||||
public float minCombatDistance = 5.0f;
|
||||
|
||||
@@ -79,7 +80,7 @@ public class EnemyAI : MonoBehaviour
|
||||
public float investigationThreshold = 30f;
|
||||
public float alertNeighborsThreshold = 70f;
|
||||
public float alertRange = 20f;
|
||||
|
||||
|
||||
public Node rootNode;
|
||||
|
||||
void Start()
|
||||
@@ -88,6 +89,19 @@ public class EnemyAI : MonoBehaviour
|
||||
rb = GetComponent<Rigidbody>();
|
||||
fov = GetComponent<FieldOfView>();
|
||||
chatBubble = GetComponentInChildren<Hallucinate.UI.ChatBubble>(true);
|
||||
mainCollider = GetComponent<Collider>();
|
||||
|
||||
// Tự động gán Layer Enemy nếu chưa có
|
||||
if (gameObject.layer == LayerMask.NameToLayer("Default"))
|
||||
{
|
||||
gameObject.layer = LayerMask.NameToLayer("Enemy");
|
||||
Debug.Log($"[AI {npcName}] Tự động chuyển Layer sang Enemy để súng có thể bắn trúng.");
|
||||
}
|
||||
|
||||
if (mainCollider == null)
|
||||
{
|
||||
Debug.LogError($"[AI {npcName}] THIẾU COLLIDER! NPC này sẽ không thể bị bắn trúng.");
|
||||
}
|
||||
|
||||
rb.isKinematic = true;
|
||||
rb.freezeRotation = true;
|
||||
@@ -105,10 +119,10 @@ public class EnemyAI : MonoBehaviour
|
||||
void InitTree()
|
||||
{
|
||||
var dodgeSequence = new Sequence(new List<Node> { new TaskNode(CheckDodgeConditions), new TaskNode(ActionDodge) });
|
||||
|
||||
|
||||
// Đổi hàm CheckHasArtifact thành CheckCombatConditions để dùng chung cho cả âm thanh
|
||||
var laserSequence = new Sequence(new List<Node> { new TaskNode(CheckCombatConditions), new TaskNode(ActionFocusAndShoot) });
|
||||
|
||||
|
||||
var chaseSequence = new Sequence(new List<Node> { new TaskNode(CheckCanSeePlayer), new TaskNode(ActionChasePlayer) });
|
||||
var investigateSequence = new Sequence(new List<Node> { new TaskNode(CheckHasInvestigateTarget), new TaskNode(ActionInvestigate) });
|
||||
var talkSequence = new Sequence(new List<Node> { new TaskNode(CheckCanTalkToNPC), new TaskNode(ActionTalk) });
|
||||
@@ -129,6 +143,13 @@ public class EnemyAI : MonoBehaviour
|
||||
{
|
||||
if (player == null) return;
|
||||
|
||||
// Đảm bảo Collider luôn bật
|
||||
if (mainCollider != null && !mainCollider.enabled)
|
||||
{
|
||||
mainCollider.enabled = true;
|
||||
Debug.LogWarning($"[AI {npcName}] Collider bị tắt trái phép! Đã tự động bật lại.");
|
||||
}
|
||||
|
||||
if (!agent.isOnNavMesh) return;
|
||||
|
||||
suspicionLevel = Mathf.Max(0, suspicionLevel - Time.deltaTime * 0.5f);
|
||||
@@ -202,7 +223,7 @@ public class EnemyAI : MonoBehaviour
|
||||
foreach (var hit in hitColliders)
|
||||
{
|
||||
if (hit.gameObject == gameObject) continue;
|
||||
|
||||
|
||||
EnemyAI other = hit.GetComponentInParent<EnemyAI>();
|
||||
if (other != null && !other.isTalking && Time.time >= other.lastTalkTime + talkCooldown)
|
||||
{
|
||||
@@ -226,8 +247,8 @@ public class EnemyAI : MonoBehaviour
|
||||
{
|
||||
suspicionLevel += volume * 15f;
|
||||
if (fov != null) fov.lastKnownPlayerPosition = location;
|
||||
|
||||
// CẬP NHẬT: Nếu AI nghe thấy tiếng động làm mức nghi ngờ vượt mốc điều tra, chuyển sang trạng thái chiến đấu (bắn bồi)
|
||||
|
||||
// Nếu AI nghe thấy tiếng động làm mức nghi ngờ vượt mốc điều tra, chuyển sang trạng thái chiến đấu
|
||||
if (suspicionLevel >= investigationThreshold)
|
||||
{
|
||||
isAggroedBySound = true;
|
||||
@@ -238,6 +259,16 @@ public class EnemyAI : MonoBehaviour
|
||||
Debug.Log($"<color=orange>[AI {npcName}]</color> Heard noise! Suspicion: {suspicionLevel}");
|
||||
}
|
||||
|
||||
public void TriggerCombatAlert(Vector3 sourceLocation)
|
||||
{
|
||||
suspicionLevel = 100f;
|
||||
isAggroedBySound = true; // Ép vào trạng thái tấn công
|
||||
if (fov != null) fov.lastKnownPlayerPosition = sourceLocation;
|
||||
StopConversation();
|
||||
AlertNeighbors();
|
||||
Debug.Log($"<color=red>[AI {npcName}] GUNFIRE DETECTED!</color> Entering combat mode.");
|
||||
}
|
||||
|
||||
public void AlertNeighbors()
|
||||
{
|
||||
Collider[] hitColliders = Physics.OverlapSphere(transform.position, alertRange);
|
||||
@@ -277,7 +308,7 @@ public class EnemyAI : MonoBehaviour
|
||||
{
|
||||
DialogueResult result = JsonUtility.FromJson<DialogueResult>(json);
|
||||
if (chatBubble != null) chatBubble.Show(result.text);
|
||||
|
||||
|
||||
moveSpeed += result.speedMod;
|
||||
suspicionLevel = Mathf.Clamp(suspicionLevel + result.suspicionMod, 0, 100);
|
||||
lastTalkTime = Time.time;
|
||||
@@ -334,7 +365,7 @@ public class EnemyAI : MonoBehaviour
|
||||
agent.isStopped = false;
|
||||
agent.speed = moveSpeed * 0.7f;
|
||||
agent.SetDestination(fov.lastKnownPlayerPosition);
|
||||
|
||||
|
||||
if (Vector3.Distance(transform.position, fov.lastKnownPlayerPosition) < 1.5f)
|
||||
{
|
||||
currentWaitTime += Time.deltaTime;
|
||||
@@ -357,12 +388,12 @@ public class EnemyAI : MonoBehaviour
|
||||
|
||||
// CẢI TIẾN: Xác định mục tiêu linh hoạt để tránh Wallhack.
|
||||
Vector3 targetPos = player.position; // Mặc định khóa chặt người chơi
|
||||
|
||||
|
||||
// Nếu không cầm Artifact và cũng chưa bị nhìn thấy, AI chỉ nhắm vào MỐC ÂM THANH
|
||||
if (!playerHasArtifact && fov != null && !fov.canSeePlayer && fov.lastKnownPlayerPosition != Vector3.zero)
|
||||
{
|
||||
targetPos = fov.lastKnownPlayerPosition;
|
||||
|
||||
|
||||
// Nếu AI tiến hành áp sát và xả đạn vào nơi phát ra tiếng mà không thấy ai, ngưng bắn
|
||||
if (Vector3.Distance(transform.position, targetPos) < 2f)
|
||||
{
|
||||
@@ -472,10 +503,16 @@ public class EnemyAI : MonoBehaviour
|
||||
isDodging = true;
|
||||
agent.enabled = false;
|
||||
rb.isKinematic = false;
|
||||
|
||||
// GIỮ COLLIDER LUÔN BẬT KHI NÉ
|
||||
if (mainCollider != null) mainCollider.enabled = true;
|
||||
|
||||
Vector3 dir = (player.position - transform.position).normalized;
|
||||
Vector3 perp = new Vector3(-dir.z, 0, dir.x);
|
||||
rb.AddForce((Random.value > 0.5f ? perp : -perp) * dodgeForce, ForceMode.Impulse);
|
||||
|
||||
yield return new WaitForSeconds(dodgeDuration);
|
||||
|
||||
rb.linearVelocity = Vector3.zero;
|
||||
rb.isKinematic = true;
|
||||
agent.enabled = true;
|
||||
|
||||
@@ -302,6 +302,15 @@ namespace Invector.vShooter
|
||||
var rotation = Quaternion.LookRotation(dir);
|
||||
GameObject bulletObject = null;
|
||||
var velocityChanged = 0f;
|
||||
|
||||
if (projectile == null)
|
||||
{
|
||||
Debug.LogError($"<color=red>WEAPON ERROR:</color> No Projectile Prefab assigned to {gameObject.name}!");
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.Log($"<color=white>WEAPON SHOOT:</color> Spawning projectile. HitLayer: {hitLayer.value}");
|
||||
|
||||
if (dispersion > 0 && projectile)
|
||||
{
|
||||
for (int i = 0; i < projectilesPerShot; i++)
|
||||
@@ -311,6 +320,12 @@ namespace Invector.vShooter
|
||||
bulletObject = Instantiate(projectile, startPoint, spreadRotation);
|
||||
|
||||
var pCtrl = bulletObject.GetComponent<vProjectileControl>();
|
||||
if (pCtrl == null)
|
||||
{
|
||||
Debug.LogError($"<color=red>PROJECTILE ERROR:</color> {projectile.name} does not have vProjectileControl script!");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pCtrl.debugTrajetory && i == 0)
|
||||
{
|
||||
startPoint.DebugPoint(Color.red, 10, 0.1f);
|
||||
@@ -338,6 +353,13 @@ namespace Invector.vShooter
|
||||
{
|
||||
bulletObject = Instantiate(projectile, startPoint, rotation);
|
||||
var pCtrl = bulletObject.GetComponent<vProjectileControl>();
|
||||
|
||||
if (pCtrl == null)
|
||||
{
|
||||
Debug.LogError($"<color=red>PROJECTILE ERROR:</color> {projectile.name} does not have vProjectileControl script!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (pCtrl.debugTrajetory)
|
||||
{
|
||||
startPoint.DebugPoint(Color.red, 10, 0.1f);
|
||||
|
||||
Reference in New Issue
Block a user