PVZFusionTranslation/Source/Patches/BaseTextObjects/InGameText_Patch.cs

369 lines
13 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using HarmonyLib;
using PvZ_Fusion_Translator.AssetStore;
using PvZ_Fusion_Translator.Patches.Modes.Odyssey;
using System.Text.RegularExpressions;
namespace PvZ_Fusion_Translator.Patches.BaseTextObjects;
[HarmonyPatch(typeof(InGameText))]
public static class InGameText_Patch
{
#pragma warning disable CA2211
public static string CurrentText = "";
#pragma warning restore CA2211
[HarmonyPatch(nameof(InGameText.ShowText)), HarmonyPostfix]
public static void ShowText(InGameText __instance) => TranslateInGameText(__instance);
[HarmonyPatch(nameof(InGameText.DebugWarning)), HarmonyPostfix]
public static void DebugWarning(InGameText __instance) => TranslateInGameText(__instance);
[HarmonyPatch(nameof(InGameText.Update)), HarmonyPostfix]
public static void Update(InGameText __instance) => TranslateInGameText(__instance);
public static void TranslateInGameText(InGameText __instance)
{
TextMeshProUGUI txt = null;
if (__instance.textMesh == null || __instance.textHead == null)
{
if (__instance.TryGetComponent(out TextMeshProUGUI selfTxt))
txt = selfTxt;
}
else
txt = __instance.textMesh;
if (txt == null)
return;
if (!txt.gameObject.active)
return;
TranslateInGameTextMesh(txt);
}
public static void TranslateInGameTextMesh(TextMeshProUGUI txt)
{
if (txt == null)
return;
if (txt.text == CurrentText)
return;
var fontAsset = FontStore.LoadTMPFont(Utils.Language.ToString());
var originalText = txt.text;
var lockedPlantMatch = CheckLockedMessage(originalText);
var travelMatch = TravelMgr_Patch.MatchTravelBuff(originalText);
var godsGachaCheck = CheckGodsGachaPopup(originalText);
var godsGachaMatch = "";
var superEditorPlantMatch = CheckSuperEditorPopup(originalText);
var customLevelRegexMatch = CheckCustomLevelRegex(originalText);
var qualityCheckMatch = CheckQualityUpgrade(originalText);
godsGachaMatch = godsGachaCheck switch
{
1 or 2 or 3 => TranslateGodsGachaPopup(originalText, godsGachaCheck),
_ => godsGachaMatch,
};
if (godsGachaMatch != "")
{
txt.text = godsGachaMatch;
if (txt.gameObject.name.Contains("main"))
{
originalText = txt.text;
var shadowText = txt.transform.parent.Find("Text_shadow");
if (shadowText != null)
shadowText.GetComponent<TextMeshProUGUI>().text = Utils.RemoveColorTags(originalText);
}
}
else if (travelMatch != "")
{
txt.text = TravelMgr_Patch.AddBuffName(travelMatch);
if (txt.gameObject.name.Contains("main"))
{
originalText = txt.text;
var shadowText = txt.transform.parent.Find("Text_shadow");
if (shadowText != null)
shadowText.GetComponent<TextMeshProUGUI>().text = Utils.RemoveColorTags(originalText);
}
}
else if (qualityCheckMatch != "")
txt.text = qualityCheckMatch;
else if (superEditorPlantMatch != "")
txt.text = superEditorPlantMatch;
else if (lockedPlantMatch != "")
txt.text = lockedPlantMatch;
else if (customLevelRegexMatch != "")
txt.text = customLevelRegexMatch;
else if (Regex.Match(txt.text, "(<color[^>]*>.*?</color>)", RegexOptions.Singleline).Success &&
!StringStore.TranslationString.ContainsKey(txt.text) &&
!StringStore.FSTipCollectionString.ContainsKey(txt.text) &&
!StringStore.IZTipCollectionString.ContainsKey(txt.text) &&
!StringStore.CustomLevelString.ContainsKey(txt.text))
{
txt.text = StringStore.TranslateColorText(txt.text, true);
if (txt.gameObject.name.Contains("main"))
{
originalText = txt.text;
var shadowText = txt.transform.parent.Find("Text_shadow");
if (shadowText != null)
shadowText.GetComponent<TextMeshProUGUI>().text = Utils.RemoveColorTags(originalText);
}
}
else
{
txt.text = StringStore.TranslateText(txt.text, true);
if (txt.gameObject.name.Contains("main"))
{
originalText = txt.text;
var shadowText = txt.transform.parent.Find("Text_shadow");
if (shadowText != null)
shadowText.GetComponent<TextMeshProUGUI>().text = Utils.RemoveColorTags(originalText);
}
}
txt.font = fontAsset;
CurrentText = txt.text;
}
public const string NamePlantedPattern = "种植了:([^\\s]+)";
public const string NameUpgradedPattern = @"升级成功:([^\s]+) -> ([^\s]+)";
public const string NameAlreadyPlantedPattern = "场上已经有一个([^\\s]+)了";
public const string UpgradePathRemovedPattern = "已移除路线:([^\\s]+)";
public const string LockedPlantPattern = @"^([\s\S]+)\+([\S]+)$";
public const string MultiLockedPlantPattern = @"^或 ([\s\S]+)\+([\S]+)$";
public const string QualityChangePattern =
"""
诸神注视着你,并选中了一个他们喜欢的词条
植物<color=green>【([\S]+)】</color>的词条<color=yellow>【强化:([\S]+)】</color>获得品质升级
当前品质:([\S]+)
""";
public static readonly Dictionary<string, string> FallbackFStrs = new()
{
{ NamePlantedPattern, "{0} planted!" },
{ NameUpgradedPattern, "{0} successfully upgraded to {1}!" },
{ NameAlreadyPlantedPattern, "{0} already exists on the lawn!" },
{ UpgradePathRemovedPattern, "Upgrade Path removed for {0}" },
{ @"([^\s]+)\((\d+)\)", "{0}({1})" },
{ LockedPlantPattern, "{0} + {1}" },
{ MultiLockedPlantPattern, "or {0} + {1}" },
{
QualityChangePattern,
"""
The gods are watching you, and they have granted you an upgrade!
The <color=yellow>{1}</color> upgrade for <color=green>{0}</color> has been upgraded.
Current Quality: {2}
"""
},
};
public static int CheckGodsGachaPopup(string originalText)
{
var res = 0;
if (Regex.IsMatch(originalText, NamePlantedPattern))
res = 1;
else if (Regex.IsMatch(originalText, NameUpgradedPattern))
res = 2;
else if (Regex.IsMatch(originalText, NameAlreadyPlantedPattern))
res = 3;
return res;
}
public static string TranslateGodsGachaPopup(string originalText, int type) =>
type switch
{
1 => StringStore.TranslateText(originalText, NamePlantedPattern),
2 => StringStore.TranslateText(originalText, NameUpgradedPattern),
3 => StringStore.TranslateText(originalText, NameAlreadyPlantedPattern),
_ => originalText,
};
public static string TranslatePlantNameParts(string originalText, string pattern)
{
var res = "";
var match = Regex.Match(originalText, pattern);
if (!match.Success)
return res;
var groups = match.Groups;
var fStr = StringStore.TranslationStringRegex.TryGetValue(pattern, out var value)
? value
: FallbackFStrs[pattern];
List<string> dynamicParts = [];
for (var i = 1; i < groups.Count; i++)
{
var group = groups[i].Value;
var plantName = Utils.GetPlantNameFromAlmanac(group);
dynamicParts.Add(plantName);
}
res = string.Format(fStr, [..dynamicParts]);
return res;
}
public static string TranslatePlantNameParts(string originalText, string pattern, string fallback)
{
var res = "";
var match = Regex.Match(originalText, pattern);
if (!match.Success)
return res;
var groups = match.Groups;
var fStr = StringStore.TranslationStringRegex.GetValueOrDefault(pattern, fallback);
List<string> dynamicParts = [];
for (var i = 1; i < groups.Count; i++)
{
var group = groups[i].Value;
var plantName = Utils.GetPlantNameFromAlmanac(group);
if (plantName == "")
plantName = StringStore.TranslateText(group);
dynamicParts.Add(plantName);
}
res = string.Format(fStr, [..dynamicParts]);
return res;
}
public static string CheckSuperEditorPopup(string originalText)
{
var res = "";
if (Regex.IsMatch(originalText, UpgradePathRemovedPattern))
res = StringStore.TranslateText(originalText, UpgradePathRemovedPattern);
else if (Regex.IsMatch(originalText, "当前全部基础植物:(.*)"))
{
const string Pattern = "当前全部基础植物:(.*)";
var match = Regex.Match(originalText, Pattern);
if (!match.Success)
return res;
var groups = match.Groups;
var plantNameGroup = groups[1].Value;
var plantNames = plantNameGroup.Split(" ");
var plantRes = "";
const string ShortPattern = @"([^\s]+)\((\d+)\)";
foreach (var shortMatch in plantNames
.Select(plantName => Regex.Match(plantName, ShortPattern))
.Where(shortMatch => shortMatch.Success))
{
var fStr = StringStore.TranslationStringRegex.TryGetValue(ShortPattern, out var value)
? value
: FallbackFStrs[ShortPattern];
var shortRes = string.Format(
fStr,
[Utils.GetPlantNameFromAlmanac(shortMatch.Groups[1].Value), shortMatch.Groups[2].Value]
);
plantRes += shortRes + " ";
}
res = StringStore.TranslateText("当前全部基础植物:" + plantRes);
}
return res;
}
public static string CheckLockedMessage(string originalText)
{
var res = "";
var lockedPlantRegex = new Regex(LockedPlantPattern);
// var multiLockedPlantRegex = new Regex(MultiLockedPlantPattern);
if (!lockedPlantRegex.IsMatch(originalText))
return res;
if (originalText.Contains('\n'))
{
var lines = originalText.Split("\n");
if (!lockedPlantRegex.IsMatch(lines[0]))
return res;
var firstLine = lines[0];
var match = lockedPlantRegex.Match(firstLine);
var groups = match.Groups;
if (Utils.PlantIndiceString.ContainsKey(groups[1].Value) &&
Utils.PlantIndiceString.ContainsKey(groups[2].Value))
{
firstLine = StringStore.TranslateText(firstLine, LockedPlantPattern);
var translatedLines = new List<string> { firstLine };
for (var i = 1; i < lines.Length; i++)
{
var nextLine = lines[i];
var translatedNextLine = StringStore.TranslateText(nextLine, MultiLockedPlantPattern);
translatedLines.Add(translatedNextLine);
}
res = string.Join("\n", translatedLines);
}
else
return "";
}
else
{
if (!lockedPlantRegex.IsMatch(originalText))
return res;
var match = lockedPlantRegex.Match(originalText);
var groups = match.Groups;
if (Utils.PlantIndiceString.ContainsKey(groups[1].Value) &&
Utils.PlantIndiceString.ContainsKey(groups[2].Value))
res = StringStore.TranslateText(originalText, LockedPlantPattern);
else
return "";
}
return res;
}
public static string CheckCustomLevelRegex(string originalText) =>
StringStore.TranslationStringRegex.All(p => !StringStore.TestRegex(originalText, p.Key)) &&
StringStore.CustomLevelStringRegex.FirstOrDefault(p => StringStore.TestRegex(originalText, p.Key)) is
{ Key: var key }
? StringStore.TranslateText(originalText, key)
: null;
public static string CheckQualityUpgrade(string originalText)
{
var res = "";
if (Regex.IsMatch(originalText, QualityChangePattern))
res = StringStore.TranslateText(originalText, QualityChangePattern);
return res;
}
}