I made a bool reverse = false in the DialogueNode.cs. If its true, I want to show go back to the root node, and get the player children and display them again.
Sounds easy as we have those methods already but I cant piece it together, having difficulties with populating the choices. I do not mind to use the next button or a coroutine (if easier)that runs if the reverse bool = true at that last node. Just stuck with the choices building, not sure if I should put the code in the DialogueUI or PlayerConversant. It sounds like building the choices should be done in the DialogueUI but not sure how to communicate between both scripts.
public class DialogueNode : ScriptableObject
{
[SerializeField] private bool isPlayerSpeaking = false;
[SerializeField] private string text;
[SerializeField] private List<string> children = new List<string>();
[SerializeField] private Rect rect = new Rect(0,0, 200, 100);
public bool reverse = false;
etc..
public class DialogueUI : MonoBehaviour
{
private PlayerConversant playerConversant;
[SerializeField] private TextMeshProUGUI npcText;
[SerializeField] private Button nextButton;
[SerializeField] private Button quitButton;
[SerializeField] private GameObject npcResponseRoot;
[SerializeField] private Transform playerChoicesTransform;
[SerializeField] private GameObject playerChoicePrefab;
private void Start()
{
playerConversant = GameObject.FindGameObjectWithTag("Player").GetComponent<PlayerConversant>();
playerConversant.onDialogueEvent += UpdateDialogueUI;
nextButton.onClick.AddListener(playerConversant.NextButtonFunctionality);
quitButton.onClick.AddListener(playerConversant.QuitDialogue);
UpdateDialogueUI();
}
private void UpdateDialogueUI()
{
gameObject.SetActive(playerConversant.IsActive());
if (!playerConversant.IsActive()) return;
npcResponseRoot.SetActive(!playerConversant.GetPlayerIsChoosing());
playerChoicesTransform.gameObject.SetActive(playerConversant.GetPlayerIsChoosing());
if(playerConversant.GetPlayerIsChoosing())
{
HandlePlayerChoosingButtons();
}
else
{
npcText.text = playerConversant.GetText();
if(!playerConversant.currentNode.reverse)
{
nextButton.gameObject.SetActive(playerConversant.DialogueHasNextNode());
return;
}
nextButton.gameObject.SetActive(true);
}
}
private void HandlePlayerChoosingButtons()
{
for (int i = 0; i < playerChoicesTransform.childCount; i++)
{
Transform childTransform = playerChoicesTransform.GetChild(i);
Destroy(childTransform.gameObject);
}
foreach (DialogueNode playerChoice in playerConversant.GetDialogueChoices())
{
GameObject choiceInstance = Instantiate(playerChoicePrefab, playerChoicesTransform);
var buttonText = choiceInstance.GetComponentInChildren<TextMeshProUGUI>();
buttonText.text = playerChoice.GetText();
Button button = choiceInstance.GetComponentInChildren<Button>();
button.onClick.AddListener(() =>
{
playerConversant.SelectDialogueChoice(playerChoice);
});
}
}
}
public class PlayerConversant : MonoBehaviour
{
public Dialogue currentDialogue;
public DialogueNode currentNode;
private bool playerIsChoosing = false;
public event Action onDialogueEvent;
public void StartDialogue(Dialogue newdialogue)
{
currentDialogue = newdialogue;
currentNode = currentDialogue.GetRootNode();
onDialogueEvent();
}
public void QuitDialogue()
{
currentDialogue = null;
currentNode = null;
playerIsChoosing = false;
onDialogueEvent();
}
public bool IsActive()
{
return currentDialogue != null;
}
public bool GetPlayerIsChoosing()
{
return playerIsChoosing;
}
public string GetText()
{
if (currentNode == null)
{
return "";
}
return currentNode.GetText();
}
public IEnumerable<DialogueNode> GetDialogueChoices()
{
return currentDialogue.GetPlayerChildren(currentNode);
}
public void SelectDialogueChoice(DialogueNode chosenNode)
{
currentNode = chosenNode;
playerIsChoosing = false;
NextButtonFunctionality();
}
public void NextButtonFunctionality()
{
if (currentNode.reverse)
{
DialogueNode rootNode = currentDialogue.GetRootNode();
// Get player children of the root node
IEnumerable<DialogueNode> playerChildren = currentDialogue.GetPlayerChildren(rootNode);
playerIsChoosing = true;
onDialogueEvent();
return;
}
int numberOfPlayerResponese = currentDialogue.GetPlayerChildren(currentNode).Count();
if(numberOfPlayerResponese > 0)
{
playerIsChoosing = true;
onDialogueEvent();
return;
}
DialogueNode[] currentDialogueChildrenNodes = currentDialogue.GetNPCChildren(currentNode).ToArray();
if(currentDialogueChildrenNodes.Length > 0)
{
currentNode = currentDialogueChildrenNodes[0];
}
onDialogueEvent();
}
public bool DialogueHasNextNode()
{
return currentDialogue.GetAllChildren(currentNode).ToArray().Count() > 0;
}
}
Currently after reaching the last node in the dialogue, when i click next, the screenshot speaks for itself, nothing shows up.