Skip to content

Commit

Permalink
1.20.2 (#856)
Browse files Browse the repository at this point in the history
## Minor features
- To avoid having to copy paste a repeated `DialogueOptionsList`, you
can instead put `ReuseDialogueOptionsListFrom` and reference another
`DialogueNode` whose options you want to repeat. Implements #854

## Improvements
- Now uses selected language instead of system language when making
strings fully uppercase or lowercase in translations
  • Loading branch information
xen-42 committed Apr 30, 2024
2 parents 17aaa9c + 70f3e92 commit e8a921d
Show file tree
Hide file tree
Showing 10 changed files with 219 additions and 16 deletions.
2 changes: 1 addition & 1 deletion NewHorizons/Builder/Props/DetailBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ public static GameObject Make(GameObject go, Sector sector, IModBehaviour mod, G
// If they're adding dialogue we have to manually register the xml text
if (isFromAssetBundle && component is CharacterDialogueTree dialogue)
{
DialogueBuilder.AddTranslation(dialogue._xmlCharacterDialogueAsset.text, null);
DialogueBuilder.HandleUnityCreatedDialogue(dialogue);
}

FixComponent(component, go, detail.ignoreSun);
Expand Down
123 changes: 118 additions & 5 deletions NewHorizons/Builder/Props/DialogueBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,14 @@
using NewHorizons.Utility.OuterWilds;
using NewHorizons.Utility.OWML;
using OWML.Common;
using System;
using System.Collections.Generic;
using System.Data.SqlTypes;
using System.IO;
using System.Xml;
using System.Xml.Linq;
using UnityEngine;
using UnityEngine.XR;

namespace NewHorizons.Builder.Props
{
Expand Down Expand Up @@ -102,7 +106,11 @@ private static CharacterDialogueTree AddToExistingDialogue(DialogueInfo info, st
// We just have to merge the dialogue options
var dialogueOptions = newDialogueNode.GetChildNode("DialogueOptionsList").GetChildNodes("DialogueOption");
var existingDialogueOptionsList = existingNode.GetChildNode("DialogueOptionsList");
var firstNode = existingDialogueOptionsList.ChildNodes[0];
if (existingDialogueOptionsList == null)
{
existingDialogueOptionsList = existingDialogueDoc.CreateElement("DialogueOptionsList");
existingNode.AppendChild(existingDialogueOptionsList);
}
foreach (XmlNode node in dialogueOptions)
{
var importedNode = existingDialogueOptionsList.OwnerDocument.ImportNode(node, true);
Expand All @@ -118,20 +126,95 @@ private static CharacterDialogueTree AddToExistingDialogue(DialogueInfo info, st
}
}

// Character name is required for adding translations, something to do with how OW prefixes its dialogue
var characterName = existingDialogueTree.SelectSingleNode("NameField").InnerText;
AddTranslation(additionalDialogueDoc.GetChildNode("DialogueTree"), characterName);

var newTextAsset = new TextAsset(existingDialogueDoc.OuterXml)
{
name = existingDialogue._xmlCharacterDialogueAsset.name
};

existingDialogue.SetTextXml(newTextAsset);

// Chracter name is required for adding translations, something to do with how OW prefixes its dialogue
var characterName = existingDialogueTree.SelectSingleNode("NameField").InnerText;
AddTranslation(xml, characterName);
FixDialogueNextFrame(existingDialogue);

return existingDialogue;
}

private static void FixDialogueNextFrame(CharacterDialogueTree characterDialogueTree)
{
Delay.FireOnNextUpdate(() =>
{
var rawText = characterDialogueTree._xmlCharacterDialogueAsset.text;
var doc = new XmlDocument();
doc.LoadXml(rawText);
var dialogueTree = doc.DocumentElement.SelectSingleNode("//DialogueTree");
DoDialogueOptionsListReplacement(dialogueTree);
var newTextAsset = new TextAsset(doc.OuterXml)
{
name = characterDialogueTree._xmlCharacterDialogueAsset.name
};
characterDialogueTree.SetTextXml(newTextAsset);
});
}

/// <summary>
/// Always call this after adding translations, else it won't update them properly
/// </summary>
/// <param name="dialogueTree"></param>
private static void DoDialogueOptionsListReplacement(XmlNode dialogueTree)
{
var optionsListsByName = new Dictionary<string, XmlNode>();
var dialogueNodes = dialogueTree.GetChildNodes("DialogueNode");
foreach (XmlNode dialogueNode in dialogueNodes)
{
var optionsList = dialogueNode.GetChildNode("DialogueOptionsList");
if (optionsList != null)
{
var name = dialogueNode.GetChildNode("Name").InnerText;
optionsListsByName[name] = optionsList;
}
}
foreach (var (name, optionsList) in optionsListsByName)
{
var replacement = optionsList.GetChildNode("ReuseDialogueOptionsListFrom");
if (replacement != null)
{
var replacementName = replacement.InnerText;
if (optionsListsByName.TryGetValue(replacementName, out var replacementOptionsList))
{
if (replacementOptionsList.GetChildNode("ReuseDialogueOptionsListFrom") != null)
{
NHLogger.LogError($"Can not target a node with ReuseDialogueOptionsListFrom that also reuses options when making dialogue. Node {name} cannot reuse the list from {replacement.InnerText}");
}
var dialogueNode = optionsList.ParentNode;
dialogueNode.RemoveChild(optionsList);
dialogueNode.AppendChild(replacementOptionsList.Clone());

// Have to manually fix the translations here
var characterName = dialogueTree.SelectSingleNode("NameField").InnerText;

var xmlText = replacementOptionsList.SelectNodes("DialogueOption/Text");
foreach (object option in xmlText)
{
var optionData = (XmlNode)option;
var text = optionData.InnerText.Trim();
TranslationHandler.ReuseDialogueTranslation(text, new string[] { characterName, replacementName }, new string[] { characterName, name });
}
}
else
{
NHLogger.LogError($"Could not reuse dialogue options list from node with Name {replacement.InnerText} to node with Name {name}");
}
}
}
}

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);
Expand Down Expand Up @@ -187,13 +270,19 @@ private static CharacterDialogueTree MakeConversationZone(GameObject planetGO, S

var dialogueTree = conversationZone.AddComponent<NHCharacterDialogueTree>();

var dialogueDoc = new XmlDocument();
dialogueDoc.LoadXml(xml);
var xmlNode = dialogueDoc.SelectSingleNode("DialogueTree");
AddTranslation(xmlNode);

xml = xmlNode.OuterXml;

var text = new TextAsset(xml)
{
// Text assets need a name to be used with VoiceMod
name = dialogueName
};
dialogueTree.SetTextXml(text);
AddTranslation(xml);

switch (info.flashlightToggle)
{
Expand All @@ -214,6 +303,8 @@ private static CharacterDialogueTree MakeConversationZone(GameObject planetGO, S

conversationZone.SetActive(true);

FixDialogueNextFrame(dialogueTree);

return dialogueTree;
}

Expand Down Expand Up @@ -378,11 +469,17 @@ private static void MakePlayerTrackingZone(GameObject go, CharacterDialogueTree
}
}

[Obsolete("Pass in the DialogueTree XmlNode instead, this is still here because Pikpik was using it in EOTP")]
public static void AddTranslation(string xml, string characterName = null)
{
var xmlDocument = new XmlDocument();
xmlDocument.LoadXml(xml);
var xmlNode = xmlDocument.SelectSingleNode("DialogueTree");
AddTranslation(xmlNode, characterName);
}

public static void AddTranslation(XmlNode xmlNode, string characterName = null)
{
var xmlNodeList = xmlNode.SelectNodes("DialogueNode");

// When adding dialogue to existing stuff, we have to pass in the character name
Expand Down Expand Up @@ -417,5 +514,21 @@ public static void AddTranslation(string xml, string characterName = null)
}
}
}

public static void HandleUnityCreatedDialogue(CharacterDialogueTree dialogue)
{
var text = dialogue._xmlCharacterDialogueAsset.text;
var dialogueDoc = new XmlDocument();
dialogueDoc.LoadXml(text);
var xmlNode = dialogueDoc.SelectSingleNode("DialogueTree");
AddTranslation(xmlNode, null);
var newTextAsset = new TextAsset(dialogueDoc.OuterXml)
{
name = dialogue._xmlCharacterDialogueAsset.name
};
dialogue.SetTextXml(newTextAsset);

FixDialogueNextFrame(dialogue);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@ internal class PlayerShipAtmosphereDetectorFix : MonoBehaviour
public void Start()
{
_fluidDetector = Locator.GetPlayerCameraDetector().GetComponent<PlayerCameraFluidDetector>();
_shipAtmosphereVolume = Locator.GetShipBody().transform.Find("Volumes/ShipAtmosphereVolume").GetComponent<SimpleFluidVolume>();
_shipAtmosphereVolume = Locator.GetShipBody()?.transform?.Find("Volumes/ShipAtmosphereVolume")?.GetComponent<SimpleFluidVolume>();
if (_shipAtmosphereVolume == null)
{
Destroy(this);
}
}

public void Update()
Expand Down
2 changes: 1 addition & 1 deletion NewHorizons/Components/ShipLog/ShipLogStarChartMode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ private void SetWarpTarget(ShipLogEntryCard shipLogEntryCard)

var name = UniqueIDToName(shipLogEntryCard.name);

var warpNotificationDataText = TranslationHandler.GetTranslation("WARP_LOCKED", TranslationHandler.TextType.UI).Replace("{0}", name.ToUpper());
var warpNotificationDataText = TranslationHandler.GetTranslation("WARP_LOCKED", TranslationHandler.TextType.UI).Replace("{0}", name.ToUpperFixed());
_warpNotificationData = new NotificationData(warpNotificationDataText);
NotificationManager.SharedInstance.PostNotification(_warpNotificationData, true);

Expand Down
22 changes: 21 additions & 1 deletion NewHorizons/Handlers/TranslationHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,26 @@ public static void AddDialogue(string rawText, bool trimRawTextForKey = false, p
TextTranslation.Get().m_table.theTable[key] = value;
}

/// <summary>
/// Two dialogue nodes might share indentical text but they will have different prefixes. Still, we want to reuse that old text.
/// </summary>
/// <param name="rawText"></param>
/// <param name="oldPrefixes"></param>
/// <param name="newPrefixes"></param>
public static void ReuseDialogueTranslation(string rawText, string[] oldPrefixes, string[] newPrefixes)
{
var key = string.Join(string.Empty, newPrefixes) + rawText;
var existingKey = string.Join(string.Empty, oldPrefixes) + rawText;
if (TextTranslation.Get().m_table.theTable.TryGetValue(existingKey, out var existingTranslation))
{
TextTranslation.Get().m_table.theTable[key] = existingTranslation;
}
else
{
NHLogger.LogWarning($"Couldn't find translation key {existingKey}");
}
}

public static void AddShipLog(string rawText, params string[] rawPreText)
{
var key = string.Join(string.Empty, rawPreText) + rawText;
Expand All @@ -189,7 +209,7 @@ public static int AddUI(string rawText)
{
var uiTable = TextTranslation.Get().m_table.theUITable;

var text = GetTranslation(rawText, TextType.UI).ToUpper();
var text = GetTranslation(rawText, TextType.UI).ToUpperFixed();

var key = uiTable.Keys.Max() + 1;
try
Expand Down
5 changes: 3 additions & 2 deletions NewHorizons/Patches/SignalPatches/AudioSignalPatches.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using NewHorizons.Builder.Props.Audio;
using NewHorizons.External;
using NewHorizons.Handlers;
using NewHorizons.Utility;
using System;
using UnityEngine;

Expand All @@ -17,7 +18,7 @@ public static bool AudioSignal_SignalNameToString(SignalName name, ref string __
var customSignalName = SignalBuilder.GetCustomSignalName(name);
if (!string.IsNullOrEmpty(customSignalName))
{
__result = TranslationHandler.GetTranslation(customSignalName, TranslationHandler.TextType.UI, false).ToUpper();
__result = TranslationHandler.GetTranslation(customSignalName, TranslationHandler.TextType.UI, false).ToUpperFixed();
return false;
}
return true;
Expand Down Expand Up @@ -68,7 +69,7 @@ public static bool AudioSignal_FrequencyToString(SignalFrequency frequency, ref
var customName = SignalBuilder.GetCustomFrequencyName(frequency);
if (!string.IsNullOrEmpty(customName))
{
if (NewHorizonsData.KnowsFrequency(customName)) __result = TranslationHandler.GetTranslation(customName, TranslationHandler.TextType.UI, false).ToUpper();
if (NewHorizonsData.KnowsFrequency(customName)) __result = TranslationHandler.GetTranslation(customName, TranslationHandler.TextType.UI, false).ToUpperFixed();
else __result = UITextLibrary.GetString(UITextType.SignalFreqUnidentified);
return false;
}
Expand Down
2 changes: 1 addition & 1 deletion NewHorizons/Utility/DebugTools/DebugReload.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public static class DebugReload

public static void InitializePauseMenu(IPauseMenuManager pauseMenu)
{
_reloadButton = pauseMenu.MakeSimpleButton(TranslationHandler.GetTranslation("Reload Configs", TranslationHandler.TextType.UI).ToUpper(), 3, true);
_reloadButton = pauseMenu.MakeSimpleButton(TranslationHandler.GetTranslation("Reload Configs", TranslationHandler.TextType.UI).ToUpperFixed(), 3, true);
_reloadButton.OnSubmitAction += ReloadConfigs;
UpdateReloadButton();
}
Expand Down
2 changes: 1 addition & 1 deletion NewHorizons/Utility/DebugTools/Menu/DebugMenu.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ private void OnChangeStarSystem(string _)

public static void InitializePauseMenu(IPauseMenuManager pauseMenu)
{
pauseMenuButton = pauseMenu.MakeSimpleButton(TranslationHandler.GetTranslation("Toggle Dev Tools Menu", TranslationHandler.TextType.UI).ToUpper(), 3, true);
pauseMenuButton = pauseMenu.MakeSimpleButton(TranslationHandler.GetTranslation("Toggle Dev Tools Menu", TranslationHandler.TextType.UI).ToUpperFixed(), 3, true);
_instance?.InitMenu();
}

Expand Down
Loading

0 comments on commit e8a921d

Please sign in to comment.