Merge branch 'main' of https://scove-vault.duckdns.org/scove/HALLUCINATION
This commit is contained in:
12
.idea/.idea.HALLUCINATE/.idea/workspace.xml
generated
12
.idea/.idea.HALLUCINATE/.idea/workspace.xml
generated
@@ -6,12 +6,12 @@
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="f9183c68-daf0-43b8-be4c-fad79983f91b" name="Changes" comment="">
|
||||
<change beforePath="$PROJECT_DIR$/.idea/.idea.HALLUCINATE/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/.idea.HALLUCINATE/.idea/workspace.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Prefabs/NPC/KamikazeAI.prefab" beforeDir="false" afterPath="$PROJECT_DIR$/Assets/Prefabs/NPC/KamikazeAI.prefab" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Prefabs/NPC/xNPC.prefab" beforeDir="false" afterPath="$PROJECT_DIR$/Assets/Prefabs/NPC/xNPC.prefab" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Prefabs/Shooter/Weapon/_bullets/vGrenadeRifle.prefab" beforeDir="false" afterPath="$PROJECT_DIR$/Assets/Prefabs/Shooter/Weapon/_bullets/vGrenadeRifle.prefab" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Prefabs/Shooter/Weapon/_weapons_WITH_Inventory/_ammo/vAmmoHandgun_Inventory.prefab" beforeDir="false" afterPath="$PROJECT_DIR$/Assets/Prefabs/Shooter/Weapon/_weapons_WITH_Inventory/_ammo/vAmmoHandgun_Inventory.prefab" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Prefabs/Shooter/Weapon/_weapons_WITH_Inventory/_weaponsPrefabs/vHandgun_Inventory.prefab" beforeDir="false" afterPath="$PROJECT_DIR$/Assets/Prefabs/Shooter/Weapon/_weapons_WITH_Inventory/_weaponsPrefabs/vHandgun_Inventory.prefab" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Scenes/Cho môn AI/Only AI/NavMesh-NavManager 1.asset" beforeDir="false" afterPath="$PROJECT_DIR$/Assets/Scenes/Cho môn AI/Only AI/NavMesh-NavManager 1.asset" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Scripts/Player/Weapon/vProjectileControl.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Assets/Scripts/Player/Weapon/vProjectileControl.cs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Scenes/Cho môn AI/Only AI.unity" beforeDir="false" afterPath="$PROJECT_DIR$/Assets/Scenes/Cho môn AI/Only AI.unity" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Scripts/AI NPC/EnemyAI.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Assets/Scripts/AI NPC/EnemyAI.cs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Scripts/Player/Weapon/vShooterWeaponBase.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Assets/Scripts/Player/Weapon/vShooterWeaponBase.cs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Third Parties/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF - Fallback.asset" beforeDir="false" afterPath="$PROJECT_DIR$/Assets/Third Parties/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF - Fallback.asset" afterDir="false" />
|
||||
</list>
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
@@ -181,7 +181,7 @@
|
||||
<workItem from="1780364354282" duration="4357000" />
|
||||
<workItem from="1780409218377" duration="9852000" />
|
||||
<workItem from="1780494322686" duration="643000" />
|
||||
<workItem from="1780633654231" duration="26606000" />
|
||||
<workItem from="1780633654231" duration="28766000" />
|
||||
</task>
|
||||
<servers />
|
||||
</component>
|
||||
|
||||
@@ -14,6 +14,7 @@ GameObject:
|
||||
- component: {fileID: 6087599376744356948}
|
||||
- component: {fileID: 3563399533700019190}
|
||||
- component: {fileID: 681314853465352057}
|
||||
- component: {fileID: 4042483058127329834}
|
||||
m_Layer: 0
|
||||
m_Name: KamikazeAI
|
||||
m_TagString: Untagged
|
||||
@@ -155,3 +156,41 @@ MonoBehaviour:
|
||||
patrolRadius: 12
|
||||
patrolWaitTime: 2
|
||||
explosionEffectPrefab: {fileID: 8568474719719117872, guid: 39bf32dcd9299df4ca44fd10a817eda4, type: 3}
|
||||
--- !u!114 &4042483058127329834
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 6425756872251228809}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: f56a83ea88140fa4f869bb2f7ffdb184, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::Invector.vHealthController
|
||||
openCloseEvents: 0
|
||||
openCloseWindow: 1
|
||||
selectedToolbar: 0
|
||||
_isDead: 1
|
||||
_currentHealth: 0
|
||||
isImmortal: 0
|
||||
fillHealthOnStart: 1
|
||||
_maxHealth: 100
|
||||
_healthRecovery: 0
|
||||
_healthRecoveryDelay: 0
|
||||
checkHealthEvents: []
|
||||
_onStartReceiveDamage:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
_onReceiveDamage:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
_onDead:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
onChangeHealth:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
onResetHealth:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
|
||||
@@ -472,6 +472,7 @@ GameObject:
|
||||
- component: {fileID: 6469822191588635990}
|
||||
- component: {fileID: 9027690817715396964}
|
||||
- component: {fileID: 204793640880232070}
|
||||
- component: {fileID: 2997468006321853334}
|
||||
m_Layer: 9
|
||||
m_Name: xNPC
|
||||
m_TagString: Enemy
|
||||
@@ -516,19 +517,20 @@ MonoBehaviour:
|
||||
patrolSpeed: 2
|
||||
patrolRadius: 5
|
||||
playerHasArtifact: 0
|
||||
isAggroedBySound: 0
|
||||
laserPrefab: {fileID: 3965388737199864462, guid: fbec2b501d70daa4c9cb481ba53fc0b8, type: 3}
|
||||
firePoint: {fileID: 5863061020199015852}
|
||||
minShootDelay: 1
|
||||
maxShootDelay: 5
|
||||
maxShootDelay: 3
|
||||
dodgeForce: 8
|
||||
dodgeDuration: 0.5
|
||||
dodgeCooldown: 3
|
||||
minStrafeDuration: 0.5
|
||||
maxStrafeDuration: 2.2
|
||||
maxSpreadAngle: 6
|
||||
maxSpreadAngle: 3
|
||||
burstInterval: 0.12
|
||||
approachWeight: 0.35
|
||||
minCombatDistance: 5
|
||||
approachWeight: 1
|
||||
minCombatDistance: 6
|
||||
npcName: Guard
|
||||
persona: You are a grumpy guard protecting gold.
|
||||
talkRange: 5
|
||||
@@ -621,18 +623,9 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: 35bba55c2a743d042ab1fff35e29db50, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::AnimatorAI
|
||||
debugMode: 1
|
||||
debugColor: {r: 1, g: 0, b: 0.21842146, a: 1}
|
||||
useSimulation: 0
|
||||
autoCycleSpeed: 0
|
||||
simVerticalVelocity: 0
|
||||
simIsSprinting: 0
|
||||
simIsAiming: 0
|
||||
simMoveSetID: 0
|
||||
sprintThreshold: 0.8
|
||||
dampTime: 0.1
|
||||
forcePlayState:
|
||||
showLayerWeights: 0
|
||||
groundDistanceValue: 0.05
|
||||
--- !u!136 &9027690817715396964
|
||||
CapsuleCollider:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -694,6 +687,24 @@ MonoBehaviour:
|
||||
onResetHealth:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
--- !u!114 &2997468006321853334
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7522161431095319480}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 9d3efef3ad62cd548b0f85eb11858ed1, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::Invector.vHitDamageParticle
|
||||
openCloseEvents: 0
|
||||
openCloseWindow: 1
|
||||
selectedToolbar: 0
|
||||
defaultDamageEffects:
|
||||
- {fileID: 120346, guid: b8f2fe1ee1a01724cb72f5b0e6bd2eef, type: 3}
|
||||
customDamageEffects: []
|
||||
--- !u!1001 &7561534673732472622
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
|
||||
@@ -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