using DG.Tweening; using TMPro; using UnityEngine; public class CafeWaiterNPC : NPCController { public FMODWhisperBridge fmodWhisperBridge; public TextMeshProUGUI notepadText; public GameObject notepad; public Transform backRoom; public float backRoomMovingTime = 5f; private Vector3 notepadOriginalRotation; private Vector3 notepadFlippedRotation; private Vector3 startingPosition; // states: // 0 - idle // 1 - waiting for player order // 2 - waiting for player to answer "is this correct?" // 3 - bringing food // 4 - waiting for player to go away private int state; private float lastPlayerVoiceUpdateTime; private void Awake() { state = 0; lastPlayerVoiceUpdateTime = Time.time; startingPosition = transform.position; } private void Start() { notepadOriginalRotation = notepad.transform.localRotation.eulerAngles; notepadFlippedRotation = notepadOriginalRotation + new Vector3(0, 180, 0); } protected override void OnPlayerApproach() { if (state == 0) { AudioManager.Instance.PlayDialogue(voiceLineKeys[0], gameObject); fmodWhisperBridge.OnWhisperSegmentUpdated += OnPlayerSpeechUpdate; fmodWhisperBridge.OnWhisperSegmentFinished += OnPlayerSpeechFinished; fmodWhisperBridge.ActivateRecording(); state = 1; } } protected override void OnPlayerLeave() { fmodWhisperBridge.OnWhisperSegmentUpdated -= OnPlayerSpeechUpdate; fmodWhisperBridge.OnWhisperSegmentFinished -= OnPlayerSpeechFinished; fmodWhisperBridge.DeactivateRecording(); // If currently not bringing food and the player leaves, then go back to idle state if (state != 3) { state = 0; } } private void OnPlayerSpeechFinished(string playerText) { if (Time.time < lastPlayerVoiceUpdateTime + 0.5f) { Debug.Log("voiceline: player said '" + playerText + "' but not enough time passed"); return; } if (string.IsNullOrEmpty(playerText) || playerText.Contains("BLANK_AUDIO")) { Debug.Log("player speech event but result empty"); return; } lastPlayerVoiceUpdateTime = Time.time; Debug.Log("state = " + state.ToString() + ", voiceline: player text: " + playerText); if (state == 1) { // Show transcription and ask whether it is correct notepadText.text = playerText; notepad.transform.DOLocalRotate(notepadFlippedRotation, 0.5f); AudioManager.Instance.PlayDialogue(voiceLineKeys[1], gameObject); state = 2; } else if (state == 2) { // Flip notepad back notepad.transform.DOLocalRotate(notepadOriginalRotation, 0.5f); // if player answered positively, bring food, otherwise ask again if (playerText.ToLower().Contains("yes")) { AudioManager.Instance.PlayDialogue(voiceLineKeys[2], gameObject); BringFood(); state = 3; } else { AudioManager.Instance.PlayDialogue(voiceLineKeys[3], gameObject); state = 1; } } } private void OnPlayerSpeechUpdate(string playerText) { if (string.IsNullOrEmpty(playerText) || playerText.Contains("BLANK_AUDIO")) { return; } notepadText.text = playerText; } private void BringFood() { notepad.SetActive(false); transform.DOMove(backRoom.position, backRoomMovingTime).OnComplete(() => { // Come back transform.DOMove(startingPosition, backRoomMovingTime).OnComplete(() => { notepad.SetActive(true); AudioManager.Instance.PlayDialogue(voiceLineKeys[4], gameObject); state = 4; }); }); } }