diff --git a/.idea/.idea.HALLUCINATE/.idea/workspace.xml b/.idea/.idea.HALLUCINATE/.idea/workspace.xml
index 73ebd0ae..29f5bc6d 100644
--- a/.idea/.idea.HALLUCINATE/.idea/workspace.xml
+++ b/.idea/.idea.HALLUCINATE/.idea/workspace.xml
@@ -4,14 +4,18 @@
-
+
+
+
+
+
-
+
@@ -95,7 +99,7 @@
-
+
@@ -106,7 +110,6 @@
-
@@ -172,7 +175,6 @@
-
diff --git a/Assets/InventoryData.json b/Assets/InventoryData.json
new file mode 100644
index 00000000..09630180
--- /dev/null
+++ b/Assets/InventoryData.json
@@ -0,0 +1,75 @@
+{
+ "itemReferences": [
+ {
+ "amount": 1,
+ "id": 10,
+ "attributes": [
+ {
+ "name": 2,
+ "value": 36,
+ "isOpen": false,
+ "isBool": false
+ },
+ {
+ "name": 6,
+ "value": 8,
+ "isOpen": false,
+ "isBool": false
+ }
+ ]
+ }
+ ],
+ "equipAreas": [
+ {
+ "slotsData": [
+ {
+ "hasItem": true,
+ "indexOfItem": 0
+ },
+ {
+ "hasItem": false,
+ "indexOfItem": 0
+ },
+ {
+ "hasItem": false,
+ "indexOfItem": 0
+ }
+ ],
+ "indexOfSelectedSlot": 0
+ },
+ {
+ "slotsData": [
+ {
+ "hasItem": false,
+ "indexOfItem": 0
+ },
+ {
+ "hasItem": false,
+ "indexOfItem": 0
+ },
+ {
+ "hasItem": false,
+ "indexOfItem": 0
+ }
+ ],
+ "indexOfSelectedSlot": 0
+ },
+ {
+ "slotsData": [
+ {
+ "hasItem": false,
+ "indexOfItem": 0
+ },
+ {
+ "hasItem": false,
+ "indexOfItem": 0
+ },
+ {
+ "hasItem": false,
+ "indexOfItem": 0
+ }
+ ],
+ "indexOfSelectedSlot": 0
+ }
+ ]
+}
\ No newline at end of file
diff --git a/Assets/InventoryData.json.meta b/Assets/InventoryData.json.meta
new file mode 100644
index 00000000..2736ed01
--- /dev/null
+++ b/Assets/InventoryData.json.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 760274f8c30c80848a1fb1c5dc64a2d5
+TextScriptImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Prefabs/Shooter/Player/vShooterMelee_Inventory.prefab b/Assets/Prefabs/Shooter/Player/vShooterMelee_Inventory.prefab
index ee4bd4ea..8d94773f 100644
--- a/Assets/Prefabs/Shooter/Player/vShooterMelee_Inventory.prefab
+++ b/Assets/Prefabs/Shooter/Player/vShooterMelee_Inventory.prefab
@@ -3271,9 +3271,9 @@ GameObject:
- component: {fileID: 114525927984870190}
- component: {fileID: 832688648}
- component: {fileID: 6688537537024804213}
+ - component: {fileID: 1505227404007521061}
- component: {fileID: -3829962440237222997}
- component: {fileID: -3602722895466718484}
- - component: {fileID: 1505227404007521061}
m_Layer: 8
m_Name: vShooterMelee_Inventory
m_TagString: Player
@@ -4686,6 +4686,20 @@ MonoBehaviour:
defaultDamageEffects:
- {fileID: 120346, guid: b8f2fe1ee1a01724cb72f5b0e6bd2eef, type: 3}
customDamageEffects: []
+--- !u!114 &1505227404007521061
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 146720}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: 16509f68a17b8004096bcf4acce328d6, type: 3}
+ m_Name:
+ m_EditorClassIdentifier: Assembly-CSharp::PlayerInventory
+ treasuresCollected: 0
+ totalTreasuresNeeded: 3
--- !u!114 &-3829962440237222997
MonoBehaviour:
m_ObjectHideFlags: 0
@@ -5065,20 +5079,6 @@ MonoBehaviour:
m_DefaultActionMap: Player
m_SplitScreenIndex: -1
m_Camera: {fileID: 0}
---- !u!114 &1505227404007521061
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 146720}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 16509f68a17b8004096bcf4acce328d6, type: 3}
- m_Name:
- m_EditorClassIdentifier: Assembly-CSharp::PlayerInventory
- treasuresCollected: 0
- totalTreasuresNeeded: 3
--- !u!1 &149606
GameObject:
m_ObjectHideFlags: 0
@@ -7002,6 +7002,108 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
mainTarget: {fileID: 0}
+ inputReader: {fileID: -3829962440237222997}
+ fpvTarget: {fileID: 463090}
+ fpvFOV: 80
+ transitionDuration: 0.3
+ characterFading:
+ useCharacterFading: 1
+ minVisibleDistance: 1.2
+ fullyHiddenDistance: 0.6
+ characterRenderers: []
+ occlusionTransparency:
+ useTransparency: 1
+ transparencyLayers:
+ serializedVersion: 2
+ m_Bits: 0
+ fadeAlpha: 0.3
+ dynamicFOV:
+ useDynamicFOV: 1
+ tpvSprintFOV: 70
+ fpvSprintFOV: 95
+ fovSmoothTime: 5
+ shakeManager:
+ useShake: 1
+ shakeFrequency: 25
+ decayCurve:
+ serializedVersion: 2
+ m_Curve:
+ - serializedVersion: 3
+ time: 0
+ value: 1
+ inSlope: 0
+ outSlope: 0
+ tangentMode: 0
+ weightedMode: 0
+ inWeight: 0
+ outWeight: 0
+ - serializedVersion: 3
+ time: 1
+ value: 0
+ inSlope: 0
+ outSlope: 0
+ tangentMode: 0
+ weightedMode: 0
+ inWeight: 0
+ outWeight: 0
+ m_PreInfinity: 2
+ m_PostInfinity: 2
+ m_RotationOrder: 4
+ enableFallImpactShake: 1
+ minFallHeightForShake: 2
+ maxFallHeightForShake: 10
+ minFallShakeIntensity: 0.5
+ maxFallShakeIntensity: 3
+ minFallShakeDuration: 0.2
+ maxFallShakeDuration: 0.8
+ fallHeightToIntensityCurve:
+ serializedVersion: 2
+ m_Curve:
+ - serializedVersion: 3
+ time: 0
+ value: 0
+ inSlope: 0
+ outSlope: 1
+ tangentMode: 0
+ weightedMode: 0
+ inWeight: 0
+ outWeight: 0
+ - serializedVersion: 3
+ time: 1
+ value: 1
+ inSlope: 1
+ outSlope: 0
+ tangentMode: 0
+ weightedMode: 0
+ inWeight: 0
+ outWeight: 0
+ m_PreInfinity: 2
+ m_PostInfinity: 2
+ m_RotationOrder: 4
+ fallHeightToDurationCurve:
+ serializedVersion: 2
+ m_Curve:
+ - serializedVersion: 3
+ time: 0
+ value: 0
+ inSlope: 0
+ outSlope: 1
+ tangentMode: 0
+ weightedMode: 0
+ inWeight: 0
+ outWeight: 0
+ - serializedVersion: 3
+ time: 1
+ value: 1
+ inSlope: 1
+ outSlope: 0
+ tangentMode: 0
+ weightedMode: 0
+ inWeight: 0
+ outWeight: 0
+ m_PreInfinity: 2
+ m_PostInfinity: 2
+ m_RotationOrder: 4
_smoothBetweenState: 6
_smoothCameraRotation: 12
_smoothSwitchSide: 2
diff --git a/Assets/Scripts/AI NPC/EnemyAI.cs b/Assets/Scripts/AI NPC/EnemyAI.cs
index 2a4c6ee7..362152d6 100644
--- a/Assets/Scripts/AI NPC/EnemyAI.cs
+++ b/Assets/Scripts/AI NPC/EnemyAI.cs
@@ -122,6 +122,8 @@ public class EnemyAI : MonoBehaviour
private NodeState ActionPatrol()
{
// Debug.Log("Patrolling...");
+ if (!agent.isActiveAndEnabled || !agent.isOnNavMesh) return NodeState.Failure;
+
agent.isStopped = false; // Đảm bảo NPC được phép di chuyển
agent.speed = moveSpeed * 0.5f; // Đi dạo nên đi chậm lại một chút
@@ -156,6 +158,8 @@ public class EnemyAI : MonoBehaviour
// Debug.Log("Chasing Player");
+ if (!agent.isActiveAndEnabled || !agent.isOnNavMesh) return NodeState.Failure;
+
agent.isStopped = false;
agent.speed = moveSpeed; // Phục hồi tốc độ rượt đuổi
agent.SetDestination(player.position);
@@ -169,6 +173,8 @@ public class EnemyAI : MonoBehaviour
// Debug.Log("Focus and Shoot!");
+ if (!agent.isActiveAndEnabled || !agent.isOnNavMesh) return NodeState.Failure;
+
// Dừng NavMeshAgent lại để đứng bắn, tránh bị trượt
agent.isStopped = true;
diff --git a/Assets/Scripts/Camera/vThirdPersonCamera.cs b/Assets/Scripts/Camera/vThirdPersonCamera.cs
index 27648294..7c724c97 100644
--- a/Assets/Scripts/Camera/vThirdPersonCamera.cs
+++ b/Assets/Scripts/Camera/vThirdPersonCamera.cs
@@ -1,6 +1,8 @@
-using Invector.vCharacterController;
+using Invector;
+using Invector.vCharacterController;
using System.Collections;
using UnityEngine;
+using OnlyScove.Scripts;
namespace Invector.vCamera
{
@@ -28,6 +30,19 @@ namespace Invector.vCamera
#region inspector properties
public Transform mainTarget;
+ public InputReader inputReader;
+
+ [Header("First Person View")]
+ public Transform fpvTarget;
+ [SerializeField] protected float fpvFOV = 80f;
+ [SerializeField] protected float transitionDuration = 0.3f;
+
+ [Header("Modular Features")]
+ [SerializeField] protected CameraCharacterFading characterFading = new CameraCharacterFading();
+ [SerializeField] protected CameraOcclusionTransparency occlusionTransparency = new CameraOcclusionTransparency();
+ [SerializeField] protected CameraDynamicFOV dynamicFOV = new CameraDynamicFOV();
+ [SerializeField] protected CameraShakeManager shakeManager = new CameraShakeManager();
+
[Tooltip("Lerp speed between Camera States")]
[SerializeField] protected float _smoothBetweenState = 6f;
public virtual float smoothBetweenState { get { return _smoothBetweenState; } set { _smoothBetweenState = value; } }
@@ -195,10 +210,56 @@ namespace Invector.vCamera
protected virtual void Start()
{
-
Init();
}
+ protected virtual void OnEnable()
+ {
+ if (inputReader != null)
+ {
+ inputReader.OnToggleViewEvent += ToggleCameraView;
+ inputReader.OnSwitchSideEvent += ToggleSwitchSide;
+ }
+ }
+
+ protected virtual void OnDisable()
+ {
+ if (inputReader != null)
+ {
+ inputReader.OnToggleViewEvent -= ToggleCameraView;
+ inputReader.OnSwitchSideEvent -= ToggleSwitchSide;
+ }
+ }
+
+ public virtual void ToggleSwitchSide()
+ {
+ SwitchRight(switchRight > 0);
+ }
+
+ public virtual void ToggleCameraView()
+ {
+ if (currentState.cameraMode == TPCameraMode.FirstPerson)
+ {
+ ChangeState("Default");
+ }
+ else
+ {
+ ChangeState("FirstPerson");
+ // If the state "FirstPerson" does not exist in the list,
+ // we force the mode to FirstPerson anyway
+ if (currentStateName != "FirstPerson")
+ {
+ currentState.cameraMode = TPCameraMode.FirstPerson;
+ currentStateName = "FirstPerson";
+ }
+ }
+ }
+
+ public virtual void TriggerFallImpactShake(float fallHeight)
+ {
+ shakeManager.TriggerFallImpactShake(fallHeight);
+ }
+
///
/// Init camera.
///
@@ -209,6 +270,9 @@ namespace Invector.vCamera
return;
}
+ if (inputReader == null) inputReader = mainTarget.GetComponent();
+ if (inputReader == null) inputReader = GameObject.FindObjectOfType();
+
firstUpdated = true;
useSmooth = true;
targetLookAt.rotation = startUsingTargetRotation ? mainTarget.rotation : transform.rotation;
@@ -256,6 +320,8 @@ namespace Invector.vCamera
currentTargetPos = new Vector3(currentTarget.position.x, currentTarget.position.y + offSetPlayerPivot, currentTarget.position.z) + currentTarget.transform.up * lerpState.height;
targetLookAt.position = currentTargetPos;
+ dynamicFOV.Initialize(currentState.fov, fpvFOV);
+
isInit = true;
}
@@ -292,7 +358,19 @@ namespace Invector.vCamera
case TPCameraMode.FixedPoint:
CameraFixed();
break;
+ case TPCameraMode.FirstPerson:
+ CameraMovement();
+ break;
}
+
+ // Modular Features
+ if (inputReader != null)
+ {
+ dynamicFOV.HandleDynamicFOV(targetCamera, inputReader,
+ currentState.cameraMode == TPCameraMode.FirstPerson ? CameraController.CameraViewMode.FirstPerson : CameraController.CameraViewMode.ThirdPerson);
+ }
+ shakeManager.HandleShake();
+ transform.position += shakeManager.ShakeOffset;
}
///
@@ -799,6 +877,12 @@ namespace Invector.vCamera
currentState.CopyState(lerpState);
}
+ if (currentState.cameraMode == TPCameraMode.FirstPerson)
+ {
+ HandleFirstPersonMovement();
+ return;
+ }
+
if (currentState.useZoom)
{
currentZoom = Mathf.Clamp(currentZoom, currentState.minDistance, currentState.maxDistance);
@@ -918,9 +1002,44 @@ namespace Invector.vCamera
_euler.z = 0;
var _rot = Quaternion.Euler(_euler + currentState.rotationOffSet);
selfRigidbody.MoveRotation(Quaternion.Lerp(startRotation, _rot, transformWeight));
+
+ // Apply Fading and Transparency
+ characterFading.HandleCharacterFading(distance);
+ occlusionTransparency.HandleTransparency(transform, targetPos);
+
movementSpeed = Vector2.zero;
}
+ protected virtual void HandleFirstPersonMovement()
+ {
+ if (fpvTarget == null) return;
+
+ distance = 0;
+ targetCamera.fieldOfView = fpvFOV;
+
+ // Position
+ current_cPos = fpvTarget.position;
+ targetLookAt.position = current_cPos;
+ selfRigidbody.MovePosition(current_cPos);
+
+ // Rotation
+ float _mouseY = Mathf.LerpAngle(mouseYStart, mouseY, transformWeight);
+ float _mouseX = Mathf.LerpAngle(mouseXStart, mouseX, transformWeight);
+ Quaternion newRot = Quaternion.Euler(_mouseY + offsetMouse.y, _mouseX + offsetMouse.x, 0);
+ targetLookAt.rotation = useSmooth ? Quaternion.Lerp(targetLookAt.rotation, newRot, smoothCameraRotation * Time.fixedDeltaTime) : newRot;
+
+ selfRigidbody.MoveRotation(targetLookAt.rotation);
+
+ // Sync player body rotation (Yaw only)
+ if (mainTarget != null)
+ {
+ mainTarget.rotation = Quaternion.Euler(0, targetLookAt.eulerAngles.y, 0);
+ }
+
+ characterFading.HandleCharacterFading(0); // Fully hide character head if desired, or set to distance 0 for full hidden
+ occlusionTransparency.HandleTransparency(transform, fpvTarget.position);
+ }
+
protected virtual void CameraFixed()
{
if (useSmooth)
diff --git a/Assets/Scripts/Camera/vThirdPersonCameraState.cs b/Assets/Scripts/Camera/vThirdPersonCameraState.cs
index 5293c657..667dc6f1 100644
--- a/Assets/Scripts/Camera/vThirdPersonCameraState.cs
+++ b/Assets/Scripts/Camera/vThirdPersonCameraState.cs
@@ -1,8 +1,16 @@
-using UnityEngine;
+using UnityEngine;
using System.Collections.Generic;
namespace Invector
{
+ public enum TPCameraMode
+ {
+ FreeDirectional,
+ FixedAngle,
+ FixedPoint,
+ FirstPerson
+ }
+
[System.Serializable]
public class vThirdPersonCameraState
{
@@ -56,6 +64,60 @@ namespace Invector
fixedAngle = Vector2.zero;
cameraMode = TPCameraMode.FreeDirectional;
}
+
+ public void CopyState(vThirdPersonCameraState state)
+ {
+ this.Name = state.Name;
+ this.forward = state.forward;
+ this.right = state.right;
+ this.defaultDistance = state.defaultDistance;
+ this.maxDistance = state.maxDistance;
+ this.minDistance = state.minDistance;
+ this.height = state.height;
+ this.smooth = state.smooth;
+ this.smoothDamp = state.smoothDamp;
+ this.xMouseSensitivity = state.xMouseSensitivity;
+ this.yMouseSensitivity = state.yMouseSensitivity;
+ this.yMinLimit = state.yMinLimit;
+ this.yMaxLimit = state.yMaxLimit;
+ this.xMinLimit = state.xMinLimit;
+ this.xMaxLimit = state.xMaxLimit;
+ this.rotationOffSet = state.rotationOffSet;
+ this.cullingHeight = state.cullingHeight;
+ this.cullingMinDist = state.cullingMinDist;
+ this.fov = state.fov;
+ this.useZoom = state.useZoom;
+ this.fixedAngle = state.fixedAngle;
+ this.lookPoints = state.lookPoints;
+ this.cameraMode = state.cameraMode;
+ }
+
+ public void Slerp(vThirdPersonCameraState state, float t)
+ {
+ this.Name = state.Name;
+ this.forward = Mathf.Lerp(this.forward, state.forward, t);
+ this.right = Mathf.Lerp(this.right, state.right, t);
+ this.defaultDistance = Mathf.Lerp(this.defaultDistance, state.defaultDistance, t);
+ this.maxDistance = Mathf.Lerp(this.maxDistance, state.maxDistance, t);
+ this.minDistance = Mathf.Lerp(this.minDistance, state.minDistance, t);
+ this.height = Mathf.Lerp(this.height, state.height, t);
+ this.smooth = Mathf.Lerp(this.smooth, state.smooth, t);
+ this.smoothDamp = Mathf.Lerp(this.smoothDamp, state.smoothDamp, t);
+ this.xMouseSensitivity = Mathf.Lerp(this.xMouseSensitivity, state.xMouseSensitivity, t);
+ this.yMouseSensitivity = Mathf.Lerp(this.yMouseSensitivity, state.yMouseSensitivity, t);
+ this.yMinLimit = Mathf.Lerp(this.yMinLimit, state.yMinLimit, t);
+ this.yMaxLimit = Mathf.Lerp(this.yMaxLimit, state.yMaxLimit, t);
+ this.xMinLimit = Mathf.Lerp(this.xMinLimit, state.xMinLimit, t);
+ this.xMaxLimit = Mathf.Lerp(this.xMaxLimit, state.xMaxLimit, t);
+ this.rotationOffSet = Vector3.Lerp(this.rotationOffSet, state.rotationOffSet, t);
+ this.cullingHeight = Mathf.Lerp(this.cullingHeight, state.cullingHeight, t);
+ this.cullingMinDist = Mathf.Lerp(this.cullingMinDist, state.cullingMinDist, t);
+ this.fov = Mathf.Lerp(this.fov, state.fov, t);
+ this.useZoom = state.useZoom;
+ this.fixedAngle = Vector2.Lerp(this.fixedAngle, state.fixedAngle, t);
+ this.lookPoints = state.lookPoints;
+ this.cameraMode = state.cameraMode;
+ }
}
[System.Serializable]
@@ -66,11 +128,4 @@ namespace Invector
public Vector3 eulerAngle;
public bool freeRotation;
}
-
- public enum TPCameraMode
- {
- FreeDirectional,
- FixedAngle,
- FixedPoint
- }
}
\ No newline at end of file
diff --git a/Assets/Scripts/Player/ThrowSystem/UI/CustomProjector/RangeIndicator.mat b/Assets/Scripts/Player/ThrowSystem/UI/CustomProjector/RangeIndicator.mat
index 4e7c485d..93e6f5dd 100644
--- a/Assets/Scripts/Player/ThrowSystem/UI/CustomProjector/RangeIndicator.mat
+++ b/Assets/Scripts/Player/ThrowSystem/UI/CustomProjector/RangeIndicator.mat
@@ -32,13 +32,13 @@ Material:
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
- m_Texture: {fileID: 2800000, guid: 1ba5636bfdd687347966f548dbf5a0bc, type: 3}
+ m_Texture: {fileID: 2800000, guid: db48e0e5caa2999469a4f3aa249c188b, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Ints: []
m_Floats: []
m_Colors:
- - _Color: {r: 8, g: 0, b: 0, a: 1}
+ - _Color: {r: 1, g: 1, b: 1, a: 1}
- _Vector0: {r: 1, g: 1, b: 0, a: 0}
m_BuildTextureStacks: []
m_AllowLocking: 1
diff --git a/Assets/Settings/InputSystem_Actions.inputactions b/Assets/Settings/InputSystem_Actions.inputactions
index f9f6a007..ed605275 100644
--- a/Assets/Settings/InputSystem_Actions.inputactions
+++ b/Assets/Settings/InputSystem_Actions.inputactions
@@ -635,7 +635,7 @@
{
"name": "",
"id": "f365517f-5a04-4d18-afa0-369ab80e0c54",
- "path": "/f2",
+ "path": "/f1",
"interactions": "",
"processors": "",
"groups": "Keyboard&Mouse",
diff --git a/ProjectSettings/TagManager.asset b/ProjectSettings/TagManager.asset
index bb1f8a2f..ccb288e8 100644
--- a/ProjectSettings/TagManager.asset
+++ b/ProjectSettings/TagManager.asset
@@ -30,6 +30,7 @@ TagManager:
- CoverPoint
- Interactable
- AIAction
+ - Check
layers:
- Default
- TransparentFX