From b172762d4fab40b6b8032f297993aab018f51499 Mon Sep 17 00:00:00 2001 From: TIBOfdg Date: Thu, 5 Feb 2026 03:20:07 +0100 Subject: [PATCH] Add detective board --- .../Camera/DefaultCameraPanSettings.asset | 5 + .../Camera/DetectiveBoardPanSettings.asset | 30 +++ .../DetectiveBoardPanSettings.asset.meta | 8 + .../Camera/SlowInspectionPanSettings.asset | 5 + .../Unheimlich_POC/Datas/DetectiveBoard.meta | 8 + .../DefaultDetectiveBoardSettings.asset | 23 +++ .../DefaultDetectiveBoardSettings.asset.meta | 8 + .../ExampleClue_BrokenDoor.asset | 25 +++ .../ExampleClue_BrokenDoor.asset.meta | 8 + .../ExampleClue_PatientTestimony.asset | 25 +++ .../ExampleClue_PatientTestimony.asset.meta | 8 + .../ExampleClue_StrangeSound.asset | 25 +++ .../ExampleClue_StrangeSound.asset.meta | 8 + .../Inputs/PlayerController.inputactions | 33 ++- .../Prefabs/Player/Player.prefab | 48 ++++- .../Prefabs/Rooms/RoomToLoadFive.prefab | 48 ++--- .../Scenes/MainScene/MainScene.unity | 100 ++++++++- .../Scripts/Datas/Camera/CameraPanSettings.cs | 24 +++ .../Scripts/Datas/DetectiveBoard.meta | 8 + .../Scripts/Datas/DetectiveBoard/ClueData.cs | 41 ++++ .../Datas/DetectiveBoard/ClueData.cs.meta | 2 + .../DetectiveBoard/DetectiveBoardSettings.cs | 42 ++++ .../DetectiveBoardSettings.cs.meta | 2 + .../Scripts/Editor/ClueDataEditor.cs | 38 ++++ .../Scripts/Editor/ClueDataEditor.cs.meta | 2 + .../Gameplay/Camera/CameraPanController.cs | 54 ++--- .../Scripts/Gameplay/DetectiveBoard.meta | 8 + .../DetectiveBoardController.cs | 186 +++++++++++++++++ .../DetectiveBoardController.cs.meta | 2 + .../GameObjects/Player/CameraHeadBob.cs | 31 ++- .../Player/DiapasonListeningHandler.cs | 15 +- .../GameObjects/Player/PlayerMovement.cs | 3 +- .../Scripts/Handlers/DetectiveBoard.meta | 8 + .../DetectiveBoard/ClueUnlockOnAudio.cs | 115 +++++++++++ .../DetectiveBoard/ClueUnlockOnAudio.cs.meta | 2 + .../DetectiveBoard/ClueUnlockOnInteraction.cs | 43 ++++ .../ClueUnlockOnInteraction.cs.meta | 2 + .../DetectiveBoard/ClueUnlockTrigger.cs | 105 ++++++++++ .../DetectiveBoard/ClueUnlockTrigger.cs.meta | 2 + .../Interactions/InteracionHandler.cs | 4 +- .../Interactions/PlayerInspectionHandler.cs | 3 +- .../Scripts/Managers/DetectiveBoardManager.cs | 193 ++++++++++++++++++ .../Managers/DetectiveBoardManager.cs.meta | 2 + .../Scripts/Managers/DialogueManager.cs | 4 +- .../Scripts/Managers/PlayerInputManager.cs | 41 +++- .../Scripts/UI/DetectiveBoard.meta | 8 + .../Scripts/UI/DetectiveBoard/ClueNodeUI.cs | 93 +++++++++ .../UI/DetectiveBoard/ClueNodeUI.cs.meta | 2 + .../DetectiveBoard/ConnectionLineRenderer.cs | 90 ++++++++ .../ConnectionLineRenderer.cs.meta | 2 + ProjectSettings/TagManager.asset | 2 +- 51 files changed, 1502 insertions(+), 92 deletions(-) create mode 100644 Assets/Unheimlich_POC/Datas/Camera/DetectiveBoardPanSettings.asset create mode 100644 Assets/Unheimlich_POC/Datas/Camera/DetectiveBoardPanSettings.asset.meta create mode 100644 Assets/Unheimlich_POC/Datas/DetectiveBoard.meta create mode 100644 Assets/Unheimlich_POC/Datas/DetectiveBoard/DefaultDetectiveBoardSettings.asset create mode 100644 Assets/Unheimlich_POC/Datas/DetectiveBoard/DefaultDetectiveBoardSettings.asset.meta create mode 100644 Assets/Unheimlich_POC/Datas/DetectiveBoard/ExampleClue_BrokenDoor.asset create mode 100644 Assets/Unheimlich_POC/Datas/DetectiveBoard/ExampleClue_BrokenDoor.asset.meta create mode 100644 Assets/Unheimlich_POC/Datas/DetectiveBoard/ExampleClue_PatientTestimony.asset create mode 100644 Assets/Unheimlich_POC/Datas/DetectiveBoard/ExampleClue_PatientTestimony.asset.meta create mode 100644 Assets/Unheimlich_POC/Datas/DetectiveBoard/ExampleClue_StrangeSound.asset create mode 100644 Assets/Unheimlich_POC/Datas/DetectiveBoard/ExampleClue_StrangeSound.asset.meta create mode 100644 Assets/Unheimlich_POC/Scripts/Datas/DetectiveBoard.meta create mode 100644 Assets/Unheimlich_POC/Scripts/Datas/DetectiveBoard/ClueData.cs create mode 100644 Assets/Unheimlich_POC/Scripts/Datas/DetectiveBoard/ClueData.cs.meta create mode 100644 Assets/Unheimlich_POC/Scripts/Datas/DetectiveBoard/DetectiveBoardSettings.cs create mode 100644 Assets/Unheimlich_POC/Scripts/Datas/DetectiveBoard/DetectiveBoardSettings.cs.meta create mode 100644 Assets/Unheimlich_POC/Scripts/Editor/ClueDataEditor.cs create mode 100644 Assets/Unheimlich_POC/Scripts/Editor/ClueDataEditor.cs.meta create mode 100644 Assets/Unheimlich_POC/Scripts/Gameplay/DetectiveBoard.meta create mode 100644 Assets/Unheimlich_POC/Scripts/Gameplay/DetectiveBoard/DetectiveBoardController.cs create mode 100644 Assets/Unheimlich_POC/Scripts/Gameplay/DetectiveBoard/DetectiveBoardController.cs.meta create mode 100644 Assets/Unheimlich_POC/Scripts/Handlers/DetectiveBoard.meta create mode 100644 Assets/Unheimlich_POC/Scripts/Handlers/DetectiveBoard/ClueUnlockOnAudio.cs create mode 100644 Assets/Unheimlich_POC/Scripts/Handlers/DetectiveBoard/ClueUnlockOnAudio.cs.meta create mode 100644 Assets/Unheimlich_POC/Scripts/Handlers/DetectiveBoard/ClueUnlockOnInteraction.cs create mode 100644 Assets/Unheimlich_POC/Scripts/Handlers/DetectiveBoard/ClueUnlockOnInteraction.cs.meta create mode 100644 Assets/Unheimlich_POC/Scripts/Handlers/DetectiveBoard/ClueUnlockTrigger.cs create mode 100644 Assets/Unheimlich_POC/Scripts/Handlers/DetectiveBoard/ClueUnlockTrigger.cs.meta create mode 100644 Assets/Unheimlich_POC/Scripts/Managers/DetectiveBoardManager.cs create mode 100644 Assets/Unheimlich_POC/Scripts/Managers/DetectiveBoardManager.cs.meta create mode 100644 Assets/Unheimlich_POC/Scripts/UI/DetectiveBoard.meta create mode 100644 Assets/Unheimlich_POC/Scripts/UI/DetectiveBoard/ClueNodeUI.cs create mode 100644 Assets/Unheimlich_POC/Scripts/UI/DetectiveBoard/ClueNodeUI.cs.meta create mode 100644 Assets/Unheimlich_POC/Scripts/UI/DetectiveBoard/ConnectionLineRenderer.cs create mode 100644 Assets/Unheimlich_POC/Scripts/UI/DetectiveBoard/ConnectionLineRenderer.cs.meta diff --git a/Assets/Unheimlich_POC/Datas/Camera/DefaultCameraPanSettings.asset b/Assets/Unheimlich_POC/Datas/Camera/DefaultCameraPanSettings.asset index 9eec3d97..8dece415 100644 --- a/Assets/Unheimlich_POC/Datas/Camera/DefaultCameraPanSettings.asset +++ b/Assets/Unheimlich_POC/Datas/Camera/DefaultCameraPanSettings.asset @@ -15,8 +15,13 @@ MonoBehaviour: PanSpeed: 3 PanBorderSize: 0.05 MaxPanAngle: 10 + EnableRecentering: 0 + RecenterSpeed: 2 + RecenterDelay: 0.1 AlignmentSpeed: 3 AlignmentThreshold: 0.5 + DisableHeadBob: 1 + ForceIdleHeadBob: 1 UseSmoothStep: 1 AlignmentCurve: serializedVersion: 2 diff --git a/Assets/Unheimlich_POC/Datas/Camera/DetectiveBoardPanSettings.asset b/Assets/Unheimlich_POC/Datas/Camera/DetectiveBoardPanSettings.asset new file mode 100644 index 00000000..22c7309f --- /dev/null +++ b/Assets/Unheimlich_POC/Datas/Camera/DetectiveBoardPanSettings.asset @@ -0,0 +1,30 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 3e231c75dddecc0469543c190a9234b1, type: 3} + m_Name: DetectiveBoardPanSettings + m_EditorClassIdentifier: Assembly-CSharp::Unheimlich.Data.CameraSettings.CameraPanSettings + PanSpeed: 2 + PanBorderSize: 0.15 + MaxPanAngle: 45 + EnableRecentering: 1 + RecenterSpeed: 0.5 + RecenterDelay: 0.1 + AlignmentSpeed: 4 + AlignmentThreshold: 0.5 + HeadBobMode: 1 + UseSmoothStep: 1 + AlignmentCurve: + serializedVersion: 2 + m_Curve: [] + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 diff --git a/Assets/Unheimlich_POC/Datas/Camera/DetectiveBoardPanSettings.asset.meta b/Assets/Unheimlich_POC/Datas/Camera/DetectiveBoardPanSettings.asset.meta new file mode 100644 index 00000000..d05a95a7 --- /dev/null +++ b/Assets/Unheimlich_POC/Datas/Camera/DetectiveBoardPanSettings.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f176d1f8c15496946994170f1b633061 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Unheimlich_POC/Datas/Camera/SlowInspectionPanSettings.asset b/Assets/Unheimlich_POC/Datas/Camera/SlowInspectionPanSettings.asset index c9dfd770..caa8f589 100644 --- a/Assets/Unheimlich_POC/Datas/Camera/SlowInspectionPanSettings.asset +++ b/Assets/Unheimlich_POC/Datas/Camera/SlowInspectionPanSettings.asset @@ -15,8 +15,13 @@ MonoBehaviour: PanSpeed: 1 PanBorderSize: 0.15 MaxPanAngle: 20 + EnableRecentering: 1 + RecenterSpeed: 2 + RecenterDelay: 0.1 AlignmentSpeed: 1.5 AlignmentThreshold: 0.5 + DisableHeadBob: 1 + ForceIdleHeadBob: 1 UseSmoothStep: 1 AlignmentCurve: serializedVersion: 2 diff --git a/Assets/Unheimlich_POC/Datas/DetectiveBoard.meta b/Assets/Unheimlich_POC/Datas/DetectiveBoard.meta new file mode 100644 index 00000000..88a949e2 --- /dev/null +++ b/Assets/Unheimlich_POC/Datas/DetectiveBoard.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e02ca21936f1f5f408a3ecdf99e2a292 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Unheimlich_POC/Datas/DetectiveBoard/DefaultDetectiveBoardSettings.asset b/Assets/Unheimlich_POC/Datas/DetectiveBoard/DefaultDetectiveBoardSettings.asset new file mode 100644 index 00000000..ad62f4ff --- /dev/null +++ b/Assets/Unheimlich_POC/Datas/DetectiveBoard/DefaultDetectiveBoardSettings.asset @@ -0,0 +1,23 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f6b20768fe570fb429fcf6a348431232, type: 3} + m_Name: DefaultDetectiveBoardSettings + m_EditorClassIdentifier: Assembly-CSharp::Unheimlich.Data.DetectiveBoard.DetectiveBoardSettings + DefaultNodeSprite: {fileID: 0} + NodeScale: 1 + NodeSpacing: 0.5 + ConnectionLineWidth: 0.05 + ConfirmedConnectionColor: {r: 0, g: 1, b: 0, a: 1} + UncertainConnectionColor: {r: 1, g: 1, b: 0, a: 1} + EliminatedConnectionColor: {r: 1, g: 0, b: 0, a: 1} + InteractionRange: 2 + HoverHighlightColor: {r: 1, g: 1, b: 0.5, a: 1} diff --git a/Assets/Unheimlich_POC/Datas/DetectiveBoard/DefaultDetectiveBoardSettings.asset.meta b/Assets/Unheimlich_POC/Datas/DetectiveBoard/DefaultDetectiveBoardSettings.asset.meta new file mode 100644 index 00000000..71b89bbb --- /dev/null +++ b/Assets/Unheimlich_POC/Datas/DetectiveBoard/DefaultDetectiveBoardSettings.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 126542fefc394584d914569b15358022 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Unheimlich_POC/Datas/DetectiveBoard/ExampleClue_BrokenDoor.asset b/Assets/Unheimlich_POC/Datas/DetectiveBoard/ExampleClue_BrokenDoor.asset new file mode 100644 index 00000000..bb9bd320 --- /dev/null +++ b/Assets/Unheimlich_POC/Datas/DetectiveBoard/ExampleClue_BrokenDoor.asset @@ -0,0 +1,25 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 166ae120db91b064c9b98086267b9783, type: 3} + m_Name: ExampleClue_BrokenDoor + m_EditorClassIdentifier: Assembly-CSharp::Unheimlich.Data.DetectiveBoard.ClueData + ClueID: clue_broken_door_002 + Title: Broken Door + Description: The door to cell 13 shows signs of forced entry. Scratch marks on + the inside. + Icon: {fileID: 0} + NodeColor: {r: 0.8, g: 0.8, b: 0.8, a: 1} + PossibleConnections: + - clue_strange_sound_001 + - clue_patient_testimony_003 + Category: Physical Evidence + InitialPosition: {x: 0.5, y: 0.5} diff --git a/Assets/Unheimlich_POC/Datas/DetectiveBoard/ExampleClue_BrokenDoor.asset.meta b/Assets/Unheimlich_POC/Datas/DetectiveBoard/ExampleClue_BrokenDoor.asset.meta new file mode 100644 index 00000000..12c037cd --- /dev/null +++ b/Assets/Unheimlich_POC/Datas/DetectiveBoard/ExampleClue_BrokenDoor.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f00adada8d7d4d24eb9e1b189cb15cd2 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Unheimlich_POC/Datas/DetectiveBoard/ExampleClue_PatientTestimony.asset b/Assets/Unheimlich_POC/Datas/DetectiveBoard/ExampleClue_PatientTestimony.asset new file mode 100644 index 00000000..9344b616 --- /dev/null +++ b/Assets/Unheimlich_POC/Datas/DetectiveBoard/ExampleClue_PatientTestimony.asset @@ -0,0 +1,25 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 166ae120db91b064c9b98086267b9783, type: 3} + m_Name: ExampleClue_PatientTestimony + m_EditorClassIdentifier: Assembly-CSharp::Unheimlich.Data.DetectiveBoard.ClueData + ClueID: clue_patient_testimony_003 + Title: Patient Testimony + Description: Patient claims to have seen shadows moving in the walls. Unreliable + witness? + Icon: {fileID: 0} + NodeColor: {r: 0.9, g: 0.7, b: 0.7, a: 1} + PossibleConnections: + - clue_strange_sound_001 + - clue_broken_door_002 + Category: Witness + InitialPosition: {x: 0.7, y: 0.6} diff --git a/Assets/Unheimlich_POC/Datas/DetectiveBoard/ExampleClue_PatientTestimony.asset.meta b/Assets/Unheimlich_POC/Datas/DetectiveBoard/ExampleClue_PatientTestimony.asset.meta new file mode 100644 index 00000000..84d78206 --- /dev/null +++ b/Assets/Unheimlich_POC/Datas/DetectiveBoard/ExampleClue_PatientTestimony.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1ef1769f9dc66c4409621d5e0e0d40b0 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Unheimlich_POC/Datas/DetectiveBoard/ExampleClue_StrangeSound.asset b/Assets/Unheimlich_POC/Datas/DetectiveBoard/ExampleClue_StrangeSound.asset new file mode 100644 index 00000000..62e3c0ed --- /dev/null +++ b/Assets/Unheimlich_POC/Datas/DetectiveBoard/ExampleClue_StrangeSound.asset @@ -0,0 +1,25 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 166ae120db91b064c9b98086267b9783, type: 3} + m_Name: ExampleClue_StrangeSound + m_EditorClassIdentifier: Assembly-CSharp::Unheimlich.Data.DetectiveBoard.ClueData + ClueID: clue_strange_sound_001 + Title: Strange Sound + Description: A mysterious sound heard in the asylum corridors. Metallic scraping, + rhythmic and deliberate. + Icon: {fileID: 0} + NodeColor: {r: 0.9, g: 0.9, b: 0.7, a: 1} + PossibleConnections: + - clue_broken_door_002 + - clue_patient_testimony_003 + Category: Audio Evidence + InitialPosition: {x: 0.3, y: 0.6} diff --git a/Assets/Unheimlich_POC/Datas/DetectiveBoard/ExampleClue_StrangeSound.asset.meta b/Assets/Unheimlich_POC/Datas/DetectiveBoard/ExampleClue_StrangeSound.asset.meta new file mode 100644 index 00000000..879c15be --- /dev/null +++ b/Assets/Unheimlich_POC/Datas/DetectiveBoard/ExampleClue_StrangeSound.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9c941404c8ea4ee40bb4817d5224eb55 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Unheimlich_POC/Inputs/PlayerController.inputactions b/Assets/Unheimlich_POC/Inputs/PlayerController.inputactions index f17dfc82..418d789e 100644 --- a/Assets/Unheimlich_POC/Inputs/PlayerController.inputactions +++ b/Assets/Unheimlich_POC/Inputs/PlayerController.inputactions @@ -55,7 +55,7 @@ "name": "Jump", "type": "Button", "id": "f1ba0d36-48eb-4cd5-b651-1c94a6531f70", - "expectedControlType": "Button", + "expectedControlType": "", "processors": "", "interactions": "", "initialStateCheck": false @@ -104,6 +104,15 @@ "processors": "", "interactions": "Press", "initialStateCheck": false + }, + { + "name": "Exit", + "type": "Button", + "id": "725de34c-d3b2-4fb0-a335-7acd9f8d2a36", + "expectedControlType": "", + "processors": "", + "interactions": "", + "initialStateCheck": false } ], "bindings": [ @@ -535,6 +544,28 @@ "action": "Fire", "isComposite": false, "isPartOfComposite": false + }, + { + "name": "", + "id": "849e2170-a3a6-440b-a211-a2c276f6ecc3", + "path": "/b", + "interactions": "", + "processors": "", + "groups": "", + "action": "Exit", + "isComposite": false, + "isPartOfComposite": false + }, + { + "name": "", + "id": "ad021a86-3ec0-4f84-8ce0-e4f00d10259a", + "path": "/buttonEast", + "interactions": "", + "processors": "", + "groups": "", + "action": "Exit", + "isComposite": false, + "isPartOfComposite": false } ] }, diff --git a/Assets/Unheimlich_POC/Prefabs/Player/Player.prefab b/Assets/Unheimlich_POC/Prefabs/Player/Player.prefab index 3e5da1e9..f2b21066 100644 --- a/Assets/Unheimlich_POC/Prefabs/Player/Player.prefab +++ b/Assets/Unheimlich_POC/Prefabs/Player/Player.prefab @@ -595,6 +595,7 @@ GameObject: - component: {fileID: 3142789394009655648} - component: {fileID: 3919526576499794210} - component: {fileID: 3942456782017280985} + - component: {fileID: 5542178260801185816} m_Layer: 0 m_Name: Player m_TagString: Player @@ -824,6 +825,10 @@ MonoBehaviour: m_Calls: [] m_ActionId: a3ec6166-3b8f-4545-9fa4-40583be0fc66 m_ActionName: Player/Fire + - m_PersistentCalls: + m_Calls: [] + m_ActionId: 725de34c-d3b2-4fb0-a335-7acd9f8d2a36 + m_ActionName: 'Player/Exit[/Keyboard/escape]' m_NeverAutoSwitchControlSchemes: 0 m_DefaultControlScheme: m_DefaultActionMap: @@ -843,9 +848,6 @@ MonoBehaviour: m_EditorClassIdentifier: MoveInput: {x: 0, y: 0} LookInput: {x: 0, y: 0} - JumpAction: {fileID: -2099379676528639254, guid: 052faaac586de48259a63d0c4782560b, type: 3} - InteractAction: {fileID: 1781555164194001046, guid: 052faaac586de48259a63d0c4782560b, type: 3} - DiapasonAction: {fileID: 0} --- !u!114 &2756854183089553922 MonoBehaviour: m_ObjectHideFlags: 0 @@ -936,6 +938,7 @@ MonoBehaviour: _diapasonObject: {fileID: 3833126793998633073} _diapasonAnimator: {fileID: 3326093237010115507} _playerCamera: {fileID: 4106604842127079875} + _cameraPanController: {fileID: 0} _listeningRange: 5 _listenableLayers: serializedVersion: 2 @@ -968,11 +971,7 @@ MonoBehaviour: m_PreInfinity: 2 m_PostInfinity: 2 m_RotationOrder: 4 - _cameraPanSpeed: 2 - _cameraPanBorderSize: 0.1 - _maxCameraPanAngle: 15 - _cameraAlignmentSpeed: 3 - _cameraAlignmentThreshold: 0.5 + _vibrationDuration: 15 _vignetteIntensity: 0.5 _vignetteEffect: {fileID: 3919526576499794210} _handTouchFeedback: {fileID: 0} @@ -983,9 +982,6 @@ MonoBehaviour: _ambientAttenuationAmount: 0.3 _audioFadeDuration: 0.5 _touchDistance: 2 - _diapasonAction: {fileID: 0} - _lookAction: {fileID: 0} - _fireAction: {fileID: 0} --- !u!114 &3919526576499794210 MonoBehaviour: m_ObjectHideFlags: 0 @@ -1022,6 +1018,25 @@ BoxCollider: serializedVersion: 3 m_Size: {x: 1, y: 0.2, z: 1} m_Center: {x: 0, y: -0.9, z: 0} +--- !u!114 &5542178260801185816 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8240327778457960307} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 9f9f72364623a2a4bb50f02537fd2e72, type: 3} + m_Name: + m_EditorClassIdentifier: Assembly-CSharp::Unheimlich.Gameplay.DetectiveBoard.DetectiveBoardController + _cameraPanController: {fileID: 953069181646740290} + _boardTransform: {fileID: 0} + _boardCameraPanSettings: {fileID: 11400000, guid: f176d1f8c15496946994170f1b633061, type: 2} + _activationRange: 5 + _boardLayer: + serializedVersion: 2 + m_Bits: 128 --- !u!1001 &3579255215054032817 PrefabInstance: m_ObjectHideFlags: 0 @@ -1095,6 +1110,17 @@ Transform: m_CorrespondingSourceObject: {fileID: 3943575771451333687, guid: e73a3b0e274984f4d8b6a073e03d4d03, type: 3} m_PrefabInstance: {fileID: 3579255215054032817} m_PrefabAsset: {fileID: 0} +--- !u!114 &953069181646740290 stripped +MonoBehaviour: + m_CorrespondingSourceObject: {fileID: 4365653766954783987, guid: e73a3b0e274984f4d8b6a073e03d4d03, type: 3} + m_PrefabInstance: {fileID: 3579255215054032817} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 69e8150bab500424eb366f0ac8761995, type: 3} + m_Name: + m_EditorClassIdentifier: Assembly-CSharp::Unheimlich.Gameplay.CameraControl.CameraPanController --- !u!20 &4106604842127079875 stripped Camera: m_CorrespondingSourceObject: {fileID: 671466249668048498, guid: e73a3b0e274984f4d8b6a073e03d4d03, type: 3} diff --git a/Assets/Unheimlich_POC/Prefabs/Rooms/RoomToLoadFive.prefab b/Assets/Unheimlich_POC/Prefabs/Rooms/RoomToLoadFive.prefab index 7140b74e..b9edff8e 100644 --- a/Assets/Unheimlich_POC/Prefabs/Rooms/RoomToLoadFive.prefab +++ b/Assets/Unheimlich_POC/Prefabs/Rooms/RoomToLoadFive.prefab @@ -188,7 +188,6 @@ GameObject: - component: {fileID: 7557062904579759447} - component: {fileID: 308102004899398107} - component: {fileID: 8372318773087887588} - - component: {fileID: 6954627091512351276} m_Layer: 0 m_Name: Cube m_TagString: Untagged @@ -205,7 +204,7 @@ Transform: m_GameObject: {fileID: 2757010966349118316} serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: -2.17, z: 0} + m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 7, y: 5, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] @@ -268,27 +267,6 @@ MeshRenderer: m_SortingOrder: 0 m_MaskInteraction: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!65 &6954627091512351276 -BoxCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2757010966349118316} - m_Material: {fileID: 0} - m_IncludeLayers: - serializedVersion: 2 - m_Bits: 0 - m_ExcludeLayers: - serializedVersion: 2 - m_Bits: 0 - m_LayerOverridePriority: 0 - m_IsTrigger: 0 - m_ProvidesContacts: 0 - m_Enabled: 1 - serializedVersion: 3 - m_Size: {x: 1, y: 1, z: 1} - m_Center: {x: 0, y: 0, z: 0} --- !u!1 &3210101827131705135 GameObject: m_ObjectHideFlags: 0 @@ -298,6 +276,7 @@ GameObject: serializedVersion: 6 m_Component: - component: {fileID: 5831650301161165405} + - component: {fileID: 300362587813736772} m_Layer: 0 m_Name: DetectiveBoard m_TagString: Untagged @@ -314,13 +293,34 @@ Transform: m_GameObject: {fileID: 3210101827131705135} serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: -0.38435, y: 6.36425, z: 13.13094} + m_LocalPosition: {x: -0.38435, y: 3.99, z: 13.13094} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: - {fileID: 3941506515996401395} m_Father: {fileID: 3965737018690194595} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!65 &300362587813736772 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3210101827131705135} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 7, y: 5, z: 1} + m_Center: {x: 0, y: 0, z: 0} --- !u!1 &3669803179848655488 GameObject: m_ObjectHideFlags: 0 diff --git a/Assets/Unheimlich_POC/Scenes/MainScene/MainScene.unity b/Assets/Unheimlich_POC/Scenes/MainScene/MainScene.unity index 15172107..39d4aa45 100644 --- a/Assets/Unheimlich_POC/Scenes/MainScene/MainScene.unity +++ b/Assets/Unheimlich_POC/Scenes/MainScene/MainScene.unity @@ -150,6 +150,7 @@ Transform: m_Children: - {fileID: 1762962819} - {fileID: 1475986548} + - {fileID: 2128643702} m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &37800871 @@ -186,6 +187,14 @@ PrefabInstance: propertyPath: m_Mesh value: objectReference: {fileID: 297438471} + - target: {fileID: 2757010966349118316, guid: 69f9e42d2acbf0344981fcdffd02d588, type: 3} + propertyPath: m_Layer + value: 7 + objectReference: {fileID: 0} + - target: {fileID: 3210101827131705135, guid: 69f9e42d2acbf0344981fcdffd02d588, type: 3} + propertyPath: m_Layer + value: 7 + objectReference: {fileID: 0} - target: {fileID: 3965737018690194595, guid: 69f9e42d2acbf0344981fcdffd02d588, type: 3} propertyPath: m_LocalPosition.x value: 20.412663 @@ -226,6 +235,26 @@ PrefabInstance: propertyPath: m_LocalEulerAnglesHint.z value: 0 objectReference: {fileID: 0} + - target: {fileID: 5831650301161165405, guid: 69f9e42d2acbf0344981fcdffd02d588, type: 3} + propertyPath: m_LocalPosition.y + value: 2.33 + objectReference: {fileID: 0} + - target: {fileID: 6121043411098075476, guid: 69f9e42d2acbf0344981fcdffd02d588, type: 3} + propertyPath: _boardTransform + value: + objectReference: {fileID: 102351985} + - target: {fileID: 6121043411098075476, guid: 69f9e42d2acbf0344981fcdffd02d588, type: 3} + propertyPath: _activationRange + value: 5 + objectReference: {fileID: 0} + - target: {fileID: 6121043411098075476, guid: 69f9e42d2acbf0344981fcdffd02d588, type: 3} + propertyPath: _boardLayer.m_Bits + value: 128 + objectReference: {fileID: 0} + - target: {fileID: 6121043411098075476, guid: 69f9e42d2acbf0344981fcdffd02d588, type: 3} + propertyPath: _cameraPanController + value: + objectReference: {fileID: 436513853} - target: {fileID: 6433754577218517818, guid: 69f9e42d2acbf0344981fcdffd02d588, type: 3} propertyPath: m_Mesh value: @@ -240,13 +269,23 @@ PrefabInstance: objectReference: {fileID: 1949684909} - target: {fileID: 8209576767969738346, guid: 69f9e42d2acbf0344981fcdffd02d588, type: 3} propertyPath: m_VersionIndex - value: 5887 + value: 5932 objectReference: {fileID: 0} - m_RemovedComponents: [] + - target: {fileID: 8358850242504541279, guid: 69f9e42d2acbf0344981fcdffd02d588, type: 3} + propertyPath: m_Layer + value: 7 + objectReference: {fileID: 0} + m_RemovedComponents: + - {fileID: 6121043411098075476, guid: 69f9e42d2acbf0344981fcdffd02d588, type: 3} m_RemovedGameObjects: [] m_AddedGameObjects: [] m_AddedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: 69f9e42d2acbf0344981fcdffd02d588, type: 3} +--- !u!4 &102351985 stripped +Transform: + m_CorrespondingSourceObject: {fileID: 5831650301161165405, guid: 69f9e42d2acbf0344981fcdffd02d588, type: 3} + m_PrefabInstance: {fileID: 102351984} + m_PrefabAsset: {fileID: 0} --- !u!43 &183470776 Mesh: m_ObjectHideFlags: 0 @@ -2712,6 +2751,51 @@ Transform: m_CorrespondingSourceObject: {fileID: 2089706605371115838, guid: 0048fed3be8aeb8449285faf2cc63a15, type: 3} m_PrefabInstance: {fileID: 3614017092883427690} m_PrefabAsset: {fileID: 0} +--- !u!1 &2128643701 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2128643702} + - component: {fileID: 2128643703} + m_Layer: 0 + m_Name: DetectiveBoardManager + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &2128643702 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2128643701} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 26219555} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &2128643703 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2128643701} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4b187cdccaa498441a752e8f49ff4290, type: 3} + m_Name: + m_EditorClassIdentifier: Assembly-CSharp::Unheimlich.Managers.DetectiveBoardManager + _settings: {fileID: 11400000, guid: 126542fefc394584d914569b15358022, type: 2} --- !u!43 &2145275082 Mesh: m_ObjectHideFlags: 0 @@ -3451,7 +3535,7 @@ PrefabInstance: objectReference: {fileID: 0} - target: {fileID: 5383576672370031505, guid: 92d3cde0c88c75f48a98d082c573338b, type: 3} propertyPath: m_LocalPosition.x - value: 23.37 + value: 18.9 objectReference: {fileID: 0} - target: {fileID: 5383576672370031505, guid: 92d3cde0c88c75f48a98d082c573338b, type: 3} propertyPath: m_LocalPosition.y @@ -3459,7 +3543,7 @@ PrefabInstance: objectReference: {fileID: 0} - target: {fileID: 5383576672370031505, guid: 92d3cde0c88c75f48a98d082c573338b, type: 3} propertyPath: m_LocalPosition.z - value: 39.92 + value: 63.8 objectReference: {fileID: 0} - target: {fileID: 5383576672370031505, guid: 92d3cde0c88c75f48a98d082c573338b, type: 3} propertyPath: m_LocalRotation.w @@ -3489,6 +3573,14 @@ PrefabInstance: propertyPath: m_LocalEulerAnglesHint.z value: 0 objectReference: {fileID: 0} + - target: {fileID: 5542178260801185816, guid: 92d3cde0c88c75f48a98d082c573338b, type: 3} + propertyPath: _boardTransform + value: + objectReference: {fileID: 102351985} + - target: {fileID: 5542178260801185816, guid: 92d3cde0c88c75f48a98d082c573338b, type: 3} + propertyPath: _activationRange + value: 10 + objectReference: {fileID: 0} - target: {fileID: 6059622576803707873, guid: 92d3cde0c88c75f48a98d082c573338b, type: 3} propertyPath: m_Enabled value: 0 diff --git a/Assets/Unheimlich_POC/Scripts/Datas/Camera/CameraPanSettings.cs b/Assets/Unheimlich_POC/Scripts/Datas/Camera/CameraPanSettings.cs index 25e7d576..584fedf5 100644 --- a/Assets/Unheimlich_POC/Scripts/Datas/Camera/CameraPanSettings.cs +++ b/Assets/Unheimlich_POC/Scripts/Datas/Camera/CameraPanSettings.cs @@ -2,6 +2,16 @@ using UnityEngine; namespace Unheimlich.Data.CameraSettings { + /// + /// Head bob mode for camera pan. + /// + public enum HeadBobMode + { + Normal, + Idle, + Disabled + } + /// /// ScriptableObject configuration for camera pan and player alignment behavior. /// Defines pan speed, borders, angles, alignment parameters, and lerp smoothness. @@ -20,6 +30,16 @@ namespace Unheimlich.Data.CameraSettings [Tooltip("Maximum angle the camera can pan from center")] public float MaxPanAngle = 15f; + [Header("Recentering")] + [Tooltip("Enable automatic return to center when idle")] + public bool EnableRecentering = true; + + [Tooltip("Speed of automatic recentering (higher = faster return to center)")] + public float RecenterSpeed = 2f; + + [Tooltip("Delay before recentering starts (in seconds)")] + public float RecenterDelay = 0.1f; + [Header("Player Alignment")] [Tooltip("Speed of player/camera alignment to target")] public float AlignmentSpeed = 3f; @@ -27,6 +47,10 @@ namespace Unheimlich.Data.CameraSettings [Tooltip("Threshold for alignment completion")] public float AlignmentThreshold = 0.5f; + [Header("Head Bob Control")] + [Tooltip("Head bob mode: Normal (default behavior), Idle (force subtle breathing), Disabled (no movement)")] + public HeadBobMode HeadBobMode = HeadBobMode.Idle; + [Header("Lerp Smoothing")] [Tooltip("Use SmoothStep for smoother interpolation (true) or linear lerp (false)")] public bool UseSmoothStep = true; diff --git a/Assets/Unheimlich_POC/Scripts/Datas/DetectiveBoard.meta b/Assets/Unheimlich_POC/Scripts/Datas/DetectiveBoard.meta new file mode 100644 index 00000000..32b843ac --- /dev/null +++ b/Assets/Unheimlich_POC/Scripts/Datas/DetectiveBoard.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 41fba9d7fa6130e42bec85319cf9caf3 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Unheimlich_POC/Scripts/Datas/DetectiveBoard/ClueData.cs b/Assets/Unheimlich_POC/Scripts/Datas/DetectiveBoard/ClueData.cs new file mode 100644 index 00000000..8bdbd7f7 --- /dev/null +++ b/Assets/Unheimlich_POC/Scripts/Datas/DetectiveBoard/ClueData.cs @@ -0,0 +1,41 @@ +using UnityEngine; + +namespace Unheimlich.Data.DetectiveBoard +{ + /// + /// Represents a single clue/evidence node on the detective board. + /// Unlocked through various triggers (audio, objects, dialogues, hallucinations, etc.). + /// + [CreateAssetMenu(fileName = "ClueData", menuName = "Unheimlich/Detective Board/Clue Data")] + public class ClueData : ScriptableObject + { + [Header("Clue Identity")] + [Tooltip("Unique identifier for this clue")] + public string ClueID; + + [Tooltip("Display title on the board")] + public string Title; + + [Tooltip("Detailed description of the clue")] + [TextArea(3, 6)] + public string Description; + + [Header("Visual Representation")] + [Tooltip("Icon or image for the node (post-it/card visual)")] + public Sprite Icon; + + [Tooltip("Color tint for the node")] + public Color NodeColor = Color.white; + + [Header("Connection Rules")] + [Tooltip("IDs of clues this can connect to")] + public string[] PossibleConnections; + + [Header("Meta")] + [Tooltip("Category for organization (e.g., 'Evidence', 'Witness', 'Location')")] + public string Category; + + [Tooltip("Initial position on the board (normalized 0-1)")] + public Vector2 InitialPosition = new Vector2(0.5f, 0.5f); + } +} diff --git a/Assets/Unheimlich_POC/Scripts/Datas/DetectiveBoard/ClueData.cs.meta b/Assets/Unheimlich_POC/Scripts/Datas/DetectiveBoard/ClueData.cs.meta new file mode 100644 index 00000000..4fe7637c --- /dev/null +++ b/Assets/Unheimlich_POC/Scripts/Datas/DetectiveBoard/ClueData.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 166ae120db91b064c9b98086267b9783 \ No newline at end of file diff --git a/Assets/Unheimlich_POC/Scripts/Datas/DetectiveBoard/DetectiveBoardSettings.cs b/Assets/Unheimlich_POC/Scripts/Datas/DetectiveBoard/DetectiveBoardSettings.cs new file mode 100644 index 00000000..43dd2f76 --- /dev/null +++ b/Assets/Unheimlich_POC/Scripts/Datas/DetectiveBoard/DetectiveBoardSettings.cs @@ -0,0 +1,42 @@ +using UnityEngine; + +namespace Unheimlich.Data.DetectiveBoard +{ + /// + /// Configuration for detective board UI behavior and appearance. + /// Defines node visuals, connection rules, and interaction parameters. + /// + [CreateAssetMenu(fileName = "DetectiveBoardSettings", menuName = "Unheimlich/Detective Board/Board Settings")] + public class DetectiveBoardSettings : ScriptableObject + { + [Header("Node Visuals")] + [Tooltip("Default sprite for nodes (post-it/card)")] + public Sprite DefaultNodeSprite; + + [Tooltip("Scale of node objects on the board")] + public float NodeScale = 1f; + + [Tooltip("Spacing between nodes when auto-arranged")] + public float NodeSpacing = 0.5f; + + [Header("Connection Visuals")] + [Tooltip("Line width for connections")] + public float ConnectionLineWidth = 0.05f; + + [Tooltip("Color for confirmed connections")] + public Color ConfirmedConnectionColor = Color.green; + + [Tooltip("Color for uncertain connections")] + public Color UncertainConnectionColor = Color.yellow; + + [Tooltip("Color for eliminated connections")] + public Color EliminatedConnectionColor = Color.red; + + [Header("Interaction")] + [Tooltip("Distance at which nodes can be interacted with")] + public float InteractionRange = 2f; + + [Tooltip("Highlight color when hovering over a node")] + public Color HoverHighlightColor = new Color(1f, 1f, 0.5f, 1f); + } +} diff --git a/Assets/Unheimlich_POC/Scripts/Datas/DetectiveBoard/DetectiveBoardSettings.cs.meta b/Assets/Unheimlich_POC/Scripts/Datas/DetectiveBoard/DetectiveBoardSettings.cs.meta new file mode 100644 index 00000000..53f15f11 --- /dev/null +++ b/Assets/Unheimlich_POC/Scripts/Datas/DetectiveBoard/DetectiveBoardSettings.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: f6b20768fe570fb429fcf6a348431232 \ No newline at end of file diff --git a/Assets/Unheimlich_POC/Scripts/Editor/ClueDataEditor.cs b/Assets/Unheimlich_POC/Scripts/Editor/ClueDataEditor.cs new file mode 100644 index 00000000..4e4c7743 --- /dev/null +++ b/Assets/Unheimlich_POC/Scripts/Editor/ClueDataEditor.cs @@ -0,0 +1,38 @@ +using UnityEngine; +using UnityEditor; +using Unheimlich.Data.DetectiveBoard; + +namespace Unheimlich.Editor +{ + [CustomEditor(typeof(ClueData))] + public class ClueDataEditor : UnityEditor.Editor + { + public override void OnInspectorGUI() + { + DrawDefaultInspector(); + + ClueData clueData = (ClueData)target; + + EditorGUILayout.Space(); + EditorGUILayout.LabelField("Quick Actions", EditorStyles.boldLabel); + + if (GUILayout.Button("Generate Unique ID")) + { + clueData.ClueID = System.Guid.NewGuid().ToString(); + EditorUtility.SetDirty(clueData); + } + + if (GUILayout.Button("Test Unlock Clue (Play Mode Only)")) + { + if (Application.isPlaying) + { + Managers.DetectiveBoardManager.Instance?.UnlockClue(clueData); + } + else + { + Debug.LogWarning("This button only works in Play Mode!"); + } + } + } + } +} diff --git a/Assets/Unheimlich_POC/Scripts/Editor/ClueDataEditor.cs.meta b/Assets/Unheimlich_POC/Scripts/Editor/ClueDataEditor.cs.meta new file mode 100644 index 00000000..b9c8b9a9 --- /dev/null +++ b/Assets/Unheimlich_POC/Scripts/Editor/ClueDataEditor.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 184cbe5b79ee0a84ba29da016ec76159 \ No newline at end of file diff --git a/Assets/Unheimlich_POC/Scripts/Gameplay/Camera/CameraPanController.cs b/Assets/Unheimlich_POC/Scripts/Gameplay/Camera/CameraPanController.cs index 703496c3..1fce256c 100644 --- a/Assets/Unheimlich_POC/Scripts/Gameplay/Camera/CameraPanController.cs +++ b/Assets/Unheimlich_POC/Scripts/Gameplay/Camera/CameraPanController.cs @@ -2,6 +2,7 @@ using System.Collections; using UnityEngine; using UnityEngine.InputSystem; using Unheimlich.Data.CameraSettings; +using PlayerInput = Unheimlich.Managers.PlayerInputManager; namespace Unheimlich.Gameplay.CameraControl { @@ -18,9 +19,6 @@ namespace Unheimlich.Gameplay.CameraControl [Header("Settings")] [SerializeField] private CameraPanSettings _settings; - [Header("Input Actions")] - [SerializeField] private InputActionReference _lookAction; - private Vector2 _originalCameraRotation; private Vector3 _originalCameraLocalPosition; private Vector3 _originalPlayerPosition; @@ -29,7 +27,6 @@ namespace Unheimlich.Gameplay.CameraControl private Coroutine _alignmentCoroutine; private Coroutine _returnCoroutine; private float _timeSinceLastInput; - private const float INPUT_IDLE_THRESHOLD = 0.1f; public bool IsPanning { get; private set; } @@ -99,9 +96,10 @@ namespace Unheimlich.Gameplay.CameraControl float panY = 0f; bool hasInput = false; - if (_lookAction != null && _lookAction.action != null) + var lookAction = PlayerInput.GetLookAction(); + if (lookAction != null) { - Vector2 lookInput = _lookAction.action.ReadValue(); + Vector2 lookInput = lookAction.ReadValue(); if (lookInput.sqrMagnitude > 0.01f) { panX = lookInput.x; @@ -150,29 +148,37 @@ namespace Unheimlich.Gameplay.CameraControl _timeSinceLastInput += Time.deltaTime; } - float targetYaw; - float targetPitch; - - if (hasInput || _timeSinceLastInput < INPUT_IDLE_THRESHOLD) - { - targetYaw = _originalCameraRotation.x + panX * _settings.MaxPanAngle; - targetPitch = _originalCameraRotation.y - panY * _settings.MaxPanAngle; - } - else - { - targetYaw = _originalCameraRotation.x; - targetPitch = _originalCameraRotation.y; - } - - targetYaw = Mathf.Clamp(targetYaw, _originalCameraRotation.x - _settings.MaxPanAngle, _originalCameraRotation.x + _settings.MaxPanAngle); - targetPitch = Mathf.Clamp(targetPitch, _originalCameraRotation.y - _settings.MaxPanAngle, _originalCameraRotation.y + _settings.MaxPanAngle); - float currentYaw = _playerTransform.eulerAngles.y; float currentPitch = _camera.transform.localEulerAngles.x; if (currentPitch > 180f) currentPitch -= 360f; - float lerpSpeed = hasInput ? _settings.PanSpeed : _settings.PanSpeed * 2f; + float targetYaw; + float targetPitch; + float lerpSpeed; + + bool shouldRecenter = _settings.EnableRecentering && _timeSinceLastInput >= _settings.RecenterDelay; + + if (hasInput) + { + targetYaw = _originalCameraRotation.x + panX * _settings.MaxPanAngle; + targetPitch = _originalCameraRotation.y - panY * _settings.MaxPanAngle; + targetYaw = Mathf.Clamp(targetYaw, _originalCameraRotation.x - _settings.MaxPanAngle, _originalCameraRotation.x + _settings.MaxPanAngle); + targetPitch = Mathf.Clamp(targetPitch, _originalCameraRotation.y - _settings.MaxPanAngle, _originalCameraRotation.y + _settings.MaxPanAngle); + lerpSpeed = _settings.PanSpeed; + } + else if (shouldRecenter) + { + targetYaw = _originalCameraRotation.x; + targetPitch = _originalCameraRotation.y; + lerpSpeed = _settings.RecenterSpeed; + } + else + { + targetYaw = currentYaw; + targetPitch = currentPitch; + lerpSpeed = 0f; + } float newYaw = Mathf.LerpAngle(currentYaw, targetYaw, Time.deltaTime * lerpSpeed); float newPitch = Mathf.LerpAngle(currentPitch, targetPitch, Time.deltaTime * lerpSpeed); diff --git a/Assets/Unheimlich_POC/Scripts/Gameplay/DetectiveBoard.meta b/Assets/Unheimlich_POC/Scripts/Gameplay/DetectiveBoard.meta new file mode 100644 index 00000000..60c2a25b --- /dev/null +++ b/Assets/Unheimlich_POC/Scripts/Gameplay/DetectiveBoard.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 82ca56838506a694196a2130ecff8694 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Unheimlich_POC/Scripts/Gameplay/DetectiveBoard/DetectiveBoardController.cs b/Assets/Unheimlich_POC/Scripts/Gameplay/DetectiveBoard/DetectiveBoardController.cs new file mode 100644 index 00000000..2cb51a9e --- /dev/null +++ b/Assets/Unheimlich_POC/Scripts/Gameplay/DetectiveBoard/DetectiveBoardController.cs @@ -0,0 +1,186 @@ +using UnityEngine; +using Unheimlich.Data.CameraSettings; +using Unheimlich.Gameplay.CameraControl; +using Unheimlich.Gameplay.Player; +using PlayerInput = Unheimlich.Managers.PlayerInputManager; + +namespace Unheimlich.Gameplay.DetectiveBoard +{ + /// + /// Controls player interaction with the detective board in world space. + /// Uses CameraPanController for wide-angle camera movement across the board. + /// Activates when player is in range and looking at the board. + /// + public class DetectiveBoardController : MonoBehaviour + { + [Header("References")] + [SerializeField] private CameraPanController _cameraPanController; + [SerializeField] private Transform _boardTransform; + + [Header("Settings")] + [SerializeField] private CameraPanSettings _boardCameraPanSettings; + [SerializeField] private float _activationRange = 2f; + [SerializeField] private LayerMask _boardLayer; + + private Camera _playerCamera; + private bool _isBoardActive; + private CameraPanSettings _originalCameraPanSettings; + private CameraHeadBob _cameraHeadBob; + + private void Awake() + { + _playerCamera = Camera.main; + + if (_cameraPanController == null) + { + _cameraPanController = FindFirstObjectByType(); + } + + _cameraHeadBob = FindFirstObjectByType(); + } + + private void Update() + { + if (_isBoardActive) + { + HandleBoardInteraction(); + } + else + { + CheckForBoardActivation(); + } + } + + /// + /// Checks if player is looking at the board and in range to activate. + /// + private void CheckForBoardActivation() + { + if (_playerCamera == null || _boardTransform == null) + return; + + float distanceToBoard = Vector3.Distance(_playerCamera.transform.position, _boardTransform.position); + if (distanceToBoard > _activationRange) + return; + + Ray ray = new Ray(_playerCamera.transform.position, _playerCamera.transform.forward); + if (Physics.Raycast(ray, out RaycastHit hit, _activationRange, _boardLayer)) + { + if (hit.transform.IsChildOf(_boardTransform) || hit.transform == _boardTransform) + { + var interactAction = PlayerInput.GetInteractAction(); + if (interactAction != null && interactAction.WasPressedThisFrame()) + { + ActivateBoard(); + } + } + } + } + + /// + /// Activates the detective board, switching to pan mode with wide-angle settings. + /// + public void ActivateBoard() + { + if (_cameraPanController == null || _boardCameraPanSettings == null) + { + Debug.LogError("[DetectiveBoardController] Missing required references!"); + return; + } + + _isBoardActive = true; + + _originalCameraPanSettings = _cameraPanController.Settings; + _cameraPanController.Settings = _boardCameraPanSettings; + + _cameraPanController.SaveOriginalState(); + _cameraPanController.AlignToTarget(_boardTransform, () => + { + _cameraPanController.StartPan(); + }); + + PlayerInput.SetContext(PlayerInput.InputContext.Listening); + + ApplyHeadBobSettings(_boardCameraPanSettings); + + Debug.Log("[DetectiveBoardController] Detective board activated"); + } + + /// + /// Handles board interaction while active (panning and exit). + /// + private void HandleBoardInteraction() + { + if (_cameraPanController != null) + { + _cameraPanController.UpdatePan(); + } + + var exitAction = PlayerInput.GetExitAction(); + if (exitAction != null && exitAction.WasPressedThisFrame()) + { + DeactivateBoard(); + } + } + + /// + /// Deactivates the board and returns to normal gameplay. + /// + public void DeactivateBoard() + { + if (!_isBoardActive) + return; + + _isBoardActive = false; + + if (_cameraPanController != null) + { + _cameraPanController.StopPan(); + _cameraPanController.ReturnToOriginalPosition(() => + { + if (_originalCameraPanSettings != null) + { + _cameraPanController.Settings = _originalCameraPanSettings; + } + }); + } + + PlayerInput.SetContext(PlayerInput.InputContext.Normal); + + RestoreHeadBob(); + + Debug.Log("[DetectiveBoardController] Detective board deactivated"); + } + + /// + /// Applies head bob settings based on CameraPanSettings configuration. + /// + private void ApplyHeadBobSettings(CameraPanSettings settings) + { + if (_cameraHeadBob == null || settings == null) + return; + + _cameraHeadBob.SetMode(settings.HeadBobMode); + } + + /// + /// Restores head bob to normal behavior. + /// + private void RestoreHeadBob() + { + if (_cameraHeadBob == null) + return; + + _cameraHeadBob.ClearOverride(); + } + + private void OnDrawGizmosSelected() + { + if (_boardTransform == null) + return; + + Gizmos.color = _isBoardActive ? Color.green : Color.yellow; + Gizmos.DrawWireSphere(_boardTransform.position, _activationRange); + } + } +} diff --git a/Assets/Unheimlich_POC/Scripts/Gameplay/DetectiveBoard/DetectiveBoardController.cs.meta b/Assets/Unheimlich_POC/Scripts/Gameplay/DetectiveBoard/DetectiveBoardController.cs.meta new file mode 100644 index 00000000..3f528b28 --- /dev/null +++ b/Assets/Unheimlich_POC/Scripts/Gameplay/DetectiveBoard/DetectiveBoardController.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 9f9f72364623a2a4bb50f02537fd2e72 \ No newline at end of file diff --git a/Assets/Unheimlich_POC/Scripts/Gameplay/GameObjects/Player/CameraHeadBob.cs b/Assets/Unheimlich_POC/Scripts/Gameplay/GameObjects/Player/CameraHeadBob.cs index 34b74963..f900c943 100644 --- a/Assets/Unheimlich_POC/Scripts/Gameplay/GameObjects/Player/CameraHeadBob.cs +++ b/Assets/Unheimlich_POC/Scripts/Gameplay/GameObjects/Player/CameraHeadBob.cs @@ -1,5 +1,6 @@ using UnityEngine; using Unheimlich.Interactions.Core; +using Unheimlich.Data.CameraSettings; namespace Unheimlich.Gameplay.Player { @@ -21,6 +22,9 @@ namespace Unheimlich.Gameplay.Player private PlayerMovement _playerMovement; private float _timer = 0f; private Vector3 _startLocalPos; + + private HeadBobMode _overrideMode = HeadBobMode.Normal; + private bool _hasOverride = false; void Start() { @@ -33,7 +37,15 @@ namespace Unheimlich.Gameplay.Player if (_playerMovement == null || _playerMovement.CharacterController == null) return; - if (PlayerInspectionHandler.Instance != null && PlayerInspectionHandler.Instance.IsInspecting) + HeadBobMode currentMode = _hasOverride ? _overrideMode : HeadBobMode.Normal; + + if (currentMode == HeadBobMode.Disabled) + { + ResetPosition(); + return; + } + + if (currentMode == HeadBobMode.Idle || (PlayerInspectionHandler.Instance != null && PlayerInspectionHandler.Instance.IsInspecting)) { ApplyBob(_idleBobSpeed, _idleBobAmplitude); return; @@ -52,6 +64,23 @@ namespace Unheimlich.Gameplay.Player else ResetPosition(); } + + /// + /// Sets the head bob mode override. + /// + public void SetMode(HeadBobMode mode) + { + _overrideMode = mode; + _hasOverride = true; + } + + /// + /// Clears the override and returns to normal behavior. + /// + public void ClearOverride() + { + _hasOverride = false; + } private void ApplyBob(float speed, float amplitude) { diff --git a/Assets/Unheimlich_POC/Scripts/Gameplay/GameObjects/Player/DiapasonListeningHandler.cs b/Assets/Unheimlich_POC/Scripts/Gameplay/GameObjects/Player/DiapasonListeningHandler.cs index 5526ba31..c00cab1b 100644 --- a/Assets/Unheimlich_POC/Scripts/Gameplay/GameObjects/Player/DiapasonListeningHandler.cs +++ b/Assets/Unheimlich_POC/Scripts/Gameplay/GameObjects/Player/DiapasonListeningHandler.cs @@ -60,10 +60,6 @@ namespace Unheimlich.Gameplay.Player [Header("Touch Settings")] [SerializeField] private float _touchDistance = 2f; - [Header("Input Action")] - [SerializeField] private InputActionReference _diapasonAction; - [SerializeField] private InputActionReference _fireAction; - public bool IsListening { get; private set; } public bool IsConcentrating { get; private set; } @@ -118,11 +114,6 @@ namespace Unheimlich.Gameplay.Player { _handTouchFeedback.SetActive(false); } - - if (_diapasonAction == null) - { - Debug.LogError("[Diapason] _diapasonAction is NOT assigned! Please assign it in the Inspector."); - } } private void Update() @@ -132,7 +123,8 @@ namespace Unheimlich.Gameplay.Player CheckForNearbyEmitter(); } - if (_diapasonAction != null && _diapasonAction.action.WasPressedThisFrame()) + var diapasonAction = InputManager.GetDiapasonAction(); + if (diapasonAction != null && diapasonAction.WasPressedThisFrame()) { if (!IsListening && !IsConcentrating && _canUseDiapason) { @@ -419,7 +411,8 @@ namespace Unheimlich.Gameplay.Player } bool firePressed = false; - if (_fireAction != null && _fireAction.action != null && _fireAction.action.WasPressedThisFrame()) + var fireAction = InputManager.GetFireAction(); + if (fireAction != null && fireAction.WasPressedThisFrame()) { firePressed = true; } diff --git a/Assets/Unheimlich_POC/Scripts/Gameplay/GameObjects/Player/PlayerMovement.cs b/Assets/Unheimlich_POC/Scripts/Gameplay/GameObjects/Player/PlayerMovement.cs index 9d01b3ba..1f8c65e4 100644 --- a/Assets/Unheimlich_POC/Scripts/Gameplay/GameObjects/Player/PlayerMovement.cs +++ b/Assets/Unheimlich_POC/Scripts/Gameplay/GameObjects/Player/PlayerMovement.cs @@ -49,7 +49,8 @@ namespace Unheimlich.Gameplay.Player { _ySpeed = _groundedGravity; - if (PlayerInputManager.Instance.JumpAction.action.WasPressedThisFrame()) + var jumpAction = PlayerInputManager.GetJumpAction(); + if (jumpAction != null && jumpAction.WasPressedThisFrame()) _ySpeed = _jumpForce; } else diff --git a/Assets/Unheimlich_POC/Scripts/Handlers/DetectiveBoard.meta b/Assets/Unheimlich_POC/Scripts/Handlers/DetectiveBoard.meta new file mode 100644 index 00000000..15c16db2 --- /dev/null +++ b/Assets/Unheimlich_POC/Scripts/Handlers/DetectiveBoard.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e555ea44c35017a42be4dd7fc559e05b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Unheimlich_POC/Scripts/Handlers/DetectiveBoard/ClueUnlockOnAudio.cs b/Assets/Unheimlich_POC/Scripts/Handlers/DetectiveBoard/ClueUnlockOnAudio.cs new file mode 100644 index 00000000..4f7aa37f --- /dev/null +++ b/Assets/Unheimlich_POC/Scripts/Handlers/DetectiveBoard/ClueUnlockOnAudio.cs @@ -0,0 +1,115 @@ +using UnityEngine; +using Unheimlich.Data.DetectiveBoard; +using Unheimlich.Managers; + +namespace Unheimlich.Handlers.DetectiveBoard +{ + /// + /// Unlocks a clue when a specific audio source plays or finishes playing. + /// Useful for triggering clues based on environmental sounds, dialogue, or hallucinations. + /// + [RequireComponent(typeof(AudioSource))] + public class ClueUnlockOnAudio : MonoBehaviour + { + public enum UnlockTrigger + { + OnPlay, + OnFinish, + OnTimeReached + } + + [Header("Clue Configuration")] + [Tooltip("The clue to unlock")] + [SerializeField] private ClueData _clueToUnlock; + + [Header("Audio Trigger")] + [Tooltip("When to unlock the clue")] + [SerializeField] private UnlockTrigger _trigger = UnlockTrigger.OnPlay; + + [Tooltip("Time in seconds to wait before unlocking (only for OnTimeReached)")] + [SerializeField] private float _unlockTime = 1f; + + private AudioSource _audioSource; + private bool _hasUnlocked; + private bool _isMonitoring; + private float _currentTime; + + private void Awake() + { + _audioSource = GetComponent(); + } + + private void OnEnable() + { + if (_audioSource != null && _audioSource.isPlaying) + { + StartMonitoring(); + } + } + + private void Update() + { + if (!_isMonitoring || _hasUnlocked) + return; + + if (_audioSource == null || !_audioSource.isPlaying) + { + if (_trigger == UnlockTrigger.OnFinish && _isMonitoring) + { + UnlockClue(); + } + _isMonitoring = false; + return; + } + + _currentTime = _audioSource.time; + + if (_trigger == UnlockTrigger.OnTimeReached && _currentTime >= _unlockTime) + { + UnlockClue(); + } + } + + /// + /// Call this when the audio starts playing. + /// + public void OnAudioPlay() + { + StartMonitoring(); + + if (_trigger == UnlockTrigger.OnPlay) + { + UnlockClue(); + } + } + + private void StartMonitoring() + { + _isMonitoring = true; + _currentTime = 0f; + } + + private void UnlockClue() + { + if (_hasUnlocked || _clueToUnlock == null) + return; + + if (DetectiveBoardManager.Instance != null) + { + DetectiveBoardManager.Instance.UnlockClue(_clueToUnlock); + _hasUnlocked = true; + + Debug.Log($"[ClueUnlockOnAudio] Unlocked clue: {_clueToUnlock.Title} via audio trigger"); + } + } + + /// + /// Resets the unlock state. + /// + public void ResetUnlock() + { + _hasUnlocked = false; + _isMonitoring = false; + } + } +} diff --git a/Assets/Unheimlich_POC/Scripts/Handlers/DetectiveBoard/ClueUnlockOnAudio.cs.meta b/Assets/Unheimlich_POC/Scripts/Handlers/DetectiveBoard/ClueUnlockOnAudio.cs.meta new file mode 100644 index 00000000..4291cb31 --- /dev/null +++ b/Assets/Unheimlich_POC/Scripts/Handlers/DetectiveBoard/ClueUnlockOnAudio.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: fcedba870c1ea9642a272a53148bb933 \ No newline at end of file diff --git a/Assets/Unheimlich_POC/Scripts/Handlers/DetectiveBoard/ClueUnlockOnInteraction.cs b/Assets/Unheimlich_POC/Scripts/Handlers/DetectiveBoard/ClueUnlockOnInteraction.cs new file mode 100644 index 00000000..279f02d6 --- /dev/null +++ b/Assets/Unheimlich_POC/Scripts/Handlers/DetectiveBoard/ClueUnlockOnInteraction.cs @@ -0,0 +1,43 @@ +using UnityEngine; +using Unheimlich.Data.DetectiveBoard; +using Unheimlich.Interactions.Core; +using Unheimlich.Managers; + +namespace Unheimlich.Handlers.DetectiveBoard +{ + /// + /// Unlocks a clue when the player interacts with this object. + /// Extends InteractableBase to integrate with the existing interaction system. + /// + public class ClueUnlockOnInteraction : InteractableBase + { + [Header("Clue Configuration")] + [Tooltip("The clue to unlock when player interacts")] + [SerializeField] private ClueData _clueToUnlock; + + [Tooltip("Only unlock once")] + [SerializeField] private bool _unlockOnlyOnce = true; + + private bool _hasUnlocked; + + public override void Interact(GameObject interactor) + { + if (_unlockOnlyOnce && _hasUnlocked) + return; + + if (_clueToUnlock == null) + { + Debug.LogError("[ClueUnlockOnInteraction] No clue data assigned!"); + return; + } + + if (DetectiveBoardManager.Instance != null) + { + DetectiveBoardManager.Instance.UnlockClue(_clueToUnlock); + _hasUnlocked = true; + + Debug.Log($"[ClueUnlockOnInteraction] Unlocked clue: {_clueToUnlock.Title} via interaction"); + } + } + } +} diff --git a/Assets/Unheimlich_POC/Scripts/Handlers/DetectiveBoard/ClueUnlockOnInteraction.cs.meta b/Assets/Unheimlich_POC/Scripts/Handlers/DetectiveBoard/ClueUnlockOnInteraction.cs.meta new file mode 100644 index 00000000..69ceb38d --- /dev/null +++ b/Assets/Unheimlich_POC/Scripts/Handlers/DetectiveBoard/ClueUnlockOnInteraction.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: cca584f48d1f0ab429416470fd01d543 \ No newline at end of file diff --git a/Assets/Unheimlich_POC/Scripts/Handlers/DetectiveBoard/ClueUnlockTrigger.cs b/Assets/Unheimlich_POC/Scripts/Handlers/DetectiveBoard/ClueUnlockTrigger.cs new file mode 100644 index 00000000..c26dad5b --- /dev/null +++ b/Assets/Unheimlich_POC/Scripts/Handlers/DetectiveBoard/ClueUnlockTrigger.cs @@ -0,0 +1,105 @@ +using UnityEngine; +using Unheimlich.Data.DetectiveBoard; +using Unheimlich.Managers; + +namespace Unheimlich.Handlers.DetectiveBoard +{ + /// + /// Generic trigger to unlock clues on the detective board. + /// Can be triggered by any game event: dialogue, object interaction, audio cue, hallucination, etc. + /// Simply call UnlockClue() when the trigger condition is met. + /// + public class ClueUnlockTrigger : MonoBehaviour + { + [Header("Clue Configuration")] + [Tooltip("The clue data to unlock when triggered")] + [SerializeField] private ClueData _clueToUnlock; + + [Header("Trigger Settings")] + [Tooltip("Automatically unlock on Start()")] + [SerializeField] private bool _unlockOnStart; + + [Tooltip("Unlock when this GameObject is enabled")] + [SerializeField] private bool _unlockOnEnable; + + [Tooltip("Delay before unlocking (useful for sequencing)")] + [SerializeField] private float _unlockDelay; + + [Tooltip("Show debug messages")] + [SerializeField] private bool _debugMode; + + private bool _hasUnlocked; + + private void Start() + { + if (_unlockOnStart) + { + UnlockClue(); + } + } + + private void OnEnable() + { + if (_unlockOnEnable && !_hasUnlocked) + { + UnlockClue(); + } + } + + /// + /// Unlocks the associated clue. Can be called from external scripts, events, or animations. + /// + public void UnlockClue() + { + if (_hasUnlocked) + { + if (_debugMode) + Debug.LogWarning($"[ClueUnlockTrigger] Clue '{_clueToUnlock?.Title}' already unlocked!"); + return; + } + + if (_clueToUnlock == null) + { + Debug.LogError("[ClueUnlockTrigger] No clue data assigned!"); + return; + } + + if (_unlockDelay > 0f) + { + Invoke(nameof(UnlockClueImmediate), _unlockDelay); + } + else + { + UnlockClueImmediate(); + } + } + + private void UnlockClueImmediate() + { + if (DetectiveBoardManager.Instance != null) + { + DetectiveBoardManager.Instance.UnlockClue(_clueToUnlock); + _hasUnlocked = true; + + if (_debugMode) + Debug.Log($"[ClueUnlockTrigger] Unlocked clue: {_clueToUnlock.Title}"); + + OnClueUnlocked?.Invoke(); + } + else + { + Debug.LogError("[ClueUnlockTrigger] DetectiveBoardManager not found!"); + } + } + + /// + /// Resets the unlock state (useful for testing). + /// + public void ResetUnlock() + { + _hasUnlocked = false; + } + + public event System.Action OnClueUnlocked; + } +} diff --git a/Assets/Unheimlich_POC/Scripts/Handlers/DetectiveBoard/ClueUnlockTrigger.cs.meta b/Assets/Unheimlich_POC/Scripts/Handlers/DetectiveBoard/ClueUnlockTrigger.cs.meta new file mode 100644 index 00000000..2cfa6eb2 --- /dev/null +++ b/Assets/Unheimlich_POC/Scripts/Handlers/DetectiveBoard/ClueUnlockTrigger.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 61b90106a531ea840b670f368e2c8aa9 \ No newline at end of file diff --git a/Assets/Unheimlich_POC/Scripts/Handlers/Interactions/InteracionHandler.cs b/Assets/Unheimlich_POC/Scripts/Handlers/Interactions/InteracionHandler.cs index b7d12c92..3768d91a 100644 --- a/Assets/Unheimlich_POC/Scripts/Handlers/Interactions/InteracionHandler.cs +++ b/Assets/Unheimlich_POC/Scripts/Handlers/Interactions/InteracionHandler.cs @@ -44,8 +44,8 @@ namespace Unheimlich.Interactions.Core private void HandleInteractionInput() { - if (PlayerInputManager.Instance != null && - PlayerInputManager.Instance.InteractAction.action.WasPressedThisFrame()) + var interactAction = PlayerInputManager.GetInteractAction(); + if (interactAction != null && interactAction.WasPressedThisFrame()) { if (_currentInteractable != null) _currentInteractable.Interact(transform.parent.gameObject); diff --git a/Assets/Unheimlich_POC/Scripts/Handlers/Interactions/PlayerInspectionHandler.cs b/Assets/Unheimlich_POC/Scripts/Handlers/Interactions/PlayerInspectionHandler.cs index 1c93724e..30af9184 100644 --- a/Assets/Unheimlich_POC/Scripts/Handlers/Interactions/PlayerInspectionHandler.cs +++ b/Assets/Unheimlich_POC/Scripts/Handlers/Interactions/PlayerInspectionHandler.cs @@ -87,7 +87,8 @@ namespace Unheimlich.Interactions.Core while (IsInspecting) { - if (InputManager.Instance.InteractAction.action.WasPressedThisFrame()) + var interactAction = InputManager.GetInteractAction(); + if (interactAction != null && interactAction.WasPressedThisFrame()) { StopInspectionInternal(); yield break; diff --git a/Assets/Unheimlich_POC/Scripts/Managers/DetectiveBoardManager.cs b/Assets/Unheimlich_POC/Scripts/Managers/DetectiveBoardManager.cs new file mode 100644 index 00000000..10b410a7 --- /dev/null +++ b/Assets/Unheimlich_POC/Scripts/Managers/DetectiveBoardManager.cs @@ -0,0 +1,193 @@ +using System.Collections.Generic; +using UnityEngine; +using Unheimlich.Core; +using Unheimlich.Data.DetectiveBoard; + +namespace Unheimlich.Managers +{ + /// + /// Manages the detective board state and clue unlocking system. + /// Tracks unlocked clues, connections, certainty levels, and eliminated hypotheses. + /// Does NOT affect game progression - purely interpretive tool for the player. + /// + public class DetectiveBoardManager : Singleton + { + public enum CertaintyLevel + { + Uncertain, + Possible, + Confident, + Certain + } + + public class ClueState + { + public ClueData Data; + public bool IsUnlocked; + public bool IsEliminated; + public Vector2 BoardPosition; + } + + public class Connection + { + public string FromClueID; + public string ToClueID; + public CertaintyLevel Certainty; + public bool IsEliminated; + } + + [Header("References")] + [SerializeField] private DetectiveBoardSettings _settings; + + private Dictionary _clueStates = new Dictionary(); + private List _connections = new List(); + + public DetectiveBoardSettings Settings => _settings; + public IReadOnlyDictionary ClueStates => _clueStates; + public IReadOnlyList Connections => _connections; + + /// + /// Unlocks a clue on the detective board. Can be triggered by any in-game event. + /// + public void UnlockClue(ClueData clueData) + { + if (clueData == null) + { + Debug.LogError("[DetectiveBoardManager] Attempted to unlock null clue!"); + return; + } + + if (!_clueStates.ContainsKey(clueData.ClueID)) + { + _clueStates[clueData.ClueID] = new ClueState + { + Data = clueData, + IsUnlocked = true, + IsEliminated = false, + BoardPosition = clueData.InitialPosition + }; + + Debug.Log($"[DetectiveBoardManager] Unlocked clue: {clueData.Title}"); + OnClueUnlocked?.Invoke(clueData); + } + else if (!_clueStates[clueData.ClueID].IsUnlocked) + { + _clueStates[clueData.ClueID].IsUnlocked = true; + Debug.Log($"[DetectiveBoardManager] Unlocked clue: {clueData.Title}"); + OnClueUnlocked?.Invoke(clueData); + } + } + + /// + /// Unlocks a clue by its ID string. + /// + public void UnlockClueByID(string clueID) + { + if (_clueStates.TryGetValue(clueID, out ClueState state)) + { + if (!state.IsUnlocked) + { + state.IsUnlocked = true; + Debug.Log($"[DetectiveBoardManager] Unlocked clue: {state.Data.Title}"); + OnClueUnlocked?.Invoke(state.Data); + } + } + else + { + Debug.LogWarning($"[DetectiveBoardManager] Clue ID '{clueID}' not found!"); + } + } + + /// + /// Registers a clue in the system without unlocking it. + /// + public void RegisterClue(ClueData clueData) + { + if (clueData == null || _clueStates.ContainsKey(clueData.ClueID)) + return; + + _clueStates[clueData.ClueID] = new ClueState + { + Data = clueData, + IsUnlocked = false, + IsEliminated = false, + BoardPosition = clueData.InitialPosition + }; + } + + /// + /// Creates a connection between two clues. + /// + public void CreateConnection(string fromClueID, string toClueID, CertaintyLevel certainty = CertaintyLevel.Uncertain) + { + if (!_clueStates.ContainsKey(fromClueID) || !_clueStates.ContainsKey(toClueID)) + { + Debug.LogWarning($"[DetectiveBoardManager] Cannot create connection - one or both clues not found!"); + return; + } + + Connection existing = _connections.Find(c => + (c.FromClueID == fromClueID && c.ToClueID == toClueID) || + (c.FromClueID == toClueID && c.ToClueID == fromClueID)); + + if (existing != null) + { + existing.Certainty = certainty; + } + else + { + _connections.Add(new Connection + { + FromClueID = fromClueID, + ToClueID = toClueID, + Certainty = certainty, + IsEliminated = false + }); + + OnConnectionCreated?.Invoke(fromClueID, toClueID); + } + } + + /// + /// Marks a clue as eliminated (incorrect hypothesis). + /// + public void EliminateClue(string clueID) + { + if (_clueStates.TryGetValue(clueID, out ClueState state)) + { + state.IsEliminated = true; + OnClueEliminated?.Invoke(clueID); + } + } + + /// + /// Marks a connection as eliminated. + /// + public void EliminateConnection(string fromClueID, string toClueID) + { + Connection connection = _connections.Find(c => + (c.FromClueID == fromClueID && c.ToClueID == toClueID) || + (c.FromClueID == toClueID && c.ToClueID == fromClueID)); + + if (connection != null) + { + connection.IsEliminated = true; + } + } + + /// + /// Updates a clue's position on the board. + /// + public void UpdateCluePosition(string clueID, Vector2 newPosition) + { + if (_clueStates.TryGetValue(clueID, out ClueState state)) + { + state.BoardPosition = newPosition; + } + } + + public event System.Action OnClueUnlocked; + public event System.Action OnConnectionCreated; + public event System.Action OnClueEliminated; + } +} diff --git a/Assets/Unheimlich_POC/Scripts/Managers/DetectiveBoardManager.cs.meta b/Assets/Unheimlich_POC/Scripts/Managers/DetectiveBoardManager.cs.meta new file mode 100644 index 00000000..d557c6d1 --- /dev/null +++ b/Assets/Unheimlich_POC/Scripts/Managers/DetectiveBoardManager.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 4b187cdccaa498441a752e8f49ff4290 \ No newline at end of file diff --git a/Assets/Unheimlich_POC/Scripts/Managers/DialogueManager.cs b/Assets/Unheimlich_POC/Scripts/Managers/DialogueManager.cs index d66fb90e..9f731dd5 100644 --- a/Assets/Unheimlich_POC/Scripts/Managers/DialogueManager.cs +++ b/Assets/Unheimlich_POC/Scripts/Managers/DialogueManager.cs @@ -107,8 +107,8 @@ namespace Unheimlich.Managers } } - if (PlayerInputManager.Instance != null && - PlayerInputManager.Instance.InteractAction.action.WasPressedThisFrame()) + var interactAction = PlayerInputManager.GetInteractAction(); + if (interactAction != null && interactAction.WasPressedThisFrame()) { EndDialogue(); } diff --git a/Assets/Unheimlich_POC/Scripts/Managers/PlayerInputManager.cs b/Assets/Unheimlich_POC/Scripts/Managers/PlayerInputManager.cs index 61770f5d..3b91ce63 100644 --- a/Assets/Unheimlich_POC/Scripts/Managers/PlayerInputManager.cs +++ b/Assets/Unheimlich_POC/Scripts/Managers/PlayerInputManager.cs @@ -26,18 +26,19 @@ namespace Unheimlich.Managers [Header("Input Values (Read only)")] public Vector2 MoveInput; public Vector2 LookInput; - public InputActionReference JumpAction; - public InputActionReference InteractAction; - public InputActionReference DiapasonAction; public static bool IsInputEnabled { get; private set; } = true; public static bool IsLookingEnabled { get; private set; } = true; public static InputContext CurrentContext { get; private set; } = InputContext.Normal; private InputActionMap _playerActionMap; + private InputAction _moveAction; private InputAction _lookAction; + private InputAction _jumpAction; private InputAction _interactAction; private InputAction _diapasonAction; + private InputAction _fireAction; + private InputAction _exitAction; private PlayerMovement _playerMovement; private PlayerLook _playerLook; @@ -51,14 +52,13 @@ namespace Unheimlich.Managers playerInput.actions.Enable(); _playerActionMap = playerInput.actions.FindActionMap("Player"); + _moveAction = _playerActionMap.FindAction("Move"); _lookAction = _playerActionMap.FindAction("Look"); + _jumpAction = _playerActionMap.FindAction("Jump"); _interactAction = _playerActionMap.FindAction("Interact"); _diapasonAction = _playerActionMap.FindAction("Diapason"); - - JumpAction.action.Enable(); - InteractAction.action.Enable(); - if (DiapasonAction != null) - DiapasonAction.action.Enable(); + _fireAction = _playerActionMap.FindAction("Fire"); + _exitAction = _playerActionMap.FindAction("Exit"); _playerMovement = GetComponent(); _playerLook = GetComponent(); @@ -101,7 +101,11 @@ namespace Unheimlich.Managers Instance._lookAction.Enable(); if (Instance._diapasonAction != null) Instance._diapasonAction.Enable(); - Instance.SetComponentsEnabled(false, false, false); + if (Instance._fireAction != null) + Instance._fireAction.Enable(); + if (Instance._exitAction != null) + Instance._exitAction.Enable(); + Instance.SetComponentsEnabled(false, false, true); IsInputEnabled = false; IsLookingEnabled = false; break; @@ -152,5 +156,24 @@ namespace Unheimlich.Managers public void OnDiapason(InputAction.CallbackContext context) { } + + public void OnFire(InputAction.CallbackContext context) + { + } + + public void OnExit(InputAction.CallbackContext context) + { + } + + /// + /// Provides public access to input actions for other systems. + /// + public static InputAction GetMoveAction() => Instance?._moveAction; + public static InputAction GetLookAction() => Instance?._lookAction; + public static InputAction GetJumpAction() => Instance?._jumpAction; + public static InputAction GetInteractAction() => Instance?._interactAction; + public static InputAction GetDiapasonAction() => Instance?._diapasonAction; + public static InputAction GetFireAction() => Instance?._fireAction; + public static InputAction GetExitAction() => Instance?._exitAction; } } diff --git a/Assets/Unheimlich_POC/Scripts/UI/DetectiveBoard.meta b/Assets/Unheimlich_POC/Scripts/UI/DetectiveBoard.meta new file mode 100644 index 00000000..a88ed1d2 --- /dev/null +++ b/Assets/Unheimlich_POC/Scripts/UI/DetectiveBoard.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2516dfad26afafc43b9ec93eda9f2155 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Unheimlich_POC/Scripts/UI/DetectiveBoard/ClueNodeUI.cs b/Assets/Unheimlich_POC/Scripts/UI/DetectiveBoard/ClueNodeUI.cs new file mode 100644 index 00000000..097a1807 --- /dev/null +++ b/Assets/Unheimlich_POC/Scripts/UI/DetectiveBoard/ClueNodeUI.cs @@ -0,0 +1,93 @@ +using UnityEngine; +using UnityEngine.UI; +using TMPro; +using Unheimlich.Data.DetectiveBoard; + +namespace Unheimlich.UI.DetectiveBoard +{ + /// + /// Visual representation of a clue node on the detective board. + /// Displays as a post-it/card with title, description, and icon. + /// Supports visual states: unlocked, eliminated, highlighted. + /// + public class ClueNodeUI : MonoBehaviour + { + [Header("References")] + [SerializeField] private Image _nodeImage; + [SerializeField] private TextMeshProUGUI _titleText; + [SerializeField] private Image _iconImage; + [SerializeField] private GameObject _eliminatedOverlay; + + private ClueData _clueData; + private bool _isEliminated; + private Color _originalColor; + + public ClueData ClueData => _clueData; + public bool IsEliminated => _isEliminated; + + /// + /// Initializes the node with clue data. + /// + public void Initialize(ClueData clueData) + { + _clueData = clueData; + + if (_titleText != null) + _titleText.text = clueData.Title; + + if (_iconImage != null && clueData.Icon != null) + { + _iconImage.sprite = clueData.Icon; + _iconImage.enabled = true; + } + else if (_iconImage != null) + { + _iconImage.enabled = false; + } + + if (_nodeImage != null) + { + _originalColor = clueData.NodeColor; + _nodeImage.color = _originalColor; + } + + if (_eliminatedOverlay != null) + _eliminatedOverlay.SetActive(false); + } + + /// + /// Marks this node as eliminated (incorrect hypothesis). + /// + public void SetEliminated(bool eliminated) + { + _isEliminated = eliminated; + + if (_eliminatedOverlay != null) + _eliminatedOverlay.SetActive(eliminated); + + if (_nodeImage != null) + { + _nodeImage.color = eliminated ? Color.gray : _originalColor; + } + } + + /// + /// Highlights the node when hovered. + /// + public void SetHighlighted(bool highlighted, Color highlightColor) + { + if (_nodeImage != null && !_isEliminated) + { + _nodeImage.color = highlighted ? highlightColor : _originalColor; + } + } + + /// + /// Updates the position of this node on the board (world space or canvas). + /// + public void SetPosition(Vector3 position) + { + transform.position = position; + } + } +} diff --git a/Assets/Unheimlich_POC/Scripts/UI/DetectiveBoard/ClueNodeUI.cs.meta b/Assets/Unheimlich_POC/Scripts/UI/DetectiveBoard/ClueNodeUI.cs.meta new file mode 100644 index 00000000..6f970837 --- /dev/null +++ b/Assets/Unheimlich_POC/Scripts/UI/DetectiveBoard/ClueNodeUI.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: a7086ec4620627b458b08500e412ee90 \ No newline at end of file diff --git a/Assets/Unheimlich_POC/Scripts/UI/DetectiveBoard/ConnectionLineRenderer.cs b/Assets/Unheimlich_POC/Scripts/UI/DetectiveBoard/ConnectionLineRenderer.cs new file mode 100644 index 00000000..c3715742 --- /dev/null +++ b/Assets/Unheimlich_POC/Scripts/UI/DetectiveBoard/ConnectionLineRenderer.cs @@ -0,0 +1,90 @@ +using UnityEngine; +using Unheimlich.Managers; + +namespace Unheimlich.UI.DetectiveBoard +{ + /// + /// Renders a connection line between two clue nodes on the detective board. + /// Visual style changes based on certainty level and elimination state. + /// + [RequireComponent(typeof(LineRenderer))] + public class ConnectionLineRenderer : MonoBehaviour + { + private LineRenderer _lineRenderer; + private string _fromClueID; + private string _toClueID; + private DetectiveBoardManager.CertaintyLevel _certainty; + private bool _isEliminated; + + public string FromClueID => _fromClueID; + public string ToClueID => _toClueID; + + private void Awake() + { + _lineRenderer = GetComponent(); + } + + /// + /// Initializes the connection line between two nodes. + /// + public void Initialize(string fromClueID, string toClueID, + DetectiveBoardManager.CertaintyLevel certainty, Color color, float width) + { + _fromClueID = fromClueID; + _toClueID = toClueID; + _certainty = certainty; + + if (_lineRenderer != null) + { + _lineRenderer.startWidth = width; + _lineRenderer.endWidth = width; + _lineRenderer.material = new Material(Shader.Find("Sprites/Default")); + _lineRenderer.startColor = color; + _lineRenderer.endColor = color; + } + } + + /// + /// Updates the line positions based on node transforms. + /// + public void UpdateLine(Vector3 startPos, Vector3 endPos) + { + if (_lineRenderer != null) + { + _lineRenderer.SetPosition(0, startPos); + _lineRenderer.SetPosition(1, endPos); + } + } + + /// + /// Updates the certainty level and visual appearance. + /// + public void SetCertainty(DetectiveBoardManager.CertaintyLevel certainty, Color color) + { + _certainty = certainty; + + if (_lineRenderer != null) + { + _lineRenderer.startColor = color; + _lineRenderer.endColor = color; + } + } + + /// + /// Marks this connection as eliminated. + /// + public void SetEliminated(bool eliminated) + { + _isEliminated = eliminated; + + if (_lineRenderer != null) + { + float alpha = eliminated ? 0.3f : 1f; + Color color = _lineRenderer.startColor; + color.a = alpha; + _lineRenderer.startColor = color; + _lineRenderer.endColor = color; + } + } + } +} diff --git a/Assets/Unheimlich_POC/Scripts/UI/DetectiveBoard/ConnectionLineRenderer.cs.meta b/Assets/Unheimlich_POC/Scripts/UI/DetectiveBoard/ConnectionLineRenderer.cs.meta new file mode 100644 index 00000000..77229511 --- /dev/null +++ b/Assets/Unheimlich_POC/Scripts/UI/DetectiveBoard/ConnectionLineRenderer.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 8d829d9811842b241b980bd64ab73bff \ No newline at end of file diff --git a/ProjectSettings/TagManager.asset b/ProjectSettings/TagManager.asset index 8c6f49a2..0f5cac93 100644 --- a/ProjectSettings/TagManager.asset +++ b/ProjectSettings/TagManager.asset @@ -12,7 +12,7 @@ TagManager: - Water - UI - Words - - + - DetectiveBoard - - -