From 4f532e7b4929221ba52d4353aa4a43b1d4559ce4 Mon Sep 17 00:00:00 2001 From: SillyStar-Github <90102598+SillyStar-Github@users.noreply.github.com> Date: Thu, 12 Feb 2026 03:16:32 -0500 Subject: [PATCH] a BUNCH of odyssey/investment translation --- MelonLoader/Core.cs | 11 +- MelonLoader/FileLoader.cs | 73 ++++++- .../BaseTextObjects/InGameText_Patch.cs | 6 +- .../Patches/Managers/DifficultyMgr_Patch.cs | 14 +- .../Managers/OppositeBuffManager_Patch.cs | 38 ++-- .../Modes/Odyssey/TravelBuffMenu_Patch.cs | 46 ++--- .../Odyssey/TravelBuffOptionButton_Patch.cs | 70 +++---- .../Modes/Odyssey/TravelInvestMenu_Patch.cs | 25 +++ .../Modes/Odyssey/TravelLookBuff_Patch.cs | 92 ++++----- .../Modes/Odyssey/TravelLookMenu_Patch.cs | 82 ++++---- .../Patches/Modes/Odyssey/TravelMgr_Patch.cs | 186 ++++++++++-------- .../Modes/Odyssey/TravelStoreWindow_Patch.cs | 97 +++++++++ .../Modes/Odyssey/TravelStore_Patch.cs | 127 ++++++------ .../Modes/Odyssey/TravelSynergyMenu_Patch.cs | 110 +++++++++++ ...PvZ Fusion Translator [MelonLoader].csproj | 3 + 15 files changed, 647 insertions(+), 333 deletions(-) create mode 100644 MelonLoader/Patches/Modes/Odyssey/TravelInvestMenu_Patch.cs create mode 100644 MelonLoader/Patches/Modes/Odyssey/TravelStoreWindow_Patch.cs create mode 100644 MelonLoader/Patches/Modes/Odyssey/TravelSynergyMenu_Patch.cs diff --git a/MelonLoader/Core.cs b/MelonLoader/Core.cs index c9eb3b3..05812ca 100644 --- a/MelonLoader/Core.cs +++ b/MelonLoader/Core.cs @@ -1,10 +1,14 @@ -using Il2CppTMPro; +using Il2Cpp; +using Il2CppTMPro; using MelonLoader; using MelonLoader.Utils; using PvZ_Fusion_Translator.AssetStore; using PvZ_Fusion_Translator.Patches.Managers; +using PvZ_Fusion_Translator.Patches.Modes.Odyssey; +using System.Runtime.CompilerServices; +using System.Text.Json; using UnityEngine; -using Il2Cpp; +using static PvZ_Fusion_Translator.FileLoader; [assembly: MelonInfo(typeof(PvZ_Fusion_Translator.Core), "PvZ Fusion Translator", "231.0.0", "dynaslash / arifrios1st / lancerx0 / JustNull / Dakosha / Mamoru-kun / cassidy / Teyliu", null)] [assembly: MelonGame("LanPiaoPiao", "PlantsVsZombiesRH")] @@ -42,7 +46,8 @@ namespace PvZ_Fusion_Translator { dtStart = DateTime.Now; replaceTextureRoutine = MelonCoroutines.Start(TextureStore.ReplaceTexturesCoroutine()); - } + TravelMgr_Patch.DumpTravelBuffs(); + } public override void OnDeinitializeMelon() { diff --git a/MelonLoader/FileLoader.cs b/MelonLoader/FileLoader.cs index c51f3d7..f4ca6b2 100644 --- a/MelonLoader/FileLoader.cs +++ b/MelonLoader/FileLoader.cs @@ -2,11 +2,11 @@ using MelonLoader; using PvZ_Fusion_Translator.AssetStore; using PvZ_Fusion_Translator.Patches.GameObjects.MinorObjects; +using PvZ_Fusion_Translator.Patches.Modes.Odyssey; using PvZ_Fusion_Translator.Patches.OtherManagers; using System.Text.Encodings.Web; using System.Text.Json; using UnityEngine; -using UnityEngine.Rendering; namespace PvZ_Fusion_Translator { @@ -81,7 +81,11 @@ namespace PvZ_Fusion_Translator } Zombie_Patch.LoadHPStrings(); } - } + else if(fileName.EndsWith("travel_buffs")) + { + TravelMgr_Patch.translatedTravelBuffs = JsonSerializer.Deserialize>>(jsonString); + } + } SaveStrings(); DumpJson(); } @@ -318,6 +322,68 @@ namespace PvZ_Fusion_Translator File.WriteAllText(Path.Combine(dumpDir, "ZombieStrings.json"), ZombieStrings); File.WriteAllText(Path.Combine(dumpDir, "AbyssBuffData.json"), AbyssBuffData); + // dump iz tips + var izLevelData = Resources.LoadAll("izleveldata"); + Dictionary izLevelDataDump = new Dictionary(); + + string izTranslatedPath = Path.Combine(GetAssetDir(AssetType.Strings, Utils.Language), "tips_iz.json"); + if (!File.Exists(izTranslatedPath)) + { + File.WriteAllText(izTranslatedPath, JsonSerializer.Serialize(izLevelDataDump)); + } + var izTranslatedTips = JsonSerializer.Deserialize>(File.ReadAllText(izTranslatedPath)); + + foreach (var level in izLevelData) + { + string data = level.text; + LevelData levelData = JsonUtility.FromJson(data); + if(levelData.tips != null) + { + izLevelDataDump.Add(level.name, levelData.tips); + if(izTranslatedTips.ContainsKey(level.name) && !StringStore.translationString.ContainsKey(levelData.tips)) + { + StringStore.translationString.Add(levelData.tips, izTranslatedTips[level.name]); + } + } + } + + File.WriteAllText(Path.Combine(dumpDir, "tips_iz.json"), JsonSerializer.Serialize(izLevelDataDump, new JsonSerializerOptions + { + WriteIndented = true, + Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping + })); + + // dump fusion showcase tips + var fusionShowcaseData = Resources.LoadAll("leveldata/explore"); + Dictionary fusionShowcaseDataDump = new Dictionary(); + + string fsTranslatedPath = Path.Combine(GetAssetDir(AssetType.Strings, Utils.Language), "tips_fs.json"); + if(!File.Exists(fsTranslatedPath)) + { + File.WriteAllText(fsTranslatedPath, JsonSerializer.Serialize(fusionShowcaseDataDump)); + } + var fsTranslatedTips = JsonSerializer.Deserialize>(File.ReadAllText(fsTranslatedPath)); + + foreach (var level in fusionShowcaseData) + { + string data = level.text; + LevelData levelData = JsonUtility.FromJson(data); + if (levelData.tips != null) + { + fusionShowcaseDataDump.Add(level.name, levelData.tips); + if (fsTranslatedTips.ContainsKey(level.name) && !StringStore.translationString.ContainsKey(levelData.tips)) + { + StringStore.translationString.Add(levelData.tips, fsTranslatedTips[level.name]); + } + } + } + + File.WriteAllText(Path.Combine(dumpDir, "tips_fs.json"), JsonSerializer.Serialize(fusionShowcaseDataDump, new JsonSerializerOptions + { + WriteIndented = true, + Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping + })); + Dictionary achievementsList = new Dictionary(); foreach (Il2CppSystem.Collections.Generic.KeyValuePair> entry in AchievementClip.achievementsText) { @@ -328,7 +394,7 @@ namespace PvZ_Fusion_Translator WriteIndented = true, Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping })); - } + } #if DEBUG public static void DumpUntranslatedStrings(string text) @@ -361,6 +427,7 @@ namespace PvZ_Fusion_Translator } } #endif + #if MULTI_LANGUAGE internal static void LoadLanguage() diff --git a/MelonLoader/Patches/BaseTextObjects/InGameText_Patch.cs b/MelonLoader/Patches/BaseTextObjects/InGameText_Patch.cs index 175eb58..6fa5ac4 100644 --- a/MelonLoader/Patches/BaseTextObjects/InGameText_Patch.cs +++ b/MelonLoader/Patches/BaseTextObjects/InGameText_Patch.cs @@ -2,6 +2,8 @@ using Il2Cpp; using Il2CppTMPro; using PvZ_Fusion_Translator.AssetStore; +using PvZ_Fusion_Translator.Patches.Modes.Odyssey; + //using PvZ_Fusion_Translator.Patches.Modes.Odyssey; using System.Text.RegularExpressions; using System.Xml.Linq; @@ -20,8 +22,8 @@ namespace PvZ_Fusion_Translator.Patches.BaseTextObjects foreach (TextMeshProUGUI txt in __instance.GetComponentsInChildren()) { - string travelMatch = ""; string originalText = txt.text; + string travelMatch = TravelMgr_Patch.MatchTravelBuff(originalText); if (txt.gameObject.name.Contains("shadow")) { @@ -41,7 +43,7 @@ namespace PvZ_Fusion_Translator.Patches.BaseTextObjects } } } - else if(Regex.Match(txt.text, @"(]*>.*?)", RegexOptions.Singleline).Success) + else if((Regex.Match(txt.text, @"(]*>.*?)", RegexOptions.Singleline).Success) && !StringStore.translationString.ContainsKey(txt.text)) { txt.text = StringStore.TranslateColorText(txt.text, true); if (txt.gameObject.name.Contains("main")) diff --git a/MelonLoader/Patches/Managers/DifficultyMgr_Patch.cs b/MelonLoader/Patches/Managers/DifficultyMgr_Patch.cs index 4b294d8..3d05ff1 100644 --- a/MelonLoader/Patches/Managers/DifficultyMgr_Patch.cs +++ b/MelonLoader/Patches/Managers/DifficultyMgr_Patch.cs @@ -8,12 +8,12 @@ namespace PvZ_Fusion_Translator.Patches.Managers [HarmonyPatch(typeof(DifficultyMgr))] public static class DifficultyMgr_Patch { - //[HarmonyPatch(nameof(DifficultyMgr.Update))] - //[HarmonyPostfix] - //private static void DifficultyMgr_Update(DifficultyMgr __instance) - //{ - // __instance.t = StringStore.TranslateText(__instance.t); - // __instance.t.autoSizeTextContainer = false; - //} + [HarmonyPatch(nameof(DifficultyMgr.Update))] + [HarmonyPostfix] + private static void DifficultyMgr_Update(DifficultyMgr __instance) + { + __instance.t = StringStore.TranslateText(__instance.t); + __instance.t.autoSizeTextContainer = false; + } } } diff --git a/MelonLoader/Patches/Managers/OppositeBuffManager_Patch.cs b/MelonLoader/Patches/Managers/OppositeBuffManager_Patch.cs index 4913c91..fbf82c7 100644 --- a/MelonLoader/Patches/Managers/OppositeBuffManager_Patch.cs +++ b/MelonLoader/Patches/Managers/OppositeBuffManager_Patch.cs @@ -2,7 +2,7 @@ using Il2Cpp; using Il2CppTMPro; using PvZ_Fusion_Translator.AssetStore; -//using PvZ_Fusion_Translator.Patches.Modes.Odyssey; +using PvZ_Fusion_Translator.Patches.Modes.Odyssey; using System.Text.RegularExpressions; using UnityEngine; @@ -11,11 +11,11 @@ namespace PvZ_Fusion_Translator.Patches.Managers [HarmonyPatch(typeof(OppositeBuffManager))] public static class OppositeBuffManager_Patch { - //public static Dictionary buffLinks = TravelMgr_Patch.buffLinks; - //public static Dictionary> translatedTravelBuffs = TravelMgr_Patch.translatedTravelBuffs; - //public static string badPattern = @"^但(.*)"; - //public static string badFormat = StringStore.translationStringRegex.ContainsKey(badPattern) ? StringStore.translationStringRegex[badPattern] : "But, {0}"; - //public static TMP_FontAsset fontAsset = FontStore.LoadTMPFont(Utils.Language.ToString()); + public static Dictionary buffLinks = TravelMgr_Patch.buffLinks; + public static Dictionary> translatedTravelBuffs = TravelMgr_Patch.translatedTravelBuffs; + public static string badPattern = @"^但(.*)"; + public static string badFormat = StringStore.translationStringRegex.ContainsKey(badPattern) ? StringStore.translationStringRegex[badPattern] : "But, {0}"; + public static TMP_FontAsset fontAsset = FontStore.LoadTMPFont(Utils.Language.ToString()); [HarmonyPatch(nameof(OppositeBuffManager.Awake))] [HarmonyPostfix] @@ -29,21 +29,21 @@ namespace PvZ_Fusion_Translator.Patches.Managers public static void TranslateOppositeText(Il2CppSystem.Collections.Generic.List textList, BuffType buffType, int buffIndex, bool isBad = false) { - //string buff = translatedTravelBuffs[buffLinks[buffType]][buffIndex]; + string buff = translatedTravelBuffs[buffLinks[buffType]][buffIndex]; - //foreach(var text in textList) - //{ - // if(isBad) - // { - // text.text = string.Format(badFormat, buff); - // } - // else - // { - // text.text = buff; - // } + foreach (var text in textList) + { + if (isBad) + { + text.text = string.Format(badFormat, buff); + } + else + { + text.text = buff; + } - // text.font = fontAsset; - //} + text.font = fontAsset; + } } } } diff --git a/MelonLoader/Patches/Modes/Odyssey/TravelBuffMenu_Patch.cs b/MelonLoader/Patches/Modes/Odyssey/TravelBuffMenu_Patch.cs index c0d6da3..95bf66a 100644 --- a/MelonLoader/Patches/Modes/Odyssey/TravelBuffMenu_Patch.cs +++ b/MelonLoader/Patches/Modes/Odyssey/TravelBuffMenu_Patch.cs @@ -1,24 +1,24 @@ -//using HarmonyLib; -//using Il2Cpp; -//using Il2CppTMPro; -//using PvZ_Fusion_Translator.AssetStore; -//using static PvZ_Fusion_Translator.Patches.Modes.Odyssey.TravelMgr_Patch; -//using UnityEngine; -//using MelonLoader; +using HarmonyLib; +using Il2Cpp; +using Il2CppTMPro; +using PvZ_Fusion_Translator.AssetStore; +using static PvZ_Fusion_Translator.Patches.Modes.Odyssey.TravelMgr_Patch; +using UnityEngine; +using MelonLoader; -//namespace PvZ_Fusion_Translator.Patches.Modes.Odyssey -//{ -// [HarmonyPatch(typeof(TravelBuffMenu))] -// public static class TravelBuffMenu_Patch -// { -// [HarmonyPatch(nameof(TravelBuffMenu.RefeshOptions))] -// [HarmonyPostfix] -// public static void RefeshOptions(TravelBuffMenu __instance) -// { -// foreach(TravelBuffOptionButton button in __instance.options) -// { -// TravelBuffOptionButton_Patch.TranslateOptionButton(button); -// } -// } -// } -//} \ No newline at end of file +namespace PvZ_Fusion_Translator.Patches.Modes.Odyssey +{ + [HarmonyPatch(typeof(TravelBuffMenu))] + public static class TravelBuffMenu_Patch + { + [HarmonyPatch(nameof(TravelBuffMenu.RefeshOptions))] + [HarmonyPostfix] + public static void RefeshOptions(TravelBuffMenu __instance) + { + foreach (TravelBuffOptionButton button in __instance.options) + { + TravelBuffOptionButton_Patch.TranslateOptionButton(button); + } + } + } +} \ No newline at end of file diff --git a/MelonLoader/Patches/Modes/Odyssey/TravelBuffOptionButton_Patch.cs b/MelonLoader/Patches/Modes/Odyssey/TravelBuffOptionButton_Patch.cs index a98e95b..a0ef13c 100644 --- a/MelonLoader/Patches/Modes/Odyssey/TravelBuffOptionButton_Patch.cs +++ b/MelonLoader/Patches/Modes/Odyssey/TravelBuffOptionButton_Patch.cs @@ -1,41 +1,41 @@ -//using HarmonyLib; -//using Il2Cpp; -//using Il2CppTMPro; -//using MelonLoader; -//using PvZ_Fusion_Translator.AssetStore; -//using static MelonLoader.MelonLogger; -//using static PvZ_Fusion_Translator.Patches.Modes.Odyssey.TravelMgr_Patch; +using HarmonyLib; +using Il2Cpp; +using Il2CppTMPro; +using MelonLoader; +using PvZ_Fusion_Translator.AssetStore; +using static MelonLoader.MelonLogger; +using static PvZ_Fusion_Translator.Patches.Modes.Odyssey.TravelMgr_Patch; -//namespace PvZ_Fusion_Translator.Patches.Modes.Odyssey -//{ -// [HarmonyPatch(typeof(TravelBuffOptionButton))] -// public static class TravelBuffOptionButton_Patch -// { -// [HarmonyPatch(nameof(TravelBuffOptionButton.Awake))] -// [HarmonyPostfix] -// public static void Awake(TravelBuffOptionButton __instance) -// { -// TranslateOptionButton(__instance); -// } +namespace PvZ_Fusion_Translator.Patches.Modes.Odyssey +{ + [HarmonyPatch(typeof(TravelBuffOptionButton))] + public static class TravelBuffOptionButton_Patch + { + [HarmonyPatch(nameof(TravelBuffOptionButton.Awake))] + [HarmonyPostfix] + public static void Awake(TravelBuffOptionButton __instance) + { + TranslateOptionButton(__instance); + } -// [HarmonyPatch(nameof(TravelBuffOptionButton.OnAnimOver))] -// [HarmonyPostfix] -// public static void OnAnimOver(TravelBuffOptionButton __instance) -// { -// TranslateOptionButton(__instance); -// } + [HarmonyPatch(nameof(TravelBuffOptionButton.OnAnimOver))] + [HarmonyPostfix] + public static void OnAnimOver(TravelBuffOptionButton __instance) + { + TranslateOptionButton(__instance); + } -// public static void TranslateOptionButton(TravelBuffOptionButton button) -// { -// List buffSet = translatedTravelBuffs[buffLinks[button.buffType]]; + public static void TranslateOptionButton(TravelBuffOptionButton button) + { + SortedDictionary buffSet = translatedTravelBuffs[buffLinks[button.buffType]]; -// string buff = button.show != null && button.introduce.text != "词条已选完" ? buffSet[button.buffIndex] : StringStore.TranslateText("词条已选完"); + string buff = button.show != null && button.introduce.text != "词条已选完" ? buffSet[button.buffIndex] : StringStore.TranslateText("词条已选完"); -// button.introduce.text = buff; -// } -// } + button.introduce.text = buff; + } + } -// //List buffSet = translatedTravelBuffs[buffLinks[__instance.buffType]]; -// //string buff = (__instance.show != null) ? buffSet[__instance.buffIndex] : StringStore.TranslateText("无"); -// //__instance.introduce.text = buff; -//} + //List buffSet = translatedTravelBuffs[buffLinks[__instance.buffType]]; + //string buff = (__instance.show != null) ? buffSet[__instance.buffIndex] : StringStore.TranslateText("无"); + //__instance.introduce.text = buff; +} diff --git a/MelonLoader/Patches/Modes/Odyssey/TravelInvestMenu_Patch.cs b/MelonLoader/Patches/Modes/Odyssey/TravelInvestMenu_Patch.cs new file mode 100644 index 0000000..bb02cf8 --- /dev/null +++ b/MelonLoader/Patches/Modes/Odyssey/TravelInvestMenu_Patch.cs @@ -0,0 +1,25 @@ +using HarmonyLib; +using Il2Cpp; +using Il2CppTMPro; +using PvZ_Fusion_Translator.AssetStore; +using UnityEngine; + +namespace PvZ_Fusion_Translator.Patches.Modes.Odyssey +{ + [HarmonyPatch(typeof(TravelInvestMenu))] + public static class TravelInvestMenu_Patch + { + [HarmonyPatch(nameof(TravelInvestMenu.Start))] + [HarmonyPostfix] + private static void Start(TravelInvestMenu __instance) + { + Transform titleText = __instance.transform.Find("Title"); + TextMeshProUGUI shadowText = titleText.GetComponent(); + + TextMeshProUGUI regularText = titleText.transform.Find("Title2").GetComponent(); + regularText.text = StringStore.TranslateText(regularText.text); + + shadowText.text = Utils.RemoveColorTags(regularText.text); + } + } +} diff --git a/MelonLoader/Patches/Modes/Odyssey/TravelLookBuff_Patch.cs b/MelonLoader/Patches/Modes/Odyssey/TravelLookBuff_Patch.cs index a7ac39f..ecf918a 100644 --- a/MelonLoader/Patches/Modes/Odyssey/TravelLookBuff_Patch.cs +++ b/MelonLoader/Patches/Modes/Odyssey/TravelLookBuff_Patch.cs @@ -1,51 +1,51 @@ -//using HarmonyLib; -//using Il2Cpp; -//using Il2CppTMPro; -//using PvZ_Fusion_Translator.AssetStore; -//using static PvZ_Fusion_Translator.Patches.Modes.Odyssey.TravelMgr_Patch; -//using UnityEngine; -//using MelonLoader; +using HarmonyLib; +using Il2Cpp; +using Il2CppTMPro; +using PvZ_Fusion_Translator.AssetStore; +using static PvZ_Fusion_Translator.Patches.Modes.Odyssey.TravelMgr_Patch; +using UnityEngine; +using MelonLoader; -//namespace PvZ_Fusion_Translator.Patches.Modes.Odyssey -//{ -// [HarmonyPatch(typeof(TravelLookBuff))] -// public static class TravelLookBuff_Patch -// { -// [HarmonyPatch(nameof(TravelLookBuff.Clear))] -// [HarmonyPostfix] -// public static void Post_Clear(TravelLookBuff __instance) -// { -// __instance.introduce.text = StringStore.TranslateText("无"); -// __instance.set = false; +namespace PvZ_Fusion_Translator.Patches.Modes.Odyssey +{ + [HarmonyPatch(typeof(TravelLookBuff))] + public static class TravelLookBuff_Patch + { + [HarmonyPatch(nameof(TravelLookBuff.Clear))] + [HarmonyPostfix] + public static void Post_Clear(TravelLookBuff __instance) + { + __instance.introduce.text = StringStore.TranslateText("无"); + __instance.set = false; -// foreach (TextMeshProUGUI text in __instance.transform.FindChild("Images").FindChild("Button").GetComponentsInChildren()) -// { -// text.text = StringStore.TranslateText(text.text); -// } -// } + foreach (TextMeshProUGUI text in __instance.transform.FindChild("Images").FindChild("Button").GetComponentsInChildren()) + { + text.text = StringStore.TranslateText(text.text); + } + } -// [HarmonyPatch(nameof(TravelLookBuff.OnMouseUpAsButton))] -// [HarmonyPostfix] -// public static void Post_OnMouseUpAsButton(TravelLookBuff __instance) -// { -// foreach (TextMeshProUGUI text in __instance.transform.FindChild("Images").FindChild("Button").GetComponentsInChildren()) -// { -// text.text = StringStore.TranslateText(text.text); -// } -// } + [HarmonyPatch(nameof(TravelLookBuff.OnMouseUpAsButton))] + [HarmonyPostfix] + public static void Post_OnMouseUpAsButton(TravelLookBuff __instance) + { + foreach (TextMeshProUGUI text in __instance.transform.FindChild("Images").FindChild("Button").GetComponentsInChildren()) + { + text.text = StringStore.TranslateText(text.text); + } + } -// [HarmonyPatch(nameof(TravelLookBuff.SetBuff))] -// [HarmonyPostfix] -// public static void Post_SetBuff(TravelLookBuff __instance) -// { -// List buffSet = translatedTravelBuffs[buffLinks[__instance.buffType]]; -// string buffText = __instance.buffIndex < buffSet.Count ? buffSet[__instance.buffIndex] : StringStore.TranslateText(__instance.introduce.text); -// __instance.introduce.text = buffText; + [HarmonyPatch(nameof(TravelLookBuff.SetBuff))] + [HarmonyPostfix] + public static void Post_SetBuff(TravelLookBuff __instance) + { + SortedDictionary buffSet = translatedTravelBuffs[buffLinks[__instance.buffType]]; + string buffText = buffSet.ContainsKey(__instance.buffIndex) ? buffSet[__instance.buffIndex] : StringStore.TranslateText(__instance.introduce.text); + __instance.introduce.text = buffText; -// foreach (TextMeshProUGUI text in __instance.transform.FindChild("Images").FindChild("Button").GetComponentsInChildren()) -// { -// text.text = StringStore.TranslateText(text.text); -// } -// } -// } -//} \ No newline at end of file + foreach (TextMeshProUGUI text in __instance.transform.FindChild("Images").FindChild("Button").GetComponentsInChildren()) + { + text.text = StringStore.TranslateText(text.text); + } + } + } +} \ No newline at end of file diff --git a/MelonLoader/Patches/Modes/Odyssey/TravelLookMenu_Patch.cs b/MelonLoader/Patches/Modes/Odyssey/TravelLookMenu_Patch.cs index b00281a..cda2c7a 100644 --- a/MelonLoader/Patches/Modes/Odyssey/TravelLookMenu_Patch.cs +++ b/MelonLoader/Patches/Modes/Odyssey/TravelLookMenu_Patch.cs @@ -1,46 +1,46 @@ -//using HarmonyLib; -//using Il2Cpp; -//using Il2CppTMPro; -//using PvZ_Fusion_Translator.AssetStore; -//using UnityEngine; +using HarmonyLib; +using Il2Cpp; +using Il2CppTMPro; +using PvZ_Fusion_Translator.AssetStore; +using UnityEngine; -//namespace PvZ_Fusion_Translator.Patches.Modes.Odyssey -//{ -// [HarmonyPatch(typeof(TravelLookMenu))] -// public static class TravelLookMenu_Patch -// { -// public static string savedAssetString = ""; +namespace PvZ_Fusion_Translator.Patches.Modes.Odyssey +{ + [HarmonyPatch(typeof(TravelLookMenu))] + public static class TravelLookMenu_Patch + { + public static string savedAssetString = ""; -// [HarmonyPatch(nameof(TravelLookMenu.Start))] -// [HarmonyPostfix] -// private static void Postfix_Start(TravelLookMenu __instance) -// { -// foreach (TextMeshProUGUI txt in __instance.GetComponentsInChildren()) -// { -// txt.text = StringStore.TranslateText(txt.text); -// txt.font = FontStore.LoadTMPFont(Utils.Language.ToString()); -// } + [HarmonyPatch(nameof(TravelLookMenu.Start))] + [HarmonyPostfix] + private static void Postfix_Start(TravelLookMenu __instance) + { + foreach (TextMeshProUGUI txt in __instance.GetComponentsInChildren()) + { + txt.text = StringStore.TranslateText(txt.text); + txt.font = FontStore.LoadTMPFont(Utils.Language.ToString()); + } -// Transform quitButtonTransform = __instance.transform.Find("Quit"); -// foreach (TextMeshProUGUI txt in quitButtonTransform.GetComponentsInChildren()) -// { -// txt.text = StringStore.TranslateText("合上"); -// txt.font = FontStore.LoadTMPFont(Utils.Language.ToString()); -// } + Transform quitButtonTransform = __instance.transform.Find("Quit"); + foreach (TextMeshProUGUI txt in quitButtonTransform.GetComponentsInChildren()) + { + txt.text = StringStore.TranslateText("合上"); + txt.font = FontStore.LoadTMPFont(Utils.Language.ToString()); + } -// __instance.treasureText.text = StringStore.TranslateText(__instance.treasureText.text); -// savedAssetString = __instance.treasureText.text; -// } + __instance.treasureText.text = StringStore.TranslateText(__instance.treasureText.text); + savedAssetString = __instance.treasureText.text; + } -// [HarmonyPatch(nameof(TravelLookMenu.Update))] -// [HarmonyPostfix] -// private static void Update(TravelLookMenu __instance) -// { -// if (savedAssetString != __instance.treasureText.text) -// { -// __instance.treasureText.text = StringStore.TranslateText(__instance.treasureText.text); -// savedAssetString = __instance.treasureText.text; -// } -// } -// } -//} \ No newline at end of file + [HarmonyPatch(nameof(TravelLookMenu.Update))] + [HarmonyPostfix] + private static void Update(TravelLookMenu __instance) + { + if (savedAssetString != __instance.treasureText.text) + { + __instance.treasureText.text = StringStore.TranslateText(__instance.treasureText.text); + savedAssetString = __instance.treasureText.text; + } + } + } +} \ No newline at end of file diff --git a/MelonLoader/Patches/Modes/Odyssey/TravelMgr_Patch.cs b/MelonLoader/Patches/Modes/Odyssey/TravelMgr_Patch.cs index 7a53177..c214ddc 100644 --- a/MelonLoader/Patches/Modes/Odyssey/TravelMgr_Patch.cs +++ b/MelonLoader/Patches/Modes/Odyssey/TravelMgr_Patch.cs @@ -1,102 +1,114 @@ -//using Il2Cpp; -//using System; -//using System.Collections.Generic; -//using System.Linq; -//using System.Text; -//using System.Text.Encodings.Web; -//using System.Text.Json; -//using System.Threading.Tasks; -//using HarmonyLib; +using HarmonyLib; +using Il2Cpp; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.Encodings.Web; +using System.Text.Json; +using System.Threading.Tasks; +using Unity.Collections; +using static PvZ_Fusion_Translator.FileLoader; -//namespace PvZ_Fusion_Translator.Patches.Modes.Odyssey -//{ -// [HarmonyPatch(typeof(TravelMgr))] -// public static class TravelMgr_Patch -// { -// public static Dictionary buffLinks = new Dictionary() -// { -// { BuffType.AdvancedBuff, "advancedUpgrades" }, -// { BuffType.UltimateBuff, "ultimateUpgrades" }, -// { BuffType.UnlockPlant, "strongUltimates" }, -// { BuffType.Debuff, "debuffs" }, -// }; +namespace PvZ_Fusion_Translator.Patches.Modes.Odyssey +{ + [HarmonyPatch(typeof(TravelMgr))] + public static class TravelMgr_Patch + { + public static Dictionary> dumpedTravelBuffs = new() + { + { "advancedBuffs", new SortedDictionary() }, + { "ultimateBuffs", new SortedDictionary() }, + { "debuffs", new SortedDictionary() }, + { "unlocks", new SortedDictionary() }, + { "investmentBuffs", new SortedDictionary() } + }; -// public static Dictionary> dumpedTravelBuffs = new Dictionary>() -// { -// { "advancedUpgrades", [] }, -// { "ultimateUpgrades", [] }, -// { "strongUltimates", [] }, -// { "debuffs", [] } -// }; + public static Dictionary> translatedTravelBuffs = new() + { + { "advancedBuffs", new SortedDictionary() }, + { "ultimateBuffs", new SortedDictionary() }, + { "debuffs", new SortedDictionary() }, + { "unlocks", new SortedDictionary() }, + { "investmentBuffs", new SortedDictionary() } + }; -// public static Dictionary> translatedTravelBuffs = new Dictionary>(); + public static Dictionary buffLinks = new() + { + { BuffType.AdvancedBuff, "advancedBuffs" }, + { BuffType.UltimateBuff, "ultimateBuffs" }, + { BuffType.Debuff, "debuffs" }, + { BuffType.UnlockPlant, "unlocks" }, + { BuffType.InvestmentBuff, "investmentBuffs" } + }; -// public static void DumpTravelBuffs(Il2CppSystem.Collections.Generic.Dictionary source, Dictionary> dest, string index) -// { -// foreach (var i in source) -// { -// if (!Utils.CheckForUntranslatedText(i.Value)) -// { -// break; -// } -// dest[index].Add(i.Value); -// } -// } + public static void DumpTravelBuffs() + { + TravelMgr.Instance.GetPlantBuffUnlockCount(PlantType.DoomGatling); -// public static string MatchTravelBuff(string originalText) -// { -// string res = ""; + foreach (var pair in TravelDictionary.advancedBuffsText) + { + dumpedTravelBuffs["advancedBuffs"].Add((int)pair.Key, pair.Value); + } -// foreach(var i in dumpedTravelBuffs) -// { -// if(i.Value.Contains(originalText)) -// { -// res = translatedTravelBuffs[i.Key][i.Value.IndexOf(originalText)]; -// break; -// } -// } + foreach (var pair in TravelDictionary.ultimateBuffsText) + { + dumpedTravelBuffs["ultimateBuffs"].Add((int)pair.Key, pair.Value); + } -// return res; -// } + foreach (var pair in TravelDictionary.debuffData) + { + dumpedTravelBuffs["debuffs"].Add((int)pair.Key, pair.Value.Item1); + } -// [HarmonyPatch(nameof(TravelMgr.Awake))] -// [HarmonyPrefix] -// private static void Pre_Awake(TravelMgr __instance) -// { -// // Dump buffs + foreach (var pair in TravelDictionary.unlocksText) + { + dumpedTravelBuffs["unlocks"].Add((int)pair.Key, pair.Value); + } -// dumpedTravelBuffs = new Dictionary>() // reset dump -// { -// { "advancedUpgrades", [] }, -// { "ultimateUpgrades", [] }, -// { "strongUltimates", [] }, -// { "debuffs", [] } -// }; + foreach (var pair in TravelMgr.InvestBuffsData) + { + dumpedTravelBuffs["investmentBuffs"].Add((int)pair.Key, pair.Value.GetDescription()); + } -// DumpTravelBuffs(TravelMgr.advancedBuffs, dumpedTravelBuffs, "advancedUpgrades"); -// DumpTravelBuffs(TravelMgr.ultimateBuffs, dumpedTravelBuffs, "ultimateUpgrades"); -// DumpTravelBuffs(TravelMgr.unlocks, dumpedTravelBuffs, "strongUltimates"); -// DumpTravelBuffs(TravelMgr.debuffs, dumpedTravelBuffs, "debuffs"); + File.WriteAllText(Path.Combine(GetAssetDir(AssetType.Dumps), "travel_buffs.json"), JsonSerializer.Serialize(dumpedTravelBuffs, new JsonSerializerOptions + { + WriteIndented = true, + Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping + })); -// string dumpDir = FileLoader.GetAssetDir(FileLoader.AssetType.Dumps); -// var options = new JsonSerializerOptions -// { -// Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping, -// WriteIndented = true -// }; -// File.WriteAllText(Path.Combine(dumpDir, "travel_buffs.json"), JsonSerializer.Serialize(dumpedTravelBuffs, options)); + string translatedTravelBuffsPath = Path.Combine(GetAssetDir(AssetType.Strings, Utils.Language), "travel_buffs.json"); -// string stringDir = FileLoader.GetAssetDir(FileLoader.AssetType.Strings, Utils.Language); -// string travelBuffDir = Path.Combine(stringDir, "travel_buffs.json"); + if (!File.Exists(translatedTravelBuffsPath)) + { + File.WriteAllText(translatedTravelBuffsPath, JsonSerializer.Serialize(dumpedTravelBuffs, new JsonSerializerOptions + { + WriteIndented = true, + Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping + })); + translatedTravelBuffs = dumpedTravelBuffs; + } + } -// if(!File.Exists(travelBuffDir)) -// { -// File.WriteAllText(travelBuffDir, JsonSerializer.Serialize(dumpedTravelBuffs, options)); -// } + public static string MatchTravelBuff(string originalText) + { + string res = ""; -// string travelBuffs = File.ReadAllText(Path.Combine(stringDir, "travel_buffs.json")); + foreach (var i in translatedTravelBuffs) + { + foreach (var j in translatedTravelBuffs[i.Key]) + { + if (j.Value == originalText) + { + res = j.Value; + break; + } + } -// translatedTravelBuffs = JsonSerializer.Deserialize>>(travelBuffs); -// } -// } -//} + if (res != "") break; + } + + return res; + } + } +} diff --git a/MelonLoader/Patches/Modes/Odyssey/TravelStoreWindow_Patch.cs b/MelonLoader/Patches/Modes/Odyssey/TravelStoreWindow_Patch.cs new file mode 100644 index 0000000..f80e5bd --- /dev/null +++ b/MelonLoader/Patches/Modes/Odyssey/TravelStoreWindow_Patch.cs @@ -0,0 +1,97 @@ +using HarmonyLib; +using Il2Cpp; +using Il2CppTMPro; +using PvZ_Fusion_Translator.AssetStore; +using static PvZ_Fusion_Translator.Patches.Modes.Odyssey.TravelMgr_Patch; +using UnityEngine; +using System.Text.RegularExpressions; + +namespace PvZ_Fusion_Translator.Patches.Modes.Odyssey +{ + [HarmonyPatch(typeof(TravelStoreWindow))] + public static class TravelStoreWindow_Patch + { + [HarmonyPatch(nameof(TravelStoreWindow.SetType))] + [HarmonyPostfix] + private static void SetType(TravelStoreWindow __instance) + { + var buffSet = translatedTravelBuffs[buffLinks[__instance.buffType]]; + + string buff = __instance.show != null && __instance.introduce.text != "词条已选完" ? buffSet[__instance.buffIndex] : StringStore.TranslateText("词条已选完"); + string originalText = __instance.introduce.text; + + string affinities = TranslateAffinities(originalText); + + __instance.introduce.text = buff + affinities; + + foreach (var text in __instance.buttonText) + { + text.text = StringStore.TranslateText(text.text); + } + } + + [HarmonyPatch(nameof(TravelStoreWindow.UpdateButtonText))] + [HarmonyPostfix] + private static void UpdateButtonText(TravelStoreWindow __instance) + { + foreach (var text in __instance.buttonText) + { + text.text = StringStore.TranslateText(text.text); + } + } + + public static string TranslateAffinities(string originalText) + { + string discolored = Utils.RemoveColorTags(originalText); + int firstNewlineIndex = discolored.IndexOf('\n'); + + string result = ""; + List translatedAffinities = []; + + if(firstNewlineIndex >= 0) + { + string affinityString = discolored.Substring(firstNewlineIndex); + string[] affinities = affinityString.Split('\n'); + + string fStr = StringStore.translationStringRegex.ContainsKey("【([^\\s]+)】_IV") ? StringStore.translationStringRegex["【([^\\s]+)】_IV"] : "[{0}]"; + string originalPattern = "【([^\\s]+)】"; + + foreach (string affinity in affinities) + { + if(affinity != "") + { + string translatedAffinity = affinity; + if (StringStore.TestRegex(affinity, originalPattern)) + { + // Extract dynamic parts from the original text + var regex = new Regex(originalPattern); + var match = regex.Match(affinity); + int groupCount = match.Groups.Count; + + // List to hold formatted dynamic parts + List dynamicParts = []; + + // Loop through each group and determine its translation + for (int i = 1; i < groupCount; i++) + { + string groupValue = match.Groups[i].Value; + string translatedValue = StringStore.translationString.ContainsKey(groupValue) + ? StringStore.translationString[groupValue] + : groupValue; + dynamicParts.Add(translatedValue); + } + + // Format the output string with dynamic parts + translatedAffinity = string.Format(fStr, [.. dynamicParts]); + } + + translatedAffinities.Add(translatedAffinity); + } + } + result = "\n" + "" + String.Join("\n", translatedAffinities) + ""; + } + + return result; + } + } +} diff --git a/MelonLoader/Patches/Modes/Odyssey/TravelStore_Patch.cs b/MelonLoader/Patches/Modes/Odyssey/TravelStore_Patch.cs index 9de6677..e641fdf 100644 --- a/MelonLoader/Patches/Modes/Odyssey/TravelStore_Patch.cs +++ b/MelonLoader/Patches/Modes/Odyssey/TravelStore_Patch.cs @@ -1,70 +1,63 @@ -//using HarmonyLib; -//using Il2Cpp; -//using Il2CppTMPro; -//using PvZ_Fusion_Translator.AssetStore; -//using static PvZ_Fusion_Translator.Patches.Modes.Odyssey.TravelMgr_Patch; -//using UnityEngine; +using HarmonyLib; +using Il2Cpp; +using Il2CppTMPro; +using PvZ_Fusion_Translator.AssetStore; +using static PvZ_Fusion_Translator.Patches.Modes.Odyssey.TravelMgr_Patch; +using UnityEngine; -//namespace PvZ_Fusion_Translator.Patches.Modes.Odyssey -//{ -// [HarmonyPatch(typeof(TravelStore))] -// public static class TravelStore_Patch -// { -// [HarmonyPatch(nameof(TravelStore.Update))] -// [HarmonyPostfix] -// private static void Update(TravelStore __instance) -// { -// foreach(TextMeshProUGUI text in __instance.introduces) -// { -// if(__instance.currentSelect != null) -// { -// var buffList = translatedTravelBuffs[buffLinks[(BuffType)__instance.currentSelect.theBuffType]]; -// if(__instance.currentSelect.theBuffNumber < buffList.Count && __instance.currentSelect.theBuffNumber > -1) -// { -// text.text = buffList[__instance.currentSelect.theBuffNumber]; -// } -// else -// { -// text.text = StringStore.TranslateText(text.text); -// } -// } -// } -// foreach (var textMesh in __instance.points) -// { -// textMesh.text = StringStore.TranslateText(textMesh.text); -// } -// } +namespace PvZ_Fusion_Translator.Patches.Modes.Odyssey +{ + [HarmonyPatch(typeof(TravelStore))] + public static class TravelStore_Patch + { + [HarmonyPatch(nameof(TravelStore.Update))] + [HarmonyPostfix] + private static void Update(TravelStore __instance) + { + TranslateStoreText(__instance); + } -// [HarmonyPatch(nameof(TravelStore.RefreshBuff))] -// [HarmonyPostfix] -// private static void RefreshBuff(TravelStore __instance) -// { -// foreach (TravelBuff buff in __instance.travelBuffs) -// { -// TextMeshProUGUI cost = buff.transform.GetChild(1).GetComponent(); -// cost.text = StringStore.TranslateText(cost.text); -// cost.font = FontStore.LoadTMPFont(Utils.Language.ToString()); -// } + [HarmonyPatch(nameof(TravelStore.RefreshBuff))] + [HarmonyPostfix] + private static void RefreshBuff(TravelStore __instance) + { + TranslateStoreText(__instance); + } -// foreach (TextMeshProUGUI text in __instance.introduces) -// { -// if (__instance.currentSelect != null) -// { -// var buffList = translatedTravelBuffs[buffLinks[(BuffType)__instance.currentSelect.theBuffType]]; -// if (__instance.currentSelect.theBuffNumber < buffList.Count && __instance.currentSelect.theBuffNumber > -1) -// { -// text.text = buffList[__instance.currentSelect.theBuffNumber]; -// } -// else -// { -// text.text = StringStore.TranslateText(text.text); -// } -// } -// } -// foreach (var textMesh in __instance.points) -// { -// textMesh.text = StringStore.TranslateText(textMesh.text); -// } -// } -// } -//} + public static void TranslateStoreText(TravelStore __instance) + { + __instance.investText.text = TranslateInvestText(__instance.investText.text); + __instance.investTextshadow.text = TranslateInvestText(__instance.investTextshadow.text); + + foreach (var text in __instance.pointText) + { + text.text = StringStore.TranslateText(text.text); + } + foreach (var text in __instance.refreshText) + { + text.text = StringStore.TranslateText(text.text); + } + foreach(var text in __instance.transform.Find("Quit").GetComponentsInChildren()) + { + text.text = StringStore.TranslateText("合上"); + } + } + + public static string TranslateInvestText(string investText) + { + string res = investText; + + string[] investStats = investText.Split("\n\n"); + List translatedInvestStats = new List(); + foreach(string investStat in investStats) + { + string translatedInvestStat = StringStore.TranslateText(investStat); + translatedInvestStats.Add(translatedInvestStat); + } + + res = String.Join("\n\n", translatedInvestStats); + + return res; + } + } +} diff --git a/MelonLoader/Patches/Modes/Odyssey/TravelSynergyMenu_Patch.cs b/MelonLoader/Patches/Modes/Odyssey/TravelSynergyMenu_Patch.cs new file mode 100644 index 0000000..f4b173c --- /dev/null +++ b/MelonLoader/Patches/Modes/Odyssey/TravelSynergyMenu_Patch.cs @@ -0,0 +1,110 @@ +using HarmonyLib; +using Il2Cpp; +using Il2CppTMPro; +using PvZ_Fusion_Translator.AssetStore; +using static PvZ_Fusion_Translator.Patches.Modes.Odyssey.TravelMgr_Patch; +using UnityEngine; +using System.Text.RegularExpressions; + +namespace PvZ_Fusion_Translator.Patches.Modes.Odyssey +{ + [HarmonyPatch(typeof(TravelSynergyMenu))] + public static class TravelSynergyMenu_Patch + { + [HarmonyPatch(nameof(TravelSynergyMenu.Awake))] + [HarmonyPostfix] + public static void Awake(TravelSynergyMenu __instance) + { + Transform background = __instance.transform.Find("Background"); + Transform tip = __instance.transform.Find("Text (TMP)"); + + foreach(TextMeshProUGUI text in background.GetComponentsInChildren()) + { + text.text = StringStore.TranslateText(text.text); + } + + foreach (TextMeshProUGUI text in tip.GetComponentsInChildren()) + { + text.text = StringStore.TranslateText(text.text); + } + } + } + + [HarmonyPatch(typeof(SynergyNode))] + public static class SynergyNode_Patch + { + [HarmonyPatch(nameof(SynergyNode.InitNode))] + [HarmonyPostfix] + public static void InitNode(SynergyNode __instance) + { + int firstNewlineIndex = __instance.synergyTitle.text.IndexOf("\n"); + string title = __instance.synergyTitle.text.Substring(0, firstNewlineIndex); + string description = __instance.synergyTitle.text.Substring(firstNewlineIndex + 1); + description = (description.Substring(0, 8) == "") ? description.Substring(8) : description; + + string pattern = @"]+>[\s\S]*?(?:<\/color>|$)|(?:<(?!color=)|[^<])+"; + string smallPattern = @"(]+>)(.*?)()"; + MatchCollection matches = Regex.Matches(description, pattern); + string translatedDescription = ""; + foreach(Match match in matches) + { + Match colorMatch = Regex.Match(match.Value, smallPattern, RegexOptions.Singleline); + if (colorMatch.Success) + { + translatedDescription += colorMatch.Groups[1].Value + TranslateSegment(colorMatch.Groups[2].Value) + colorMatch.Groups[3].Value; + } + else + { + FileLoader.DumpUntranslatedStrings(match.Value); + translatedDescription += TranslateSegment(match.Value) + "\n"; + } + } + + __instance.synergyTitle.text = "" + StringStore.TranslateColorText(title) + "\n" + translatedDescription; + } + + public static string TranslateSegment(string text) + { + string res = ""; + + List parts = SplitSecondNewLines(text); + + foreach(string part in parts) + { + string temp = ""; + string[] lines = part.Split('\n'); + if(lines.Length > 1) + { + FileLoader.DumpUntranslatedStrings(lines[0]); + FileLoader.DumpUntranslatedStrings(lines[1]); + temp = StringStore.TranslateText(lines[0]) + "\n" + StringStore.TranslateText(lines[1]); + } + res += temp + "\n"; + } + return res.Substring(0, res.Length - 1); + } + + public static List SplitSecondNewLines(string originalText) + { + List results = new List(); + + string[] lines = originalText.Split('\n'); + for (int i = 0; i < lines.Length; i += 2) + { + string res = ""; + if(i + 1 < lines.Length) + { + res = lines[i] + "\n" + lines[i + 1]; + results.Add(res); + } + else + { + res = lines[i]; + results.Add(res); + } + } + + return results; + } + } +} diff --git a/MelonLoader/PvZ Fusion Translator [MelonLoader].csproj b/MelonLoader/PvZ Fusion Translator [MelonLoader].csproj index 3ccbe6a..3e06e1e 100644 --- a/MelonLoader/PvZ Fusion Translator [MelonLoader].csproj +++ b/MelonLoader/PvZ Fusion Translator [MelonLoader].csproj @@ -401,6 +401,9 @@ + + +