using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Events; using UnityEngine.Playables; using RPGTALK.Snippets; [AddComponentMenu("Seize Studios/RPGTalk/RPGTalk Area")] public class RPGTalkArea : MonoBehaviour { /// /// The RPGTalk to be played. Can be left null if you only need to play a timeline director, for instance /// public RPGTalk rpgtalkTarget; /// /// Should the Talk start only when the player hit a button? /// public bool shouldInteractWithButton; /// /// When the player can interact, show/hide any GameObjects. Useful for something like 'Press A to talk' /// public GameObject[] showWhenInteractionIsPossible; /// /// What is the key that should be used to interact? You can override the Update function and write your /// own conditions, if needed /// public KeyCode interactionKey = KeyCode.None; /// /// What button, set in the Input Settings, should interact with the area /// public string interactionButton; /// /// Should the are interact when the player clicks with the left button of the mouse? /// public bool interactWithMouse; bool canInteract; /// /// The talk will only begin if someone with this tag hits it. Leave blank to accept anyone /// public string checkIfColliderHasTag = ""; /// /// A series of events to be called before the talk starts /// public UnityEvent callbackBeforeTalk; /// /// What line to start the talk /// public string lineToStart = "1"; /// /// What line to finish the talk (leave -1 to read the file until the end) /// public string lineToBreak = "-1"; /// /// The text file to be parsed into the talks. Leave empty if it is the same as the rpgtalkTarget /// public TextAsset txtToParse; /// /// Overwrite the variable callback on RPGTalk. Leave empty if no ovewrite is wanted /// public UnityEvent overwriteCallbackAfterTalk; /// /// Should this talk/interaction be available only once? /// public bool happenOnlyOnce; [HideInInspector] /// /// This talk already happened before? /// public bool alreadyHappened; /// /// Activate talk on trigger enter? (ignored if shouldInteractWithButton is true) /// public bool triggerEnter = true; /// /// Activate talk on trigger exit? (ignored if shouldInteractWithButton is true) /// public bool triggerExit = false; /// /// After the talk finishes, the canvas shold stay on the screen? /// public bool shouldStayOnScreen; /// /// Forbids the talk to be initialized if the rpgtalkTarget is already showing something else. /// public bool forbidPlayIfRpgtalkIsPlaying; /// /// The timeline director can be played with the same rules as the talk. /// public PlayableDirector timelineDirectorToPlay; /// /// Save (With RPGTAlkSaveInstance on RPGTalk Holder), if this area has already happened. The name of the object will be the saveData value. /// public bool saveAlreadyHappened; /// /// Should the talk pass itself? /// public bool autoPass = false; /// /// How many seconds should RPGTalk wait after the animation stopped to autoPass /// public float secondsAutoPass = 3f; /// /// If it has a RPGTalkFollowCharacter, should it be contained inside the screen? /// public bool containInsideScreen; /// /// Hide anything that shouldn't be showing upon the start /// protected virtual void Start () { HideInteractionInstruction (); if (saveAlreadyHappened) { if (rpgtalkTarget.saveInstance) { alreadyHappened = rpgtalkTarget.saveInstance.GetSavedData(name, 1); } } } /// /// Check for the interaction. Override this method to implement your own rules /// protected virtual void Update () { if (shouldInteractWithButton && canInteract) { if ((interactionKey != KeyCode.None && Input.GetKeyDown (interactionKey)) || (interactionButton != "" && Input.GetButtonDown(interactionButton)) || (interactWithMouse && Input.GetMouseButtonDown(0)) ) { StartTalk (); } } } /// /// Check the rules and put it into rpgtalkTarget, initializing a new talk. /// protected virtual void NewTalk(){ if (rpgtalkTarget == null || (happenOnlyOnce && alreadyHappened) || (forbidPlayIfRpgtalkIsPlaying && rpgtalkTarget.isPlaying)) { return; } alreadyHappened = true; if (saveAlreadyHappened) { if (rpgtalkTarget.saveInstance) { rpgtalkTarget.saveInstance.SaveData(name, 1); } } callbackBeforeTalk.Invoke(); TextAsset newTxt = rpgtalkTarget.txtToParse; if (txtToParse != null) { newTxt = txtToParse; } rpgtalkTarget.shouldStayOnScreen = shouldStayOnScreen; rpgtalkTarget.autoPass = autoPass; rpgtalkTarget.secondsAutoPass = secondsAutoPass; RPGTalkFollowCharacter followCharacter = rpgtalkTarget.GetComponent(); if (followCharacter) { followCharacter.containInsideScreen = containInsideScreen; } rpgtalkTarget.NewTalk (lineToStart, lineToBreak, newTxt, overwriteCallbackAfterTalk); } /// /// Show anything in the showWhenInteractionIsPossible array /// protected virtual void ShowInteractionInstruction(){ if (happenOnlyOnce && alreadyHappened) { return; } foreach (GameObject GO in showWhenInteractionIsPossible) { GO.SetActive (true); } } /// /// Hides anything in the showWhenInteractionIsPossible array /// protected virtual void HideInteractionInstruction(){ foreach (GameObject GO in showWhenInteractionIsPossible) { GO.SetActive (false); } } /// /// Prepare the variables for the interaction or just call a new talk /// /// Should only work with specifc tag? /// Was called from an OnTriggerExite? protected virtual void PrepareInteraction(string tagName, bool gettingOut = false){ if(tagName == checkIfColliderHasTag || checkIfColliderHasTag == ""){ if (shouldInteractWithButton) { if (!gettingOut) { canInteract = true; ShowInteractionInstruction (); } else { canInteract = false; HideInteractionInstruction (); } } else { if((gettingOut && triggerExit) || (!gettingOut && triggerEnter)){ StartTalk (); } } } } protected virtual void OnTriggerEnter(Collider col){ PrepareInteraction (col.tag); } protected virtual void OnTriggerExit(Collider col){ PrepareInteraction (col.tag,true); } protected virtual void OnTriggerEnter2D(Collider2D col){ PrepareInteraction (col.tag); } protected virtual void OnTriggerExit2D(Collider2D col){ PrepareInteraction (col.tag,true); } /// /// Hide anything that should be showing, starts a new talk and plays the timeline director /// protected virtual void StartTalk(){ HideInteractionInstruction (); if (rpgtalkTarget != null) { NewTalk (); } if (timelineDirectorToPlay != null) { timelineDirectorToPlay.Play (); } } }