Firstborn/Assets/RPG Creation Kit/Scripts/Player/PlayerInteractor.cs

1483 lines
44 KiB
C#
Raw Normal View History

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
using RPGCreationKit;
using RPGCreationKit.CellsSystem;
using RPGCreationKit.DialogueSystem;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using RPGCreationKit.AI;
using XNode;
namespace RPGCreationKit.Player
{
public class PlayerInteractor : PlayerMovements, IDialoguable
{
//[SerializeField] private PlayerInteractorUI interactorUI;
[SerializeField] private LayerMask rayMask;
[SerializeField] private Transform camT;
public bool isInConversation;
public bool isInteracting;
public bool isReadingBook;
public bool isPickingLock;
public bool isLooting;
public bool isCrafting;
Ray ray;
RaycastHit rayHit;
[SerializeField] private Transform rayStartPoint;
// Dialogue
public IDialoguable speakingTo;
[SerializeField] private float dialogueDistance = 2.5f; // The distance of which a dialogue is possible
// Interact object
public InteractiveObject_Behaviour interactiveObject;
[SerializeField] private float interactiveObjectDistance = 2.5f; // The distance of which a dialogue is possible
// Looting
[HideInInspector] public LootingPoint objLooting; // If so, track the InteractiveObject
[SerializeField] private float lootingPointDistance = 2.5f; // The distance to interact with an InteractiveObject
// Crafting
[HideInInspector] public CraftingPoint objCrafting; // If so, track the InteractiveObject
[SerializeField] private float CraftingDistance = 2.5f;
// Items
[SerializeField] private float itemDistance = 2.5f;
[SerializeField] private float doorDistance = 2.5f;
private bool cameraLookNPC;
Rigidbody itemRigidbody;
private ItemInWorld dragItemScript;
Vector3 dragDirection;
[SerializeField] private float dragDistance = 2.5f;
public float dragForce = 50f;
public bool dragKeyBeingHeld;
public bool isDragging;
string cmdStr;
public void INPUT_DragKey(InputAction.CallbackContext value)
{
if (value.started)
dragKeyBeingHeld = true;
else if (value.canceled)
dragKeyBeingHeld = false;
}
public override void Start()
{
base.Start();
}
public override void Update()
{
base.Update();
// DialogueFix
if (isInConversation && !RckInput.isUsingGamepad && uiManager.allPlayerQuestions.Count > 0 && uiManager.playerQuestionsContainer.gameObject.activeInHierarchy)
Cursor.lockState = CursorLockMode.None;
if (isInCutsceneMode || !isLoaded || !IsControlledByPlayer())
{
if (uiManager.Interact_text.isActiveAndEnabled)
uiManager.Interact_text.gameObject.SetActive(false);
return;
}
if (uiManager.Interact_text.isActiveAndEnabled)
uiManager.Interact_text.gameObject.SetActive(false);
cmdStr = RckInput.isUsingGamepad ? "(A)" : "E)";
Raycast();
}
public override void FixedUpdate()
{
base.FixedUpdate();
ManageDraggable();
}
public void Raycast()
{
ray = new Ray(camT.position, camT.forward);
if(Physics.Raycast(ray, out rayHit, RCKSettings.INTERACTOR_RAYCAST_MAXDISTANCE, rayMask))
{
if (!RckPlayer.instance.iscrouching) {
if (rayHit.distance <= dialogueDistance) {
CheckForIDialoguable();
}
} else if (rayHit.distance <= lootingPointDistance) {
CheckForLootingPoint(true);
}
if (rayHit.distance <= itemDistance)
CheckForItemsInWorld();
if (rayHit.distance <= RCKSettings.PLAYER_DISTANCE_TO_DISPLAY_ENEMY_BAR) {
CheckForIDamageable();
} else {
// UnityEngine.Utility.WaitForSeconds(3.0f); @ Schaken -- Find another way to do this.
uiManager.enemyHealthContainer.SetActive(false);
}
if (rayHit.distance <= interactiveObjectDistance)
CheckForInteractiveObjects();
if (rayHit.distance <= lootingPointDistance)
CheckForLootingPoint(false);
if (rayHit.distance <= doorDistance)
CheckForDoors();
if (rayHit.distance <= dragDistance)
CheckForIDraggable();
if (rayHit.distance <= CraftingDistance)
CheckForCrafting();
}
}
private void CheckForIDialoguable()
{
IDialoguable dialoguable = rayHit.transform.gameObject.GetComponent<IDialoguable>();
if(dialoguable != null && dialoguable.CanDialogue() && !isInConversation)
{
// Set the UI
uiManager.Interact_text.gameObject.SetActive(true);
uiManager.Interact_text.text = cmdStr+" Speak: " + dialoguable.GetDialoguableName();
if (input.actions.FindAction("Interact").triggered)
{
StartDialogue(dialoguable);
}
}
}
private void CheckForItemsInWorld()
{
if(rayHit.transform.CompareTag("RPG Creation Kit/ItemInWorld"))
{
// When we find one, we save this reference
ItemInWorld obj = rayHit.transform.gameObject.GetComponent<ItemInWorld>();
if (obj == null)
return;
if (obj.hasBeenTaken)
return;
uiManager.Interact_text.gameObject.SetActive(true);
if (obj.Item is BookItem)
{
uiManager.Interact_text.text = cmdStr+" Read: " + obj.Item.ItemName;
}
else
{
string action = obj.Metadata.IsOwnedByNPC ? " Steal: " : " Take: ";
if (obj.Amount == 1)
uiManager.Interact_text.text = cmdStr + action + obj.Item.ItemName;
else
// E) Take item.name (Number)
uiManager.Interact_text.text = cmdStr + action + obj.Item.ItemName + " (" + obj.Amount + ")";
}
if (input.actions.FindAction("Interact").triggered)
{
if (obj.Item is BookItem) {
// ReadBook
if(!RckPlayer.instance.isReadingBook) {
BookReaderManager.instance.ReadBook((BookItem)obj.Item, true, obj);
}
} else {
TakeItemInWorld(obj);
}
}
}
}
public void TakeItemInWorld(ItemInWorld _item)
{
_item.hasBeenTaken = true;
inventory.AddItem(_item.Item, _item.Metadata, _item.Amount);
// We trigger activators
if (_item.events.EvaluateConditions())
{
QuestManager.instance.QuestDealerActivator(_item.events.questDealers);
QuestManager.instance.QuestUpdaterActivator(_item.events.questUpdaters);
ConsequenceManager.instance.ConsequencesActivator(gameObject, _item.events.consequences);
}
// Play sound
if (_item.Item.sOnPickUp)
GameAudioManager.instance.PlayOneShot(AudioSources.GeneralSounds, _item.Item.sOnPickUp);
// If It's NOT created item, save the state
if(!_item.isCreatedItem)
_item.SaveOnFile(true);
else
{
// Otherwise, remove it from the dictionary
_item.DeleteCreatedRecord();
}
// Steal
if (_item.Metadata.IsOwnedByNPC)
{
// Aggro nearby NPC's since you stole something
// TODO: Optomize this, Just going over everything could become an issue when theres hundreds of NPC's
// maybe use factions? getowner() - getfaction() - ifisinfaction,then... ?
foreach (var activeCell in CellInformation.activeCells)
{
foreach (var AI in activeCell.Value.aiInWorld)
{
// if is in faction...
AI.Value.TryEngageWithPlayer();
}
}
}
Destroy(_item.gameObject);
}
private void CheckForIDamageable()
{
IDamageable damageable = rayHit.transform.gameObject.GetComponent<IDamageable>();
if (damageable != null && damageable.IsAlive() && !damageable.IsUnconscious())
{
if (damageable.ShouldDisplayHealthIfHostile() && (damageable.IsHostile() || damageable.IsHostileAgainstPC()))
{
uiManager.enemyHealthSlider.maxValue = damageable.GetMaxHP();
uiManager.enemyHealthSlider.value = damageable.GetCurrentHP();
uiManager.enemyName.text = damageable.GetEntityName();
uiManager.enemyHealthContainer.SetActive(true);
}
else
uiManager.enemyHealthContainer.SetActive(false);
}
else
uiManager.enemyHealthContainer.SetActive(false);
}
/// <summary>
/// Check with Rays if we're near InteractiveObjects
/// </summary>
private void CheckForInteractiveObjects()
{
// When we find one, we save this reference
InteractiveObject_Behaviour obj = rayHit.transform.gameObject.GetComponent<InteractiveObject_Behaviour>();
if (obj == null ||obj.interactiveObj == null)
return;
// If the NPC is interactable (not dead and not hostile and we're not yet in a conversation with him)
if (obj.canInteract && !isInteracting)
{
// Set the UI
uiManager.Interact_text.gameObject.SetActive(true);
uiManager.Interact_text.text = cmdStr+" " + obj.interactiveObj.Action + ": " + obj.interactiveObj.Name;
// Check for Key to speak with him
if (input.actions.FindAction("Interact").triggered)
InteractWithObject(obj);
}
else
uiManager.Interact_text.gameObject.SetActive(false);
}
/// <summary>
/// Called when we select to interact with an Object
/// </summary>
private void InteractWithObject(InteractiveObject_Behaviour obj)
{
input.SwitchCurrentActionMap("InteractUI");
// Flag that we're interacting
isInteracting = true;
// If we can choose between multiple options
if (obj.interactiveObj.InteractiveOptions.Length > 1)
{
// Disable player controls
RckPlayer.instance.EnableDisableControls(false);
// Set UI
uiManager.interactiveObjectUIContainer.SetActive(true);
uiManager.interactiveObjectName.text = obj.interactiveObj.Name;
uiManager.interactiveObjectDescription.text = obj.interactiveObj.Description;
// Instantiate InteractiveOptionsUI
if (obj.interactiveObj.InteractiveOptions.Length > 0)
{
for (int i = 0; i < obj.interactiveObj.InteractiveOptions.Length; i++)
{
GameObject newOption = Instantiate(uiManager.interactiveOptionUIPrefab, uiManager.interactiveOptionContent);
newOption.GetComponent<InteractiveObjectUI>().Init(obj, obj.interactiveObj, obj.interactiveObj.InteractiveOptions[i]);
if (i == 0 && RckInput.isUsingGamepad)
newOption.GetComponent<Selectable>().Select();
}
}
// Otherwise if we have only one option
}
else if (obj.interactiveObj.InteractiveOptions.Length == 1)
{
// We just trigger the events
DoInteractiveAction(obj, obj.interactiveObj.InteractiveOptions[0]);
}
}
/// <summary>
/// Called by InteractiveObject UI Buttons, perform interactive actions
/// </summary>
/// <param name="obj"></param>
/// <param name="option"></param>
public void DoInteractiveAction(InteractiveObject_Behaviour obj, InteractiveOptions option)
{
// We initialize the array element
int arrayElement = -1;
// We find at what index are the Events of the selected 'option'
for (int i = 0; i < obj.interactiveObj.InteractiveOptions.Length; i++)
{
if (option == obj.interactiveObj.InteractiveOptions[i])
{
// We save it
arrayElement = i;
break;
}
}
// We trigger activators
if (obj.events[arrayElement].EvaluateConditions())
{
QuestManager.instance.QuestDealerActivator(obj.events[arrayElement].questDealers);
QuestManager.instance.QuestUpdaterActivator(obj.events[arrayElement].questUpdaters);
ConsequenceManager.instance.ConsequencesActivator(gameObject, obj.events[arrayElement].consequences);
}
// Trigger the Result Script
if (!string.IsNullOrEmpty(obj.resultScripts[arrayElement]))
RCKFunctions.ExecuteScript(obj.resultScripts[arrayElement]);
// Enable player controls
EnableDisableControls(true);
uiManager.interactiveObjectUIContainer.SetActive(false);
// Remove all the previous instantiated options
foreach (Transform t in uiManager.interactiveOptionContent)
Destroy(t.gameObject);
StartCoroutine(StopInteractingFixed());
input.SwitchCurrentActionMap("Player");
}
IEnumerator StopInteractingFixed() {
yield return new WaitForEndOfFrame();
isInteracting = false;
}
private void CheckForLootingPoint(bool isPickPocket) {
if (isPickPocket == false) {
if (rayHit.transform.CompareTag("RPG Creation Kit/Looting Point"))
{
// When we find one, we save this reference
LootingPoint obj = rayHit.collider.transform.gameObject.GetComponent<LootingPoint>();
bool isOwned = obj.Metadata.IsOwnedByNPC;
// Set the UI
if (!isLooting) {
uiManager.Interact_text.gameObject.SetActive(true);
if (obj.inventory.Items.Count > 0) {
if (obj.locked) {
bool HasPick = false;
if (obj.key != null && Inventory.PlayerInventory.GetItemCount(obj.key.ItemID) <= 0) {
if (Inventory.PlayerInventory.GetItemCount(LockpickingManager.instance.LockPick) > 0) {
if (isOwned) {
uiManager.Interact_text.text = cmdStr + " Search: " + obj.pointName + " (Use Lockpick) (Owned)";
} else {
uiManager.Interact_text.text = cmdStr + " Search: " + obj.pointName + " (Use Lockpick)";
}
HasPick = true;
}
}
if (HasPick == false) {
if (isOwned) {
uiManager.Interact_text.text = cmdStr+" Search: " + obj.pointName + " (Locked) (Owned)"; // orig
} else {
uiManager.Interact_text.text = cmdStr+" Search: " + obj.pointName + " (Locked)"; // orig
}
}
} else {
if (isOwned) {
uiManager.Interact_text.text = cmdStr+" Search: " + obj.pointName + " (Owned)";
} else {
uiManager.Interact_text.text = cmdStr+" Search: " + obj.pointName;
}
}
} else {
if (obj.locked) {
bool HasPick = false;
if (obj.key != null && Inventory.PlayerInventory.GetItemCount(obj.key.ItemID) <= 0) {
if (Inventory.PlayerInventory.GetItemCount(LockpickingManager.instance.LockPick) > 0) {
if (isOwned) {
uiManager.Interact_text.text = cmdStr + " Search: " + obj.pointName + " (Empty) (Use Lockpick) (Owned)";
} else {
uiManager.Interact_text.text = cmdStr + " Search: " + obj.pointName + " (Empty) (Use Lockpick)";
}
HasPick = true;
}
}
if (HasPick == false) {
if (isOwned) {
uiManager.Interact_text.text = cmdStr+" Search: " + obj.pointName + " (Empty) (Locked) (Owned)"; // orig
} else {
uiManager.Interact_text.text = cmdStr+" Search: " + obj.pointName + " (Empty) (Locked)"; // orig
}
}
} else {
if (isOwned) {
uiManager.Interact_text.text = cmdStr+" Search: " + obj.pointName + " (Empty) (Owned)";
} else {
uiManager.Interact_text.text = cmdStr+" Search: " + obj.pointName + " (Empty)";
}
}
}
}
// Check for Key to speak with him
if (input.actions.FindAction("Interact").triggered) {
if (obj.locked) {
if (obj.key != null && Inventory.PlayerInventory.GetItemCount(obj.key.ItemID) > 0) {
if (obj.onLocked != null) {
GameAudioManager.instance.PlayOneShot(AudioSources.PlayerFPS, obj.onLocked);
} else {
Debug.Log("SCHAKEN - You need a UNLOCKING sound!!!");
}
StartCoroutine(UnlockThenOpen(obj)); // Added a delay for locking sound and realism
} else {
if (obj.key != null && Inventory.PlayerInventory.GetItemCount(LockpickingManager.instance.LockPick) > 0) {
if (!RckPlayer.instance.isPickingLock) {
LockpickingManager.instance.StartPicking(obj);
}
} else {
// We don't have the key, alert message the player
AlertMessage.instance.InitAlertMessage("You don't have the key", 3f);
}
if (obj.onUnlocked != null) {
GameAudioManager.instance.PlayOneShot(AudioSources.PlayerFPS, obj.onUnlocked);
}
}
} else {
OpenLootPoint(obj);
}
}
}
} else {
// When we find one, we save this reference
RckAI obj = rayHit.transform.gameObject.GetComponent<RckAI>();
if (obj != null) {
// Set the UI
if (!isLooting) {
uiManager.Interact_text.gameObject.SetActive(true);
uiManager.Interact_text.text = cmdStr + " Pickpocket: " + obj.GetEntityName();
}
// Check for Key to speak with him
if (input.actions.FindAction("Interact").triggered) {
OpenLootPoint(obj);
}
}
// Check for Key to speak with him
}
}
IEnumerator UnlockThenOpen(LootingPoint obj) {
yield return new WaitForSeconds(0.7f);
obj.UnlockContainer();
OpenLootPoint(obj);
}
private void OpenLootPoint(RckAI _AI) {
isLooting = true;
LootingInventoryUI.instance.OpenLootingPanel(_AI.gameObject.GetComponentInChildren<LootingPoint>(), true, true, _AI);
}
private void OpenLootPoint(LootingPoint _point) {
isLooting = true;
objLooting = _point;
if (_point.openSound)
GameAudioManager.instance.PlayOneShot(AudioSources.GeneralSounds, _point.openSound);
if (_point.anim != null) {
_point.OpenCloseContainer();
StartCoroutine(DelayOpenLootingPoint(_point));
} else {
LootingInventoryUI.instance.OpenLootingPanel(_point);
}
}
IEnumerator DelayOpenLootingPoint(LootingPoint _point) {
yield return new WaitForSeconds(0.7f);
LootingInventoryUI.instance.OpenLootingPanel(_point);
}
private void CheckForDoors()
{
if(rayHit.transform.CompareTag("RPG Creation Kit/Door") || (rayHit.transform.CompareTag("RPG Creation Kit/Cave")))
{
// When we find one, we save this reference
Door obj = rayHit.transform.gameObject.GetComponent<Door>();
// Set the UI
uiManager.Interact_text.gameObject.SetActive(true);
if (obj.teleports && rayHit.transform.CompareTag("RPG Creation Kit/Door")) {
uiManager.Interact_text.text = cmdStr+" Door to: " + obj.toCell.cellName;
} else if (obj.teleports && rayHit.transform.CompareTag("RPG Creation Kit/Cave")) {
uiManager.Interact_text.text = cmdStr+" Enter: " + obj.toCell.cellName;
} else {
if (obj.isOpened) {
uiManager.Interact_text.text = cmdStr+" Close: Door";
} else {
if (obj.locked) {
bool HasPick = false;
if (obj.key != null && Inventory.PlayerInventory.GetItemCount(obj.key.ItemID) <= 0) {
if (Inventory.PlayerInventory.GetItemCount(LockpickingManager.instance.LockPick) > 0) { //HERE we arent seeing it..
uiManager.Interact_text.text = cmdStr + " Open: Door (Use Lockpick)";
HasPick = true;
}
}
if (HasPick == false) {
uiManager.Interact_text.text = cmdStr+" Open: Door (Locked)";
}
} else {
uiManager.Interact_text.text = cmdStr+" Open: Door";
}
}
}
// Check for opening door
if (input.actions.FindAction("Interact").triggered && !WorldManager.instance.isLoading) {
if (!obj.isOpened) {
if (obj.locked) {
// We have the key
if (obj.key != null && Inventory.PlayerInventory.GetItemCount(obj.key.ItemID) > 0) {
if (obj.onDoorOpenLocked != null) {
GameAudioManager.instance.PlayOneShot(AudioSources.PlayerFPS, obj.onDoorOpenUnlocked);
}
StartCoroutine(UnlockDoorThenOpen(obj));// Just delaying for realism and sounds
//obj.UnlockDoor();
//OpenDoor(obj);
} else {
if (obj.key != null && Inventory.PlayerInventory.GetItemCount(LockpickingManager.instance.LockPick) > 0) {
if (!RckPlayer.instance.isPickingLock) {
LockpickingManager.instance.StartPicking(obj);
}
} else {
// We don't have the key, alert message the player
AlertMessage.instance.InitAlertMessage("You don't have the key to open this door", 3f);
if (obj.onDoorOpenLocked != null) {
GameAudioManager.instance.PlayOneShot(AudioSources.PlayerFPS, obj.onDoorOpenLocked);
}
}
}
} else {
if (obj.onDoorOpen != null) {
GameAudioManager.instance.PlayOneShot(AudioSources.PlayerFPS, obj.onDoorOpen);
}
OpenDoor(obj);
}
} else {
if (obj.onDoorOpen != null) {
GameAudioManager.instance.PlayOneShot(AudioSources.PlayerFPS, obj.onDoorOpen);
}
OpenDoor(obj);
}
}
}
}
IEnumerator UnlockDoorThenOpen(Door obj) {
yield return new WaitForSeconds(0.7f);
obj.UnlockDoor();
OpenDoor(obj);
}
private void OpenDoor(Door obj) {
if (obj.onDoorOpen) {
GameAudioManager.instance.PlayOneShot(AudioSources.GeneralSounds, obj.onDoorOpen);
} else {
Debug.Log("SCHAKEN - Add sounds here!");
}
if (obj.teleports) {
FreezeAndDisableControl();
WorldManager.instance.LoadCell(obj.toCell, UnityEngine.Random.Range(int.MinValue, int.MaxValue), false, obj, null, true);
} else {
// Open door by rotating pivot/playing animation
obj.OpenCloseDoor();
}
}
private void CheckForCrafting() {
if (rayHit.transform.CompareTag("RPG Creation Kit/Crafting")) {
// When we find one, we save this reference
CraftingPoint obj = rayHit.collider.transform.gameObject.GetComponent<CraftingPoint>();
// Set the UI
if (!isCrafting) {
uiManager.Interact_text.gameObject.SetActive(true);
uiManager.Interact_text.text = cmdStr+" Use: " + obj.pointName;
}
// Check for Key to speak with him
if (input.actions.FindAction("Interact").triggered) {
GameAudioManager.instance.PlayOneShot(AudioSources.PlayerFPS, obj.Using);
AlchemyManager.instance.OpenAlchemyPanel();
}
}
}
public void StartDialogue(IDialoguable dialoguable) {
speakingTo = dialoguable;
dialoguable.SetSpeakerIndex(0); // Always 0 here because the player is talking to someone
dialoguable.OnDialogueStarts(this.gameObject);
DialogueLogic(dialoguable.GetCurrentDialogueGraph());
}
void DialogueLogic(DialogueGraph dialogue) {
if (dialogue != null) {
StartCoroutine(ExecuteNode(dialogue.GetEntryNode()));
}
}
public bool isPlainLineDialogue = false;
IEnumerator ExecuteNode(XNode.Node _node)
{
// Trigger Events and Script
DialogueNode globalNode = (DialogueNode)_node;
RCKFunctions.ExecuteEvents(globalNode.events);
if (!string.IsNullOrEmpty(globalNode.resultScript))
RCKFunctions.ExecuteScript(globalNode.resultScript);
if (_node is EntryNode)
{
EntryNode thisNode = (EntryNode)_node;
StartCoroutine(ExecuteNode(thisNode.GetOutputPort("firstNode").Connection.node));
}
else if (_node is ConditionsNode)
{
ConditionsNode thisNode = (ConditionsNode)_node;
bool conditionsResult = RCKFunctions.VerifyConditions(thisNode.conditions);
if (conditionsResult)
StartCoroutine(ExecuteNode(thisNode.GetOutputPort("resultTrue").Connection.node));
else
StartCoroutine(ExecuteNode(thisNode.GetOutputPort("resultFalse").Connection.node));
}
else if (_node is NPCDialogueLineNode)
{
NPCDialogueLineNode thisNode = (NPCDialogueLineNode)_node;
// Set the Dialoguable state
speakingTo.OnSpeakALine(thisNode);
if (!thisNode.plainLine)
{
input.SwitchCurrentActionMap("DialogueUI");
// Flag that we're in conversation
isInConversation = true;
// Disable player controls
mouseLook.SetLookAtTarget(speakingTo.GetEntityLookAtPos());
EnableDisableControls(false);
// Set the UI properly
uiManager.heardDialogues.gameObject.SetActive(false);
uiManager.playerQuestionsContainer.SetActive(false);
uiManager.compassGameObject.SetActive(false);
uiManager.StatsUIGameObject.SetActive(false);
uiManager.crosshairGameObject.SetActive(false);
// Npc Name
uiManager.npc_Name.text = speakingTo.GetDialoguableName();
uiManager.npc_Name.gameObject.SetActive(true);
// Npc Line
uiManager.npc_Line.text = thisNode.line;
uiManager.npc_Line.gameObject.SetActive(true);
// Whole Dialogue UI
uiManager.dialogueContainer.SetActive(true);
cameraLookNPC = true;
}
else
{
// Flag that we're in conversation
isInConversation = true;
isPlainLineDialogue = true;
uiManager.heardDialogues.text = thisNode.line;
uiManager.heardDialogues.gameObject.SetActive(true);
}
// - End UI
// - End Updaters
// Play the audio if exists
if (thisNode.audioClip != null)
{
speakingTo.PlayAudioClip(thisNode.audioClip);
speakingTo.GetEntityGameObject().GetComponent<Equipment>().characterModel.Voice.Talk(thisNode.audioClip);
}
// Play talking animation if choosen
if(!string.IsNullOrEmpty(thisNode.dialogueAnimationStr))
{
speakingTo.GetAnimator().CrossFade(thisNode.dialogueAnimationStr, .1f);
}
// Check for the timing of the line
bool outOfTime = false;
float startTime = Time.time;
// To wait until the line ends
while (!outOfTime)
{
// If we press X button
if (input.actions.FindAction("SkipDialogue").triggered && Time.time - startTime >= 0.5f && !thisNode.plainLine ||
WorldManager.instance.isLoading)
outOfTime = true;
// If the time expires
if (!thisNode.useLenghtOfClip)
{
if (Time.time - startTime >= thisNode.lineTime)
outOfTime = true;
}
else
{
if (Time.time - startTime >= thisNode.audioClip.length)
outOfTime = true;
}
yield return null;
}
// Line has finished and player was teleported
if (WorldManager.instance.isLoading)
{
// Reset the player status
isInConversation = false;
isPlainLineDialogue = false;
// Disable the UI
if (!thisNode.plainLine)
{
uiManager.dialogueContainer.SetActive(false);
uiManager.compassGameObject.SetActive(true);
uiManager.StatsUIGameObject.SetActive(true);
uiManager.crosshairGameObject.SetActive(true);
EnableDisableControls(false);
cameraLookNPC = false;
}
else
{
uiManager.heardDialogues.gameObject.SetActive(false);
}
// Destroy every previous question
foreach (Transform t in uiManager.playerQuestionsContent)
Destroy(t.gameObject);
speakingTo = null;
yield break;
}
// Stop the audio source
if(speakingTo != null)
speakingTo.StopAudio();
// Check what we have to do next
switch (thisNode.afterLine)
{
case AfterLine.NPC_DialogueLine:
// If we have to trigger another dialogue line, we just re-start this courutine with the new line
StartCoroutine(ExecuteNode(thisNode.GetOutputPort("nextLine").Connection.node));
yield break;
case AfterLine.PlayerQuestions:
// Play listening animation if choosen
if (!string.IsNullOrEmpty(thisNode.dialogueAnimationListeningStr))
{
speakingTo.GetAnimator().CrossFade(thisNode.dialogueAnimationListeningStr, .1f);
}
if (thisNode.removePreviousQuestions)
{
foreach (Transform t in uiManager.playerQuestionsContent)
Destroy(t.gameObject);
}
else if (thisNode.questionsToRemove.Length > 0)
{
List<GameObject> toDelete = new List<GameObject>();
foreach (Transform t in uiManager.playerQuestionsContent)
{
for (int i = 0; i < thisNode.questionsToRemove.Length; i++)
{
if (t.GetComponent<PlayerQuestionUI>().question.qID == thisNode.questionsToRemove[i])
toDelete.Add(t.gameObject);
}
}
foreach (GameObject go in toDelete)
{
Destroy(go);
}
}
List<PlayerQuestionUI> questions = new List<PlayerQuestionUI>();
// Check if we have to add some new question
for (int i = 0; i < thisNode.playerQuestions.Count; i++)
{
int tempPosition = thisNode.playerQuestions[i].Position;
// In case, add them
GameObject newQuestion = Instantiate(uiManager.playerQuestionPrefab, uiManager.playerQuestionsContent);
if (tempPosition == 0)
tempPosition = i;
questions.Add(newQuestion.GetComponent<PlayerQuestionUI>());
newQuestion.GetComponent<PlayerQuestionUI>()
.Init(thisNode.playerQuestions[i], speakingTo,
(DialogueNode)thisNode.GetOutputPort("playerQuestions " + i).Connection.node,
thisNode.playerQuestions[i].Question, thisNode.playerQuestions[i].DeleteAfterAnswer,
tempPosition);
newQuestion.GetComponent<RectTransform>().SetSiblingIndex(tempPosition);
}
// Set the UI to allow the player to ask questions
uiManager.npc_Line.gameObject.SetActive(false);
uiManager.playerQuestionsContainer.SetActive(true);
// Reset the scroll bar of the PlayerQuestionScrollView
if (uiManager.playerQuestionsContainer.GetComponentInChildren<Scrollbar>() != null)
uiManager.playerQuestionsContainer.GetComponentInChildren<Scrollbar>().value = 1f;
speakingTo.OnFinishedSpeakingALine();
yield return new WaitForEndOfFrame();
uiManager.ReorderQuestions();
uiManager.PreventUnselectedQuestionWithGamepad();
yield return new WaitForEndOfFrame();
uiManager.PreventUnselectedQuestionWithGamepad();
yield break;
case AfterLine.EndDialogue:
speakingTo.OnDialogueEnds(this.gameObject);
// Reset the player status
isInConversation = false;
// Disable the UI
if (!thisNode.plainLine)
{
uiManager.dialogueContainer.SetActive(false);
uiManager.compassGameObject.SetActive(true);
uiManager.StatsUIGameObject.SetActive(true);
uiManager.crosshairGameObject.SetActive(true);
EnableDisableControls(true);
cameraLookNPC = false;
EndDialogue();
}
else
{
isPlainLineDialogue = false;
uiManager.heardDialogues.gameObject.SetActive(false);
}
// Destroy every previous question
foreach (Transform t in uiManager.playerQuestionsContent)
Destroy(t.gameObject);
// Reset speaking to animator
if(speakingTo != null && speakingTo.GetAnimator() != null)
speakingTo.GetAnimator().SetTrigger("CancelDialogueAnimation");
speakingTo = null;
yield break;
case AfterLine.Continue:
StartCoroutine(ExecuteNode(thisNode.GetOutputPort("output").Connection.node));
break;
}
}
else if (_node is PlayerQuestionsNode)
{
PlayerQuestionsNode thisNode = (PlayerQuestionsNode)_node;
// Play listening animation if choosen
if (!string.IsNullOrEmpty(thisNode.dialogueAnimationListeningStr))
{
speakingTo.GetAnimator().CrossFade(thisNode.dialogueAnimationListeningStr, .1f);
}
else
{
// Reset speaking to animator
speakingTo.GetAnimator().SetTrigger("CancelDialogueAnimation");
}
// Flag that we're in conversation
isInConversation = true;
input.SwitchCurrentActionMap("DialogueUI");
mouseLook.SetLookAtTarget(speakingTo.GetEntityLookAtPos());
// Disable player controls
EnableDisableControls(false);
// Set the UI properly
uiManager.heardDialogues.gameObject.SetActive(false);
uiManager.playerQuestionsContainer.SetActive(false);
uiManager.compassGameObject.SetActive(false);
uiManager.StatsUIGameObject.SetActive(false);
uiManager.crosshairGameObject.SetActive(false);
// Npc Name
uiManager.npc_Name.text = speakingTo.GetDialoguableName();
uiManager.npc_Name.gameObject.SetActive(true);
// Whole Dialogue UI
uiManager.dialogueContainer.SetActive(true);
cameraLookNPC = true;
if (thisNode.removePreviousQuestions)
{
foreach (Transform t in uiManager.playerQuestionsContent)
Destroy(t.gameObject);
}
else if (thisNode.questionsToRemove.Length > 0)
{
List<GameObject> toDelete = new List<GameObject>();
foreach (Transform t in uiManager.playerQuestionsContent)
{
for (int i = 0; i < thisNode.questionsToRemove.Length; i++)
{
if (t.GetComponent<PlayerQuestionUI>().question.qID == thisNode.questionsToRemove[i])
toDelete.Add(t.gameObject);
}
}
foreach (GameObject go in toDelete)
{
Destroy(go);
}
}
List<PlayerQuestionUI> questions = new List<PlayerQuestionUI>();
// Check if we have to add some new question
for (int i = 0; i < thisNode.playerQuestions.Count; i++)
{
int tempPosition = thisNode.playerQuestions[i].Position;
// In case, add them
GameObject newQuestion = Instantiate(uiManager.playerQuestionPrefab, uiManager.playerQuestionsContent);
if (tempPosition == 0)
tempPosition = i;
questions.Add(newQuestion.GetComponent<PlayerQuestionUI>());
newQuestion.GetComponent<PlayerQuestionUI>()
.Init(thisNode.playerQuestions[i], speakingTo,
(DialogueNode)thisNode.GetOutputPort("playerQuestions " + i).Connection.node,
thisNode.playerQuestions[i].Question, thisNode.playerQuestions[i].DeleteAfterAnswer,
tempPosition);
newQuestion.GetComponent<RectTransform>().SetSiblingIndex(tempPosition);
}
// Set the UI to allow the player to ask questions
uiManager.npc_Line.gameObject.SetActive(false);
uiManager.playerQuestionsContainer.SetActive(true);
// Reset the scroll bar of the PlayerQuestionScrollView
if (uiManager.playerQuestionsContainer.GetComponentInChildren<Scrollbar>() != null)
uiManager.playerQuestionsContainer.GetComponentInChildren<Scrollbar>().value = 1f;
speakingTo.OnFinishedSpeakingALine();
yield return new WaitForEndOfFrame();
uiManager.ReorderQuestions();
uiManager.PreventUnselectedQuestionWithGamepad();
yield return new WaitForEndOfFrame();
uiManager.PreventUnselectedQuestionWithGamepad();
}
else if (_node is ChangeDialogueNode)
{
ChangeDialogueNode thisNode = (ChangeDialogueNode)_node;
if (thisNode.onNPCWhosSpeaking)
{
speakingTo.ChangeDialogueGraph(thisNode.newDialogue);
if (thisNode.startDialogueImmediatly)
{
var npcSpeakingSaved = speakingTo;
EndDialogue();
StartDialogue(npcSpeakingSaved);
}
else
StartCoroutine(ExecuteNode(thisNode.GetOutputPort("output").Connection.node));
}
else
{
RCKFunctions.ChangeDialogueToRckAI(thisNode.npcRef, thisNode.newDialogue.ID);
StartCoroutine(ExecuteNode(thisNode.GetOutputPort("output").Connection.node));
}
yield break;
}
else if (_node is ChangeStateNode)
{
ChangeStateNode thisNode = (ChangeStateNode)_node;
switch (thisNode.stateChange)
{
case ChangeStateNode.DialogueStateChange.Trade:
if (thisNode.toCurrentNPC)
RCKFunctions.StartTrading(speakingTo.GetEntityGameObject().GetComponent<Merchant>());
// TODO find npc and do stuff
break;
case ChangeStateNode.DialogueStateChange.Loot:
// TODO find looting point and do stuff
break;
case ChangeStateNode.DialogueStateChange.Teleport:
//WorldStreaming.manager.Teleport(thisNode.coordinates);
break;
case ChangeStateNode.DialogueStateChange.ChangeCell:
//WorldStreaming.manager.StartLoadingInterior(thisNode.cell.worldspace, thisNode.cell, null, thisNode.coordinates);
break;
case ChangeStateNode.DialogueStateChange.SpeakToNPC:
// TODO Find the NPC and do stuff
break;
}
if (thisNode.interruptsDialogue)
EndDialogue();
StartCoroutine(ExecuteNode(thisNode.GetOutputPort("output").Connection.node));
}
else if (_node is RandomNode)
{
RandomNode thisNode = (RandomNode)_node;
StartCoroutine(ExecuteNode(thisNode.PickRandomExit()));
}
else if(_node is Dialogue_AISetFieldNode)
{
Dialogue_AISetFieldNode thisNode = (Dialogue_AISetFieldNode)_node;
thisNode.OnStart();
if(thisNode.speakerID == 0) // Its to the NPC we're talking to
{
var component = speakingTo.GetEntityGameObject().GetComponent<RckAI>(); // it's always the speaker with id 0 because it's player to ai dialogue
if (component == null)
{
Debug.Log("Dialogue Node : Tried to SetField but the given Component: \"RckAI\" was not found on Speaker Index 0. Node fails.");
yield break;
}
var field = component.GetType().GetField(thisNode.FieldToSet);
field.SetValue(component, thisNode.storedValue.GetValue());
}
StartCoroutine(ExecuteNode(thisNode.GetOutputPort("output").Connection.node));
}
else if(_node is Dialogue_AIInvokeNode)
{
Dialogue_AIInvokeNode thisNode = (Dialogue_AIInvokeNode)_node;
NodesHelper.AIInvokeCall(thisNode.MethodToCall, speakingTo.GetEntityGameObject().GetComponent<RckAI>(), thisNode.parameters);
StartCoroutine(ExecuteNode(thisNode.GetOutputPort("output").Connection.node));
}
else if (_node is EndNode)
{
EndNode thisNode = (EndNode)_node;
// Reset speaking to animator
speakingTo.GetAnimator().SetTrigger("CancelDialogueAnimation");
speakingTo.OnDialogueEnds(this.gameObject);
EndDialogue();
yield break;
}
yield return null;
}
void EndDialogue()
{
//speakingTo.OnDialogueEnds(this.gameObject);
mouseLook.ApplyCurrentRotation();
mouseLook.ClearLookAt();
// Reset the player status
isInConversation = false;
isPlainLineDialogue = false;
// Disable the UI
uiManager.dialogueContainer.SetActive(false);
uiManager.compassGameObject.SetActive(true);
uiManager.StatsUIGameObject.SetActive(true);
uiManager.crosshairGameObject.SetActive(true);
EnableDisableControls(true);
cameraLookNPC = false;
uiManager.heardDialogues.gameObject.SetActive(false);
// Destroy every previous question
foreach (Transform t in uiManager.playerQuestionsContent)
Destroy(t.gameObject);
speakingTo = null;
// Input scheme
input.SwitchCurrentActionMap("Player");
}
public static int SortByPosition(PlayerQuestionUI p1, PlayerQuestionUI p2)
{
return p1.position.CompareTo(p2.position);
}
/// <summary>
/// Method called from PlayerQuestionUI to ask a question
/// </summary>
/// <param name="npc">The NPC with we are speaking with</param>
/// <param name="response">His response to our question</param>
/// <param name="DestroyQuestion">Destroy the question after answer?</param>
/// <param name="theQuestion">The question to destroy</param>
public void AskQuestion(IDialoguable _dialoguable, XNode.Node response, bool DestroyQuestion, GameObject theQuestion = null, bool isNpcToNpcDialogue = false, IDialoguable[] _dialoguables = null)
{
if (!isNpcToNpcDialogue)
StartCoroutine(ExecuteNode(response));
else
{
isInConversation = false;
speakingTo = null;
_dialoguable.ExecuteDialogueNode(response, _dialoguables);
}
// DestroyQuestion = What we said in the ScriptableObject
// Destroy after .05f seconds to not have bad effects in the PlayerQuestionUI (Question disappear before the panel's fadeout)
if (DestroyQuestion)
Destroy(theQuestion, .05f);
}
private void CheckForIDraggable()
{
IDraggable draggable = rayHit.transform.gameObject.GetComponent<IDraggable>();
if (draggable != null && !isDragging)
{
if(!isDragging && dragKeyBeingHeld)
{
itemRigidbody = draggable.GetGameObject().GetComponent<Rigidbody>();
dragItemScript = draggable.GetGameObject().GetComponent<ItemInWorld>();
if (itemRigidbody != null)
{
draggable.OnBeingDragged();
BeginDragItem();
}
}
}
}
private void BeginDragItem()
{
//if (ItemUnderFeet())
// return;
itemRigidbody.angularVelocity = Vector3.zero;
itemRigidbody.velocity = Vector3.zero;
itemRigidbody.useGravity = false;
isDragging = true;
}
public float powerVector = 5f;
public float droppingDistance = 3f;
public float moveThresold = .1f;
public float stopThresold = .1f;
private void ManageDraggable()
{
if (isDragging && itemRigidbody != null)
{
if (!dragKeyBeingHeld)
StopDragging();
else if(itemRigidbody != null && dragKeyBeingHeld && dragItemScript.canBeDragged)
{
//if (ItemUnderFeet())
//{
// StopDragging();
// return;
//}
//itemRigidbody.position = Vector3.Lerp(itemRigidbody.position, mainCamera.transform.position + mainCamera.transform.forward * 1f, (dragForce * Time.deltaTime));
//itemRigidbody.MovePosition(Vector3.Lerp(itemRigidbody.transform.position, mainCamera.transform.position + mainCamera.transform.forward, Time.fixedDeltaTime * dragForce));
//Vector3 toCameraCenterVector = (mainCamera.transform.position + mainCamera.transform.forward) - itemRigidbody.transform.position;
//toCameraCenterVector = toCameraCenterVector.normalized;
//itemRigidbody.AddForce(Vector3.MoveTowards(itemRigidbody.transform.position, toCameraCenterVector, dragForce * Time.deltaTime) * powerVector, ForceMode.VelocityChange);
//itemRigidbody.velocity = Vector3.zero;
Vector3 toCameraCenterVector = (mainCamera.transform.position + mainCamera.transform.forward) - itemRigidbody.transform.position;
toCameraCenterVector = toCameraCenterVector.normalized * .25f;
var dst = Vector3.Distance(itemRigidbody.transform.position, mainCamera.transform.position + mainCamera.transform.forward);
if (dst > moveThresold)
dragForce = 1000f;
else
dragForce = 150f;
if(dst > stopThresold)
itemRigidbody.AddForce(toCameraCenterVector * (dragForce * Time.fixedDeltaTime), ForceMode.VelocityChange);
itemRigidbody.velocity = Vector3.zero;
Debug.DrawRay(itemRigidbody.transform.position, toCameraCenterVector, Color.red);
if (Mathf.Abs(mouseLook.x) > 2f || Mathf.Abs(mouseLook.y) > 2f)
{
dragDirection = new Vector3(mouseLook.x, mouseLook.y, 0);
dragDirection = transform.TransformDirection(dragDirection.normalized * (dragForce * Time.fixedDeltaTime));
}
else
dragDirection = Vector3.zero;
if (Vector3.Distance(mainCamera.transform.position + mainCamera.transform.forward, itemRigidbody.transform.position) > droppingDistance)
StopDragging();
}
}
else
{
isDragging = false;
}
}
public void DisplayHeardLine(string _line, float _time)
{
uiManager.heardDialogues.text = _line;
uiManager.heardDialogues.gameObject.SetActive(true);
Invoke("HideHeardLine", _time);
}
public void HideHeardLine()
{
uiManager.heardDialogues.gameObject.SetActive(false);
}
/// <summary>
/// Called when we stop to drag the item, reset its state to default world item
/// </summary>
public void StopDragging()
{
itemRigidbody.useGravity = true;
itemRigidbody.velocity = Vector3.zero;
itemRigidbody = null;
isDragging = false;
}
public void SetSpeakerIndex(int index)
{
throw new System.NotImplementedException();
}
public void DialogueLogic(IDialoguable[] entities, DialogueGraph dialogue)
{
throw new System.NotImplementedException();
}
public IEnumerator ExecuteDialogueNode(Node _node, IDialoguable[] _entities)
{
throw new System.NotImplementedException();
}
public void SpeakToEntity(IDialoguable target)
{
throw new System.NotImplementedException();
}
public void ChangeDialogueGraph(DialogueGraph _newDialogueGraph)
{
throw new System.NotImplementedException();
}
public bool CanDialogue()
{
return (isAlive && !isInConversation && !isInteracting && !isLooting && isLoaded);
}
public string GetDialoguableName()
{
throw new System.NotImplementedException();
}
public void OnDialogueStarts(GameObject target)
{
throw new System.NotImplementedException();
}
public void OnDialogueEnds(GameObject target)
{
throw new System.NotImplementedException();
}
public DialogueGraph GetCurrentDialogueGraph()
{
throw new System.NotImplementedException();
}
public void OnSpeakALine(NPCDialogueLineNode currentNode)
{
throw new System.NotImplementedException();
}
public void OnFinishedSpeakingALine()
{
throw new System.NotImplementedException();
}
public Transform GetEntityLookAtPos()
{
throw new System.NotImplementedException();
}
public GameObject GetEntityGameObject()
{
return gameObject;
}
public void PlayAudioClip(AudioClip clip)
{
throw new System.NotImplementedException();
}
public void StopAudio()
{
throw new System.NotImplementedException();
}
public bool IsTalking()
{
throw new System.NotImplementedException();
}
Animator IDialoguable.GetAnimator()
{
throw new System.NotImplementedException();
}
int IDialoguable.GetSpeakerIndex()
{
throw new System.NotImplementedException();
}
void IDialoguable.ForceToStopDialogue()
{
throw new System.NotImplementedException();
}
}
}