Set pathToExisting dialogue to merge dialogue into existing ones

This commit is contained in:
Nick 2024-02-26 00:57:03 -05:00
parent 3084a97df1
commit 0298173935
3 changed files with 95 additions and 2 deletions

View File

@ -1,3 +1,4 @@
using Delaunay;
using NewHorizons.Components.Props;
using NewHorizons.External.Modules.Props.Dialogue;
using NewHorizons.Handlers;
@ -5,7 +6,9 @@ using NewHorizons.Utility;
using NewHorizons.Utility.OuterWilds;
using NewHorizons.Utility.OWML;
using OWML.Common;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
using UnityEngine;
@ -24,6 +27,18 @@ namespace NewHorizons.Builder.Props
// Create dialogue directly from xml string instead of loading it from a file
public static (CharacterDialogueTree, RemoteDialogueTrigger) Make(GameObject go, Sector sector, DialogueInfo info, string xml, string dialogueName)
{
if (string.IsNullOrEmpty(info.pathToExistingDialogue))
{
return MakeNewDialogue(go, sector, info, xml, dialogueName);
}
else
{
return (AddToExistingDialogue(info, xml), null);
}
}
private static (CharacterDialogueTree, RemoteDialogueTrigger) MakeNewDialogue(GameObject go, Sector sector, DialogueInfo info, string xml, string dialogueName)
{
NHLogger.LogVerbose($"[DIALOGUE] Created a new character dialogue [{info.rename}] on [{info.parentPath}]");
@ -54,6 +69,68 @@ namespace NewHorizons.Builder.Props
return (dialogue, remoteTrigger);
}
private static CharacterDialogueTree AddToExistingDialogue(DialogueInfo info, string xml)
{
AddTranslation(xml);
var existingDialogue = SearchUtilities.Find(info.pathToExistingDialogue)?.GetComponent<CharacterDialogueTree>();
if (existingDialogue == null)
{
NHLogger.LogError($"Couldn't find dialogue at {info.pathToExistingDialogue}!");
return null;
}
var existingText = existingDialogue._xmlCharacterDialogueAsset.text;
var existingDialogueDoc = new XmlDocument();
existingDialogueDoc.LoadXml(existingText);
var existingDialogueTree = existingDialogueDoc.DocumentElement.SelectSingleNode("//DialogueTree");
var existingDialogueNodesByName = new Dictionary<string, XmlNode>();
foreach (XmlNode existingDialogueNode in existingDialogueTree.GetChildNodes("DialogueNode"))
{
var name = existingDialogueNode.GetChildNode("Name").InnerText;
existingDialogueNodesByName[name] = existingDialogueNode;
}
var additionalDialogueDoc = new XmlDocument();
additionalDialogueDoc.LoadXml(xml);
var newDialogueNodes = additionalDialogueDoc.DocumentElement.SelectSingleNode("//DialogueTree").GetChildNodes("DialogueNode");
foreach (XmlNode newDialogueNode in newDialogueNodes)
{
var name = newDialogueNode.GetChildNode("Name").InnerText;
if (existingDialogueNodesByName.TryGetValue(name, out var existingNode))
{
// We just have to merge the dialogue options
var dialogueOptions = newDialogueNode.GetChildNode("DialogueOptionsList").GetChildNodes("DialogueOption");
var existingDialogueOptionsList = existingNode.GetChildNode("DialogueOptionsList");
foreach (XmlNode node in dialogueOptions)
{
var importedNode = existingDialogueOptionsList.OwnerDocument.ImportNode(node, true);
existingDialogueOptionsList.AppendChild(importedNode);
}
}
else
{
// We add the new dialogue node to the existing dialogue
var importedNode = existingDialogueTree.OwnerDocument.ImportNode(newDialogueNode, true);
existingDialogueTree.AppendChild(importedNode);
}
}
var newTextAsset = new TextAsset(existingDialogueDoc.OuterXml)
{
name = existingDialogue._xmlCharacterDialogueAsset.name
};
existingDialogue.SetTextXml(newTextAsset);
return existingDialogue;
}
private static RemoteDialogueTrigger MakeRemoteDialogueTrigger(GameObject planetGO, Sector sector, DialogueInfo info, CharacterDialogueTree dialogue)
{
var conversationTrigger = GeneralPropBuilder.MakeNew("ConversationTrigger", planetGO, sector, info.remoteTrigger, defaultPosition: info.position, defaultParentPath: info.pathToAnimController);

View File

@ -31,6 +31,11 @@ namespace NewHorizons.External.Modules.Props.Dialogue
/// </summary>
public string pathToAnimController;
/// <summary>
/// If this dialogue is adding to existing character dialogue, put a path to the game object with the dialogue on it here
/// </summary>
public string pathToExistingDialogue;
/// <summary>
/// Radius of the spherical collision volume where you get the "talk to" prompt when looking at. If you use a
/// remoteTrigger, you can set this to 0 to make the dialogue only trigger remotely.

View File

@ -12,6 +12,7 @@ using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using UnityEngine;
using static NewHorizons.External.Modules.ParticleFieldModule;
using NomaiCoordinates = NewHorizons.External.Configs.StarSystemConfig.NomaiCoordinates;
@ -24,7 +25,7 @@ namespace NewHorizons.Utility
{
NullValueHandling = NullValueHandling.Ignore,
DefaultValueHandling = DefaultValueHandling.Ignore,
Formatting = Formatting.Indented,
Formatting = Newtonsoft.Json.Formatting.Indented,
};
private static StringBuilder stringBuilder = new StringBuilder();
@ -36,7 +37,7 @@ namespace NewHorizons.Utility
{
using (JsonTextWriter jsonTextWriter = new JsonTextWriter(stringWriter)
{
Formatting = Formatting.Indented,
Formatting = Newtonsoft.Json.Formatting.Indented,
IndentChar = '\t',
Indentation = 1
})
@ -339,5 +340,15 @@ namespace NewHorizons.Utility
}
}
}
public static List<XmlNode> GetChildNodes(this XmlNode parentNode, string tagName)
{
return parentNode.ChildNodes.Cast<XmlNode>().Where(node => node.LocalName == tagName).ToList();
}
public static XmlNode GetChildNode(this XmlNode parentNode, string tagName)
{
return parentNode.ChildNodes.Cast<XmlNode>().First(node => node.LocalName == tagName);
}
}
}