2026-05-30 17:41:31 +07:00
using UnityEngine ;
using UnityEngine.InputSystem ;
2026-06-05 14:57:25 +07:00
using System.Collections ;
2026-06-04 23:01:39 +07:00
using Hallucinate.Audio ;
2026-06-05 14:57:25 +07:00
using Hallucinate.AI ;
2026-06-02 10:00:42 +07:00
public class GerminiNPC : MonoBehaviour
2026-05-30 17:41:31 +07:00
{
[SerializeField]
2026-06-05 14:57:25 +07:00
private string npcPersona =
2026-06-02 10:00:42 +07:00
"Ngươi là một lão thợ rèn cọc cằn tên là Tom, ngươi rất ghét những kẻ mang phế liệu đến tiệm của mình. Chỉ trả lời ngắn gọn trong 2 câu, theo phong cách trung cổ." ;
2026-05-30 17:41:31 +07:00
public string playerHeldItem = "Thanh kiếm rỉ sét" ;
2026-06-02 10:00:42 +07:00
public float interactionDistance = 5f ; // Khoảng cách tối đa để nói chuyện
public Transform playerTransform ; // Gán transform của Player vào đây
2026-05-30 17:41:31 +07:00
2026-06-04 23:01:39 +07:00
[Header("Audio")]
public string startTalkSound = "NPC_Interact" ;
public string responseSound = "NPC_Response" ;
2026-05-30 17:41:31 +07:00
private void Update ( )
{
2026-06-02 10:00:42 +07:00
if ( Keyboard . current ! = null & & Keyboard . current . fKey . wasPressedThisFrame )
{
if ( CanSeePlayer ( ) )
{
2026-06-04 23:01:39 +07:00
AudioManager . Instance ? . Play ( startTalkSound , position : transform . position ) ;
2026-06-02 10:00:42 +07:00
StartCoroutine ( GetGerminiReponse ( ) ) ;
}
else
{
Debug . Log ( "<color=yellow>Hệ thống:</color> Bạn ở quá xa hoặc bị tường che khuất!" ) ;
}
}
}
private bool CanSeePlayer ( )
{
if ( playerTransform = = null )
{
// Tự tìm player nếu chưa gán
GameObject player = GameObject . FindGameObjectWithTag ( "Player" ) ;
if ( player ! = null ) playerTransform = player . transform ;
else return false ;
}
// 1. Check khoảng cách
float dist = Vector3 . Distance ( transform . position , playerTransform . position ) ;
if ( dist > interactionDistance ) return false ;
// 2. Check xem có bị tường che không (Raycast)
Vector3 direction = ( playerTransform . position + Vector3 . up ) - ( transform . position + Vector3 . up ) ;
RaycastHit hit ;
if ( Physics . Raycast ( transform . position + Vector3 . up , direction , out hit , interactionDistance ) )
2026-05-30 17:41:31 +07:00
{
2026-06-02 10:00:42 +07:00
if ( hit . collider . CompareTag ( "Player" ) | | hit . collider . transform . IsChildOf ( playerTransform ) )
{
return true ; // Thấy đầu/người player
}
2026-05-30 17:41:31 +07:00
}
2026-06-02 10:00:42 +07:00
return false ;
2026-05-30 17:41:31 +07:00
}
private IEnumerator GetGerminiReponse ( )
{
2026-06-05 14:57:25 +07:00
string prompt = $"Ta muốn bán cho ông món đồ này: {playerHeldItem}" ;
Hallucinate . AI . GeminiService . Instance . GetResponse ( npcPersona , prompt , ( response ) = > {
2026-06-05 21:24:41 +07:00
string finalMsg = response ;
try {
DialogueResult result = JsonUtility . FromJson < DialogueResult > ( response ) ;
finalMsg = result . text ;
} catch { }
Debug . Log ( $"<color=green>Tom:</color> {finalMsg}" ) ;
2026-06-05 14:57:25 +07:00
AudioManager . Instance ? . Play ( responseSound , position : transform . position ) ;
var bubble = GetComponentInChildren < Hallucinate . UI . ChatBubble > ( true ) ;
2026-06-05 21:24:41 +07:00
if ( bubble ! = null ) bubble . Show ( finalMsg ) ;
2026-06-05 14:57:25 +07:00
} ) ;
yield break ;
2026-05-30 17:41:31 +07:00
}
}