Compare commits

..

15 commits

Author SHA1 Message Date
SillyStar-Github
36dfab123f Merge branch 'cassidy' 2026-07-28 13:32:33 -04:00
SillyStar-Github
dc2ba53835 3.8.1 + some fixes
almanac fallback fonts now work and custom level regexes wont interfere with normal regexes
2026-07-28 13:32:14 -04:00
SillyStar-Github
083eb07d91 Merge branch 'cassidy' 2026-07-15 17:17:48 -04:00
SillyStar-Github
f2e4e78750 3.8 code 2026-07-15 17:17:28 -04:00
SillyStar-Github
e2fe3c2bed Merge branch 'cassidy' 2026-07-06 05:16:43 -04:00
SillyStar-Github
25cfb74d38 3.7 code i forgot to push 😭 2026-07-06 05:16:02 -04:00
SillyStar-Github
44909e1df4 just pushing these as the final 3.6.1 changes 2026-06-02 13:09:42 -04:00
SillyStar-Github
c5720a02ca Merge branch 'cassidy' 2026-05-15 18:12:40 -04:00
SillyStar-Github
5a923186f2 3.6.1 release code 2026-05-15 18:12:30 -04:00
SillyStar-Github
66cf7bcf95 Merge branch 'cassidy' 2026-05-05 18:48:07 -04:00
SillyStar-Github
92f03fdcb7 3.6 code IDK something update 2026-05-05 18:47:29 -04:00
SillyStar-Github
22e503bd32 3.6 code 2026-05-01 16:58:57 -04:00
SillyStar-Github
0515bba2b7 final 3.5 update 2026-04-24 23:25:20 -04:00
SillyStar-Github
b3c2200c7e lag fixes + dll updater 2026-04-06 16:33:31 -04:00
SillyStar-Github
bf3516898c more code changes for 3.5 2026-04-06 01:01:44 -04:00
99 changed files with 4331 additions and 716 deletions

15
.idea/.idea.PvZ Fusion Translator/.idea/.gitignore generated vendored Normal file
View file

@ -0,0 +1,15 @@
# Default ignored files
/shelf/
/workspace.xml
# Rider ignored files
/.idea.PvZ Fusion Translator.iml
/contentModel.xml
/projectSettingsUpdater.xml
/modules.xml
# Editor-based HTTP Client requests
/httpRequests/
# Ignored default folder with query files
/queries/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

View file

@ -0,0 +1 @@
PvZ Fusion Translator

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="UserContentModel">
<attachedFolders />
<explicitIncludes />
<explicitExcludes />
</component>
</project>

View file

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DiscordProjectSettings">
<option name="show" value="ASK" />
<option name="description" value="" />
<option name="applicationTheme" value="default" />
<option name="iconsTheme" value="default" />
<option name="button1Title" value="" />
<option name="button1Url" value="" />
<option name="button2Title" value="" />
<option name="button2Url" value="" />
<option name="customApplicationId" value="" />
</component>
</project>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

View file

@ -155,6 +155,9 @@ namespace PvZ_Fusion_Translator.AssetStore
if (__instance.clip == null) if (__instance.clip == null)
return; return;
if (Il2CppRhythmGame.RhythmGameManager.Instance != null && __instance.clip.name == "loon")
return;
if (LogSounds) if (LogSounds)
MelonLogger.Msg($"Playing \"{__instance.clip.name}\" from object \"{__instance.gameObject.name}\""); MelonLogger.Msg($"Playing \"{__instance.clip.name}\" from object \"{__instance.gameObject.name}\"");

View file

@ -0,0 +1,115 @@
/*using MelonLoader;
using MelonLoader.Utils;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PvZ_Fusion_Translator.AssetStore
{
public static class DllStore
{
public static Dictionary<string, byte[]> dllData = new Dictionary<string, byte[]>()
{
{ "Blooms_QOL.dll", null },
{ "PvZ_Fusion_Translator.dll", null }
};
public static bool updateOnClose = false;
public static void Init(string gameVersion) => TryGetNewDll(gameVersion);
public static void TryGetNewDll(string gameVersion)
{
bool ableToUpdate = true;
string unableReason = "";
string getGameVersionRequest = Utils.GetDataFromWeb("https://raw.githubusercontent.com/SillyStar-Github/PvZF-Translation-DLLs/refs/heads/main/CURRENT_GAME_VER").Result;
if(getGameVersionRequest != null)
{
Log.LogDebug($"Requst game version: {getGameVersionRequest} -> {Utils.CalculateGameVersion(getGameVersionRequest)}");
Log.LogDebug($"This game version: {gameVersion} -> {Utils.CalculateGameVersion(gameVersion)}");
if (Utils.CalculateGameVersion(getGameVersionRequest) != Utils.CalculateGameVersion(gameVersion))
{
ableToUpdate = false;
unableReason = "Incorrect game version...";
}
}
else
{
ableToUpdate = false;
unableReason = "Couldn't get latest game version info...";
}
if (ableToUpdate)
{
foreach(var key in dllData.Keys)
{
byte[] newDllRequest = Utils.GetByteDataFromWeb($"https://raw.githubusercontent.com/SillyStar-Github/PvZF-Translation-DLLs/refs/heads/main/{key}").Result;
if(newDllRequest != null)
{
dllData[key] = newDllRequest;
SaveNewDll(key);
}
else
{
Log.LogError($"Couldn't get latest {key} data!");
}
}
}
else
{
Log.LogError($"Unable to update! {unableReason}");
}
}
public static void SaveNewDll(string name)
{
byte[] newDllData = dllData[name];
if(newDllData != null)
{
string basePath = MelonEnvironment.ModsDirectory;
string toSavePath = Path.Combine(basePath, name + ".update");
File.WriteAllBytes(toSavePath, newDllData);
}
}
public static void UpdateNewDll()
{
foreach(var pair in dllData)
{
if(pair.Value != null)
{
updateOnClose = true;
}
}
if(updateOnClose)
{
int processId = (Process.GetCurrentProcess().Id);
var assembly = Core.Instance.MelonAssembly.Assembly;
string programName = "PvZ_Fusion_Translator.Resources.ModUpdateUtil.exe";
using var exeResourceStream = assembly.GetManifestResourceStream(programName);
string tempPath = Path.Combine(MelonEnvironment.ModsDirectory, "ModUpdateUtil.exe");
using (var fileStream = File.Create(tempPath))
{
exeResourceStream.CopyTo(fileStream);
}
Process.Start(new ProcessStartInfo
{
FileName = tempPath,
Arguments = $"{processId.ToString()} {string.Join(",", dllData.Keys)} \"{MelonEnvironment.ModsDirectory}\"",
UseShellExecute = true
});
}
else
{
Log.LogError("Cannot update on close! All .dll data is null!");
}
}
}
}
*/

View file

@ -1,4 +1,8 @@
using Il2CppTMPro; using Il2CppTMPro;
using MelonLoader;
using System.Reflection;
using UnityEngine;
using UnityEngine.TextCore.Text;
namespace PvZ_Fusion_Translator.AssetStore namespace PvZ_Fusion_Translator.AssetStore
{ {
@ -11,28 +15,24 @@ namespace PvZ_Fusion_Translator.AssetStore
{ {
string fontsDir = Path.Combine(Core.Instance.modsDirectory, "[Custom Fonts]"); string fontsDir = Path.Combine(Core.Instance.modsDirectory, "[Custom Fonts]");
AssetBundle assetBundle = Utils.GetAssetBundle(Path.Combine(fontsDir, "translation"));
#if MULTI_LANGUAGE #if MULTI_LANGUAGE
foreach (string file in Directory.GetFiles(fontsDir)) foreach (string file in assetBundle.GetAllAssetNames())
{ {
string fileName = Path.GetFileNameWithoutExtension(file); string fileName = Path.GetFileNameWithoutExtension(file);
string fileExtension = Path.GetExtension(file);
if (fileExtension == ".ttf" || fileExtension == ".otf") if (!fileName.EndsWith("_almanac") && !fileName.EndsWith("_fallback"))
{ {
if (!fileName.EndsWith("_Almanac") && !fileName.EndsWith("_Fallback")) TMP_FontAsset fontAsset = assetBundle.LoadAsset<TMP_FontAsset>(file);
{
string fontPath = Path.Combine("PvZ_Fusion_Translator", "[Custom Fonts]", fileName + fileExtension);
TMP_FontAsset fontAsset = FontHandler.LoadTMPFont(fontPath, true); fontAssetDict.Add(fileName, fontAsset);
fontAsset.name = fileName;
fontAssetDict.Add(fileName, fontAsset);
Log.LogInfo($"Font for language '{fileName}' loaded"); Log.LogInfo($"Font for language '{fileName}' loaded");
}
} }
} }
InitFallback(); InitFallback(assetBundle);
#else #else
string defaultFontDir = Path.Combine("PvZ_Fusion_Translator", "[Custom Fonts]", "English.ttf"); string defaultFontDir = Path.Combine("PvZ_Fusion_Translator", "[Custom Fonts]", "English.ttf");
@ -41,43 +41,23 @@ namespace PvZ_Fusion_Translator.AssetStore
#endif #endif
} }
internal static void InitFallback() internal static void InitFallback(AssetBundle assetBundle)
{ {
string fontsDir = Path.Combine(Core.Instance.modsDirectory, "[Custom Fonts]"); string fontsDir = Path.Combine(Core.Instance.modsDirectory, "[Custom Fonts]");
foreach (string file in Directory.GetFiles(fontsDir))
foreach (string file in assetBundle.GetAllAssetNames())
{ {
string fileName = Path.GetFileNameWithoutExtension(file); string fileName = Path.GetFileNameWithoutExtension(file);
string fileExtension = Path.GetExtension(file);
if (fileExtension == ".ttf" || fileExtension == ".otf") if (fileName.EndsWith("_almanac") || fileName.EndsWith("_fallback"))
{ {
if (fileName.EndsWith("_Almanac") || fileName.EndsWith("_Fallback")) TMP_FontAsset fallbackFont = assetBundle.LoadAsset<TMP_FontAsset>(file);
{
string fallbackPath = Path.Combine("PvZ_Fusion_Translator", "[Custom Fonts]", fileName + fileExtension);
TMP_FontAsset fallbackFont = FontHandler.LoadTMPFont(fallbackPath, true);
fallbackFont.name = fileName;
string fileNameLanguage = fileName.Replace("_Fallback", "").Replace("_Almanac", ""); string fileNameLanguage = fileName.Replace("_fallback", "").Replace("_almanac", "");
if (fontAssetDictSecondary.ContainsKey(fileNameLanguage)) Utils.TryAdd(fontAssetDictSecondary, fileName, fallbackFont);
{
if (fileName.EndsWith("_Fallback"))
{
fontAssetDictSecondary.Add(fileNameLanguage + "_Almanac", fontAssetDictSecondary[fileNameLanguage]);
fontAssetDictSecondary.Remove(fileNameLanguage);
}
else
{
fontAssetDictSecondary.Add(fileNameLanguage + "_Fallback", fontAssetDictSecondary[fileNameLanguage]);
fontAssetDictSecondary.Remove(fileNameLanguage);
}
fontAssetDictSecondary.Add(fileName, fallbackFont);
}
else
fontAssetDictSecondary.Add(fileNameLanguage, fallbackFont);
// Log.LogInfo($"Fallback font for language '{fileNameLanguage}' loaded"); // Log.LogInfo($"Fallback font for language '{fileNameLanguage}' loaded");
}
} }
} }
AddFallback(); AddFallback();
@ -98,15 +78,15 @@ namespace PvZ_Fusion_Translator.AssetStore
Log.LogInfo("Fallback font for language '" + lang + "' added"); Log.LogInfo("Fallback font for language '" + lang + "' added");
continue; continue;
} }
if (fontAssetDictSecondary.ContainsKey(lang + "_Almanac")) if (fontAssetDictSecondary.ContainsKey(lang + "_almanac"))
{ {
fontAssetDict[lang].fallbackFontAssetTable.Add(fontAssetDictSecondary[lang + "_Almanac"]); fontAssetDict[lang].fallbackFontAssetTable.Add(fontAssetDictSecondary[lang + "_almanac"]);
Log.LogInfo("Fallback font for language '" + lang + "' added"); Log.LogInfo("Fallback font for language '" + lang + "' added");
continue; continue;
} }
if (fontAssetDictSecondary.ContainsKey(lang + "_Fallback")) if (fontAssetDictSecondary.ContainsKey(lang + "_fallback"))
{ {
fontAssetDict[lang].fallbackFontAssetTable.Add(fontAssetDictSecondary[lang + "_Fallback"]); fontAssetDict[lang].fallbackFontAssetTable.Add(fontAssetDictSecondary[lang + "_fallback"]);
Log.LogInfo("Fallback font for language '" + lang + "' added"); Log.LogInfo("Fallback font for language '" + lang + "' added");
continue; continue;
} }
@ -116,7 +96,7 @@ namespace PvZ_Fusion_Translator.AssetStore
#if MULTI_LANGUAGE #if MULTI_LANGUAGE
public static TMP_FontAsset LoadTMPFont(string language) public static TMP_FontAsset LoadTMPFont(string language)
{ {
if (fontAssetDict.TryGetValue(language, out TMP_FontAsset font)) if (fontAssetDict.TryGetValue(language.ToLower(), out TMP_FontAsset font))
{ {
TMP_FontAsset fontAsset = font; TMP_FontAsset fontAsset = font;
if (fontAsset.fallbackFontAssetTable != null) if (fontAsset.fallbackFontAssetTable != null)
@ -125,7 +105,7 @@ namespace PvZ_Fusion_Translator.AssetStore
} }
return fontAsset; return fontAsset;
} }
return fontAssetDict.GetValueOrDefault("English"); return fontAssetDict.GetValueOrDefault("english");
} }
#else #else
public static TMP_FontAsset LoadTMPFont() public static TMP_FontAsset LoadTMPFont()
@ -137,22 +117,22 @@ namespace PvZ_Fusion_Translator.AssetStore
public static TMP_FontAsset LoadTMPFontAlmanac(string language) public static TMP_FontAsset LoadTMPFontAlmanac(string language)
{ {
if (fontAssetDictSecondary.ContainsKey(language)) if (fontAssetDictSecondary.ContainsKey(language.ToLower()))
{ {
if (fontAssetDictSecondary.TryGetValue(language, out TMP_FontAsset almanacAsset)) if (fontAssetDictSecondary.TryGetValue(language.ToLower(), out TMP_FontAsset almanacAsset))
{ {
return almanacAsset; return almanacAsset;
} }
} }
if (fontAssetDictSecondary.ContainsKey(language + "_Almanac")) if (fontAssetDictSecondary.ContainsKey(language.ToLower() + "_almanac"))
{ {
if (fontAssetDictSecondary.TryGetValue(language + "_Almanac", out TMP_FontAsset almanacAsset)) if (fontAssetDictSecondary.TryGetValue(language.ToLower() + "_almanac", out TMP_FontAsset almanacAsset))
{ {
return almanacAsset; return almanacAsset;
} }
} }
return fontAssetDict.GetValueOrDefault("English"); return fontAssetDict.GetValueOrDefault("english");
} }
#if MULTI_LANGUAGE #if MULTI_LANGUAGE

View file

@ -1,4 +1,5 @@
using Il2CppTMPro; using Il2CppTMPro;
using PvZ_Fusion_Translator.Patches.BaseTextObjects;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using UnityEngine; using UnityEngine;
@ -12,6 +13,10 @@ namespace PvZ_Fusion_Translator.AssetStore
public static Dictionary<string, string> translationString = new(); public static Dictionary<string, string> translationString = new();
public static Dictionary<string, string> customLevelStringRegex = new();
public static Dictionary<string, string> customLevelString = new();
public static Dictionary<string, string> izLevelTipDictionary = new(); public static Dictionary<string, string> izLevelTipDictionary = new();
public static Dictionary<string, string> izTipCollectionString = new(); public static Dictionary<string, string> izTipCollectionString = new();
@ -78,10 +83,14 @@ namespace PvZ_Fusion_Translator.AssetStore
{ {
translationString.Clear(); translationString.Clear();
translationStringRegex.Clear(); translationStringRegex.Clear();
customLevelString.Clear();
customLevelStringRegex.Clear();
izLevelTipDictionary.Clear(); izLevelTipDictionary.Clear();
izTipCollectionString.Clear(); izTipCollectionString.Clear();
fsLevelTipDictionary.Clear(); fsLevelTipDictionary.Clear();
fsTipCollectionString.Clear(); fsTipCollectionString.Clear();
InGameText_Patch.currentText = "";
Utils.RegisterPlantIndices();
FileLoader.LoadStrings(); FileLoader.LoadStrings();
} }
@ -103,6 +112,12 @@ namespace PvZ_Fusion_Translator.AssetStore
public static TextMeshProUGUI TranslateText(TextMeshProUGUI originalTMP, bool isLog = false) public static TextMeshProUGUI TranslateText(TextMeshProUGUI originalTMP, bool isLog = false)
{ {
/*var frame = new StackTrace().GetFrame(1);
var method = frame.GetMethod();
var className = method.DeclaringType.Name;
Console.WriteLine($"tmp pro ugui: {className}.{method.Name}");*/
#if MULTI_LANGUAGE #if MULTI_LANGUAGE
string currentLanguage = Utils.Language.ToString(); string currentLanguage = Utils.Language.ToString();
TMP_FontAsset fontAsset = FontStore.LoadTMPFont(currentLanguage); TMP_FontAsset fontAsset = FontStore.LoadTMPFont(currentLanguage);
@ -138,42 +153,73 @@ namespace PvZ_Fusion_Translator.AssetStore
public static string TranslateText(string originalText, string pattern, bool isLog = false) public static string TranslateText(string originalText, string pattern, bool isLog = false)
{ {
if (TestRegex(originalText, pattern) && translationStringRegex.ContainsKey(pattern)) if (TestRegex(originalText, pattern))
{ {
// Extract dynamic parts from the original text if(translationStringRegex.ContainsKey(pattern))
var regex = new Regex(pattern); {
var match = regex.Match(originalText); // Extract dynamic parts from the original text
int groupCount = match.Groups.Count; var regex = new Regex(pattern);
var match = regex.Match(originalText);
int groupCount = match.Groups.Count;
if (isLog) if (isLog)
Log.LogDebug("Text found in translationStringRegex {0}: {1}", match, groupCount); Log.LogDebug("Text found in translationStringRegex {0}: {1}", match, groupCount);
// List to hold formatted dynamic parts // List to hold formatted dynamic parts
List<string> dynamicParts = []; List<string> dynamicParts = [];
// Loop through each group and determine its translation // Loop through each group and determine its translation
for (int i = 1; i < groupCount; i++) for (int i = 1; i < groupCount; i++)
{ {
string groupValue = match.Groups[i].Value; string groupValue = match.Groups[i].Value;
string translatedValue = translationString.ContainsKey(groupValue) string translatedValue = DoTranslateString(groupValue);
? translationString[groupValue] dynamicParts.Add(translatedValue);
: groupValue; }
dynamicParts.Add(translatedValue);
}
// Format the output string with dynamic parts // Format the output string with dynamic parts
return string.Format(translationStringRegex[pattern], [.. dynamicParts]); return string.Format(translationStringRegex[pattern], [.. dynamicParts]);
} }
else if(customLevelStringRegex.ContainsKey(pattern))
{
// Extract dynamic parts from the original text
var regex = new Regex(pattern);
var match = regex.Match(originalText);
int groupCount = match.Groups.Count;
if (isLog)
Log.LogDebug("Text found in customLevelStringRegex {0}: {1}", match, groupCount);
// List to hold formatted dynamic parts
List<string> dynamicParts = [];
// Loop through each group and determine its translation
for (int i = 1; i < groupCount; i++)
{
string groupValue = match.Groups[i].Value;
string translatedValue = customLevelString.ContainsKey(groupValue)
? customLevelString[groupValue]
: groupValue;
dynamicParts.Add(translatedValue);
}
// Format the output string with dynamic parts
return string.Format(customLevelStringRegex[pattern], [.. dynamicParts]);
}
else
{
return originalText;
}
}
else else
{ {
if (isLog) if (isLog)
Log.LogDebug($"Text '{originalText}' not translated"); Log.LogDebug($"Text '{originalText}' not translated");
FileLoader.DumpUntranslatedStrings(originalText); FileLoader.DumpUntranslatedStrings(originalText);
return originalText; return originalText;
} }
} }
public static string DoTranslateText(string originalText, bool isLog = false) public static string DoTranslateString(string originalText, bool isLog = false)
{ {
if (string.IsNullOrEmpty(originalText)) if (string.IsNullOrEmpty(originalText))
{ {
@ -208,6 +254,82 @@ namespace PvZ_Fusion_Translator.AssetStore
return fsTipCollectionString[originalText]; return fsTipCollectionString[originalText];
} }
if(customLevelString.ContainsKey(originalText))
{
if(isLog)
{
Log.LogDebug($"Text '{originalText}' found in customLevelString");
}
return customLevelString[originalText];
}
if (Utils.plantIndiceString.ContainsKey(originalText))
{
if(isLog)
{
Log.LogDebug($"Text '{originalText}' found in plantIndiceString");
}
return Utils.plantIndiceString[originalText];
}
return originalText;
}
public static string DoTranslateText(string originalText, bool isLog = false)
{
if (string.IsNullOrEmpty(originalText))
{
if (isLog)
Log.LogError("Text Null or Empty");
return string.Empty;
}
if (!Utils.CheckForUntranslatedText(originalText) && !(originalText).Contains("_")) return originalText;
if (translationString.ContainsKey(originalText))
{
if (isLog)
Log.LogDebug($"Text '{originalText} found in translationString");
return translationString[originalText];
}
if(izTipCollectionString.ContainsKey(originalText))
{
if(isLog)
{
Log.LogDebug($"Text '{originalText}' found in izTipCollectionString");
}
return izTipCollectionString[originalText];
}
if(fsTipCollectionString.ContainsKey(originalText))
{
if(isLog)
{
Log.LogDebug($"Text '{originalText}' found in fsTipCollectionString");
}
return fsTipCollectionString[originalText];
}
if(customLevelString.ContainsKey(originalText))
{
if(isLog)
{
Log.LogDebug($"Text '{originalText}' found in customLevelString");
}
return customLevelString[originalText];
}
if (Utils.plantIndiceString.ContainsKey(originalText))
{
if(isLog)
{
Log.LogDebug($"Text '{originalText}' found in plantIndiceString");
}
return Utils.plantIndiceString[originalText];
}
// Regex-based dynamic translation // Regex-based dynamic translation
foreach (var entry in translationStringRegex) foreach (var entry in translationStringRegex)
{ {
@ -228,8 +350,36 @@ namespace PvZ_Fusion_Translator.AssetStore
for (int i = 1; i < groupCount; i++) for (int i = 1; i < groupCount; i++)
{ {
string groupValue = match.Groups[i].Value; string groupValue = match.Groups[i].Value;
string translatedValue = translationString.ContainsKey(groupValue) string translatedValue = DoTranslateString(groupValue);
? translationString[groupValue] dynamicParts.Add(translatedValue);
}
// Format the output string with dynamic parts
return string.Format(entry.Value, [.. dynamicParts]);
}
}
foreach (var entry in customLevelStringRegex)
{
if (TestRegex(originalText, entry.Key))
{
// Extract dynamic parts from the original text
var regex = new Regex(entry.Key);
var match = regex.Match(originalText);
int groupCount = match.Groups.Count;
if (isLog)
Log.LogDebug("Text found in customLevelRegex {0}: {1}", match, groupCount);
// List to hold formatted dynamic parts
List<string> dynamicParts = [];
// Loop through each group and determine its translation
for (int i = 1; i < groupCount; i++)
{
string groupValue = match.Groups[i].Value;
string translatedValue = customLevelString.ContainsKey(groupValue)
? customLevelString[groupValue]
: groupValue; : groupValue;
dynamicParts.Add(translatedValue); dynamicParts.Add(translatedValue);
} }

View file

@ -6,8 +6,8 @@ namespace PvZ_Fusion_Translator.AssetStore
{ {
public static class TextureStore public static class TextureStore
{ {
internal static Dictionary<string, string> textureDict = []; internal static Dictionary<string, byte[]> textureDict = [];
internal static Dictionary<string, string> spriteDict = []; internal static Dictionary<string, byte[]> spriteDict = [];
internal static void Init() => FileLoader.LoadTextures(); internal static void Init() => FileLoader.LoadTextures();
@ -55,13 +55,13 @@ namespace PvZ_Fusion_Translator.AssetStore
} }
#endif #endif
public static void LogAll() /*public static void LogAll()
{ {
Log.LogInfo("Logging all TextureStore entries."); Log.LogInfo("Logging all TextureStore entries.");
foreach (KeyValuePair<string, string> entry in textureDict) foreach (KeyValuePair<string, string> entry in textureDict)
{ {
Log.LogInfo("TextureDict Entry: " + entry.Key + " | " + entry.Value); Log.LogInfo("TextureDict Entry: " + entry.Key + " | " + entry.Value);
} }
} }*/
} }
} }

View file

@ -1,13 +1,8 @@
using Il2Cpp; using MelonLoader;
using Il2CppTMPro;
using MelonLoader;
using MelonLoader.Utils; using MelonLoader.Utils;
using PvZ_Fusion_Translator.AssetStore; using PvZ_Fusion_Translator.AssetStore;
using PvZ_Fusion_Translator.Patches.Managers; using PvZ_Fusion_Translator.Patches.Managers;
using PvZ_Fusion_Translator.Patches.Modes.Odyssey;
using PvZ_Fusion_Translator.Patches.Modes.Super_Editor; using PvZ_Fusion_Translator.Patches.Modes.Super_Editor;
using System.Runtime.CompilerServices;
using System.Text.Json;
using UnityEngine; using UnityEngine;
using static PvZ_Fusion_Translator.FileLoader; using static PvZ_Fusion_Translator.FileLoader;
@ -21,6 +16,7 @@ namespace PvZ_Fusion_Translator
private static DateTime dtStart; private static DateTime dtStart;
private static DateTime? dtStartToast; private static DateTime? dtStartToast;
private static string toast_txt; private static string toast_txt;
public static bool isInitialized = false;
public static Core Instance { get; private set; } public static Core Instance { get; private set; }
object replaceTextureRoutine = null; object replaceTextureRoutine = null;
@ -31,6 +27,7 @@ namespace PvZ_Fusion_Translator
{ {
base.OnInitializeMelon(); base.OnInitializeMelon();
Instance = this; Instance = this;
Config(); Config();
#if MULTI_LANGUAGE #if MULTI_LANGUAGE
FileLoader.LoadLanguage(); FileLoader.LoadLanguage();
@ -39,15 +36,16 @@ namespace PvZ_Fusion_Translator
StringStore.Init(); StringStore.Init();
AudioStore.Init(); AudioStore.Init();
FontStore.Init(); FontStore.Init();
Utils.RegisterPlantIndices();
//Utils.RegisterRecipeLinks(); isInitialized = true;
} }
public override void OnLateInitializeMelon() public override void OnLateInitializeMelon()
{ {
dtStart = DateTime.Now; dtStart = DateTime.Now;
replaceTextureRoutine = MelonCoroutines.Start(TextureStore.ReplaceTexturesCoroutine()); replaceTextureRoutine = MelonCoroutines.Start(TextureStore.ReplaceTexturesCoroutine());
TravelMgr_Patch.DumpTravelBuffs(); LoadTravelBuffs();
Utils.RegisterPlantIndices();
} }
public override void OnDeinitializeMelon() public override void OnDeinitializeMelon()
@ -56,6 +54,7 @@ namespace PvZ_Fusion_Translator
#if MULTI_LANGUAGE #if MULTI_LANGUAGE
FileLoader.SaveLanguage(); FileLoader.SaveLanguage();
#endif #endif
//DllStore.UpdateNewDll();
#if OBFUSCATE && !RELEASE #if OBFUSCATE && !RELEASE
CheckSumStore.ConvertMD5Json(); CheckSumStore.ConvertMD5Json();
#endif #endif
@ -78,9 +77,9 @@ namespace PvZ_Fusion_Translator
Utils.OpenSaveDirectory(); Utils.OpenSaveDirectory();
} }
if (Input.GetKeyDown(KeyCode.Delete)) if (Input.GetKeyDown(KeyCode.PageUp))
{ {
Utils.OpenTrello(); Utils.OpenOnlineAlmanac();
} }
TowerManager_Patch.UpdateText(); TowerManager_Patch.UpdateText();

View file

@ -1,4 +1,5 @@
using Il2Cpp; using Il2Cpp;
using Il2CppAlmanacData;
using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppInterop.Runtime.InteropTypes.Arrays;
using JetBrains.Annotations; using JetBrains.Annotations;
using MelonLoader; using MelonLoader;
@ -40,6 +41,10 @@ namespace PvZ_Fusion_Translator
internal static void LoadStrings(Utils.LanguageEnum language) internal static void LoadStrings(Utils.LanguageEnum language)
{ {
string stringDir = GetAssetDir(AssetType.Strings, Utils.Language); string stringDir = GetAssetDir(AssetType.Strings, Utils.Language);
if (!Directory.Exists(stringDir))
{
Directory.CreateDirectory(stringDir);
}
if(!Utils.useLocal) if(!Utils.useLocal)
{ {
@ -75,19 +80,34 @@ namespace PvZ_Fusion_Translator
} }
} }
// load travel_buffs string customLevelStringsContent = Utils.GetDataFromWeb($"https://raw.githubusercontent.com/Teyliu/PVZF-Translation/refs/heads/main/PvZ_Fusion_Translator/Localization/{Utils.Language.ToString()}/Strings/customlevel_strings.json").Result;
string travelBuffsContent = Utils.GetDataFromWeb($"https://raw.githubusercontent.com/Teyliu/PVZF-Translation/refs/heads/main/PvZ_Fusion_Translator/Localization/{Utils.Language.ToString()}/Strings/travel_buffs.json").Result;
if(travelBuffsContent != null) if(customLevelStringsContent != null)
{ {
TravelMgr_Patch.translatedTravelBuffs = System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, SortedDictionary<int, string>>>(travelBuffsContent); LoadCustomLevelStrings(customLevelStringsContent);
} }
else else
{ {
string travelBuffsPath = Path.Combine(GetAssetDir(AssetType.Strings, Utils.Language), "travel_buffs.json"); string customLevelStringsPath = Path.Combine(GetAssetDir(AssetType.Strings, Utils.Language), "customlevel_strings.json");
if(File.Exists(travelBuffsPath)) if(File.Exists(customLevelStringsPath))
{ {
TravelMgr_Patch.translatedTravelBuffs = System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, SortedDictionary<int, string>>>(File.ReadAllText(travelBuffsPath)); LoadCustomLevelStrings(File.ReadAllText(customLevelStringsPath));
}
}
// load translationRegexs
string customLevelRegexsContent = Utils.GetDataFromWeb($"https://raw.githubusercontent.com/Teyliu/PVZF-Translation/refs/heads/main/PvZ_Fusion_Translator/Localization/{Utils.Language.ToString()}/Strings/customlevel_regexs.json").Result;
if(customLevelRegexsContent != null)
{
LoadCustomLevelRegexs(customLevelRegexsContent);
}
else
{
string customLevelRegexsPath = Path.Combine(GetAssetDir(AssetType.Strings, Utils.Language), "customlevel_regexs.json");
if(File.Exists(customLevelRegexsPath))
{
LoadCustomLevelRegexs(File.ReadAllText(customLevelRegexsPath));
} }
} }
@ -127,19 +147,26 @@ namespace PvZ_Fusion_Translator
} }
// load almanacs // load almanacs
string almanacDir = GetAssetDir(AssetType.Almanac, Utils.Language);
if(!Directory.Exists(almanacDir))
{
Directory.CreateDirectory(almanacDir);
}
string plantAlmanacContent = Utils.GetDataFromWeb($"https://raw.githubusercontent.com/Teyliu/PVZF-Translation/refs/heads/main/PvZ_Fusion_Translator/Localization/{Utils.Language.ToString()}/Almanac/LawnStringsTranslate.json").Result; string plantAlmanacContent = Utils.GetDataFromWeb($"https://raw.githubusercontent.com/Teyliu/PVZF-Translation/refs/heads/main/PvZ_Fusion_Translator/Localization/{Utils.Language.ToString()}/Almanac/LawnStringsTranslate.json").Result;
if(plantAlmanacContent != null) if(plantAlmanacContent != null)
{ {
AlmanacPlantMenu_Patch.almanacJson = plantAlmanacContent; AlmanacPlantMenu_Patch.LoadPlantAlmanacData(plantAlmanacContent);
} }
else else
{ {
string almanacDir = GetAssetDir(AssetType.Almanac, Utils.Language);
string path = Path.Combine(almanacDir, "LawnStringsTranslate.json"); string path = Path.Combine(almanacDir, "LawnStringsTranslate.json");
if(File.Exists(path)) if(File.Exists(path))
{ {
AlmanacPlantMenu_Patch.almanacJson = File.ReadAllText(path); AlmanacPlantMenu_Patch.LoadPlantAlmanacData(File.ReadAllText(path));
} }
} }
@ -151,7 +178,6 @@ namespace PvZ_Fusion_Translator
} }
else else
{ {
string almanacDir = GetAssetDir(AssetType.Almanac, Utils.Language);
string path = Path.Combine(almanacDir, "ZombieStringsTranslate.json"); string path = Path.Combine(almanacDir, "ZombieStringsTranslate.json");
if(File.Exists(path)) if(File.Exists(path))
{ {
@ -159,9 +185,27 @@ namespace PvZ_Fusion_Translator
} }
} }
string detailStringsContent = Utils.GetDataFromWeb($"https://raw.githubusercontent.com/Teyliu/PVZF-Translation/refs/heads/main/PvZ_Fusion_Translator/Localization/{Utils.Language.ToString()}/Almanac/DetailStringsTranslate.json").Result;
if(detailStringsContent != null)
{
LoadDetailStrings(detailStringsContent);
}
else
{
string path = Path.Combine(almanacDir, "DetailStringsTranslate.json");
if(File.Exists(path))
{
LoadDetailStrings(File.ReadAllText(path));
}
}
// load travel_buffs
LoadTravelBuffs();
// load abyss buffs // load abyss buffs
Patches.Modes.Abyss.AbyssBuffMenu_Patch.LoadAbyssBuffData(); //Patches.Modes.Abyss.AbyssBuffMenu_Patch.LoadAbyssBuffData();
SaveStrings(); SaveStrings();
DumpJson(); DumpJson();
@ -191,17 +235,21 @@ namespace PvZ_Fusion_Translator
Log.LogInfo("Loading File : " + filepath); Log.LogInfo("Loading File : " + filepath);
#endif #endif
string jsonString = File.ReadAllText(filepath); string jsonString = File.ReadAllText(filepath);
if (fileName.EndsWith("_strings")) if (fileName.EndsWith("translation_strings"))
{ {
LoadTranslationStrings(jsonString); LoadTranslationStrings(jsonString);
} }
else if (fileName.EndsWith("_regexs")) else if (fileName.EndsWith("translation_regexs"))
{ {
LoadTranslationRegexs(jsonString); LoadTranslationRegexs(jsonString);
} }
else if(fileName.EndsWith("travel_buffs")) else if (fileName.EndsWith("customlevel_strings"))
{ {
TravelMgr_Patch.translatedTravelBuffs = System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, SortedDictionary<int, string>>>(jsonString); LoadCustomLevelStrings(jsonString);
}
else if (fileName.EndsWith("customlevel_regexs"))
{
LoadCustomLevelRegexs(jsonString);
} }
else if(fileName.EndsWith("tips_iz")) else if(fileName.EndsWith("tips_iz"))
{ {
@ -211,25 +259,44 @@ namespace PvZ_Fusion_Translator
{ {
LoadFSStrings(jsonString); LoadFSStrings(jsonString);
} }
else if(fileName.EndsWith("abyss_buffs")) //else if(fileName.EndsWith("abyss_buffs"))
//{
// Patches.Modes.Abyss.AbyssBuffMenu_Patch.LoadAbyssBuffData();
//}
else if (fileName.EndsWith("travel_buffs"))
{ {
Patches.Modes.Abyss.AbyssBuffMenu_Patch.LoadAbyssBuffData(); LoadTravelBuffs();
} }
} }
string almanacDir = GetAssetDir(AssetType.Almanac, Utils.Language); string almanacDir = GetAssetDir(AssetType.Almanac, Utils.Language);
string plantAlmanacPath = Path.Combine(almanacDir, "LawnStringsTranslate.json");
if(File.Exists(plantAlmanacPath)) if(!Directory.Exists(almanacDir))
{ {
AlmanacPlantMenu_Patch.almanacJson = File.ReadAllText(plantAlmanacPath); Directory.CreateDirectory(almanacDir);
} }
string zombieAlmanacPlant = Path.Combine(almanacDir, "ZombieStringsTranslate.json"); string plantAlmanacPath = Path.Combine(almanacDir, "LawnStringsTranslate.json");
if(File.Exists(zombieAlmanacPlant))
if(File.Exists(plantAlmanacPath))
{ {
AlmanacZombieMenu_Patch.almanacJson = File.ReadAllText(zombieAlmanacPlant); AlmanacPlantMenu_Patch.LoadPlantAlmanacData(File.ReadAllText(plantAlmanacPath));
} }
string zombieAlmanacPath = Path.Combine(almanacDir, "ZombieStringsTranslate.json");
if(File.Exists(zombieAlmanacPath))
{
AlmanacZombieMenu_Patch.almanacJson = File.ReadAllText(zombieAlmanacPath);
}
string detailStringsPath = Path.Combine(almanacDir, "DetailStringsTranslate.json");
if(File.Exists(detailStringsPath))
{
LoadDetailStrings(File.ReadAllText(detailStringsPath));
}
LoadChangelogText();
SaveStrings(); SaveStrings();
DumpJson(); DumpJson();
} }
@ -262,6 +329,24 @@ namespace PvZ_Fusion_Translator
Zombie_Patch.LoadHPStrings(); Zombie_Patch.LoadHPStrings();
} }
internal static void LoadCustomLevelStrings(string content)
{
Dictionary<string, string> dictionary = System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, string>>(content);
foreach (var (key, value) in dictionary)
{
StringStore.customLevelString[key] = value;
}
}
internal static void LoadCustomLevelRegexs(string content)
{
Dictionary<string, string> dictionary = System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, string>>(content);
foreach (var (key, value) in dictionary)
{
StringStore.customLevelStringRegex[key] = value;
}
}
internal static void LoadIZStrings(string content) internal static void LoadIZStrings(string content)
{ {
var izDump = DumpIZStrings(); var izDump = DumpIZStrings();
@ -308,11 +393,42 @@ namespace PvZ_Fusion_Translator
} }
} }
internal static void LoadDetailStrings(string content)
{
var detailStringsDump = DumpDetailStrings();
var detailStringsData = detailStringsDump.Item1;
var detailStrings = detailStringsDump.Item2;
var translatedDetailStrings = System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, string>>(content);
AlmanacSelectMenu_Patch.detailStrings = translatedDetailStrings;
foreach (var detailString in detailStringsData.details)
{
if (translatedDetailStrings.ContainsKey(detailString.title))
{
if(!AlmanacSelectMenu_Patch.detailTranslateStrings.ContainsKey(detailString.text))
{
AlmanacSelectMenu_Patch.detailTranslateStrings.Add(detailString.text, translatedDetailStrings[detailString.title]);
}
else
{
AlmanacSelectMenu_Patch.detailTranslateStrings[detailString.text] = translatedDetailStrings[detailString.title];
}
}
}
}
internal static void LoadChangelogText() internal static void LoadChangelogText()
{ {
string stringDir = FileLoader.GetAssetDir(FileLoader.AssetType.Strings, Utils.Language); string stringDir = FileLoader.GetAssetDir(FileLoader.AssetType.Strings, Utils.Language);
string changelogDir = Path.Combine(stringDir, "changelog.txt"); string changelogDir = Path.Combine(stringDir, "changelog.txt");
string changelogText = File.ReadAllText(changelogDir); string changelogText = "";
if (!File.Exists(changelogDir))
{
File.WriteAllText(changelogDir, "");
}
changelogText = File.ReadAllText(changelogDir);
if(!Utils.useLocal) if(!Utils.useLocal)
{ {
@ -323,17 +439,55 @@ namespace PvZ_Fusion_Translator
changelogText = changelogContent; changelogText = changelogContent;
} }
} }
else
{
changelogText = File.ReadAllText(changelogDir);
}
NoticePauseMenu_Patch.changelogText = changelogText; NoticePauseMenu_Patch.changelogText = changelogText;
} }
internal static void LoadTravelBuffs()
{
if (!Utils.useLocal)
{
string travelBuffsContent = Utils.GetDataFromWeb($"https://raw.githubusercontent.com/Teyliu/PVZF-Translation/refs/heads/main/PvZ_Fusion_Translator/Localization/{Utils.Language.ToString()}/Strings/travel_buffs.json").Result;
if (travelBuffsContent != null)
{
TravelMgr_Patch.GenerateTranslatedTravelBuffs(travelBuffsContent);
}
else
{
string travelBuffsPath = Path.Combine(GetAssetDir(AssetType.Strings, Utils.Language), "travel_buffs.json");
if (File.Exists(travelBuffsPath))
{
TravelMgr_Patch.GenerateTranslatedTravelBuffs(File.ReadAllText(travelBuffsPath));
}
}
}
else
{
string stringDir = FileLoader.GetAssetDir(FileLoader.AssetType.Strings, Utils.Language);
foreach (string filepath in Directory.EnumerateFiles(stringDir, "*.json", SearchOption.AllDirectories))
{
string fileName = Path.GetFileNameWithoutExtension(filepath);
string jsonString = File.ReadAllText(filepath);
if (fileName.EndsWith("travel_buffs"))
{
TravelMgr_Patch.GenerateTranslatedTravelBuffs(jsonString);
}
}
}
}
public static bool loadDefaultTextures = MelonPreferences.GetEntryValue<bool>("PvZ_Fusion_Translator", "DefaultTextures"); public static bool loadDefaultTextures = MelonPreferences.GetEntryValue<bool>("PvZ_Fusion_Translator", "DefaultTextures");
internal static void LoadTextures() internal static void LoadTextures()
{ {
// Default or Custom Texturse -> English Textures -> Localized Textures // Default or Custom Texturse -> English Textures -> Localized Textures
try try
{ {
if (Utils.customTextures) if (Utils.customTextures)
{ {
LoadCustomTextures(); LoadCustomTextures();
@ -365,6 +519,73 @@ namespace PvZ_Fusion_Translator
} }
try try
{ {
Dictionary<string, string> localTOC = new Dictionary<string, string>();
string localTOCDir = Path.Combine(textureDir, "Texture_TOC.json");
if (!File.Exists(localTOCDir))
{
File.WriteAllText(localTOCDir, "{}");
}
string localTOCContent = File.ReadAllText(localTOCDir);
localTOC = System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, string>>(localTOCContent);
string basePath = Core.Instance.modsDirectory;
if (!Utils.useLocal)
{
string textureTOCRequest = Utils.GetDataFromWeb($"https://raw.githubusercontent.com/Teyliu/PVZF-Translation/refs/heads/main/PvZ_Fusion_Translator/Localization/{Utils.Language.ToString()}/Textures/Texture_TOC.json").Result;
if (textureTOCRequest != null)
{
Dictionary<string, string> textureTOC = JsonConvert.DeserializeObject<Dictionary<string, string>>(textureTOCRequest);
List<string> toDownload = new();
foreach(var pair in textureTOC)
{
if(!localTOC.ContainsKey(pair.Key))
{
toDownload.Add(pair.Key);
continue;
}
if(pair.Value != localTOC[pair.Key])
{
toDownload.Add(pair.Key);
}
if(!File.Exists(Path.Combine(basePath, pair.Key)))
{
toDownload.Add(pair.Key);
continue;
}
}
string toWriteText = SerializeWithIndentation(textureTOC);
File.WriteAllText(localTOCDir, toWriteText);
foreach(string path in toDownload)
{
string downloadPath = Path.Combine(basePath, path);
string baseUrl = $"https://raw.githubusercontent.com/Teyliu/PVZF-Translation/refs/heads/main/PvZ_Fusion_Translator/";
string url = baseUrl + path;
byte[] imageData = Utils.GetByteDataFromWeb(url).Result;
if(imageData != null)
{
string fileName = Path.GetFileName(downloadPath);
Texture2D texture2D = Utils.LoadImage(imageData);
TextureStore.textureDict[fileName] = imageData;
if(!Directory.Exists(Path.GetDirectoryName(downloadPath)))
{
Directory.CreateDirectory(Path.GetDirectoryName(downloadPath));
}
File.WriteAllBytes(downloadPath, imageData);
}
}
}
}
foreach (string filepath in Directory.EnumerateFiles(textureDir, "*.png", SearchOption.AllDirectories)) foreach (string filepath in Directory.EnumerateFiles(textureDir, "*.png", SearchOption.AllDirectories))
{ {
if (filepath.Contains("[Custom Textures]", StringComparison.OrdinalIgnoreCase) && loadDefaultTextures) if (filepath.Contains("[Custom Textures]", StringComparison.OrdinalIgnoreCase) && loadDefaultTextures)
@ -372,6 +593,9 @@ namespace PvZ_Fusion_Translator
continue; continue;
} }
if (!localTOC.ContainsKey(filepath.Replace(basePath + "\\", "").Replace("\\", "/"))
&& (SerializeWithIndentation(localTOC) != "{}")) continue;
#if OBFUSCATE #if OBFUSCATE
if (CheckSumStore.IsModified(filepath)) if (CheckSumStore.IsModified(filepath))
{ {
@ -384,8 +608,9 @@ namespace PvZ_Fusion_Translator
Log.LogDebug("Loading File : " + filepath); Log.LogDebug("Loading File : " + filepath);
#endif #endif
Texture2D texture2D = Utils.LoadImage(filepath); byte[] imageData = File.ReadAllBytes(filepath);
TextureStore.textureDict[Path.GetFileNameWithoutExtension(filepath)] = filepath; Texture2D texture2D = Utils.LoadImage(imageData);
TextureStore.textureDict[Path.GetFileNameWithoutExtension(filepath)] = imageData;
} }
} }
@ -406,12 +631,83 @@ namespace PvZ_Fusion_Translator
} }
try try
{ {
foreach (string filepath in Directory.EnumerateFiles(textureDir, "*.png", SearchOption.AllDirectories)) string trueTextureDir = GetAssetDir(AssetType.Textures, language);
{ Dictionary<string, string> localTOC = new Dictionary<string, string>();
if (filepath.Contains("[Custom Textures]", StringComparison.OrdinalIgnoreCase) && loadDefaultTextures) string localTOCDir = Path.Combine(trueTextureDir, "Texture_TOC.json");
{ if (!File.Exists(localTOCDir))
continue; {
} File.WriteAllText(localTOCDir, "{}");
}
string localTOCContent = File.ReadAllText(localTOCDir);
localTOC = System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, string>>(localTOCContent);
string basePath = Core.Instance.modsDirectory;
if(!Utils.useLocal)
{
string textureTOCRequest = Utils.GetDataFromWeb($"https://raw.githubusercontent.com/Teyliu/PVZF-Translation/refs/heads/main/PvZ_Fusion_Translator/Localization/{Utils.Language.ToString()}/Textures/Texture_TOC.json").Result;
if (textureTOCRequest != null)
{
Dictionary<string, string> textureTOC = JsonConvert.DeserializeObject<Dictionary<string, string>>(textureTOCRequest);
List<string> toDownload = new();
foreach(var pair in textureTOC)
{
if(!localTOC.ContainsKey(pair.Key))
{
toDownload.Add(pair.Key);
continue;
}
if(pair.Value != localTOC[pair.Key])
{
toDownload.Add(pair.Key);
}
if(!File.Exists(Path.Combine(basePath, pair.Key)))
{
toDownload.Add(pair.Key);
continue;
}
}
string toWriteText = SerializeWithIndentation(textureTOC);
File.WriteAllText(localTOCDir, toWriteText);
foreach(string path in toDownload)
{
string downloadPath = Path.Combine(basePath, path);
string baseUrl = $"https://raw.githubusercontent.com/Teyliu/PVZF-Translation/refs/heads/main/PvZ_Fusion_Translator/";
string url = baseUrl + path;
byte[] imageData = Utils.GetByteDataFromWeb(url).Result;
if(imageData != null)
{
string fileName = Path.GetFileName(downloadPath);
Texture2D texture2D = Utils.LoadImage(imageData);
TextureStore.spriteDict[fileName] = imageData;
if(!Directory.Exists(Path.GetDirectoryName(downloadPath)))
{
Directory.CreateDirectory(Path.GetDirectoryName(downloadPath));
}
File.WriteAllBytes(downloadPath, imageData);
}
}
}
}
foreach (string filepath in Directory.EnumerateFiles(textureDir, "*.png", SearchOption.AllDirectories))
{
if (filepath.Contains("[Custom Textures]", StringComparison.OrdinalIgnoreCase) && loadDefaultTextures)
{
continue;
}
if (!localTOC.ContainsKey(filepath.Replace(basePath + "\\", "").Replace("\\", "/"))
&& (SerializeWithIndentation(localTOC) != "{}")) continue;
#if OBFUSCATE #if OBFUSCATE
if (CheckSumStore.IsModified(filepath)) if (CheckSumStore.IsModified(filepath))
@ -422,12 +718,13 @@ namespace PvZ_Fusion_Translator
#endif #endif
#if DEBUG #if DEBUG
Log.LogDebug("Loading File (Sprite): " + filepath); Log.LogDebug("Loading File (Sprite): " + filepath);
#endif #endif
Texture2D texture2D = Utils.LoadImage(filepath); byte[] imageData = File.ReadAllBytes(filepath);
TextureStore.spriteDict[Path.GetFileNameWithoutExtension(filepath)] = filepath; Texture2D texture2D = Utils.LoadImage(imageData);
} TextureStore.spriteDict[Path.GetFileNameWithoutExtension(filepath)] = imageData;
}
} }
catch (Exception e) catch (Exception e)
@ -448,8 +745,78 @@ namespace PvZ_Fusion_Translator
} }
try try
{ {
foreach (string filepath in Directory.EnumerateFiles(textureDefaultDir, "*.png", SearchOption.AllDirectories)) string trueTextureDir = Path.Combine(Core.Instance.modsDirectory, "[Custom Textures]");
{ Dictionary<string, string> localTOC = new Dictionary<string, string>();
string localTOCDir = Path.Combine(trueTextureDir, "Default_TOC.json");
if (!File.Exists(localTOCDir))
{
File.WriteAllText(localTOCDir, "{}");
}
string localTOCContent = File.ReadAllText(localTOCDir);
localTOC = System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, string>>(localTOCContent);
string basePath = Core.Instance.modsDirectory;
if (!Utils.useLocal)
{
string textureTOCRequest = Utils.GetDataFromWeb($"https://raw.githubusercontent.com/Teyliu/PVZF-Translation/refs/heads/main/PvZ_Fusion_Translator/{Uri.EscapeDataString("[Custom Textures]")}/Default_TOC.json").Result;
if (textureTOCRequest != null)
{
Dictionary<string, string> textureTOC = JsonConvert.DeserializeObject<Dictionary<string, string>>(textureTOCRequest);
List<string> toDownload = new();
foreach (var pair in textureTOC)
{
if (!localTOC.ContainsKey(pair.Key))
{
toDownload.Add(pair.Key);
continue;
}
if (pair.Value != localTOC[pair.Key])
{
toDownload.Add(pair.Key);
}
if(!File.Exists(Path.Combine(basePath, pair.Key)))
{
toDownload.Add(pair.Key);
continue;
}
}
string toWriteText = SerializeWithIndentation(textureTOC);
File.WriteAllText(localTOCDir, toWriteText);
foreach (string path in toDownload)
{
string downloadPath = Path.Combine(basePath, path);
string baseUrl = $"https://raw.githubusercontent.com/Teyliu/PVZF-Translation/refs/heads/main/PvZ_Fusion_Translator/";
string url = baseUrl + path;
byte[] imageData = Utils.GetByteDataFromWeb(url).Result;
if (imageData != null)
{
string fileName = Path.GetFileName(downloadPath);
Texture2D texture2D = Utils.LoadImage(imageData);
TextureStore.textureDict[fileName] = imageData;
if(!Directory.Exists(Path.GetDirectoryName(downloadPath)))
{
Directory.CreateDirectory(Path.GetDirectoryName(downloadPath));
}
File.WriteAllBytes(downloadPath, imageData);
}
}
}
}
foreach (string filepath in Directory.EnumerateFiles(textureDefaultDir, "*.png", SearchOption.AllDirectories))
{
if (!localTOC.ContainsKey(filepath.Replace(basePath + "\\", "").Replace("\\", "/"))
&& (SerializeWithIndentation(localTOC) != "{}")) continue;
#if OBFUSCATE #if OBFUSCATE
if (CheckSumStore.IsModified(filepath)) if (CheckSumStore.IsModified(filepath))
@ -459,9 +826,10 @@ namespace PvZ_Fusion_Translator
} }
#endif #endif
Texture2D texture2D = Utils.LoadImage(filepath); byte[] imageData = File.ReadAllBytes(filepath);
TextureStore.textureDict[Path.GetFileNameWithoutExtension(filepath)] = filepath; Texture2D texture2D = Utils.LoadImage(imageData);
} TextureStore.textureDict[Path.GetFileNameWithoutExtension(filepath)] = imageData;
}
} }
catch (Exception e) catch (Exception e)
@ -482,18 +850,91 @@ namespace PvZ_Fusion_Translator
} }
try try
{ {
string trueTextureDir = Path.Combine(Core.Instance.modsDirectory, "[Custom Textures]");
Dictionary<string, string> localTOC = new Dictionary<string, string>();
string localTOCDir = Path.Combine(trueTextureDir, "Custom_TOC.json");
if (!File.Exists(localTOCDir))
{
File.WriteAllText(localTOCDir, "{}");
}
string localTOCContent = File.ReadAllText(localTOCDir);
localTOC = System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, string>>(localTOCContent);
string basePath = Core.Instance.modsDirectory;
if (!Utils.useLocal)
{
string textureTOCRequest = Utils.GetDataFromWeb($"https://raw.githubusercontent.com/Teyliu/PVZF-Translation/refs/heads/main/PvZ_Fusion_Translator/{Uri.EscapeDataString("[Custom Textures]")}/Custom_TOC.json").Result;
if (textureTOCRequest != null)
{
Dictionary<string, string> textureTOC = JsonConvert.DeserializeObject<Dictionary<string, string>>(textureTOCRequest);
List<string> toDownload = new();
foreach (var pair in textureTOC)
{
if (!localTOC.ContainsKey(pair.Key))
{
toDownload.Add(pair.Key);
continue;
}
if (pair.Value != localTOC[pair.Key])
{
toDownload.Add(pair.Key);
continue;
}
if(!File.Exists(Path.Combine(basePath, pair.Key)))
{
toDownload.Add(pair.Key);
continue;
}
}
string toWriteText = SerializeWithIndentation(textureTOC);
File.WriteAllText(localTOCDir, toWriteText);
foreach (string path in toDownload)
{
string downloadPath = Path.Combine(basePath, path);
string baseUrl = $"https://raw.githubusercontent.com/Teyliu/PVZF-Translation/refs/heads/main/PvZ_Fusion_Translator/";
string url = baseUrl + path;
byte[] imageData = Utils.GetByteDataFromWeb(url).Result;
if (imageData != null)
{
string fileName = Path.GetFileName(downloadPath);
Texture2D texture2D = Utils.LoadImage(imageData);
TextureStore.textureDict[fileName] = imageData;
if(!Directory.Exists(Path.GetDirectoryName(downloadPath)))
{
Directory.CreateDirectory(Path.GetDirectoryName(downloadPath));
}
File.WriteAllBytes(downloadPath, imageData);
}
}
}
}
foreach (string filepath in Directory.EnumerateFiles(texturePackDir, "*.png", SearchOption.AllDirectories)) foreach (string filepath in Directory.EnumerateFiles(texturePackDir, "*.png", SearchOption.AllDirectories))
{ {
#if OBFUSCATE #if OBFUSCATE
if (CheckSumStore.IsModified(filepath)) if (CheckSumStore.IsModified(filepath))
{ {
Log.LogError("File {0} was modified!" , filepath); Log.LogError("File {0} was modified!" , filepath);
continue; continue;
} }
#endif #endif
Texture2D texture2D = Utils.LoadImage(filepath); if (!localTOC.ContainsKey(filepath.Replace(basePath + "\\", "").Replace("\\", "/"))
TextureStore.textureDict[Path.GetFileNameWithoutExtension(filepath)] = filepath; && (SerializeWithIndentation(localTOC) != "{}")) continue;
byte[] imageData = File.ReadAllBytes(filepath);
Texture2D texture2D = Utils.LoadImage(imageData);
TextureStore.textureDict[Path.GetFileNameWithoutExtension(filepath)] = imageData;
} }
} }
@ -540,12 +981,6 @@ namespace PvZ_Fusion_Translator
File.WriteAllText(Path.Combine(stringDir, "tips_fs.json"), fsLevelTipDictionary); File.WriteAllText(Path.Combine(stringDir, "tips_fs.json"), fsLevelTipDictionary);
// save travel buffs
string travelBuffs = SerializeWithIndentation(TravelMgr_Patch.translatedTravelBuffs);
File.WriteAllText(Path.Combine(stringDir, "travel_buffs.json"), travelBuffs);
// save changelog // save changelog
if(NoticePauseMenu_Patch.changelogText != "") if(NoticePauseMenu_Patch.changelogText != "")
@ -555,11 +990,11 @@ namespace PvZ_Fusion_Translator
// save abyss buffs // save abyss buffs
if(Patches.Modes.Abyss.AbyssBuffMenu_Patch.abyssBuffData != new Dictionary<string, string>()) //if(Patches.Modes.Abyss.AbyssBuffMenu_Patch.abyssBuffData != new Dictionary<string, string>())
{ //{
string abyssBuffData = SerializeWithIndentation(Patches.Modes.Abyss.AbyssBuffMenu_Patch.abyssBuffData, 2); // string abyssBuffData = SerializeWithIndentation(Patches.Modes.Abyss.AbyssBuffMenu_Patch.abyssBuffData, 2);
File.WriteAllText(Path.Combine(stringDir, "abyss_buffs.json"), abyssBuffData); // File.WriteAllText(Path.Combine(stringDir, "abyss_buffs.json"), abyssBuffData);
} //}
// save almanacs // save almanacs
@ -578,6 +1013,13 @@ namespace PvZ_Fusion_Translator
File.WriteAllText(Path.Combine(almanacDir, "ZombieStringsTranslate.json"), AlmanacZombieMenu_Patch.almanacJson); File.WriteAllText(Path.Combine(almanacDir, "ZombieStringsTranslate.json"), AlmanacZombieMenu_Patch.almanacJson);
} }
if(AlmanacSelectMenu_Patch.detailStrings != new Dictionary<string, string>())
{
string detailStrings = SerializeWithIndentation(AlmanacSelectMenu_Patch.detailStrings);
File.WriteAllText(Path.Combine(almanacDir, "DetailStringsTranslate.json"), detailStrings);
}
} }
public static string SerializeWithIndentation<T>(T value, int size = 4, char indentChar = ' ') public static string SerializeWithIndentation<T>(T value, int size = 4, char indentChar = ' ')
@ -607,10 +1049,10 @@ namespace PvZ_Fusion_Translator
} }
string LawnStrings = Resources.Load<TextAsset>("LawnStrings").text; string LawnStrings = Resources.Load<TextAsset>("LawnStrings").text;
string ZombieStrings = Resources.Load<TextAsset>("ZombieStrings").text; string ZombieStrings = Resources.Load<TextAsset>("ZombieStrings").text;
string AbyssBuffData = Resources.Load<TextAsset>("AbyssBuffData").text; //string AbyssBuffData = Resources.Load<TextAsset>("AbyssBuffData").text;
File.WriteAllText(Path.Combine(dumpDir, "LawnStrings.json"), LawnStrings); File.WriteAllText(Path.Combine(dumpDir, "LawnStrings.json"), LawnStrings);
File.WriteAllText(Path.Combine(dumpDir, "ZombieStrings.json"), ZombieStrings); File.WriteAllText(Path.Combine(dumpDir, "ZombieStrings.json"), ZombieStrings);
File.WriteAllText(Path.Combine(dumpDir, "AbyssBuffData.json"), AbyssBuffData); //File.WriteAllText(Path.Combine(dumpDir, "AbyssBuffData.json"), AbyssBuffData);
// dump iz tips // dump iz tips
var izDump = DumpIZStrings(); var izDump = DumpIZStrings();
@ -634,7 +1076,18 @@ namespace PvZ_Fusion_Translator
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
})); }));
Dictionary<Achievement, AchievementObject> achievementsList = new Dictionary<Achievement, AchievementObject>(); // dump almanac mechanics
var detailStringsDump = DumpDetailStrings();
var detailStringsData = detailStringsDump.Item1;
var detailStrings = detailStringsDump.Item2;
File.WriteAllText(Path.Combine(dumpDir, "DetailStrings.json"), System.Text.Json.JsonSerializer.Serialize(detailStrings, new JsonSerializerOptions
{
WriteIndented = true,
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
}));
/*Dictionary<Achievement, AchievementObject> achievementsList = new Dictionary<Achievement, AchievementObject>();
foreach (Il2CppSystem.Collections.Generic.KeyValuePair<Achievement, Il2CppSystem.Tuple<string, string>> entry in AchievementClip.achievementsText) foreach (Il2CppSystem.Collections.Generic.KeyValuePair<Achievement, Il2CppSystem.Tuple<string, string>> entry in AchievementClip.achievementsText)
{ {
achievementsList.Add(entry.Key, new AchievementObject(entry.Key, entry.Value.Item1, entry.Value.Item2)); achievementsList.Add(entry.Key, new AchievementObject(entry.Key, entry.Value.Item1, entry.Value.Item2));
@ -643,7 +1096,7 @@ namespace PvZ_Fusion_Translator
{ {
WriteIndented = true, WriteIndented = true,
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
})); }));*/
} }
public static ValueTuple<Il2CppArrayBase<TextAsset>, Dictionary<string, string>> DumpIZStrings() public static ValueTuple<Il2CppArrayBase<TextAsset>, Dictionary<string, string>> DumpIZStrings()
@ -678,6 +1131,26 @@ namespace PvZ_Fusion_Translator
return new ValueTuple<Il2CppArrayBase<TextAsset>, Dictionary<string, string>>(fusionShowcaseData, fusionShowcaseDataDump); return new ValueTuple<Il2CppArrayBase<TextAsset>, Dictionary<string, string>>(fusionShowcaseData, fusionShowcaseDataDump);
} }
public static ValueTuple<Il2CppAlmanacData.AlmanacData, Dictionary<string, string>> DumpDetailStrings()
{
string detailStringsData = Resources.Load<TextAsset>("detailstrings").text;
Il2CppAlmanacData.AlmanacData detailStrings = JsonUtility.FromJson<Il2CppAlmanacData.AlmanacData>(detailStringsData);
Dictionary<string, string> detailStringsDump = new Dictionary<string, string>();
foreach (var detailString in detailStrings.details)
{
if(detailStringsDump.ContainsKey(detailString.title))
{
detailStringsDump[detailString.title] = detailString.text;
}
else
{
detailStringsDump.Add(detailString.title, detailString.text);
}
}
return new ValueTuple<Il2CppAlmanacData.AlmanacData, Dictionary<string, string>>(detailStrings, detailStringsDump);
}
#if DEBUG #if DEBUG
public static void DumpUntranslatedStrings(string text) public static void DumpUntranslatedStrings(string text)
{ {

View file

@ -1,4 +1,6 @@
//#if DEBUG //#if DEBUG
using Il2Cpp;
using Il2CppGameLevel;
using PvZ_Fusion_Translator.AssetStore; using PvZ_Fusion_Translator.AssetStore;
using PvZ_Fusion_Translator.Patches.Modes.Super_Editor; using PvZ_Fusion_Translator.Patches.Modes.Super_Editor;
using UnityEngine; using UnityEngine;
@ -10,7 +12,8 @@ namespace PvZ_Fusion_Translator
public enum ModType public enum ModType
{ {
ReloadStrings, ReloadStrings,
ReloadTextures ReloadTextures,
ExportLevelStrings
} }
private class ModFeature private class ModFeature
@ -43,13 +46,26 @@ namespace PvZ_Fusion_Translator
Core.ShowToast("Textures Reloaded!"); Core.ShowToast("Textures Reloaded!");
return; return;
} }
if (this.ModType == ModType.ExportLevelStrings)
{
CustomMenu customMenu = UnityEngine.Object.FindObjectOfType<CustomMenu>();
if (!customMenu) return;
if(customMenu.isActiveAndEnabled)
{
Patches.Modes.Super_Editor.GameLevel.LevelManager_Patch.ExportLevelStrings(customMenu.LevelData);
Core.ShowToast("Dumped level strings!");
}
return;
}
} }
} }
private static Dictionary<ModType, ModFeature> featureLists = new() private static Dictionary<ModType, ModFeature> featureLists = new()
{ {
{ModType.ReloadStrings,new ModFeature("Reload Strings",ModType.ReloadStrings,KeyCode.Home, true)}, {ModType.ReloadStrings,new ModFeature("Reload Strings",ModType.ReloadStrings,KeyCode.Home, true)},
{ModType.ReloadTextures,new ModFeature("Reload Textures",ModType.ReloadTextures,KeyCode.End, true)} {ModType.ReloadTextures,new ModFeature("Reload Textures",ModType.ReloadTextures,KeyCode.End, true)},
{ModType.ExportLevelStrings,new ModFeature("Export Level Strings",ModType.ExportLevelStrings,KeyCode.N, true)}
}; };

View file

@ -1,10 +1,10 @@
using HarmonyLib; using HarmonyLib;
using Il2Cpp; using Il2Cpp;
using Il2CppCore;
using Il2CppAlmanacData;
using Il2CppTMPro; using Il2CppTMPro;
using PvZ_Fusion_Translator.AssetStore; using PvZ_Fusion_Translator.AssetStore;
using PvZ_Fusion_Translator.Patches.Modes.Odyssey; using PvZ_Fusion_Translator.Patches.Modes.Odyssey;
//using PvZ_Fusion_Translator.Patches.Modes.Odyssey;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Xml.Linq; using System.Xml.Linq;
using UnityEngine; using UnityEngine;
@ -20,10 +20,6 @@ namespace PvZ_Fusion_Translator.Patches.BaseTextObjects
[HarmonyPostfix] [HarmonyPostfix]
public static void ShowText(InGameText __instance) public static void ShowText(InGameText __instance)
{ {
if(__instance.textHead == null) return;
if(!__instance.textHead.active) return;
TranslateInGameText(__instance); TranslateInGameText(__instance);
} }
@ -31,10 +27,6 @@ namespace PvZ_Fusion_Translator.Patches.BaseTextObjects
[HarmonyPostfix] [HarmonyPostfix]
public static void DebugWarning(InGameText __instance) public static void DebugWarning(InGameText __instance)
{ {
if(__instance.textHead == null) return;
if(!__instance.textHead.active) return;
TranslateInGameText(__instance); TranslateInGameText(__instance);
} }
@ -42,29 +34,48 @@ namespace PvZ_Fusion_Translator.Patches.BaseTextObjects
[HarmonyPostfix] [HarmonyPostfix]
public static void Update(InGameText __instance) public static void Update(InGameText __instance)
{ {
if(__instance.textHead == null) return;
if(!__instance.textHead.active) return;
TranslateInGameText(__instance); TranslateInGameText(__instance);
} }
public static void TranslateInGameText(InGameText __instance) public static void TranslateInGameText(InGameText __instance)
{ {
if (__instance.textMesh == null) return; TextMeshProUGUI txt = null;
if(!__instance.textHead.active) return; if (__instance.textMesh == null || __instance.textHead == null)
{
if (__instance.TryGetComponent<TextMeshProUGUI>(out TextMeshProUGUI selfTxt))
{
txt = selfTxt;
}
}
else
{
txt = __instance.textMesh;
}
if(txt != null)
{
if (!txt.gameObject.active) return;
TranslateInGameTextMesh(txt);
}
}
public static void TranslateInGameTextMesh(TextMeshProUGUI txt)
{
if (txt == null) return;
if (txt.text == currentText) return;
TMP_FontAsset fontAsset = FontStore.LoadTMPFont(Utils.Language.ToString()); TMP_FontAsset fontAsset = FontStore.LoadTMPFont(Utils.Language.ToString());
currentText = __instance.textMesh.text;
TextMeshProUGUI txt = __instance.textMesh;
string originalText = txt.text; string originalText = txt.text;
string lockedPlantMatch = CheckLockedMessage(originalText);
string travelMatch = TravelMgr_Patch.MatchTravelBuff(originalText); string travelMatch = TravelMgr_Patch.MatchTravelBuff(originalText);
int godsGachaCheck = CheckGodsGachaPopup(originalText); int godsGachaCheck = CheckGodsGachaPopup(originalText);
string godsGachaMatch = ""; string godsGachaMatch = "";
string superEditorPlantMatch = CheckSuperEditorPopup(originalText); string superEditorPlantMatch = CheckSuperEditorPopup(originalText);
string customLevelRegexMatch = CheckCustomLevelRegex(originalText);
string qualityCheckMatch = CheckQualityUpgrade(originalText);
switch(godsGachaCheck) switch(godsGachaCheck)
{ {
@ -92,7 +103,7 @@ namespace PvZ_Fusion_Translator.Patches.BaseTextObjects
} }
else if (travelMatch != "") else if (travelMatch != "")
{ {
txt.text = travelMatch; txt.text = TravelMgr_Patch.AddBuffName(travelMatch);
if (txt.gameObject.name.Contains("main")) if (txt.gameObject.name.Contains("main"))
{ {
originalText = txt.text; originalText = txt.text;
@ -103,11 +114,27 @@ namespace PvZ_Fusion_Translator.Patches.BaseTextObjects
} }
} }
} }
else if(qualityCheckMatch != "")
{
txt.text = qualityCheckMatch;
}
else if(superEditorPlantMatch != "") else if(superEditorPlantMatch != "")
{ {
txt.text = superEditorPlantMatch; txt.text = superEditorPlantMatch;
} }
else if((Regex.Match(txt.text, @"(<color[^>]*>.*?</color>)", RegexOptions.Singleline).Success) && !StringStore.translationString.ContainsKey(txt.text)) 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); txt.text = StringStore.TranslateColorText(txt.text, true);
if (txt.gameObject.name.Contains("main")) if (txt.gameObject.name.Contains("main"))
@ -134,19 +161,30 @@ namespace PvZ_Fusion_Translator.Patches.BaseTextObjects
} }
} }
txt.font = fontAsset; txt.font = fontAsset;
currentText = txt.text;
} }
public static string namePlantedPattern = "种植了:([^\\s]+)"; public static string namePlantedPattern = "种植了:([^\\s]+)";
public static string nameUpgradedPattern = "升级成功:([^\\s]+) -> ([^\\s]+)"; public static string nameUpgradedPattern = "升级成功:([^\\s]+) -> ([^\\s]+)";
public static string nameAlreadyPlantedPattern = "场上已经有一个([^\\s]+)了"; public static string nameAlreadyPlantedPattern = "场上已经有一个([^\\s]+)了";
public static string upgradePathRemovedPattern = "已移除路线:([^\\s]+)";
public static string lockedPlantPattern = "^([\\s\\S]+)\\+([\\S]+)$";
public static string multiLockedPlantPattern = "^或 ([\\s\\S]+)\\+([\\S]+)$";
public static string qualityChangePattern = "诸神注视着你,并选中了一个他们喜欢的词条\n植物<color=green>【([\\S]+)】</color>的词条<color=yellow>【强化:([\\S]+)】</color>获得品质升级\n当前品质:([\\S]+)";
public static Dictionary<string, string> fallbackFStrs = new Dictionary<string, string>() public static Dictionary<string, string> fallbackFStrs = new Dictionary<string, string>()
{ {
{"种植了:([^\\s]+)", "{0} planted!"}, { namePlantedPattern, "{0} planted!"},
{"升级成功:([^\\s]+) -> ([^\\s]+)", "{0} successfully upgraded to {1}!"}, { nameUpgradedPattern, "{0} successfully upgraded to {1}!"},
{"场上已经有一个([^\\s]+)了", "{0} already exists on the lawn!"}, { nameAlreadyPlantedPattern, "{0} already exists on the lawn!"},
{"已移除路线:([^\\s]+)", "Upgrade Path removed for {0}" }, { upgradePathRemovedPattern, "Upgrade Path removed for {0}" },
{ @"([^\s]+)\((\d+)\)", "{0}({1})" } { @"([^\s]+)\((\d+)\)", "{0}({1})" },
{ lockedPlantPattern, "{0} + {1}" },
{ multiLockedPlantPattern, "or {0} + {1}" },
{ qualityChangePattern, "The gods are watching you, and they have granted you an upgrade!\nThe <color=yellow>{1}</color> upgrade for <color=green>{0}</color> has been upgraded.\nCurrent Quality: {2}" }
}; };
public static int CheckGodsGachaPopup(string originalText) public static int CheckGodsGachaPopup(string originalText)
@ -176,13 +214,13 @@ namespace PvZ_Fusion_Translator.Patches.BaseTextObjects
switch(type) switch(type)
{ {
case 1: case 1:
res = TranslatePlantNameParts(originalText, namePlantedPattern); res = StringStore.TranslateText(originalText, namePlantedPattern);
break; break;
case 2: case 2:
res = TranslatePlantNameParts(originalText, nameUpgradedPattern); res = StringStore.TranslateText(originalText, nameUpgradedPattern);
break; break;
case 3: case 3:
res = TranslatePlantNameParts(originalText, nameAlreadyPlantedPattern); res = StringStore.TranslateText(originalText, nameAlreadyPlantedPattern);
break; break;
default: default:
break; break;
@ -212,13 +250,35 @@ namespace PvZ_Fusion_Translator.Patches.BaseTextObjects
return res; return res;
} }
public static string TranslatePlantNameParts(string originalText, string pattern, string fallback)
{
string res = "";
string fStr = "";
Match match = Regex.Match(originalText, pattern);
if(match.Success)
{
GroupCollection groups = match.Groups;
fStr = StringStore.translationStringRegex.ContainsKey(pattern) ? StringStore.translationStringRegex[pattern] : fallback;
List<string> dynamicParts = [];
for(int i = 1; i < groups.Count; i++)
{
string group = groups[i].Value;
string 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) public static string CheckSuperEditorPopup(string originalText)
{ {
string res = ""; string res = "";
if(Regex.IsMatch(originalText, "已移除路线:([^\\s]+)")) if(Regex.IsMatch(originalText, upgradePathRemovedPattern))
{ {
res = TranslatePlantNameParts(originalText, "已移除路线:([^\\s]+)"); res = StringStore.TranslateText(originalText, upgradePathRemovedPattern);
} }
else if(Regex.IsMatch(originalText, "当前全部基础植物:(.*)")) else if(Regex.IsMatch(originalText, "当前全部基础植物:(.*)"))
{ {
@ -247,5 +307,94 @@ namespace PvZ_Fusion_Translator.Patches.BaseTextObjects
return res; return res;
} }
public static string CheckLockedMessage(string originalText)
{
string res = "";
Regex lockedPlantRegex = new Regex(lockedPlantPattern);
Regex multiLockedPlantRegex = new Regex(multiLockedPlantPattern);
if(lockedPlantRegex.IsMatch(originalText))
{
if(originalText.Contains("\n"))
{
string[] lines = originalText.Split("\n");
if (lockedPlantRegex.IsMatch(lines[0]))
{
string firstLine = lines[0];
Match match = lockedPlantRegex.Match(firstLine);
GroupCollection groups = match.Groups;
if (Utils.plantIndiceString.ContainsKey(groups[1].Value) && Utils.plantIndiceString.ContainsKey(groups[2].Value))
{
firstLine = StringStore.TranslateText(firstLine, lockedPlantPattern);
List<string> translatedLines = new List<string>() { firstLine };
for(int i = 1; i < lines.Length; i++)
{
string nextLine = lines[i];
string translatedNextLine = StringStore.TranslateText(nextLine, multiLockedPlantPattern);
translatedLines.Add(translatedNextLine);
}
res = string.Join("\n", translatedLines);
}
else
{
return "";
}
}
}
else
{
if (lockedPlantRegex.IsMatch(originalText))
{
Match match = lockedPlantRegex.Match(originalText);
GroupCollection 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)
{
string res = "";
foreach(var pair in StringStore.customLevelStringRegex)
{
if(StringStore.TestRegex(originalText, pair.Key))
{
res = StringStore.TranslateText(originalText, pair.Key);
}
}
foreach(var pair in StringStore.translationStringRegex)
{
if(StringStore.TestRegex(originalText, pair.Key))
{
res = "";
}
}
return res;
}
public static string CheckQualityUpgrade(string originalText)
{
string res = "";
if(Regex.IsMatch(originalText, qualityChangePattern))
{
res = StringStore.TranslateText(originalText, qualityChangePattern);
}
return res;
}
} }
} }

View file

@ -0,0 +1,49 @@
using HarmonyLib;
using Il2Cpp;
using Il2CppTMPro;
using PvZ_Fusion_Translator.Patches.Managers;
using PvZ_Fusion_Translator.AssetStore;
using UnityEngine;
using UnityEngine.UI;
namespace PvZ_Fusion_Translator.Patches.BaseTextObjects
{
[HarmonyPatch(typeof(TMP_Dropdown))]
public static class TMP_Dropdown_Patch
{
[HarmonyPatch(nameof(TMP_Dropdown.Awake))]
[HarmonyPatch(nameof(TMP_Dropdown.Start))]
[HarmonyPatch(nameof(TMP_Dropdown.Show))]
[HarmonyPatch(nameof(TMP_Dropdown.SetValue))]
[HarmonyPostfix]
public static void Awake(TMP_Dropdown __instance)
{
if(__instance.captionText)
{
TMP_Text txt = __instance.captionText;
txt.text = StringStore.translationString.ContainsKey(txt.text + "_code") ? StringStore.TranslateText(txt.text + "_code") : StringStore.TranslateText(txt.text);
}
if(__instance.itemText)
{
TMP_Text txt = __instance.itemText;
txt.text = StringStore.translationString.ContainsKey(txt.text + "_code") ? StringStore.TranslateText(txt.text + "_code") : StringStore.TranslateText(txt.text);
}
foreach(TMP_Dropdown.DropdownItem dropdownItem in __instance.m_Items)
{
TMP_Text txt = dropdownItem.text;
txt.text = StringStore.translationString.ContainsKey(txt.text + "_code") ? StringStore.TranslateText(txt.text + "_code") : StringStore.TranslateText(txt.text);
}
}
[HarmonyPatch(nameof(TMP_Dropdown.CreateDropdownList))]
public static void CreateDropdownList(TMP_Dropdown __instance)
{
foreach(TMP_Text txt in __instance.GetComponentsInChildren<TMP_Text>(true))
{
txt.text = StringStore.translationString.ContainsKey(txt.text + "_code") ? StringStore.TranslateText(txt.text + "_code") : StringStore.TranslateText(txt.text);
}
}
}
}

View file

@ -10,7 +10,7 @@ namespace PvZ_Fusion_Translator.Patches.BaseTextObjects
{ {
[HarmonyPatch(nameof(TMP_InputField.OnEnable))] [HarmonyPatch(nameof(TMP_InputField.OnEnable))]
[HarmonyPostfix] [HarmonyPostfix]
private static void OnEnable(TMP_InputField __instance) public static void OnEnable(TMP_InputField __instance)
{ {
if (!string.IsNullOrEmpty(__instance.text)) if (!string.IsNullOrEmpty(__instance.text))
{ {

View file

@ -17,12 +17,24 @@ namespace PvZ_Fusion_Translator.Patches.BaseTextObjects
{ {
if (!string.IsNullOrEmpty(__instance.text)) if (!string.IsNullOrEmpty(__instance.text))
{ {
if(__instance.transform.parent.parent != null) __instance.font = FontStore.LoadTMPFont(Utils.Language.ToString());
if (!Utils.CheckForUntranslatedText(__instance.text) && !(__instance.text).Contains("_")) return;
if(__instance.transform.parent != null)
{ {
if (__instance.transform.parent.parent.name.Contains("AbyssBagMenu")) if(__instance.transform.parent.name.Contains("DrawCardsText"))
{ {
return; return;
} }
if(__instance.transform.parent.parent != null)
{
if (__instance.transform.parent.parent.name.Contains("AbyssBagMenu"))
{
return;
}
}
} }
__instance = StringStore.TranslateText(__instance); __instance = StringStore.TranslateText(__instance);
@ -32,7 +44,7 @@ namespace PvZ_Fusion_Translator.Patches.BaseTextObjects
{ {
__instance.text = __instance.text.Replace("\n", " "); __instance.text = __instance.text.Replace("\n", " ");
if (__instance.name == "LevelName2" || __instance.name == "LevelName3") if ((__instance.name == "LevelName2" || __instance.name == "LevelName3") && !(__instance.gameObject.transform.parent.name.Contains("Difficulty") || __instance.gameObject.name.Contains("Difficulty")))
{ {
TowerManager_Patch.updatedText.Add(__instance.transform); TowerManager_Patch.updatedText.Add(__instance.transform);
} }
@ -47,7 +59,7 @@ namespace PvZ_Fusion_Translator.Patches.BaseTextObjects
} }
} }
[HarmonyPatch(nameof(TextMeshProUGUI.Awake))] /*[HarmonyPatch(nameof(TextMeshProUGUI.Awake))]
[HarmonyPostfix] [HarmonyPostfix]
private static void Awake(TextMeshProUGUI __instance) private static void Awake(TextMeshProUGUI __instance)
{ {
@ -77,9 +89,10 @@ namespace PvZ_Fusion_Translator.Patches.BaseTextObjects
// __instance.ForceMeshUpdate(); // __instance.ForceMeshUpdate();
} }
} }*/
} }
[HarmonyPatch(typeof(TMP_SubMeshUI))]
/*[HarmonyPatch(typeof(TMP_SubMeshUI))]
public static class TMP_SubMeshUI_Patch public static class TMP_SubMeshUI_Patch
{ {
[HarmonyPatch(nameof(TMP_SubMeshUI.OnEnable))] [HarmonyPatch(nameof(TMP_SubMeshUI.OnEnable))]
@ -93,5 +106,5 @@ namespace PvZ_Fusion_Translator.Patches.BaseTextObjects
__instance.textComponent.text = StringStore.TranslateText(text); __instance.textComponent.text = StringStore.TranslateText(text);
} }
} }
} }*/
} }

View file

@ -13,7 +13,11 @@ namespace PvZ_Fusion_Translator.Patches.BaseTextObjects
{ {
if (!string.IsNullOrEmpty(__instance.text)) if (!string.IsNullOrEmpty(__instance.text))
{ {
if (__instance.transform.parent.name.StartsWith("AlmanacHelp") || __instance.transform.parent.name.StartsWith("CardBank")) if(__instance.transform.parent.name.Contains("DrawCardsText"))
{
return;
}
else if (__instance.transform.parent.name.StartsWith("AlmanacHelp") || __instance.transform.parent.name.StartsWith("CardBank"))
{ {
__instance = StringStore.TranslateText(__instance); __instance = StringStore.TranslateText(__instance);
__instance.autoSizeTextContainer = false; __instance.autoSizeTextContainer = false;

View file

@ -0,0 +1,100 @@
using HarmonyLib;
using Il2Cpp;
using Il2CppAlmanacData;
using Il2CppTMPro;
using PvZ_Fusion_Translator.AssetStore;
using UnityEngine;
using System.Drawing;
using static Il2Cpp.AlmanacBuffMenu;
using static PvZ_Fusion_Translator.FileLoader;
using static PvZ_Fusion_Translator.Patches.Modes.Odyssey.TravelMgr_Patch;
using static PvZ_Fusion_Translator.Utils;
using Unity.VisualScripting;
namespace PvZ_Fusion_Translator.Patches.GameObjects
{
[HarmonyPatch(typeof(AlmanacBuffMenu))]
public static class AlmanacBuffMenu_Patch
{
[HarmonyPatch(nameof(AlmanacBuffMenu.Awake))]
[HarmonyPostfix]
public static void Post_Awake(AlmanacBuffMenu __instance)
{
foreach(AlmanacCardUI cardUI in __instance.cards)
{
AlmanacBuffMenu.CardInfo cardInfo = __instance.cardInfos[cardUI];
var buffData = FindBuffData(cardInfo.description);
if (buffData.Item1 == null || buffData.Item3 == null) continue;
cardUI.cost.text = (buffData.Item4) ? buffData.Item1 : $"{buffData.Item1} #{buffData.Item2}";
}
Post_OnCardClick(__instance);
}
[HarmonyPatch(nameof(AlmanacBuffMenu.SetAllCards))]
[HarmonyPatch(nameof(AlmanacBuffMenu.Start))]
[HarmonyPatch(nameof(AlmanacBuffMenu.InitMenu))]
[HarmonyPostfix]
public static void Post_SetAllCards(AlmanacBuffMenu __instance)
{
foreach(AlmanacCardUI cardUI in __instance.cards)
{
AlmanacBuffMenu.CardInfo cardInfo = __instance.cardInfos[cardUI];
var buffData = FindBuffData(cardInfo.description);
if (buffData.Item1 == null || buffData.Item3 == null) continue;
cardUI.cost.text = (buffData.Item4) ? buffData.Item1 : $"{buffData.Item1} #{buffData.Item2}";
}
Post_OnToolClick(__instance);
Post_OnCardClick(__instance);
}
[HarmonyPatch(nameof(AlmanacBuffMenu.OnToolClick))]
[HarmonyPostfix]
public static void Post_OnToolClick(AlmanacBuffMenu __instance)
{
foreach(TextMeshProUGUI txt in __instance.toolButton.GetComponentsInChildren<TextMeshProUGUI>())
{
txt.text = StringStore.TranslateText(txt.text);
txt.font = FontStore.LoadTMPFont(Utils.Language.ToString());
}
}
[HarmonyPatch(nameof(AlmanacBuffMenu.OnCardClick))]
[HarmonyPostfix]
public static void Post_OnCardClick(AlmanacBuffMenu __instance)
{
var buffData = FindBuffData(__instance.buffDescription.text);
if (buffData.Item1 == null || buffData.Item3 == null)
{
return;
}
__instance.buffTitle.text = (buffData.Item4) ? buffData.Item1 : $"{buffData.Item1} #{buffData.Item2}";
__instance.buffTitle.font = FontStore.LoadTMPFont(Utils.Language.ToString());
string buffFStr = StringStore.translationStringRegex.ContainsKey("BUFF_NAME_FORMAT") ? StringStore.translationStringRegex["BUFF_NAME_FORMAT"] : "{0}: {1}";
string fBuffDesc = string.Format(buffFStr, buffData.Item1, buffData.Item3);
__instance.buffDescription.text = (buffData.Item4) ? fBuffDesc + "\n\n" : buffData.Item3 + "\n\n";
__instance.buffDescription.font = FontStore.LoadTMPFont(Utils.Language.ToString());
string colorHex = StringStore.translationString.ContainsKey("MOD_ALMANAC_COL") ? StringStore.TranslateText("MOD_ALMANAC_COL") : "#000000";
System.Drawing.Color descriptionColor = ColorTranslator.FromHtml(colorHex);
__instance.buffDescription.color = new UnityEngine.Color(descriptionColor.R / 255.0f, descriptionColor.G / 255.0f, descriptionColor.B / 255.0f);
__instance.buffDescription.fontSizeMax = 18;
__instance.buffDescription.margin = new Vector4(8, 4, 25, 0);
__instance.buffDescription.enableWordWrapping = true;
__instance.buffDescription.overflowMode = TextOverflowModes.ScrollRect;
Canvas.ForceUpdateCanvases();
__instance.buffDescription.ForceMeshUpdate();
Post_OnToolClick(__instance);
}
}
}

View file

@ -0,0 +1,28 @@
using HarmonyLib;
using Il2Cpp;
using PvZ_Fusion_Translator.AssetStore;
namespace PvZ_Fusion_Translator.Patches.GameObjects
{
[HarmonyPatch(typeof(AlmanacCardUI))]
public static class AlmanacCardUI_Patch
{
[HarmonyPatch(nameof(AlmanacCardUI.Awake))]
[HarmonyPostfix]
public static void Awake(AlmanacCardUI __instance)
{
if (!Utils.CheckForUntranslatedText(__instance.cost.text)) return;
__instance.cost.text = StringStore.TranslateText(__instance.cost.text);
}
/*[HarmonyPatch(nameof(AlmanacCardUI.OnPointerDown))]
[HarmonyPostfix]
public static void OnPointerDown(AlmanacCardUI __instance)
{
foreach (AlmanacCardUI almanacCardUI in __instance.menu.GetComponentsInChildren<AlmanacCardUI>())
{
AlmanacCardUI_Patch.Awake(almanacCardUI);
}
}*/
}
}

View file

@ -1,13 +1,16 @@
using HarmonyLib; using HarmonyLib;
using Il2Cpp; using Il2Cpp;
using Il2CppAlmanacData;
using Il2CppTMPro; using Il2CppTMPro;
using MelonLoader.TinyJSON;
using PvZ_Fusion_Translator.AssetStore; using PvZ_Fusion_Translator.AssetStore;
using System.Text.Json;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using Unity.Collections; using Unity.Collections;
using Unity.VisualScripting; using Unity.VisualScripting;
using UnityEngine; using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
using static Il2Cpp.AlmanacPlantBank; using UnityEngine.UIElements;
using static PvZ_Fusion_Translator.FileLoader; using static PvZ_Fusion_Translator.FileLoader;
using static PvZ_Fusion_Translator.Utils; using static PvZ_Fusion_Translator.Utils;
@ -17,6 +20,7 @@ namespace PvZ_Fusion_Translator.Patches.GameObjects
public static class AlmanacPlantMenu_Patch public static class AlmanacPlantMenu_Patch
{ {
public static string almanacJson = ""; public static string almanacJson = "";
public static Dictionary<int, Il2CppAlmanacData.PlantInfo> plantInfoDict = new();
[HarmonyPatch(nameof(AlmanacPlantMenu.Awake))] [HarmonyPatch(nameof(AlmanacPlantMenu.Awake))]
[HarmonyPostfix] [HarmonyPostfix]
@ -26,7 +30,7 @@ namespace PvZ_Fusion_Translator.Patches.GameObjects
foreach (TextMeshProUGUI text in __instance.GetComponentsInChildren<TextMeshProUGUI>(true)) foreach (TextMeshProUGUI text in __instance.GetComponentsInChildren<TextMeshProUGUI>(true))
{ {
bool isPlantName = text.gameObject.name.Contains("Name") && text.transform.parent.name != "Background"; bool isPlantName = text.gameObject.name.Contains("Name") && text.transform.parent.name != "Background";
if (text.gameObject.name != "Description" && !isPlantName) if (text.gameObject.name != "Description" && !isPlantName && !text.gameObject.name.Contains("Cost"))
{ {
text.text = StringStore.TranslateText(text.text); text.text = StringStore.TranslateText(text.text);
text.font = font; text.font = font;
@ -34,14 +38,16 @@ namespace PvZ_Fusion_Translator.Patches.GameObjects
} }
} }
foreach (AlmanacCardUI almanacCardUI in __instance.GetComponentsInChildren<AlmanacCardUI>())
{
AlmanacCardUI_Patch.Awake(almanacCardUI);
}
// skin button resize // skin button resize
AlmanacPlantWindow window = __instance.window; AlmanacPlantWindow window = __instance.window;
GameObject skinButton = window.skinButton; GameObject skinButton = window.skinButton;
GameObject skinTextObj = skinButton.transform.GetChild(0).gameObject; GameObject skinTextObj = skinButton.transform.Find("text_1").gameObject;
GameObject skinShadowTextObj = skinTextObj.transform.GetChild(0).gameObject;
TextMeshProUGUI skinShadowText = skinShadowTextObj.GetComponent<TextMeshProUGUI>();
skinShadowText.text = StringStore.TranslateText("换肤_S");
skinButton.transform.localScale /= 1.75f; skinButton.transform.localScale /= 1.75f;
skinButton.transform.localPosition = new Vector3(0.0f, 111.345f, 0.0f); skinButton.transform.localPosition = new Vector3(0.0f, 111.345f, 0.0f);
skinButton.transform.GetChild(1).Translate(new Vector3(-0.35f, 0)); skinButton.transform.GetChild(1).Translate(new Vector3(-0.35f, 0));
@ -63,7 +69,7 @@ namespace PvZ_Fusion_Translator.Patches.GameObjects
TMP_FontAsset fontAsset = FontStore.LoadTMPFont(currentLanguage); TMP_FontAsset fontAsset = FontStore.LoadTMPFont(currentLanguage);
PlantData plantData = JsonUtility.FromJson<PlantData>(json); AlmanacData plantData = JsonUtility.FromJson<AlmanacData>(json);
Il2CppSystem.Collections.Generic.List<PlantType> searchedPlants = new(); Il2CppSystem.Collections.Generic.List<PlantType> searchedPlants = new();
@ -73,6 +79,10 @@ namespace PvZ_Fusion_Translator.Patches.GameObjects
{ {
searchedPlants.Add((PlantType)plantInfo.seedType); searchedPlants.Add((PlantType)plantInfo.seedType);
} }
else if ($"{plantInfo.seedType}".ToLower().StartsWith(search.ToLower()))
{
searchedPlants.Add((PlantType)plantInfo.seedType);
}
} }
__instance.ShowPlants(searchedPlants); __instance.ShowPlants(searchedPlants);
@ -82,5 +92,46 @@ namespace PvZ_Fusion_Translator.Patches.GameObjects
return true; return true;
} }
[HarmonyPatch(nameof(AlmanacPlantMenu.ShowPlants), argumentTypes: [typeof(Il2CppSystem.Func<PlantType, bool>)])]
[HarmonyPostfix]
public static void ShowPlants(AlmanacPlantMenu __instance, ref Func<PlantType, bool> condition)
{
foreach (AlmanacCardUI cardUI in __instance.cards)
{
AlmanacCardUI_Patch.Awake(cardUI);
}
}
[HarmonyPatch(nameof(AlmanacPlantMenu.ClassicMix))]
[HarmonyPostfix]
public static void ClassicMix(AlmanacPlantMenu __instance)
{
foreach (AlmanacCardUI cardUI in __instance.cards)
{
AlmanacCardUI_Patch.Awake(cardUI);
}
}
public static void LoadPlantAlmanacData(string json)
{
if (json == null) return;
almanacJson = json;
var plantData = JsonUtility.FromJson<Il2CppAlmanacData.AlmanacData>(almanacJson);
foreach (Il2CppAlmanacData.PlantInfo plantInfo in plantData.plants)
{
if(plantInfoDict.ContainsKey(plantInfo.seedType))
{
plantInfoDict[plantInfo.seedType] = plantInfo;
}
else
{
plantInfoDict.Add(plantInfo.seedType, plantInfo);
}
}
}
} }
} }

View file

@ -1,5 +1,6 @@
using HarmonyLib; using HarmonyLib;
using Il2Cpp; using Il2Cpp;
using Il2CppAlmanacData;
using Il2CppTMPro; using Il2CppTMPro;
using PvZ_Fusion_Translator.AssetStore; using PvZ_Fusion_Translator.AssetStore;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
@ -26,7 +27,7 @@ namespace PvZ_Fusion_Translator.Patches.GameObjects
bool hasAlmanacFont = false; bool hasAlmanacFont = false;
TMP_FontAsset almanacFontAsset = null; TMP_FontAsset almanacFontAsset = null;
if (FontStore.fontAssetDictSecondary.ContainsKey(currentLanguage + "_Almanac") || FontStore.fontAssetDictSecondary.ContainsKey(currentLanguage)) if (FontStore.fontAssetDictSecondary.ContainsKey((currentLanguage + "_almanac").ToLower()) || FontStore.fontAssetDictSecondary.ContainsKey((currentLanguage).ToLower()))
{ {
almanacFontAsset = FontStore.LoadTMPFontAlmanac(currentLanguage); almanacFontAsset = FontStore.LoadTMPFontAlmanac(currentLanguage);
hasAlmanacFont = true; hasAlmanacFont = true;
@ -34,35 +35,34 @@ namespace PvZ_Fusion_Translator.Patches.GameObjects
TMP_FontAsset fontAsset = (hasAlmanacFont) ? FontStore.LoadTMPFontAlmanac(Utils.Language.ToString()) : FontStore.LoadTMPFont(Utils.Language.ToString()); TMP_FontAsset fontAsset = (hasAlmanacFont) ? FontStore.LoadTMPFontAlmanac(Utils.Language.ToString()) : FontStore.LoadTMPFont(Utils.Language.ToString());
AlmanacPlantBank.PlantData plantData = JsonUtility.FromJson<AlmanacPlantBank.PlantData>(json); AlmanacData plantData = JsonUtility.FromJson<AlmanacData>(json);
foreach (AlmanacPlantBank.PlantInfo plantInfo in plantData.plants) if(AlmanacPlantMenu_Patch.plantInfoDict.ContainsKey((int)__instance.currentPlantType))
{ {
if (plantInfo.seedType == (int)__instance.currentPlantType) PlantInfo plantInfo = AlmanacPlantMenu_Patch.plantInfoDict[(int)__instance.currentPlantType];
foreach (TextMeshProUGUI text in __instance.showedPlantName)
{ {
foreach (TextMeshProUGUI text in __instance.showedPlantName) text.autoSizeTextContainer = false;
{ text.text = $"{Utils.RemoveSizeTags(plantInfo.name)} ({plantInfo.seedType})";
text.autoSizeTextContainer = false; text.font = fontAsset;
text.text = $"{Utils.RemoveSizeTags(plantInfo.name)} ({plantInfo.seedType})"; text.fontSizeMax = 21;
text.font = fontAsset;
text.fontSizeMax = 21;
}
char[] toTrim = Environment.NewLine.ToCharArray();
__instance.showedPlantIntroduce.text = Utils.RemoveSizeTags(plantInfo.info) + "\n\n" + Utils.RemoveSizeTags(plantInfo.introduce) + "\n\n" + Utils.RemoveSizeTags(plantInfo.cost).TrimStart(toTrim) + "\n\n";
__instance.showedPlantIntroduce.font = fontAsset;
__instance.showedPlantIntroduce.fontSizeMax = 21;
__instance.showedPlantIntroduce.margin = new Vector4(6, 2, 12, 0);
__instance.showedPlantIntroduce.enableWordWrapping = true;
__instance.showedPlantIntroduce.overflowMode = TextOverflowModes.ScrollRect;
Canvas.ForceUpdateCanvases();
__instance.showedPlantIntroduce.ForceMeshUpdate();
float textHeight = __instance.showedPlantIntroduce.preferredHeight;
__instance.plantTextContent.sizeDelta = new Vector2(__instance.plantTextContent.sizeDelta.x, textHeight);
} }
char[] toTrim = Environment.NewLine.ToCharArray();
__instance.showedPlantIntroduce.text = Utils.RemoveSizeTags(plantInfo.info) + "\n\n" + Utils.RemoveSizeTags(plantInfo.introduce) + "\n\n" + Utils.RemoveSizeTags(plantInfo.cost).TrimStart(toTrim) + "\n\n";
__instance.showedPlantIntroduce.font = fontAsset;
__instance.showedPlantIntroduce.fontSizeMax = 21;
__instance.showedPlantIntroduce.margin = new Vector4(6, 2, 12, 0);
__instance.showedPlantIntroduce.enableWordWrapping = true;
__instance.showedPlantIntroduce.overflowMode = TextOverflowModes.ScrollRect;
Canvas.ForceUpdateCanvases();
__instance.showedPlantIntroduce.ForceMeshUpdate();
float textHeight = __instance.showedPlantIntroduce.preferredHeight;
__instance.plantTextContent.sizeDelta = new Vector2(__instance.plantTextContent.sizeDelta.x, textHeight);
} }
} }
} }

View file

@ -0,0 +1,56 @@
using HarmonyLib;
using Il2Cpp;
using Il2CppAlmanacData;
using Il2CppTMPro;
using PvZ_Fusion_Translator.AssetStore;
using System.Text.RegularExpressions;
using Unity.Collections;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.UIElements;
using static PvZ_Fusion_Translator.FileLoader;
using static PvZ_Fusion_Translator.Utils;
namespace PvZ_Fusion_Translator.Patches.GameObjects
{
[HarmonyPatch(typeof(AlmanacSelectMenu))]
public static class AlmanacSelectMenu_Patch
{
public static Dictionary<string, string> detailStrings = new Dictionary<string, string>();
public static Dictionary<string, string> detailTranslateStrings = new Dictionary<string, string>();
[HarmonyPatch(nameof(AlmanacSelectMenu.Awake))]
[HarmonyPostfix]
public static void Awake(AlmanacSelectMenu __instance)
{
TranslateAlmanacSelectMenu(__instance);
foreach(UIButton uiButton in __instance.GetComponentsInChildren<UIButton>())
{
if(uiButton.gameObject.name.Contains("Selection(Clone)"))
{
uiButton.clickEvent.AddListener(new Action(() => { TranslateAlmanacSelectMenu(__instance); }));
}
}
}
[HarmonyPatch(nameof(AlmanacSelectMenu.InitMenu))]
[HarmonyPostfix]
public static void InitMenu(AlmanacSelectMenu __instance)
{
TranslateAlmanacSelectMenu(__instance);
}
public static void TranslateAlmanacSelectMenu(AlmanacSelectMenu __instance)
{
TMP_FontAsset font = FontStore.LoadTMPFont(Utils.Language.ToString());
foreach(TextMeshProUGUI txt in __instance.GetComponentsInChildren<TextMeshProUGUI>())
{
txt.text = detailTranslateStrings.ContainsKey(txt.text) ? detailTranslateStrings[txt.text] : StringStore.TranslateText(txt.text);
txt.font = font;
}
}
}
}

View file

@ -16,13 +16,15 @@ namespace PvZ_Fusion_Translator.Patches.GameObjects
{ {
public static string almanacJson = ""; public static string almanacJson = "";
[HarmonyPatch(nameof(AlmanacZombieMenu.Awake))] [HarmonyPatch(nameof(AlmanacZombieMenu.Start))]
[HarmonyPostfix] [HarmonyPostfix]
private static void Awake(AlmanacZombieMenu __instance) private static void Start(AlmanacZombieMenu __instance)
{ {
TMP_FontAsset font = FontStore.LoadTMPFont(Utils.Language.ToString()); TMP_FontAsset font = FontStore.LoadTMPFont(Utils.Language.ToString());
foreach (TextMeshProUGUI text in __instance.GetComponentsInChildren<TextMeshProUGUI>(true)) foreach (TextMeshProUGUI text in __instance.GetComponentsInChildren<TextMeshProUGUI>(true))
{ {
if (text.gameObject.name.Contains("Cost")) continue;
bool isZombieName = text.gameObject.name.Contains("Name") && text.transform.parent.name != "Background"; bool isZombieName = text.gameObject.name.Contains("Name") && text.transform.parent.name != "Background";
if (text.gameObject.name != "Description" && !isZombieName) if (text.gameObject.name != "Description" && !isZombieName)
{ {

View file

@ -25,7 +25,7 @@ namespace PvZ_Fusion_Translator.Patches.GameObjects
bool hasAlmanacFont = false; bool hasAlmanacFont = false;
TMP_FontAsset almanacFontAsset = null; TMP_FontAsset almanacFontAsset = null;
if (FontStore.fontAssetDictSecondary.ContainsKey(currentLanguage + "_Almanac") || FontStore.fontAssetDictSecondary.ContainsKey(currentLanguage)) if (FontStore.fontAssetDictSecondary.ContainsKey((currentLanguage + "_almanac").ToLower()) || FontStore.fontAssetDictSecondary.ContainsKey((currentLanguage).ToLower()))
{ {
almanacFontAsset = FontStore.LoadTMPFontAlmanac(currentLanguage); almanacFontAsset = FontStore.LoadTMPFontAlmanac(currentLanguage);
hasAlmanacFont = true; hasAlmanacFont = true;
@ -33,10 +33,10 @@ namespace PvZ_Fusion_Translator.Patches.GameObjects
TMP_FontAsset fontAsset = (hasAlmanacFont) ? FontStore.LoadTMPFontAlmanac(Utils.Language.ToString()) : FontStore.LoadTMPFont(Utils.Language.ToString()); TMP_FontAsset fontAsset = (hasAlmanacFont) ? FontStore.LoadTMPFontAlmanac(Utils.Language.ToString()) : FontStore.LoadTMPFont(Utils.Language.ToString());
ZombieAlmanacData zombieAlmanacData = JsonUtility.FromJson<ZombieAlmanacData>(json); Il2CppAlmanacData.AlmanacData zombieAlmanacData = JsonUtility.FromJson<Il2CppAlmanacData.AlmanacData>(json);
var zombieDataDic = ZombieDataManager.zombieDataDic; var zombieDataDic = ZombieDataManager.zombieDataDic;
foreach (ZombieInfo zombieInfo in zombieAlmanacData.zombies) foreach (Il2CppAlmanacData.ZombieInfo zombieInfo in zombieAlmanacData.zombies)
{ {
if (zombieInfo.theZombieType == __instance.currentZombieType) if (zombieInfo.theZombieType == __instance.currentZombieType)
{ {

View file

@ -18,12 +18,12 @@ namespace PvZ_Fusion_Translator.Patches.GameObjects
TranslateAlmanacMenu(__instance); TranslateAlmanacMenu(__instance);
} }
[HarmonyPatch(nameof(Almanac.OldAlmanac))] /*[HarmonyPatch(nameof(Almanac.OldAlmanac))]
[HarmonyPostfix] [HarmonyPostfix]
private static void OldAlmanac(Almanac __instance) private static void OldAlmanac(Almanac __instance)
{ {
TranslateAlmanacMenu(__instance); TranslateAlmanacMenu(__instance);
} }*/
[HarmonyPatch(nameof(Almanac.AnimSwitch))] [HarmonyPatch(nameof(Almanac.AnimSwitch))]
[HarmonyPostfix] [HarmonyPostfix]
@ -37,6 +37,8 @@ namespace PvZ_Fusion_Translator.Patches.GameObjects
TMP_FontAsset font = FontStore.LoadTMPFont(Utils.Language.ToString()); TMP_FontAsset font = FontStore.LoadTMPFont(Utils.Language.ToString());
foreach (TextMeshProUGUI text in __instance.GetComponentsInChildren<TextMeshProUGUI>()) foreach (TextMeshProUGUI text in __instance.GetComponentsInChildren<TextMeshProUGUI>())
{ {
if (text.gameObject.name.Contains("Cost")) continue;
if(text.text == "关闭") if(text.text == "关闭")
{ {
text.text = StringStore.TranslateText("合上"); text.text = StringStore.TranslateText("合上");

View file

@ -1,5 +1,6 @@
using HarmonyLib; using HarmonyLib;
using Il2Cpp; using Il2Cpp;
using Il2CppAlmanacData;
using Il2CppTMPro; using Il2CppTMPro;
using PvZ_Fusion_Translator.AssetStore; using PvZ_Fusion_Translator.AssetStore;
using UnityEngine; using UnityEngine;
@ -34,12 +35,20 @@ namespace PvZ_Fusion_Translator.Patches.GameObjects
MainMenu_Patch.AnimOver(__instance); MainMenu_Patch.AnimOver(__instance);
} }
TranslateBaseMenu(__instance, "Level"); if(__instance.name.StartsWith("PlantDamageMenu"))
TranslateBaseMenu(__instance, "Levels"); {
TranslateBaseMenu(__instance, "CustomLevel"); PlantDamageMenu_Patch.Awake(__instance);
}
TranslateBaseMenuTransform(__instance, "Level");
TranslateBaseMenuTransform(__instance, "Levels");
TranslateBaseMenuTransform(__instance, "CustomLevel");
StringStore.TranslateTextTransform(__instance.transform.Find("Goback"));
StringStore.TranslateTextTransform(__instance.transform.Find("Switich"));
} }
public static void TranslateBaseMenu(BaseMenu __instance, string levelsName) public static void TranslateBaseMenuTransform(BaseMenu __instance, string levelsName)
{ {
Transform levels = __instance.transform.Find(levelsName); Transform levels = __instance.transform.Find(levelsName);
if (levels != null) if (levels != null)
@ -52,9 +61,6 @@ namespace PvZ_Fusion_Translator.Patches.GameObjects
StringStore.TranslateTextTransform(child); StringStore.TranslateTextTransform(child);
} }
} }
StringStore.TranslateTextTransform(__instance.transform.Find("Goback"));
StringStore.TranslateTextTransform(__instance.transform.Find("Switich"));
} }
} }
} }

View file

@ -9,9 +9,9 @@ namespace PvZ_Fusion_Translator.Patches.GameObjects.ButtonObjects
[HarmonyPatch(typeof(InGameBtn))] [HarmonyPatch(typeof(InGameBtn))]
public static class InGameBtn_Patch public static class InGameBtn_Patch
{ {
[HarmonyPatch(nameof(InGameBtn.Update))] [HarmonyPatch(nameof(InGameBtn.Start))]
[HarmonyPostfix] [HarmonyPostfix]
private static void Update(InGameBtn __instance) private static void Start(InGameBtn __instance)
{ {
Transform sceneText = __instance.transform.FindChild("SceneText"); Transform sceneText = __instance.transform.FindChild("SceneText");
if(sceneText != null) if(sceneText != null)

View file

@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HarmonyLib;
using Il2Cpp;
using Il2CppTMPro;
using PvZ_Fusion_Translator.AssetStore;
using UnityEngine;
namespace PvZ_Fusion_Translator.Patches.GameObjects.ButtonObjects
{
public static class LevelSaveEnter_Patch
{
public static void TranslateEnter(LevelSaveEnter __instance)
{
TMP_FontAsset fontAsset = FontStore.LoadTMPFont(Utils.Language.ToString());
__instance.text.text = StringStore.TranslateText(__instance.text.text);
__instance.text.font = fontAsset;
}
}
}

View file

@ -1,4 +1,4 @@
using HarmonyLib; /*using HarmonyLib;
using Il2Cpp; using Il2Cpp;
using Il2CppTMPro; using Il2CppTMPro;
using UnityEngine; using UnityEngine;
@ -34,3 +34,4 @@ namespace PvZ_Fusion_Translator.Patches.GameObjects.ButtonObjects
} }
} }
*/

View file

@ -137,7 +137,8 @@ namespace PvZ_Fusion_Translator.Patches.GameObjects.ButtonObjects
data.IsNextButton = false; data.IsNextButton = false;
btn.gameObject.SetActive(true); btn.gameObject.SetActive(true);
UpdateButtonText(btn, Utils.LanguageNames[lang], FontStore.LoadTMPFont(lang.ToString())); string languageName = Utils.LanguageNames.ContainsKey(lang) ? Utils.LanguageNames[lang] : lang.ToString();
UpdateButtonText(btn, languageName, FontStore.LoadTMPFont(lang.ToString()));
} }
else else
{ {
@ -160,12 +161,25 @@ namespace PvZ_Fusion_Translator.Patches.GameObjects.ButtonObjects
data.Toggle = toggle; data.Toggle = toggle;
data.IsNextButton = false; data.IsNextButton = false;
btn.gameObject.SetActive(true); btn.gameObject.SetActive(true);
string buttonText = Utils.ToggleNames[toggle]; string buttonText = Utils.ToggleNames.ContainsKey(toggle) ? Utils.ToggleNames[toggle] : toggle.ToString();
UpdateButtonText(btn, StringStore.TranslateText(buttonText), FontStore.LoadTMPFont(Utils.Language.ToString())); UpdateButtonText(btn, StringStore.TranslateText(buttonText), FontStore.LoadTMPFont(Utils.Language.ToString()));
if(i == 2) string sourceMsg = "";
switch(i)
{ {
string sourceMsg = "<size=10>" + (!(Utils.useLocal) ? "Translation Source:\nOnline" : "Translation Source:\nLocal"); case 0:
FlashMessage(btn, sourceMsg, 0.1f, false); sourceMsg = "<size=10>" + (!(Utils.customTextures) ? "Texture Source:\nDefault" : "Texture Source:\nCustom");
FlashMessage(btn, sourceMsg, 0.1f, false);
break;
case 1:
sourceMsg = "<size=10>" + (!(Utils.customAudio) ? "Audio Source:\nDefault" : "Audio Source:\nCustom");
FlashMessage(btn, sourceMsg, 0.1f, false);
break;
case 2:
sourceMsg = "<size=10>" + (!(Utils.useLocal) ? "Translation Source:\nOnline" : "Translation Source:\nLocal");
FlashMessage(btn, sourceMsg, 0.1f, false);
break;
default:
break;
} }
} }
else else
@ -223,8 +237,10 @@ namespace PvZ_Fusion_Translator.Patches.GameObjects.ButtonObjects
if (child != null) if (child != null)
{ {
var text = child.GetComponent<TextMeshProUGUI>(); var text = child.GetComponent<TextMeshProUGUI>();
string originalMsg = "";
if (text != null) if (text != null)
{ {
originalMsg = text.text;
text.text = message; text.text = message;
OptionButtonData data; OptionButtonData data;
bool isToggle = ToggleBtnDict.TryGetValue(button.GetInstanceID(), out data); bool isToggle = ToggleBtnDict.TryGetValue(button.GetInstanceID(), out data);
@ -248,7 +264,24 @@ namespace PvZ_Fusion_Translator.Patches.GameObjects.ButtonObjects
{ {
if (button != null && child != null && child.gameObject.activeSelf) if (button != null && child != null && child.gameObject.activeSelf)
{ {
child.gameObject.SetActive(false); OptionButtonData buttonData = ToggleBtnDict[button.GetInstanceID()];
if(buttonData.Toggle != null)
{
string sourceMsg = originalMsg;
switch(buttonData.Toggle)
{
case Utils.ToggleEnum.Textures:
sourceMsg = "<size=10>" + (!(Utils.customTextures) ? "Texture Source:\nDefault" : "Texture Source:\nCustom");
break;
case Utils.ToggleEnum.Audio:
sourceMsg = "<size=10>" + (!(Utils.customAudio) ? "Audio Source:\nDefault" : "Audio Source:\nCustom");
break;
default:
break;
}
text.text = sourceMsg;
}
} }
}); });
} }
@ -329,14 +362,14 @@ namespace PvZ_Fusion_Translator.Patches.GameObjects.ButtonObjects
{ {
string toggleType = toggleData.Toggle.ToString(); string toggleType = toggleData.Toggle.ToString();
ToggleCustomAssets(toggleType); ToggleCustomAssets(toggleType);
if (toggleType == "Textures") if (toggleType == "Textures")
{ {
FlashMessage(toggleData.Button, "<size=10>Toggled custom textures!", 0.1f); FlashMessage(toggleData.Button, "<size=10>Toggled custom textures!\n(Restart Required)", 0.1f);
} }
else if (toggleType == "Audio") else if (toggleType == "Audio")
{ {
FlashMessage(toggleData.Button, "<size=10>Toggled custom audio!", 0.1f); FlashMessage(toggleData.Button, "<size=10>Toggled custom audio!", 0.1f);
} }
} }
} }

View file

@ -1,12 +1,13 @@
using HarmonyLib; using HarmonyLib;
using Il2Cpp; using Il2Cpp;
using Il2CppPVPScaryPot;
using Il2CppTMPro; using Il2CppTMPro;
using PvZ_Fusion_Translator.AssetStore; using PvZ_Fusion_Translator.AssetStore;
using UnityEngine; using UnityEngine;
namespace PvZ_Fusion_Translator.Patches.GameObjects.ButtonObjects namespace PvZ_Fusion_Translator.Patches.GameObjects.ButtonObjects
{ {
[HarmonyPatch(typeof(PVPPotBtn))] /*[HarmonyPatch(typeof(PVPPotBtn))]
public class PVPPotBtn_Patch public class PVPPotBtn_Patch
{ {
[HarmonyPostfix] [HarmonyPostfix]
@ -38,5 +39,5 @@ namespace PvZ_Fusion_Translator.Patches.GameObjects.ButtonObjects
__instance.gameObject.SetActive(true); __instance.gameObject.SetActive(true);
} }
} }
} }*/
} }

View file

@ -46,40 +46,11 @@ namespace PvZ_Fusion_Translator.Patches.GameObjects
[HarmonyPostfix] [HarmonyPostfix]
public static void Postfix_OnMouseUpAsButton(UIButton __instance) public static void Postfix_OnMouseUpAsButton(UIButton __instance)
{ {
try foreach(TextMeshProUGUI txt in __instance.GetComponentsInChildren<TextMeshProUGUI>())
{ {
if (__instance.transform.childCount >= 2) txt.text = StringStore.TranslateText(txt.text);
{ txt.font = FontStore.LoadTMPFont(Utils.Language.ToString());
if (__instance.name == "EditMode")
{
TMP_FontAsset fontAsset = FontStore.LoadTMPFont(Utils.Language.ToString());
TextMeshProUGUI text = __instance.transform.GetChild(0).GetComponent<TextMeshProUGUI>();
TextMeshProUGUI[] extraTexts = __instance.transform.GetChild(1).GetComponentsInChildren<TextMeshProUGUI>();
text.text = StringStore.TranslateText(text.text, false);
text.font = fontAsset;
foreach (TextMeshProUGUI extraText in extraTexts)
{
extraText.text = StringStore.TranslateText(extraText.text, false);
extraText.font = fontAsset;
}
}
else
{
TextMeshProUGUI text = __instance.transform.GetChild(0).GetComponent<TextMeshProUGUI>();
TextMeshProUGUI textShadow = __instance.transform.GetChild(1).GetComponent<TextMeshProUGUI>();
text.text = StringStore.TranslateText(text.text, false);
textShadow.text = StringStore.TranslateText(textShadow.text, false);
text.font = FontStore.LoadTMPFont(Utils.Language.ToString());
textShadow.font = FontStore.LoadTMPFont(Utils.Language.ToString());
}
}
} }
catch (Exception) { }
} }
} }
} }

View file

@ -1,4 +1,4 @@
using HarmonyLib; /*using HarmonyLib;
using Il2Cpp; using Il2Cpp;
using Il2CppTMPro; using Il2CppTMPro;
using PvZ_Fusion_Translator.AssetStore; using PvZ_Fusion_Translator.AssetStore;
@ -50,3 +50,4 @@ namespace PvZ_Fusion_Translator.Patches.GameObjects
} }
} }
} }
*/

View file

@ -1,24 +1,24 @@
using HarmonyLib; //using HarmonyLib;
using Il2Cpp; //using Il2Cpp;
using PvZ_Fusion_Translator.AssetStore; //using PvZ_Fusion_Translator.AssetStore;
namespace PvZ_Fusion_Translator.Patches.GameObjects //namespace PvZ_Fusion_Translator.Patches.GameObjects
{ //{
[HarmonyPatch(typeof(CustomSettings))] // [HarmonyPatch(typeof(CustomSettings))]
public static class CustomSettings_Patch // public static class CustomSettings_Patch
{ // {
[HarmonyPatch(nameof(CustomSettings.Awake))] // [HarmonyPatch(nameof(CustomSettings.Awake))]
[HarmonyPostfix] // [HarmonyPostfix]
private static void Awake(CustomSettings __instance) // private static void Awake(CustomSettings __instance)
{ // {
__instance.textMesh = StringStore.TranslateText(__instance.textMesh); // __instance.textMesh = StringStore.TranslateText(__instance.textMesh);
} // }
[HarmonyPatch(nameof(CustomSettings.ChangeText))] // [HarmonyPatch(nameof(CustomSettings.ChangeText))]
[HarmonyPostfix] // [HarmonyPostfix]
private static void ChangeText(CustomSettings __instance) // private static void ChangeText(CustomSettings __instance)
{ // {
__instance.textMesh = StringStore.TranslateText(__instance.textMesh); // __instance.textMesh = StringStore.TranslateText(__instance.textMesh);
} // }
} // }
} //}

View file

@ -1,4 +1,4 @@
using HarmonyLib; /*using HarmonyLib;
using Il2Cpp; using Il2Cpp;
using Il2CppTMPro; using Il2CppTMPro;
using PvZ_Fusion_Translator.AssetStore; using PvZ_Fusion_Translator.AssetStore;
@ -43,3 +43,4 @@ namespace PvZ_Fusion_Translator.Patches.GameObjects
} }
} }
} }
*/

View file

@ -2,6 +2,7 @@
using Il2Cpp; using Il2Cpp;
using PvZ_Fusion_Translator.AssetStore; using PvZ_Fusion_Translator.AssetStore;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using Il2CppZenGarden;
namespace PvZ_Fusion_Translator.Patches.GameObjects namespace PvZ_Fusion_Translator.Patches.GameObjects
{ {

View file

@ -0,0 +1,40 @@
using HarmonyLib;
using Il2Cpp;
using Il2CppAlmanacData;
using Il2CppTMPro;
using PvZ_Fusion_Translator.AssetStore;
using UnityEngine;
using System.Drawing;
using Il2CppZenGarden;
namespace PvZ_Fusion_Translator.Patches.GameObjects
{
[HarmonyPatch(typeof(GardenStoreMenu))]
public static class GardenStoreMenu_Patch
{
[HarmonyPatch(nameof(GardenStoreMenu.InitGoodsList))]
[HarmonyPatch(nameof(GardenStoreMenu.GetDatas))]
[HarmonyPatch(nameof(GardenStoreMenu.PurchaseGoods))]
[HarmonyPatch(nameof(GardenStoreMenu.Update))]
[HarmonyPatch(nameof(GardenStoreMenu.Start))]
[HarmonyPostfix]
public static void TranslateGardenStoreMenu(GardenStoreMenu __instance)
{
foreach(GardenShopSlot slot in __instance.GetComponentsInChildren<GardenShopSlot>())
{
TranslateGardenShopSlot(slot);
}
}
[HarmonyPatch(nameof(GardenShopSlot.Start))]
[HarmonyPostfix]
public static void TranslateGardenShopSlot(GardenShopSlot __instance)
{
foreach(TextMeshProUGUI txt in __instance.GetComponentsInChildren<TextMeshProUGUI>())
{
txt.text = StringStore.TranslateText(txt.text);
txt.font = FontStore.LoadTMPFont(Utils.Language.ToString());
}
}
}
}

View file

@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Il2Cpp;
using UnityEngine;
using HarmonyLib;
using Il2CppTMPro;
using PvZ_Fusion_Translator.AssetStore;
namespace PvZ_Fusion_Translator.Patches.GameObjects
{
[HarmonyPatch(typeof(LevelResultMenu))]
public static class LevelResultMenu_Patch
{
[HarmonyPatch(nameof(LevelResultMenu.Start))]
[HarmonyPatch(nameof(LevelResultMenu.ShowResult))]
[HarmonyPostfix]
public static void Awake(LevelResultMenu __instance)
{
foreach (TextMeshProUGUI txt in __instance.GetComponentsInChildren<TextMeshProUGUI>())
{
txt.text = StringStore.TranslateText(txt.text);
}
}
}
}

View file

@ -11,13 +11,15 @@ using UnityEngine.UIElements;
namespace PvZ_Fusion_Translator.Patches.GameObjects namespace PvZ_Fusion_Translator.Patches.GameObjects
{ {
[HarmonyPatch(typeof(MainMenu))]
public class MainMenu_Patch public class MainMenu_Patch
{ {
public static void AnimOver(BaseMenu __instance) public static void AnimOver(BaseMenu __instance)
{ {
Transform changelogObj = __instance.transform.Find("Grave/UpdateInfo"); Transform changelogObj = __instance.transform.Find("Grave/UpdateInfoButton");
Transform langObj = UnityEngine.Object.Instantiate(changelogObj, changelogObj.position + new Vector3(0.0f, 0.855f), changelogObj.rotation, __instance.transform.Find("Grave")); Transform langObj = UnityEngine.Object.Instantiate(changelogObj, changelogObj.position + new Vector3(0.0f, 0.855f), changelogObj.rotation, __instance.transform.Find("Grave"));
langObj.name = "Languages"; langObj.name = "LanguagesButton";
__instance.collider2Ds.Add(langObj.GetComponent<Collider2D>());
UIButton langBtn = langObj.GetComponent<UIButton>(); UIButton langBtn = langObj.GetComponent<UIButton>();
foreach(TextMeshProUGUI text in langObj.GetComponentsInChildren<TextMeshProUGUI>()) foreach(TextMeshProUGUI text in langObj.GetComponentsInChildren<TextMeshProUGUI>())
@ -27,7 +29,6 @@ namespace PvZ_Fusion_Translator.Patches.GameObjects
langBtn.clickEvent = new UnityEvent(); langBtn.clickEvent = new UnityEvent();
langBtn.clickEvent.AddListener(new Action(() => OpenLanguageMenu(langBtn.gameObject))); langBtn.clickEvent.AddListener(new Action(() => OpenLanguageMenu(langBtn.gameObject)));
langBtn.clickEvent.AddListener(new Action(() => HideLangButton(langBtn.gameObject)));
} }
public static void OpenLanguageMenu(GameObject langBtn) public static void OpenLanguageMenu(GameObject langBtn)
@ -45,13 +46,13 @@ namespace PvZ_Fusion_Translator.Patches.GameObjects
} }
} }
OptionBtn templateButton = newOptionsMenu.transform.Find("F").GetComponent<OptionBtn>(); OptionBtn templateButton = newOptionsMenu.transform.Find("Buttons/F").GetComponent<OptionBtn>();
OptLanguageBtn_Patch.OptLangBtn_Patch.Awake(templateButton); OptLanguageBtn_Patch.OptLangBtn_Patch.Awake(templateButton);
UIButton goBackButton = newOptionsMenu.transform.Find("Goback").GetComponent<UIButton>(); UIButton goBackButton = newOptionsMenu.transform.Find("Goback").GetComponent<UIButton>();
goBackButton.clickEvent.AddListener(new Action(() => ShowLangButton(langBtn.gameObject)));
newOptionsMenu.transform.Find("F").gameObject.SetActive(false); newOptionsMenu.transform.Find("Buttons/F").gameObject.SetActive(false);
newOptionsMenu.transform.Find("Buttons").gameObject.SetActive(true);
foreach (TextMeshProUGUI text in newOptionsMenu.transform.Find("Background").GetComponentsInChildren<TextMeshProUGUI>()) foreach (TextMeshProUGUI text in newOptionsMenu.transform.Find("Background").GetComponentsInChildren<TextMeshProUGUI>())
{ {
@ -93,14 +94,16 @@ namespace PvZ_Fusion_Translator.Patches.GameObjects
messageText.text = "Hello this is multilanguage choose language over there ------>";*/ messageText.text = "Hello this is multilanguage choose language over there ------>";*/
} }
public static void HideLangButton(GameObject btn) [HarmonyPatch(nameof(MainMenu.EnterUpdateUrl))]
[HarmonyPrefix]
public static bool Pre_EnterUpdateUrl(MainMenu __instance)
{ {
btn.GetComponent<BoxCollider2D>().enabled = false; System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo
} {
FileName = @"https://github.com/Teyliu/PVZF-Translation",
public static void ShowLangButton(GameObject btn) UseShellExecute = true
{ });
btn.GetComponent<BoxCollider2D>().enabled = true; return false;
} }
} }
} }

View file

@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HarmonyLib;
using UnityEngine;
using Il2Cpp;
using Il2CppCore;
using PvZ_Fusion_Translator.Patches.BaseTextObjects;
namespace PvZ_Fusion_Translator.Patches.GameObjects.MinorObjects
{
[HarmonyPatch(typeof(GameLose))]
public static class GameLose_Patch
{
[HarmonyPatch(nameof(GameLose.UpdateSecondChanceTimer))]
public static void UpdateSecondChanceTimer(GameLose __instance)
{
if (InGameText.Instance == null) return;
if (InGameText.Instance.timer < 0) return;
InGameText_Patch.TranslateInGameText(InGameText.Instance);
}
}
}

View file

@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Il2Cpp;
using HarmonyLib;
using UnityEngine;
using Il2CppTMPro;
using PvZ_Fusion_Translator.AssetStore;
using Unity.VisualScripting;
namespace PvZ_Fusion_Translator.Patches.GameObjects.MinorObjects
{
[HarmonyPatch(typeof(HealthSlider))]
public static class HealthSlider_Patch
{
public static TMP_FontAsset fontAsset = null;
[HarmonyPatch(nameof(HealthSlider.Start))]
[HarmonyPostfix]
public static void Post_Start(HealthSlider __instance)
{
if(!fontAsset)
{
fontAsset = FontStore.LoadTMPFont(Utils.Language.ToString());
}
}
[HarmonyPatch(nameof(HealthSlider.UpdateText))]
[HarmonyPostfix]
public static void Post_UpdateText(HealthSlider __instance)
{
if(!fontAsset) fontAsset = FontStore.LoadTMPFont(Utils.Language.ToString());
if (__instance.healthText.font != fontAsset) __instance.healthText.font = fontAsset;
foreach(TextMeshProUGUI txt in __instance.healthTextContainer.GetComponentsInChildren<TextMeshProUGUI>(true))
{
txt.text = StringStore.TranslateText(txt.text);
txt.font = fontAsset;
}
}
}
}

View file

@ -4,7 +4,7 @@ using PvZ_Fusion_Translator.AssetStore;
namespace PvZ_Fusion_Translator.Patches.GameObjects.MinorObjects namespace PvZ_Fusion_Translator.Patches.GameObjects.MinorObjects
{ {
[HarmonyPatch(typeof(LanternUmbrella))] /*[HarmonyPatch(typeof(LanternUmbrella))]
public class LanternUmbrella_Patch public class LanternUmbrella_Patch
{ {
[HarmonyPostfix] [HarmonyPostfix]
@ -14,5 +14,5 @@ namespace PvZ_Fusion_Translator.Patches.GameObjects.MinorObjects
__instance.energyText = StringStore.TranslateText(__instance.energyText); __instance.energyText = StringStore.TranslateText(__instance.energyText);
__instance.energyTextShadow = StringStore.TranslateText(__instance.energyTextShadow); __instance.energyTextShadow = StringStore.TranslateText(__instance.energyTextShadow);
} }
} }*/
} }

View file

@ -11,6 +11,7 @@ namespace PvZ_Fusion_Translator.Patches.GameObjects.MinorObjects
[HarmonyPatch(nameof(Money.Update))] [HarmonyPatch(nameof(Money.Update))]
private static void Update(Money __instance) private static void Update(Money __instance)
{ {
if (!Utils.CheckForUntranslatedText(__instance.beanCount.text)) return;
__instance.beanCount.text = StringStore.TranslateText(__instance.beanCount.text); __instance.beanCount.text = StringStore.TranslateText(__instance.beanCount.text);
__instance.beanCount2.text = StringStore.TranslateText(__instance.beanCount2.text); __instance.beanCount2.text = StringStore.TranslateText(__instance.beanCount2.text);
} }

View file

@ -4,7 +4,7 @@ using System.Text.RegularExpressions;
namespace PvZ_Fusion_Translator.Patches.GameObjects.MinorObjects namespace PvZ_Fusion_Translator.Patches.GameObjects.MinorObjects
{ {
[HarmonyPatch(typeof(Plant))] /*[HarmonyPatch(typeof(Plant))]
public static class Plant_Patch public static class Plant_Patch
{ {
[HarmonyPostfix] [HarmonyPostfix]
@ -43,5 +43,5 @@ namespace PvZ_Fusion_Translator.Patches.GameObjects.MinorObjects
} }
return originalText; return originalText;
} }
} }*/
} }

View file

@ -1,4 +1,4 @@
using HarmonyLib; /*using HarmonyLib;
using Il2Cpp; using Il2Cpp;
using PvZ_Fusion_Translator.AssetStore; using PvZ_Fusion_Translator.AssetStore;
@ -14,4 +14,4 @@ namespace PvZ_Fusion_Translator.Patches.GameObjects.MinorObjects
__instance.textMesh.text = StringStore.TranslateText(__instance.textMesh.text); __instance.textMesh.text = StringStore.TranslateText(__instance.textMesh.text);
} }
} }
} }*/

View file

@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Il2Cpp;
using UnityEngine;
using HarmonyLib;
using Il2CppTMPro;
using PvZ_Fusion_Translator.AssetStore;
namespace PvZ_Fusion_Translator.Patches.GameObjects.MinorObjects
{
[HarmonyPatch(typeof(PumpinerChestMenu))]
public static class PumpinerChestMenu_Patch
{
[HarmonyPatch(nameof(PumpinerChestMenu.InitPlants))]
[HarmonyPostfix]
public static void Post_InitPlants(PumpinerChestMenu __instance)
{
Transform closeBtnTransform = __instance.transform.Find("SampleButton");
TextMeshProUGUI txt = closeBtnTransform.GetComponentInChildren<TextMeshProUGUI>();
txt.text = StringStore.TranslateText("合上");
}
}
}

View file

@ -1,4 +1,4 @@
using HarmonyLib; /*using HarmonyLib;
using Il2Cpp; using Il2Cpp;
using PvZ_Fusion_Translator.AssetStore; using PvZ_Fusion_Translator.AssetStore;
@ -19,3 +19,4 @@ namespace PvZ_Fusion_Translator.Patches.GameObjects.MinorObjects
} }
} }
} }
*/

View file

@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HarmonyLib;
using Il2Cpp;
using Il2CppTMPro;
using PvZ_Fusion_Translator.AssetStore;
using UnityEngine;
namespace PvZ_Fusion_Translator.Patches.GameObjects.MinorObjects
{
[HarmonyPatch(typeof(SpecialCard))]
public static class SpecialCard_Patch
{
[HarmonyPatch(nameof(SpecialCard.Awake))]
[HarmonyPatch(nameof(SpecialCard.Start))]
[HarmonyPatch(nameof(SpecialCard.ClickedEvent))]
[HarmonyPostfix]
public static void Post_Awake(SpecialCard __instance)
{
TMP_FontAsset fontAsset = FontStore.LoadTMPFont(Utils.Language.ToString());
foreach(TextMeshProUGUI txt in __instance.GetComponentsInChildren<TextMeshProUGUI>())
{
txt.text = StringStore.TranslateText(txt.text);
txt.font = fontAsset;
}
}
}
}

View file

@ -10,7 +10,7 @@ namespace PvZ_Fusion_Translator.Patches.GameObjects.MinorObjects
public static void UpdateHealthText(TrainingDummy __instance) public static void UpdateHealthText(TrainingDummy __instance)
{ {
Zombie_Patch.TranslateHpUI_T(__instance.healthText, __instance); Zombie_Patch.TranslateHpUI_T(__instance.healthText, __instance);
Zombie_Patch.TranslateHpUI_T(__instance.healthTextShadow, __instance); //Zombie_Patch.TranslateHpUI_T(__instance.healthTextShadow, __instance);
} }
} }
} }

View file

@ -4,7 +4,7 @@ using PvZ_Fusion_Translator.AssetStore;
namespace PvZ_Fusion_Translator.Patches.GameObjects.MinorObjects namespace PvZ_Fusion_Translator.Patches.GameObjects.MinorObjects
{ {
[HarmonyPatch(typeof(UltimateChomper), nameof(UltimateChomper.UpdateText))] /*[HarmonyPatch(typeof(UltimateChomper), nameof(UltimateChomper.UpdateText))]
public static class UltimateChomper_Patch public static class UltimateChomper_Patch
{ {
[HarmonyPostfix] [HarmonyPostfix]
@ -13,5 +13,5 @@ namespace PvZ_Fusion_Translator.Patches.GameObjects.MinorObjects
StringStore.TranslateText(__instance.killingText); StringStore.TranslateText(__instance.killingText);
StringStore.TranslateText(__instance.killingTextShadow); StringStore.TranslateText(__instance.killingTextShadow);
} }
} }*/
} }

View file

@ -14,9 +14,9 @@ namespace PvZ_Fusion_Translator.Patches.GameObjects.MinorObjects
private static Dictionary<string, string> HPStrings = new Dictionary<string, string>() private static Dictionary<string, string> HPStrings = new Dictionary<string, string>()
{ {
{ "最后一击:(\\d+)\nDPS:([^\\s]+)\n总伤害:(\\d+)", "Last Damage: {0}\nDPS: {1}\nTotal: {2}" }, { "最后一击:(\\d+)\nDPS:([^\\s]+)\n总伤害:(\\d+)", "Last Damage: {0}\nDPS: {1}\nTotal: {2}" },
{ "^HP:(\\d+)/(\\d+)\n一类:(\\d+)/(\\d+)\n二类:(\\d+)/(\\d+)$", "HP: {0}/{1}\nType 1 armor: {2}/{3}\nType 2 armor: {4}/{5}" }, { "^HP:(\\d+)/(\\d+)\n一类:(\\d+)/(\\d+)\n二类:(\\d+)/(\\d+)$", "HP: {0}/{1}\nT1 armor: {2}/{3}\nT2 armor: {4}/{5}" },
{ "^HP:(\\d+)/(\\d+)\n一类:(\\d+)/(\\d+)$", "HP: {0}/{1}\nType 1 armor: {2}/{3}" }, { "^HP:(\\d+)/(\\d+)\n一类:(\\d+)/(\\d+)$", "HP: {0}/{1}\nT1 armor: {2}/{3}" },
{ "^HP:(\\d+)/(\\d+)\n二类:(\\d+)/(\\d+)$", "HP: {0}/{1}\nType 2 armor: {2}/{3}" }, { "^HP:(\\d+)/(\\d+)\n二类:(\\d+)/(\\d+)$", "HP: {0}/{1}\nT2 armor: {2}/{3}" },
{ "^HP:(\\d+)/(\\d+)$", "HP: {0}/{1}" } { "^HP:(\\d+)/(\\d+)$", "HP: {0}/{1}" }
}; };
@ -32,20 +32,23 @@ namespace PvZ_Fusion_Translator.Patches.GameObjects.MinorObjects
public static void Start(Zombie __instance) public static void Start(Zombie __instance)
{ {
TranslateHpUI(__instance.healthText, __instance); TranslateHpUI(__instance.healthText, __instance);
TranslateHpUI(__instance.healthTextShadow, __instance); //TranslateHpUI(__instance.healthTextShadow, __instance);
if (__instance.healthText.transform.rotation != Quaternion.Euler(0, 0, 0)) if (__instance.healthText.transform.rotation != Quaternion.Euler(0, 0, 0))
__instance.healthText.transform.rotation = Quaternion.Euler(0f, 0f, 0f); __instance.healthText.transform.rotation = Quaternion.Euler(0f, 0f, 0f);
} }
[HarmonyPatch(nameof(Zombie.Update))] [HarmonyPatch(nameof(Zombie.UpdateHealthText))]
[HarmonyPrefix] [HarmonyPostfix]
public static void Update(Zombie __instance) public static void Update(Zombie __instance)
{ {
if (__instance.theZombieType == ZombieType.TrainingDummy || !Board.Instance.showZombieHealth) if (__instance.theZombieType == ZombieType.TrainingDummy || !Board.Instance.showZombieHealth)
return; return;
if (__instance.healthText == null) return;
TranslateHpUI(__instance.healthText, __instance); TranslateHpUI(__instance.healthText, __instance);
TranslateHpUI(__instance.healthTextShadow, __instance); //TranslateHpUI(__instance.healthTextShadow, __instance);
if (__instance.healthText.transform.rotation != Quaternion.Euler(0f, 0f, 0f)) if (__instance.healthText.transform.rotation != Quaternion.Euler(0f, 0f, 0f))
__instance.healthText.transform.rotation = Quaternion.Euler(0f, 0f, 0f); __instance.healthText.transform.rotation = Quaternion.Euler(0f, 0f, 0f);
@ -158,13 +161,11 @@ namespace PvZ_Fusion_Translator.Patches.GameObjects.MinorObjects
if (fIndex > -1 && found) if (fIndex > -1 && found)
{ {
string fStr = HPStrings.ElementAt(fIndex).Value; string fStr = HPStrings.ElementAt(fIndex).Value;
string DPS = originalText.Split("\n")[1].Replace("DPS:", "");
DPS = StringStore.TranslateText(DPS);
switch (fIndex) switch (fIndex)
{ {
case 0: case 0:
finalText = string.Format(fStr, __instance.lastDamage, DPS, __instance.totalDamage); finalText = string.Format(fStr, __instance.lastDamage, __instance.CurrentDPS, __instance.totalDamage);
break; break;
default: default:
break; break;

View file

@ -0,0 +1,22 @@
using HarmonyLib;
using Il2Cpp;
using Il2CppTMPro;
using PvZ_Fusion_Translator.AssetStore;
using UnityEngine;
namespace PvZ_Fusion_Translator.Patches.GameObjects
{
[HarmonyPatch(typeof(PlantCardPackageBuilder))]
public static class PlantCardPackageBuilder_Patch
{
[HarmonyPatch(nameof(PlantCardPackageBuilder.UpdateText))]
[HarmonyPostfix]
private static void UpdateText(PlantCardPackageBuilder __instance)
{
TMP_FontAsset fontAsset = FontStore.LoadTMPFont(Utils.Language.ToString());
__instance.text.text = StringStore.TranslateText(__instance.text.text);
__instance.text.font = fontAsset;
}
}
}

View file

@ -10,26 +10,27 @@ namespace PvZ_Fusion_Translator.Patches.GameObjects
[HarmonyPatch(typeof(PlantDamageMenu))] [HarmonyPatch(typeof(PlantDamageMenu))]
public static class PlantDamageMenu_Patch public static class PlantDamageMenu_Patch
{ {
[HarmonyPatch(nameof(PlantDamageMenu.Awake))] public static void Awake(BaseMenu __instance)
[HarmonyPostfix]
private static void Awake(PlantDamageMenu __instance)
{ {
TMP_FontAsset fontAsset = FontStore.LoadTMPFont(Utils.Language.ToString()); TMP_FontAsset fontAsset = FontStore.LoadTMPFont(Utils.Language.ToString());
foreach(TextMeshProUGUI text in __instance.GetComponentsInChildren<TextMeshProUGUI>()) foreach(TextMeshProUGUI text in __instance.GetComponentsInChildren<TextMeshProUGUI>())
{ {
text.text = StringStore.TranslateText(text.text); string originalKey = StringStore.translationString.FirstOrDefault(x => x.Value == text.text).Key;
text.text = StringStore.translationString.ContainsKey(originalKey + "_RM") ? StringStore.TranslateText(originalKey + "_RM") : StringStore.TranslateText(text.text);
text.font = fontAsset; text.font = fontAsset;
} }
} }
[HarmonyPatch(nameof(PlantDamageMenu.Awake))]
[HarmonyPatch(nameof(PlantDamageMenu.InitCards))] [HarmonyPatch(nameof(PlantDamageMenu.InitCards))]
[HarmonyPostfix] [HarmonyPostfix]
private static void InitCards(PlantDamageMenu __instance) public static void InitCards(PlantDamageMenu __instance)
{ {
TMP_FontAsset fontAsset = FontStore.LoadTMPFont(Utils.Language.ToString()); TMP_FontAsset fontAsset = FontStore.LoadTMPFont(Utils.Language.ToString());
foreach (TextMeshProUGUI text in __instance.GetComponentsInChildren<TextMeshProUGUI>()) foreach (TextMeshProUGUI text in __instance.GetComponentsInChildren<TextMeshProUGUI>())
{ {
text.text = StringStore.TranslateText(text.text); string originalKey = StringStore.translationString.FirstOrDefault(x => x.Value == text.text).Key;
text.text = StringStore.translationString.ContainsKey(originalKey + "_RM") ? StringStore.TranslateText(originalKey + "_RM") : StringStore.TranslateText(text.text);
text.font = fontAsset; text.font = fontAsset;
} }
} }

View file

@ -21,12 +21,12 @@ namespace PvZ_Fusion_Translator.Patches.GameObjects
TranslatePlantDataMenu(__instance); TranslatePlantDataMenu(__instance);
} }
[HarmonyPatch(nameof(PlantDataMenu.Update))] /*[HarmonyPatch(nameof(PlantDataMenu.Update))]
[HarmonyPostfix] [HarmonyPostfix]
public static void Post_Update(PlantDataMenu __instance) public static void Post_Update(PlantDataMenu __instance)
{ {
TranslatePlantDataMenu(__instance); TranslatePlantDataMenu(__instance);
} }*/
[HarmonyPatch(nameof(PlantDataMenu.InitDataFromPlant))] [HarmonyPatch(nameof(PlantDataMenu.InitDataFromPlant))]
[HarmonyPostfix] [HarmonyPostfix]
@ -37,6 +37,8 @@ namespace PvZ_Fusion_Translator.Patches.GameObjects
public static void TranslatePlantDataMenu(PlantDataMenu __instance) public static void TranslatePlantDataMenu(PlantDataMenu __instance)
{ {
if (!__instance) return;
PlantType thePlantType = __instance.plant.thePlantType; PlantType thePlantType = __instance.plant.thePlantType;
string plantName = Utils.GetPlantNameFromAlmanac(thePlantType); string plantName = Utils.GetPlantNameFromAlmanac(thePlantType);

View file

@ -26,10 +26,10 @@ namespace PvZ_Fusion_Translator.Patches.GameObjects
public static void TranslateCreatePlayerSaveMenu() public static void TranslateCreatePlayerSaveMenu()
{ {
Transform createPlayerSaveMenuTransform = GameAPP.canvasUp.Find("CreatePlayerSaveMenu(Clone)"); Transform reNameMenuTransform = GameAPP.canvasUp.Find("ReNameMenu(Clone)");
if(createPlayerSaveMenuTransform.TryGetComponent<CreatePlayerSaveMenu>(out CreatePlayerSaveMenu createPlayerSaveMenu)) if(reNameMenuTransform.TryGetComponent<ReNameMenu>(out ReNameMenu reNameMenu))
{ {
createPlayerSaveMenu.title.text = StringStore.TranslateText(createPlayerSaveMenu.title.text); reNameMenu.title.text = StringStore.TranslateText(reNameMenu.title.text);
} }
} }
} }

View file

@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HarmonyLib;
using UnityEngine;
using Il2Cpp;
using PvZ_Fusion_Translator.AssetStore;
namespace PvZ_Fusion_Translator.Patches.GameObjects
{
[HarmonyPatch(typeof(ReNameMenu))]
public static class ReNameMenu_Patch
{
[HarmonyPatch(nameof(ReNameMenu.SetTitle))]
[HarmonyPostfix]
public static void SetTitle(ReNameMenu __instance)
{
__instance.title.text = StringStore.TranslateText(__instance.title.text);
}
[HarmonyPatch(nameof(ReNameMenu.SetInputText))]
[HarmonyPostfix]
public static void SetInputText(ReNameMenu __instance)
{
__instance.input.text = StringStore.TranslateText(__instance.input.text);
}
}
}

View file

@ -31,5 +31,28 @@ namespace PvZ_Fusion_Translator.Patches.GameObjects
} }
} }
} }
[HarmonyPatch(nameof(SeedLibrary.Start))]
[HarmonyPatch(nameof(SeedLibrary.SetAllCards))]
[HarmonyPostfix]
private static void SetAllCards(SeedLibrary __instance)
{
TMP_FontAsset fontAsset = FontStore.LoadTMPFont(Utils.Language.ToString());
//foreach (TextMeshProUGUI txt in __instance.GetComponentsInChildren<TextMeshProUGUI>())
//{
// txt.text = StringStore.TranslateText(txt.text);
// txt.font = fontAsset;
//}
foreach(TextMeshProUGUI txt in __instance.page.GetComponentsInChildren<TextMeshProUGUI>(true))
{
txt.font = fontAsset;
if (!Utils.CheckForUntranslatedText(txt.text))
{
txt.text = StringStore.TranslateText(txt.text);
}
}
}
} }
} }

View file

@ -6,7 +6,7 @@ using UnityEngine;
namespace PvZ_Fusion_Translator.Patches.GameObjects namespace PvZ_Fusion_Translator.Patches.GameObjects
{ {
[HarmonyPatch(typeof(ShootingMenu))] /*[HarmonyPatch(typeof(ShootingMenu))]
public static class ShootingMenu_Patch public static class ShootingMenu_Patch
{ {
[HarmonyPatch(nameof(ShootingMenu.Update))] [HarmonyPatch(nameof(ShootingMenu.Update))]
@ -21,5 +21,5 @@ namespace PvZ_Fusion_Translator.Patches.GameObjects
txt.font = fontAsset; txt.font = fontAsset;
} }
} }
} }*/
} }

View file

@ -7,7 +7,7 @@ using System.Text.RegularExpressions;
namespace PvZ_Fusion_Translator.Patches.GameObjects namespace PvZ_Fusion_Translator.Patches.GameObjects
{ {
[HarmonyPatch(typeof(ShootingSelectWindow))] /*[HarmonyPatch(typeof(ShootingSelectWindow))]
public static class ShootingSelectWindow_Patch public static class ShootingSelectWindow_Patch
{ {
[HarmonyPatch(nameof(ShootingSelectWindow.InitPlantType))] [HarmonyPatch(nameof(ShootingSelectWindow.InitPlantType))]
@ -69,5 +69,5 @@ namespace PvZ_Fusion_Translator.Patches.GameObjects
introduceText.text = StringStore.TranslateText(introduceText.text); introduceText.text = StringStore.TranslateText(introduceText.text);
introduceText.font = fontAsset; introduceText.font = fontAsset;
} }
} }*/
} }

View file

@ -14,11 +14,8 @@ namespace PvZ_Fusion_Translator.Patches.GameObjects
[HarmonyPostfix] [HarmonyPostfix]
private static void Update(UIDifficulty __instance) private static void Update(UIDifficulty __instance)
{ {
if (!Utils.CheckForUntranslatedText(__instance.t.text)) return;
__instance.t.text = StringStore.TranslateText(__instance.t.text); __instance.t.text = StringStore.TranslateText(__instance.t.text);
foreach(TextMeshProUGUI text in __instance.GetComponentsInChildren<TextMeshProUGUI>())
{
text.text = StringStore.TranslateText(text.text);
}
} }
} }
} }

View file

@ -1,4 +1,4 @@
using HarmonyLib; /*using HarmonyLib;
using Il2Cpp; using Il2Cpp;
using Il2CppTMPro; using Il2CppTMPro;
using PvZ_Fusion_Translator.AssetStore; using PvZ_Fusion_Translator.AssetStore;
@ -125,4 +125,4 @@ namespace PvZ_Fusion_Translator.Patches.Managers
return true; return true;
} }
} }
} }*/

View file

@ -1,4 +1,4 @@
using HarmonyLib; /*using HarmonyLib;
using Il2Cpp; using Il2Cpp;
using Il2CppTMPro; using Il2CppTMPro;
using PvZ_Fusion_Translator.AssetStore; using PvZ_Fusion_Translator.AssetStore;
@ -197,4 +197,4 @@ namespace PvZ_Fusion_Translator.Patches.Managers
__instance.skinButton.transform.GetChild(2).Translate(new Vector3(-0.35f, 0)); __instance.skinButton.transform.GetChild(2).Translate(new Vector3(-0.35f, 0));
} }
} }
} }*/

View file

@ -1,8 +1,9 @@
using HarmonyLib; using HarmonyLib;
using Il2Cpp; using Il2Cpp;
using Il2CppTMPro; using Il2CppTMPro;
using Il2CppSystem.Collections.Generic;
using PvZ_Fusion_Translator.AssetStore; using PvZ_Fusion_Translator.AssetStore;
using PvZ_Fusion_Translator.Patches.BaseTextObjects;
using System.Text.RegularExpressions;
using UnityEngine; using UnityEngine;
using UnityEngine.TextCore.Text; using UnityEngine.TextCore.Text;
using static MelonLoader.MelonLogger; using static MelonLoader.MelonLogger;
@ -12,48 +13,66 @@ namespace PvZ_Fusion_Translator.Patches.GameObjects
[HarmonyPatch(typeof(DrawCardManager))] [HarmonyPatch(typeof(DrawCardManager))]
public static class DrawCardManager_Patch public static class DrawCardManager_Patch
{ {
public static TMP_FontAsset fontAsset = FontStore.LoadTMPFont(Utils.Language.ToString());
[HarmonyPatch(nameof(DrawCardManager.Awake))]
[HarmonyPostfix]
private static void Awake(DrawCardManager __instance)
{
fontAsset = FontStore.LoadTMPFont(Utils.Language.ToString());
}
[HarmonyPatch(nameof(DrawCardManager.UpdateText))] [HarmonyPatch(nameof(DrawCardManager.UpdateText))]
[HarmonyPostfix] [HarmonyPostfix]
private static void Postfix_UpdateText(DrawCardManager __instance) private static void Postfix_UpdateText(DrawCardManager __instance)
{ {
Il2CppSystem.Collections.Generic.List<TextMeshProUGUI> texts = __instance.texts; KeyValuePair<string, string> regexPair = new KeyValuePair<string, string>("抽取次数:\n(\\d+)/(\\d+)\n当前up植物:\n([^\\s]+)\nup刷新倒计时:\n(\\d+)", "Draw Count:\n{0}/{1}\nCurrent Up:\n{2}\nNext Up in: \n{3}s");
__instance.upName = StringStore.TranslateText(__instance.upName);
if (texts != null && texts.Count > 0) foreach(TextMeshProUGUI txt in __instance.texts)
{ {
foreach (TextMeshProUGUI textComponent in texts) if(Regex.IsMatch(txt.text, regexPair.Key))
{ {
if (textComponent != null) txt.text = TranslateGashaponText(txt.text, regexPair.Key, regexPair.Value, __instance.up);
{ txt.font = fontAsset;
string translatedText = StringStore.TranslateText(textComponent.text);
TMP_FontAsset fontAsset = FontStore.LoadTMPFont(Utils.Language.ToString());
textComponent.text = translatedText;
textComponent.font = fontAsset;
}
} }
} }
} }
[HarmonyPatch(nameof(DrawCardManager.Update))] public static string TranslateGashaponText(string originalText, string pattern, string fallback, PlantType up)
{
string res = "";
string fStr = "";
Match match = Regex.Match(originalText, pattern);
if(match.Success)
{
GroupCollection groups = match.Groups;
fStr = StringStore.translationStringRegex.ContainsKey(pattern) ? StringStore.translationStringRegex[pattern] : fallback;
List<string> dynamicParts = [];
for(int i = 1; i < groups.Count; i++)
{
string group = groups[i].Value;
string translatedGroup = "";
if(i == 3 && up != PlantType.Peashooter)
{
translatedGroup = Utils.GetPlantNameFromAlmanac(up);
}
else
{
translatedGroup = StringStore.TranslateText(group);
}
dynamicParts.Add(translatedGroup);
}
res = string.Format(fStr, [.. dynamicParts]);
}
return res;
}
/*[HarmonyPatch(nameof(DrawCardManager.Update))]
[HarmonyPostfix] [HarmonyPostfix]
private static void Postfix_Update(DrawCardManager __instance) private static void Postfix_Update(DrawCardManager __instance)
{ {
Il2CppSystem.Collections.Generic.List<TextMeshProUGUI> texts = __instance.texts; Postfix_UpdateText(__instance);
__instance.upName = StringStore.TranslateText(__instance.upName); }*/
if (texts != null && texts.Count > 0)
{
foreach (TextMeshProUGUI textComponent in texts)
{
if (textComponent != null)
{
string translatedText = StringStore.TranslateText(textComponent.text);
TMP_FontAsset fontAsset = FontStore.LoadTMPFont(Utils.Language.ToString());
textComponent.text = translatedText;
textComponent.font = fontAsset;
}
}
}
}
} }
} }

View file

@ -3,6 +3,7 @@ using Il2Cpp;
using Il2CppTMPro; using Il2CppTMPro;
using PvZ_Fusion_Translator; using PvZ_Fusion_Translator;
using PvZ_Fusion_Translator.AssetStore; using PvZ_Fusion_Translator.AssetStore;
using PvZ_Fusion_Translator.Patches.BaseTextObjects;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using Unity.Collections; using Unity.Collections;
@ -11,83 +12,42 @@ namespace PvZ_Fusion_Translator.Patches.Managers
[HarmonyPatch(typeof(InGameUI))] [HarmonyPatch(typeof(InGameUI))]
public static class InGameUI_Patch public static class InGameUI_Patch
{ {
public static string travelAdventurePattern = "^旅行冒险 ([^\\s:]+)";
public static string travelAdventureFallback = "Odyssey Adventure: {0}";
[HarmonyPatch(nameof(InGameUI.Start))] [HarmonyPatch(nameof(InGameUI.Start))]
[HarmonyPostfix] [HarmonyPostfix]
private static void Start(InGameUI __instance) private static void Start(InGameUI __instance)
{ {
foreach(TextMeshProUGUI text in __instance.T) SetLevelName(__instance);
{
if (text.text == null) continue;
string originalText = text.text;
text.text = text.text.Replace("\n", " ");
Regex checkFusionChallenge = new Regex("^超级([^\\s:]+)(:?挑战1?)");
if (text.text.Contains("配方:") && !checkFusionChallenge.IsMatch(text.text))
{
string[] lines = text.text.Split(":");
lines[1] = Utils.GetPlantNameFromAlmanac(lines[1]);
if (lines[1] == "")
{
Log.LogError("Couldn't find plant! (Fusion Showcase)");
lines[1] = StringStore.TranslateText(lines[1]);
}
text.text = StringStore.TranslateText("配方:") + lines[1];
text.autoSizeTextContainer = true;
}
else
{
text.text = (StringStore.translationString.ContainsKey(text.text + "_MG")) ? StringStore.TranslateText(text.text + "_MG") : StringStore.TranslateText(text.text);
text.text = text.text.Replace("\n", " ");
}
}
} }
[HarmonyPatch(nameof(InGameUI.SetUniqueText))] [HarmonyPatch(nameof(InGameUI.SetUniqueText))]
[HarmonyPostfix] [HarmonyPostfix]
private static void SetUniqueText(InGameUI __instance) private static void SetUniqueText(InGameUI __instance)
{ {
foreach(TextMeshProUGUI text in __instance.T) SetLevelName(__instance);
{
if (text.text == null) continue;
string originalText = text.text;
text.text = text.text.Replace("\n", " ");
Regex checkFusionChallenge = new Regex("^超级([^\\s:]+)(:?挑战1?)");
if (text.text.Contains("配方:") && !checkFusionChallenge.IsMatch(text.text))
{
string[] lines = text.text.Split(":");
lines[1] = Utils.GetPlantNameFromAlmanac(lines[1]);
if (lines[1] == "")
{
Log.LogError("Couldn't find plant! (Fusion Showcase)");
lines[1] = StringStore.TranslateText(lines[1]);
}
text.text = StringStore.TranslateText("配方:") + lines[1];
text.autoSizeTextContainer = true;
}
else
{
text.text = (StringStore.translationString.ContainsKey(text.text + "_MG")) ? StringStore.TranslateText(text.text + "_MG") : StringStore.TranslateText(text.text);
text.text = text.text.Replace("\n", " ");
}
}
} }
[HarmonyPatch(nameof(InGameUI.SetLevelName))] [HarmonyPatch(nameof(InGameUI.SetLevelName))]
[HarmonyPostfix] [HarmonyPostfix]
private static void SetLevelName(InGameUI __instance) private static void SetLevelName(InGameUI __instance)
{ {
foreach(TextMeshProUGUI text in __instance.T) foreach (TextMeshProUGUI text in __instance.levelNameText)
{ {
if (text.text == null) continue; if (text.text == null) continue;
string originalText = text.text; string originalText = text.text;
text.text = text.text.Replace("\n", " "); text.text = text.text.Replace("\n", " ");
Regex checkFusionChallenge = new Regex("^超级([^\\s:]+)(:?挑战1?)");
if (text.text.Contains("配方:") && !checkFusionChallenge.IsMatch(text.text)) Regex checkFusionChallenge = new Regex("^超级([^\\s:]+)(:?挑战1?)");
Regex checkTravelAdv = new Regex(travelAdventurePattern);
if(checkTravelAdv.IsMatch(originalText))
{
text.text = InGameText_Patch.TranslatePlantNameParts(originalText, travelAdventurePattern, travelAdventureFallback);
}
else if (text.text.Contains("配方:") && !checkFusionChallenge.IsMatch(text.text))
{ {
string[] lines = text.text.Split(":"); string[] lines = text.text.Split(":");
lines[1] = Utils.GetPlantNameFromAlmanac(lines[1]); lines[1] = Utils.GetPlantNameFromAlmanac(lines[1]);
@ -106,5 +66,22 @@ namespace PvZ_Fusion_Translator.Patches.Managers
} }
} }
} }
/*[HarmonyPatch(nameof(InGameUI.Update))]
[HarmonyPostfix]
private static void Update(InGameUI __instance)
{
if (!__instance.board.boardTag.isDrawCards) return;
KeyValuePair<string, string> regexPair = new KeyValuePair<string, string>("抽取次数:\n(\\d+)/(\\d+)\n当前up植物:\n([^\\s]+)\nup刷新倒计时:\n(\\d+)", "Draw Count:\n{0}/{1}\nCurrent Up:\n{2}\nNext Up in: \n{3}s");
foreach(TextMeshProUGUI txt in __instance.DrawCardsHead.GetComponentsInChildren<TextMeshProUGUI>())
{
if(Regex.IsMatch(txt.text, regexPair.Key))
{
txt.text = InGameText_Patch.TranslatePlantNameParts(txt.text, regexPair.Key, regexPair.Value);
}
}
}*/
} }
} }

View file

@ -0,0 +1,34 @@
using Il2Cpp;
using UnityEngine;
using HarmonyLib;
using Il2CppPVPScaryPot;
using PvZ_Fusion_Translator.AssetStore;
namespace PvZ_Fusion_Translator.Patches.Managers
{
[HarmonyPatch(typeof(PVPScareyPot))]
public static class PVPScareyPot_Patch
{
[HarmonyPatch(nameof(PVPScareyPot.Awake))]
[HarmonyPatch(nameof(PVPScareyPot.Start))]
[HarmonyPatch(nameof(PVPScareyPot.AutoRuleUpdate))]
[HarmonyPatch(nameof(PVPScareyPot.RandomCardUpdate))]
[HarmonyPatch(nameof(PVPScareyPot.Update))]
[HarmonyPostfix]
public static void TranslatePlayerDatas(PVPScareyPot __instance)
{
TranslatePlayerData(__instance.player1);
TranslatePlayerData(__instance.player2);
TranslatePlayerData(__instance.currentPlayer);
}
public static void TranslatePlayerData(PVPScareyPot.PlayerData playerData)
{
if(playerData != null)
{
playerData.textMesh.text = StringStore.TranslateText(playerData.textMesh.text);
playerData.textMesh.font = FontStore.LoadTMPFont(Utils.Language.ToString());
}
}
}
}

View file

@ -2,6 +2,8 @@
using Il2Cpp; using Il2Cpp;
using Il2CppTMPro; using Il2CppTMPro;
using PvZ_Fusion_Translator.AssetStore; using PvZ_Fusion_Translator.AssetStore;
using PvZ_Fusion_Translator.Patches.GameObjects.ButtonObjects;
using UnityEngine;
namespace PvZ_Fusion_Translator.Patches.Managers namespace PvZ_Fusion_Translator.Patches.Managers
{ {
@ -9,20 +11,27 @@ namespace PvZ_Fusion_Translator.Patches.Managers
public static class SaveMenu_Patch public static class SaveMenu_Patch
{ {
[HarmonyPatch(nameof(SaveMenu.Start))] [HarmonyPatch(nameof(SaveMenu.Start))]
[HarmonyPatch(nameof(SaveMenu.CreateLevelEnter))]
[HarmonyPatch(nameof(SaveMenu.InitLevelSaveEnters))]
[HarmonyPostfix] [HarmonyPostfix]
private static void Start(SaveMenu __instance) private static void Start(SaveMenu __instance)
{ {
TMP_FontAsset fontAsset = FontStore.LoadTMPFont(Utils.Language.ToString()); TMP_FontAsset fontAsset = FontStore.LoadTMPFont(Utils.Language.ToString());
__instance.title.text = StringStore.TranslateText(__instance.title.text); __instance.menuTitle.text = StringStore.TranslateText(__instance.menuTitle.text);
__instance.title.font = fontAsset; __instance.menuTitle.font = fontAsset;
__instance.title_shadow.text = StringStore.TranslateText(__instance.title_shadow.text);
__instance.title_shadow.font = fontAsset;
foreach(SaveMenuBtn level in __instance.levels) foreach(LevelSaveEnter enter in __instance.GetComponentsInChildren<LevelSaveEnter>())
{ {
level.theName.text = StringStore.TranslateText(level.theName.text); LevelSaveEnter_Patch.TranslateEnter(enter);
} }
} }
[HarmonyPatch(nameof(SaveMenu.OnEditSelectedButtonClicked))]
[HarmonyPostfix]
private static void OnEditSelectedButtonClicked(SaveMenu __instance)
{
}
} }
} }

View file

@ -2,23 +2,23 @@
using Il2Cpp; using Il2Cpp;
using Il2CppTMPro; using Il2CppTMPro;
using PvZ_Fusion_Translator.AssetStore; using PvZ_Fusion_Translator.AssetStore;
using UnityEngine;
using UnityEngine.EventSystems; using UnityEngine.EventSystems;
using UnityEngine.UI; using UnityEngine.UI;
namespace PvZ_Fusion_Translator.Patches.Managers namespace PvZ_Fusion_Translator.Patches.Managers
{ {
[HarmonyPatch(typeof(GameAPP))] [HarmonyPatch(typeof(Screen))]
public static class GameAPP_Patch public static class Screen_Patch
{ {
[HarmonyPatch(nameof(GameAPP.Update))] [HarmonyPatch(nameof(Screen.SetResolution), argumentTypes: [typeof(int), typeof(int), typeof(bool)])]
[HarmonyPrefix] [HarmonyPrefix]
private static bool Update(GameAPP __instance) private static bool SetResolution(Screen __instance)
{ {
if(EventSystem.current.currentSelectedGameObject != null) if(EventSystem.current.currentSelectedGameObject != null)
{ {
if (EventSystem.current.currentSelectedGameObject.TryGetComponent<TMP_InputField>(out TMP_InputField field)) if (EventSystem.current.currentSelectedGameObject.TryGetComponent<TMP_InputField>(out TMP_InputField field))
{ {
__instance.MusicUpdate();
return false; return false;
} }
} }

View file

@ -17,7 +17,10 @@ namespace PvZ_Fusion_Translator.Patches.Managers
{ {
if (transform != null) if (transform != null)
{ {
transform.GetComponent<TextMeshProUGUI>().text = StringStore.TranslateText(transform.GetComponent<TextMeshProUGUI>().text); if(transform.gameObject.active)
{
transform.GetComponent<TextMeshProUGUI>().text = StringStore.TranslateText(transform.GetComponent<TextMeshProUGUI>().text);
}
} }
} }
} }

View file

@ -15,7 +15,7 @@ using static PvZ_Fusion_Translator.FileLoader;
namespace PvZ_Fusion_Translator.Patches.Modes.Abyss namespace PvZ_Fusion_Translator.Patches.Modes.Abyss
{ {
[HarmonyPatch(typeof(AbyssBuffMenu))] /*[HarmonyPatch(typeof(AbyssBuffMenu))]
public static class AbyssBuffMenu_Patch public static class AbyssBuffMenu_Patch
{ {
public static Dictionary<string, string> abyssBuffData = new Dictionary<string, string>(); public static Dictionary<string, string> abyssBuffData = new Dictionary<string, string>();
@ -129,5 +129,5 @@ namespace PvZ_Fusion_Translator.Patches.Modes.Abyss
return null; return null;
} }
} }*/
} }

View file

@ -6,7 +6,7 @@ using UnityEngine;
namespace PvZ_Fusion_Translator.Patches.Modes.Abyss namespace PvZ_Fusion_Translator.Patches.Modes.Abyss
{ {
[HarmonyPatch(typeof(AbyssGoods))] /*[HarmonyPatch(typeof(AbyssGoods))]
public static class AbyssGoods_Patch public static class AbyssGoods_Patch
{ {
[HarmonyPostfix] [HarmonyPostfix]
@ -18,5 +18,5 @@ namespace PvZ_Fusion_Translator.Patches.Modes.Abyss
__instance.hasText.text = StringStore.TranslateText(__instance.hasText.text, false); __instance.hasText.text = StringStore.TranslateText(__instance.hasText.text, false);
__instance.hasText_shadow.text = StringStore.TranslateText(__instance.hasText_shadow.text, false); __instance.hasText_shadow.text = StringStore.TranslateText(__instance.hasText_shadow.text, false);
} }
} }*/
} }

View file

@ -6,7 +6,7 @@ using UnityEngine;
namespace PvZ_Fusion_Translator.Patches.Modes.Abyss namespace PvZ_Fusion_Translator.Patches.Modes.Abyss
{ {
[HarmonyPatch(typeof(AbyssLevelEnter))] /*[HarmonyPatch(typeof(AbyssLevelEnter))]
public static class AbyssLevelEnter_Patch public static class AbyssLevelEnter_Patch
{ {
[HarmonyPatch(nameof(AbyssLevelEnter.SetLevel))] [HarmonyPatch(nameof(AbyssLevelEnter.SetLevel))]
@ -15,5 +15,5 @@ namespace PvZ_Fusion_Translator.Patches.Modes.Abyss
{ {
__instance.levelName = StringStore.TranslateText(__instance.levelName); __instance.levelName = StringStore.TranslateText(__instance.levelName);
} }
} }*/
} }

View file

@ -11,7 +11,7 @@ using MelonLoader.Utils;
namespace PvZ_Fusion_Translator.Patches.Modes.Abyss namespace PvZ_Fusion_Translator.Patches.Modes.Abyss
{ {
[HarmonyPatch(typeof(AbyssMenu))] /*[HarmonyPatch(typeof(AbyssMenu))]
public static class AbyssMenu_Patch public static class AbyssMenu_Patch
{ {
[HarmonyPatch(nameof(AbyssMenu.Awake))] [HarmonyPatch(nameof(AbyssMenu.Awake))]
@ -45,5 +45,5 @@ namespace PvZ_Fusion_Translator.Patches.Modes.Abyss
txt.font = fontAsset; txt.font = fontAsset;
} }
} }
} }*/
} }

View file

@ -7,7 +7,7 @@ using System.Text.RegularExpressions;
namespace PvZ_Fusion_Translator.Patches.Modes.Abyss namespace PvZ_Fusion_Translator.Patches.Modes.Abyss
{ {
[HarmonyPatch(typeof(AbyssSelectBuffWindow))] /*[HarmonyPatch(typeof(AbyssSelectBuffWindow))]
public static class AbyssSelectBuffWindow_Patch public static class AbyssSelectBuffWindow_Patch
{ {
[HarmonyPatch(nameof(AbyssSelectBuffWindow.OnAnimOver))] [HarmonyPatch(nameof(AbyssSelectBuffWindow.OnAnimOver))]
@ -53,5 +53,5 @@ namespace PvZ_Fusion_Translator.Patches.Modes.Abyss
__instance.introduce.font = fontAsset; __instance.introduce.font = fontAsset;
} }
} }
} }*/
} }

View file

@ -5,7 +5,7 @@ using PvZ_Fusion_Translator.AssetStore;
namespace PvZ_Fusion_Translator.Patches.Modes.Abyss namespace PvZ_Fusion_Translator.Patches.Modes.Abyss
{ {
[HarmonyPatch(typeof(AbyssStoreMenu))] /*[HarmonyPatch(typeof(AbyssStoreMenu))]
public static class AbyssStoreMenu_Patch public static class AbyssStoreMenu_Patch
{ {
[HarmonyPatch(nameof(AbyssStoreMenu.Update))] [HarmonyPatch(nameof(AbyssStoreMenu.Update))]
@ -20,5 +20,5 @@ namespace PvZ_Fusion_Translator.Patches.Modes.Abyss
text.font = fontAsset; text.font = fontAsset;
} }
} }
} }*/
} }

View file

@ -0,0 +1,61 @@
using HarmonyLib;
using Il2Cpp;
using Il2CppTMPro;
using PvZ_Fusion_Translator.AssetStore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.TextCore.Text;
namespace PvZ_Fusion_Translator.Patches.Modes.Odyssey
{
[HarmonyPatch(typeof(MultipleChoiceMenu))]
public static class MultipleChoiceMenu_Patch
{
public static TMP_FontAsset fontAsset => FontStore.LoadTMPFont(Utils.Language.ToString());
[HarmonyPatch(nameof(MultipleChoiceMenu.Awake))]
[HarmonyPatch(nameof(MultipleChoiceMenu.Cancel))]
[HarmonyPatch(nameof(MultipleChoiceMenu.Refresh))]
[HarmonyPatch(nameof(MultipleChoiceMenu.TurnPage))]
[HarmonyPatch(nameof(MultipleChoiceMenu.UpdateWindow))]
[HarmonyPostfix]
public static void Awake(MultipleChoiceMenu __instance)
{
foreach(BaseWindow window in __instance.windows)
{
TranslateWindowText(window.title);
TranslateWindowText(window.introduce);
}
foreach(TheButton button in __instance.GetComponentsInChildren<TheButton>())
{
foreach(TextMeshProUGUI txt in button.GetComponentsInChildren<TextMeshProUGUI>())
{
txt.text = StringStore.translationString.ContainsKey(txt.text + "_MC") ? StringStore.TranslateText(txt.text + "_MC") : StringStore.TranslateText(txt.text);
txt.font = fontAsset;
}
}
}
public static void TranslateWindowText(TextMeshProUGUI txt)
{
txt.font = fontAsset;
if(StringStore.customLevelString.ContainsKey(txt.text))
{
txt.text = StringStore.customLevelString[txt.text];
}
else if(Utils.GetPlantNameFromAlmanac(txt.text) != "")
{
txt.text = Utils.GetPlantNameFromAlmanac(txt.text);
}
else
{
txt.text = StringStore.translationString.ContainsKey(txt.text + "_MC") ? StringStore.TranslateText(txt.text + "_MC") : StringStore.TranslateText(txt.text);
}
}
}
}

View file

@ -7,7 +7,7 @@ using UnityEngine;
namespace PvZ_Fusion_Translator.Patches.Modes.Odyssey namespace PvZ_Fusion_Translator.Patches.Modes.Odyssey
{ {
[HarmonyPatch(typeof(OppositeBuffManager))] /*[HarmonyPatch(typeof(OppositeBuffManager))]
public static class OppositeBuffManager_Patch public static class OppositeBuffManager_Patch
{ {
public static Dictionary<BuffType, string> buffLinks = TravelMgr_Patch.buffLinks; public static Dictionary<BuffType, string> buffLinks = TravelMgr_Patch.buffLinks;
@ -16,33 +16,37 @@ namespace PvZ_Fusion_Translator.Patches.Modes.Odyssey
public static string badFormat = StringStore.translationStringRegex.ContainsKey(badPattern) ? StringStore.translationStringRegex[badPattern] : "But, {0}"; 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 TMP_FontAsset fontAsset = FontStore.LoadTMPFont(Utils.Language.ToString());
[HarmonyPatch(nameof(OppositeBuffManager.Awake))] [HarmonyPatch(nameof(OppositeBuffManager.SetText))]
[HarmonyPostfix] [HarmonyPostfix]
private static void Awake(OppositeBuffManager __instance) private static void SetText(OppositeBuffManager __instance)
{ {
TranslateOppositeText(__instance.textA_bad, BuffType.Debuff, __instance.buffA.theDebuffID, true); *//*if (TravelMgr_Patch.travelBuffString.ContainsKey(__result))
TranslateOppositeText(__instance.textA_good, __instance.buffA.theOptionType, __instance.buffA.theOptionID); {
TranslateOppositeText(__instance.textB_bad, BuffType.Debuff, __instance.buffB.theDebuffID, true); __result = TravelMgr_Patch.travelBuffString[__result];
TranslateOppositeText(__instance.textB_good, __instance.buffB.theOptionType, __instance.buffB.theOptionID); }
else if(TravelMgr_Patch.travelBuffString.ContainsKey(TravelMgr_Patch.RemoveBuffName(__result)))
{
__result = TravelMgr_Patch.travelBuffString[TravelMgr_Patch.RemoveBuffName(__result)];
}*//*
} }
public static void TranslateOppositeText(Il2CppSystem.Collections.Generic.List<TextMeshProUGUI> textList, BuffType buffType, int buffIndex, bool isBad = false) public static void TranslateOppositeText(Il2CppSystem.Collections.Generic.List<TextMeshProUGUI> textList, Il2CppSystem.Object buff, bool isBad = false)
{ {
string buff = translatedTravelBuffs[buffLinks[buffType]][buffIndex]; string buffText = TravelMgr.Instance.GetText(buff);
foreach (var text in textList) foreach (var text in textList)
{ {
if (isBad) if (isBad)
{ {
text.text = string.Format(badFormat, buff); text.text = string.Format(badFormat, buffText);
} }
else else
{ {
text.text = buff; text.text = buffText;
} }
text.font = fontAsset; text.font = fontAsset;
} }
} }
} }*/
} }

View file

@ -0,0 +1,583 @@
using HarmonyLib;
using Il2CppGameLevel.RogueShooting;
using PvZ_Fusion_Translator.AssetStore;
using UnityEngine;
namespace PvZ_Fusion_Translator.Patches.Modes.Odyssey
{
[HarmonyPatch(typeof(ShootingManager))]
public static class ShootingManager_Patch
{
[HarmonyPatch(nameof(ShootingManager.RegisterCoreBuff))]
[HarmonyPatch(nameof(ShootingManager.RegisterExpertBuff))]
[HarmonyPatch(nameof(ShootingManager.RegisterGetPlantBuff))]
[HarmonyPatch(nameof(ShootingManager.RegisterOtherBuff))]
[HarmonyPostfix]
public static void UpgradeBuff(ShootingManager __instance, ref Il2Cpp.MultipleChoiceMenu menu)
{
MultipleChoiceMenu_Patch.Awake(menu);
}
public static void GetBuffs()
{
/*#region code
AbyssSwordStar t0 = new();
Bamboo t1 = new();
BigChomper t4 = new();
BigGatling t5 = new();
CabbageCannon t6 = new();
Cabbagepult t7 = new();
Cactus t8 = new();
Caltrop t9 = new();
CaltropNut t10 = new();
CattailLour t11 = new();
CherryChomper t12 = new();
CherryGatling t13 = new();
CherrySquash t14 = new();
Chomper t15 = new();
Cornpult t17 = new();
DoomCactus t20 = new();
DoomChomper t21 = new();
DoomSniper t22 = new();
EmeraleBlover t23 = new();
FireMelon t24 = new();
FumeShroom t25 = new();
GarlicFume t26 = new();
GloomShroom t28 = new();
GoldCabbage t29 = new();
HelmetGatling t30 = new();
HypnoEmperor t31 = new();
HypnoNut t32 = new();
HypnoShroom t33 = new();
IceFumeShroom t34 = new();
IcePuff t35 = new();
IFVIronPuff t36 = new();
IronPuff t37 = new();
LanternSplit t38 = new();
LanternUmbrella t39 = new();
LaserUmbrella t40 = new();
LotusBamboo t41 = new();
Melonpult t42 = new();
NuclearSquash t43 = new();
ObsidianSpike t44 = new();
ObsidianWallNut t45 = new();
PeaMine t46 = new();
Peashooter t47 = new();
PortalCorn t48 = new();
PotatoMine t49 = new();
ScaredyDoom t54 = new();
ScaredyShroom t55 = new();
SmallPuff t57 = new();
SniperPea t58 = new();
SnowGatlingPuff t59 = new();
SpikeRock t61 = new();
Squalour t62 = new();
Squash t63 = new();
StarFruit t64 = new();
SuperChomper t66 = new();
SuperHypno t67 = new();
SuperMelon t68 = new();
SuperStar t69 = new();
SuperThreePeater t70 = new();
SwordStar t71 = new();
TallNut t72 = new();
ThreeMine t73 = new();
ThreePeater t74 = new();
ThreeSquash t75 = new();
UltimateBamboo t76 = new();
UltimateBigChomper t77 = new();
UltimateBigGatling t78 = new();
UltimateBlover t79 = new();
UltimateCabbage t80 = new();
UltimateCabbageCannon t81 = new();
UltimateCactus t82 = new();
UltimateChomper t83 = new();
UltimateCorn t84 = new();
UltimateDoomScared t85 = new();
UltimateFume t86 = new();
UltimateGatling t87 = new();
UltimateGloom t88 = new();
UltimateHelmetGatling t89 = new();
UltimateHypno t90 = new();
UltimateLanternSplit t91 = new();
UltimateMelon t92 = new();
UltimateMinigun t93 = new();
UltimatePoisonFume t94 = new();
UltimateSniperGatling t95 = new();
UltimateSpring t96 = new();
UltimateStar t97 = new();
UltimateStarTorch t98 = new();
UltimateTallNut t99 = new();
UltimateWinterMelon t100 = new();
Umbrellaleaf t101 = new();
WallNut t103 = new();
WinterMelon t104 = new();
Dictionary<string, string> t = new();
#region 3
if(t0.Buffs != null)
{
Utils.TryAdd(t, t0.Role, t0.Role);
}
if(t1.Buffs != null)
{
Utils.TryAdd(t, t1.Role, t1.Role);
}
if(t4.Buffs != null)
{
Utils.TryAdd(t, t4.Role, t4.Role);
}
if(t5.Buffs != null)
{
Utils.TryAdd(t, t5.Role, t5.Role);
}
if(t6.Buffs != null)
{
Utils.TryAdd(t, t6.Role, t6.Role);
}
if(t7.Buffs != null)
{
Utils.TryAdd(t, t7.Role, t7.Role);
}
if(t8.Buffs != null)
{
Utils.TryAdd(t, t8.Role, t8.Role);
}
if(t9.Buffs != null)
{
Utils.TryAdd(t, t9.Role, t9.Role);
}
if(t10.Buffs != null)
{
Utils.TryAdd(t, t10.Role, t10.Role);
}
if(t11.Buffs != null)
{
Utils.TryAdd(t, t11.Role, t11.Role);
}
if(t12.Buffs != null)
{
Utils.TryAdd(t, t12.Role, t12.Role);
}
if(t13.Buffs != null)
{
Utils.TryAdd(t, t13.Role, t13.Role);
}
if(t14.Buffs != null)
{
Utils.TryAdd(t, t14.Role, t14.Role);
}
if(t15.Buffs != null)
{
Utils.TryAdd(t, t15.Role, t15.Role);
}
if(t17.Buffs != null)
{
Utils.TryAdd(t, t17.Role, t17.Role);
}
if(t20.Buffs != null)
{
Utils.TryAdd(t, t20.Role, t20.Role);
}
if(t21.Buffs != null)
{
Utils.TryAdd(t, t21.Role, t21.Role);
}
if(t22.Buffs != null)
{
Utils.TryAdd(t, t22.Role, t22.Role);
}
if(t23.Buffs != null)
{
Utils.TryAdd(t, t23.Role, t23.Role);
}
if(t24.Buffs != null)
{
Utils.TryAdd(t, t24.Role, t24.Role);
}
if(t25.Buffs != null)
{
Utils.TryAdd(t, t25.Role, t25.Role);
}
if(t26.Buffs != null)
{
Utils.TryAdd(t, t26.Role, t26.Role);
}
if(t28.Buffs != null)
{
Utils.TryAdd(t, t28.Role, t28.Role);
}
if(t29.Buffs != null)
{
Utils.TryAdd(t, t29.Role, t29.Role);
}
if(t30.Buffs != null)
{
Utils.TryAdd(t, t30.Role, t30.Role);
}
if(t31.Buffs != null)
{
Utils.TryAdd(t, t31.Role, t31.Role);
}
if(t32.Buffs != null)
{
Utils.TryAdd(t, t32.Role, t32.Role);
}
if(t33.Buffs != null)
{
Utils.TryAdd(t, t33.Role, t33.Role);
}
if(t34.Buffs != null)
{
Utils.TryAdd(t, t34.Role, t34.Role);
}
if(t35.Buffs != null)
{
Utils.TryAdd(t, t35.Role, t35.Role);
}
if(t36.Buffs != null)
{
Utils.TryAdd(t, t36.Role, t36.Role);
}
if(t37.Buffs != null)
{
Utils.TryAdd(t, t37.Role, t37.Role);
}
if(t38.Buffs != null)
{
Utils.TryAdd(t, t38.Role, t38.Role);
}
if(t39.Buffs != null)
{
Utils.TryAdd(t, t39.Role, t39.Role);
}
if(t40.Buffs != null)
{
Utils.TryAdd(t, t40.Role, t40.Role);
}
if(t41.Buffs != null)
{
Utils.TryAdd(t, t41.Role, t41.Role);
}
if(t42.Buffs != null)
{
Utils.TryAdd(t, t42.Role, t42.Role);
}
if(t43.Buffs != null)
{
Utils.TryAdd(t, t43.Role, t43.Role);
}
if(t44.Buffs != null)
{
Utils.TryAdd(t, t44.Role, t44.Role);
}
if(t45.Buffs != null)
{
Utils.TryAdd(t, t45.Role, t45.Role);
}
if(t46.Buffs != null)
{
Utils.TryAdd(t, t46.Role, t46.Role);
}
if(t47.Buffs != null)
{
Utils.TryAdd(t, t47.Role, t47.Role);
}
if(t48.Buffs != null)
{
Utils.TryAdd(t, t48.Role, t48.Role);
}
if(t49.Buffs != null)
{
Utils.TryAdd(t, t49.Role, t49.Role);
}
if(t54.Buffs != null)
{
Utils.TryAdd(t, t54.Role, t54.Role);
}
if(t55.Buffs != null)
{
Utils.TryAdd(t, t55.Role, t55.Role);
}
if(t57.Buffs != null)
{
Utils.TryAdd(t, t57.Role, t57.Role);
}
if(t58.Buffs != null)
{
Utils.TryAdd(t, t58.Role, t58.Role);
}
if(t59.Buffs != null)
{
Utils.TryAdd(t, t59.Role, t59.Role);
}
if(t61.Buffs != null)
{
Utils.TryAdd(t, t61.Role, t61.Role);
}
if(t62.Buffs != null)
{
Utils.TryAdd(t, t62.Role, t62.Role);
}
if(t63.Buffs != null)
{
Utils.TryAdd(t, t63.Role, t63.Role);
}
if(t64.Buffs != null)
{
Utils.TryAdd(t, t64.Role, t64.Role);
}
if(t66.Buffs != null)
{
Utils.TryAdd(t, t66.Role, t66.Role);
}
if(t67.Buffs != null)
{
Utils.TryAdd(t, t67.Role, t67.Role);
}
if(t68.Buffs != null)
{
Utils.TryAdd(t, t68.Role, t68.Role);
}
if(t69.Buffs != null)
{
Utils.TryAdd(t, t69.Role, t69.Role);
}
if(t70.Buffs != null)
{
Utils.TryAdd(t, t70.Role, t70.Role);
}
if(t71.Buffs != null)
{
Utils.TryAdd(t, t71.Role, t71.Role);
}
if(t72.Buffs != null)
{
Utils.TryAdd(t, t72.Role, t72.Role);
}
if(t73.Buffs != null)
{
Utils.TryAdd(t, t73.Role, t73.Role);
}
if(t74.Buffs != null)
{
Utils.TryAdd(t, t74.Role, t74.Role);
}
if(t75.Buffs != null)
{
Utils.TryAdd(t, t75.Role, t75.Role);
}
if(t76.Buffs != null)
{
Utils.TryAdd(t, t76.Role, t76.Role);
}
if(t77.Buffs != null)
{
Utils.TryAdd(t, t77.Role, t77.Role);
}
if(t78.Buffs != null)
{
Utils.TryAdd(t, t78.Role, t78.Role);
}
if(t79.Buffs != null)
{
Utils.TryAdd(t, t79.Role, t79.Role);
}
if(t80.Buffs != null)
{
Utils.TryAdd(t, t80.Role, t80.Role);
}
if(t81.Buffs != null)
{
Utils.TryAdd(t, t81.Role, t81.Role);
}
if(t82.Buffs != null)
{
Utils.TryAdd(t, t82.Role, t82.Role);
}
if(t83.Buffs != null)
{
Utils.TryAdd(t, t83.Role, t83.Role);
}
if(t84.Buffs != null)
{
Utils.TryAdd(t, t84.Role, t84.Role);
}
if(t85.Buffs != null)
{
Utils.TryAdd(t, t85.Role, t85.Role);
}
if(t86.Buffs != null)
{
Utils.TryAdd(t, t86.Role, t86.Role);
}
if(t87.Buffs != null)
{
Utils.TryAdd(t, t87.Role, t87.Role);
}
if(t88.Buffs != null)
{
Utils.TryAdd(t, t88.Role, t88.Role);
}
if(t89.Buffs != null)
{
Utils.TryAdd(t, t89.Role, t89.Role);
}
if(t90.Buffs != null)
{
Utils.TryAdd(t, t90.Role, t90.Role);
}
if(t91.Buffs != null)
{
Utils.TryAdd(t, t91.Role, t91.Role);
}
if(t92.Buffs != null)
{
Utils.TryAdd(t, t92.Role, t92.Role);
}
if(t93.Buffs != null)
{
Utils.TryAdd(t, t93.Role, t93.Role);
}
if(t94.Buffs != null)
{
Utils.TryAdd(t, t94.Role, t94.Role);
}
if(t95.Buffs != null)
{
Utils.TryAdd(t, t95.Role, t95.Role);
}
if(t96.Buffs != null)
{
Utils.TryAdd(t, t96.Role, t96.Role);
}
if(t97.Buffs != null)
{
Utils.TryAdd(t, t97.Role, t97.Role);
}
if(t98.Buffs != null)
{
Utils.TryAdd(t, t98.Role, t98.Role);
}
if(t99.Buffs != null)
{
Utils.TryAdd(t, t99.Role, t99.Role);
}
if(t100.Buffs != null)
{
Utils.TryAdd(t, t100.Role, t100.Role);
}
if(t101.Buffs != null)
{
Utils.TryAdd(t, t101.Role, t101.Role);
}
if(t103.Buffs != null)
{
Utils.TryAdd(t, t103.Role, t103.Role);
}
if(t104.Buffs != null)
{
Utils.TryAdd(t, t104.Role, t104.Role);
}
#endregion
File.WriteAllText("tge_roles.json", FileLoader.SerializeWithIndentation(t));
#endregion*/
}
}
}

View file

@ -15,8 +15,7 @@ namespace PvZ_Fusion_Translator.Patches.Modes.Odyssey
[HarmonyPostfix] [HarmonyPostfix]
public static void Start(SynergyDisplay __instance) public static void Start(SynergyDisplay __instance)
{ {
__instance.text1.text = TranslateInvestDisplay(__instance.text1.text); __instance.text.text = TranslateInvestDisplay(__instance.text.text);
__instance.text_shadow.text = Utils.RemoveColorTags(__instance.text1.text);
} }
public static string TranslateInvestDisplay(string originalText) public static string TranslateInvestDisplay(string originalText)

View file

@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HarmonyLib;
using Il2Cpp;
using PvZ_Fusion_Translator.AssetStore;
using UnityEngine;
namespace PvZ_Fusion_Translator.Patches.Modes.Odyssey
{
[HarmonyPatch(typeof(TravelAdvantureMenu))]
public static class TravelAdvantureMenu_Patch
{
[HarmonyPatch(nameof(TravelAdvantureMenu.Awake))]
[HarmonyPostfix]
public static void Awake(TravelAdvantureMenu __instance)
{
foreach(CustomButton_enterGame button in __instance.GetComponentsInChildren<CustomButton_enterGame>())
{
string plantName = Utils.GetPlantNameFromAlmanac(button.levelName.text);
if(Utils.Language == Utils.LanguageEnum.Arabic)
{
button.levelName.text = StringStore.TranslateText(button.levelName.text);
}
else
{
button.levelName.text = (plantName != "") ? plantName : StringStore.TranslateText(button.levelName.text);
}
}
}
[HarmonyPatch(nameof(TravelAdvantureMenu.LookWeak))]
[HarmonyPostfix]
public static void LookWeak(TravelAdvantureMenu __instance)
{
Awake(__instance);
}
[HarmonyPatch(nameof(TravelAdvantureMenu.LookUlti))]
[HarmonyPostfix]
public static void LookUlti(TravelAdvantureMenu __instance)
{
Awake(__instance);
}
}
}

View file

@ -27,11 +27,21 @@ namespace PvZ_Fusion_Translator.Patches.Modes.Odyssey
public static void TranslateOptionButton(TravelBuffOptionButton button) public static void TranslateOptionButton(TravelBuffOptionButton button)
{ {
SortedDictionary<int, string> buffSet = translatedTravelBuffs[buffLinks[button.buffType]]; if(TravelMgr_Patch.travelBuffString.ContainsKey(button.introduce.text))
{
string translatedBuff = travelBuffString[button.introduce.text];
button.introduce.text = AddBuffName(translatedBuff);
}
string buff = button.show != null && button.introduce.text != "词条已选完" ? buffSet[button.buffIndex] : StringStore.TranslateText("词条已选完"); if(!Utils.CheckForUntranslatedText(button.introduce.text))
{
button.introduce.text = AddBuffName(button.introduce.text);
}
button.introduce.text = buff; if(!TravelMgr_Patch.travelBuffString.ContainsKey(button.introduce.text) && Utils.CheckForUntranslatedText(button.introduce.text))
{
button.introduce.text = StringStore.TranslateText(button.introduce.text);
}
} }
} }

View file

@ -38,9 +38,28 @@ namespace PvZ_Fusion_Translator.Patches.Modes.Odyssey
[HarmonyPostfix] [HarmonyPostfix]
public static void Post_SetBuff(TravelLookBuff __instance) public static void Post_SetBuff(TravelLookBuff __instance)
{ {
SortedDictionary<int, string> buffSet = translatedTravelBuffs[buffLinks[__instance.buffType]]; /*SortedDictionary<int, string> buffSet = translatedTravelBuffs[buffLinks[__instance.buffType]];
string buffText = buffSet.ContainsKey(__instance.buffIndex) ? buffSet[__instance.buffIndex] : StringStore.TranslateText(__instance.introduce.text); string buffText = buffSet.ContainsKey(__instance.buffIndex) ? buffSet[__instance.buffIndex] : StringStore.TranslateText(__instance.introduce.text);
__instance.introduce.text = buffText; __instance.introduce.text = buffText;*/
foreach (TextMeshProUGUI text in __instance.transform.FindChild("Images").FindChild("Introduce").GetComponentsInChildren<TextMeshProUGUI>())
{
if(TravelMgr_Patch.travelBuffString.ContainsKey(text.text))
{
string translatedBuff = travelBuffString[text.text];
text.text = AddBuffName(translatedBuff);
}
if(!Utils.CheckForUntranslatedText(text.text))
{
text.text = AddBuffName(text.text);
}
if(!TravelMgr_Patch.travelBuffString.ContainsKey(text.text) && Utils.CheckForUntranslatedText(text.text))
{
text.text = StringStore.TranslateText(text.text);
}
}
foreach (TextMeshProUGUI text in __instance.transform.FindChild("Images").FindChild("Button").GetComponentsInChildren<TextMeshProUGUI>()) foreach (TextMeshProUGUI text in __instance.transform.FindChild("Images").FindChild("Button").GetComponentsInChildren<TextMeshProUGUI>())
{ {

View file

@ -1,5 +1,6 @@
using HarmonyLib; using HarmonyLib;
using Il2Cpp; using Il2Cpp;
using PvZ_Fusion_Translator.AssetStore;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@ -13,25 +14,85 @@ using static PvZ_Fusion_Translator.FileLoader;
namespace PvZ_Fusion_Translator.Patches.Modes.Odyssey namespace PvZ_Fusion_Translator.Patches.Modes.Odyssey
{ {
public class TravelBuffInfo
{
public string name = "";
public string desc = "";
public TravelBuffInfo(string name_a = "", string desc_a = "")
{
name = name_a;
desc = desc_a;
}
}
public class TravelBuffSet
{
public SortedDictionary<int, TravelBuffInfo> advancedBuffs = new();
public SortedDictionary<int, TravelBuffInfo> ultimateBuffs = new();
public SortedDictionary<int, TravelBuffInfo> debuffs = new();
public SortedDictionary<int, TravelBuffInfo> unlocks = new();
public SortedDictionary<int, TravelBuffInfo> investmentBuffs = new();
private Dictionary<string, SortedDictionary<int, TravelBuffInfo>> _travelBuffSets = [];
public TravelBuffSet()
{
advancedBuffs = new();
ultimateBuffs = new();
debuffs = new();
unlocks = new();
investmentBuffs = new();
_travelBuffSets = new()
{
{ "advancedBuffs", advancedBuffs },
{ "ultimateBuffs", ultimateBuffs },
{ "debuffs", debuffs },
{ "unlocks", unlocks },
{ "investmentBuffs", investmentBuffs }
};
}
public SortedDictionary<int, TravelBuffInfo> TryGet(string name)
{
switch(name)
{
case "advancedBuffs":
return advancedBuffs;
case "ultimateBuffs":
return ultimateBuffs;
case "debuffs":
return debuffs;
case "unlocks":
return unlocks;
case "investmentBuffs":
return investmentBuffs;
default:
return null;
}
}
public IEnumerator<ValueTuple<string, SortedDictionary<int, TravelBuffInfo>>> GetEnumerator()
{
foreach(var item in _travelBuffSets)
{
yield return new(item.Key, item.Value);
}
}
}
[HarmonyPatch(typeof(TravelMgr))] [HarmonyPatch(typeof(TravelMgr))]
public static class TravelMgr_Patch public static class TravelMgr_Patch
{ {
public static Dictionary<string, SortedDictionary<int, string>> dumpedTravelBuffs = new() public static readonly TravelBuffSet templateTravelBuffs = new();
{
{ "advancedBuffs", new SortedDictionary<int, string>() },
{ "ultimateBuffs", new SortedDictionary<int, string>() },
{ "debuffs", new SortedDictionary<int, string>() },
{ "unlocks", new SortedDictionary<int, string>() },
{ "investmentBuffs", new SortedDictionary<int, string>() }
};
public static Dictionary<string, SortedDictionary<int, string>> translatedTravelBuffs = new() public static TravelBuffSet dumpedTravelBuffs = new();
public static TravelBuffSet translatedTravelBuffs = new();
public static Dictionary<string, string> travelBuffString = new()
{ {
{ "advancedBuffs", new SortedDictionary<int, string>() },
{ "ultimateBuffs", new SortedDictionary<int, string>() },
{ "debuffs", new SortedDictionary<int, string>() },
{ "unlocks", new SortedDictionary<int, string>() },
{ "investmentBuffs", new SortedDictionary<int, string>() }
}; };
public static Dictionary<BuffType, string> buffLinks = new() public static Dictionary<BuffType, string> buffLinks = new()
@ -43,65 +104,135 @@ namespace PvZ_Fusion_Translator.Patches.Modes.Odyssey
{ BuffType.InvestmentBuff, "investmentBuffs" } { BuffType.InvestmentBuff, "investmentBuffs" }
}; };
[HarmonyPatch(nameof(TravelMgr.GetText))]
[HarmonyPostfix]
public static void GetText(TravelMgr __instance, ref string __result)
{
if (travelBuffString.ContainsKey(__result))
{
__result = travelBuffString[__result];
}
else if(travelBuffString.ContainsKey(RemoveBuffName(__result)))
{
__result = travelBuffString[RemoveBuffName(__result)];
}
else
{
__result = StringStore.TranslateText(__result);
}
}
public static void DumpTravelBuffs() public static void DumpTravelBuffs()
{ {
TravelMgr.Instance.GetPlantBuffUnlockCount(PlantType.DoomGatling); TravelMgr.Instance.GetPlantBuffUnlockCount(PlantType.DoomGatling);
dumpedTravelBuffs = new();
travelBuffString.Clear();
foreach (var pair in TravelDictionary.advancedBuffsText) foreach (var pair in TravelDictionary.advancedBuffsText)
{ {
dumpedTravelBuffs["advancedBuffs"].Add((int)pair.Key, pair.Value); Utils.TryAdd(dumpedTravelBuffs.advancedBuffs, (int)pair.Key, new TravelBuffInfo("", pair.Value));
Utils.TryAdd(travelBuffString, pair.Value, pair.Value);
} }
foreach (var pair in TravelDictionary.ultimateBuffsText) foreach (var pair in TravelDictionary.ultimateBuffsText)
{ {
dumpedTravelBuffs["ultimateBuffs"].Add((int)pair.Key, pair.Value); Utils.TryAdd(dumpedTravelBuffs.ultimateBuffs, (int)pair.Key, new TravelBuffInfo("", pair.Value));
Utils.TryAdd(travelBuffString, pair.Value, pair.Value);
} }
foreach (var pair in TravelDictionary.debuffData) foreach (var pair in TravelDictionary.debuffData)
{ {
dumpedTravelBuffs["debuffs"].Add((int)pair.Key, pair.Value.Item1); Utils.TryAdd(dumpedTravelBuffs.debuffs, (int)pair.Key, new TravelBuffInfo("", pair.Value.Item1));
Utils.TryAdd(travelBuffString, pair.Value.Item1, pair.Value.Item1);
} }
foreach (var pair in TravelDictionary.unlocksText) foreach (var pair in TravelDictionary.unlocksText)
{ {
dumpedTravelBuffs["unlocks"].Add((int)pair.Key, pair.Value); Utils.TryAdd(dumpedTravelBuffs.unlocks, (int)pair.Key, new TravelBuffInfo("", pair.Value));
Utils.TryAdd(travelBuffString, pair.Value, pair.Value);
} }
foreach (var pair in TravelMgr.InvestBuffsData) foreach (var pair in TravelMgr.InvestBuffsData)
{ {
dumpedTravelBuffs["investmentBuffs"].Add((int)pair.Key, pair.Value.GetDescription()); Utils.TryAdd(dumpedTravelBuffs.investmentBuffs, (int)pair.Key, new TravelBuffInfo("", pair.Value.GetDescription()));
Utils.TryAdd(travelBuffString, pair.Value.GetDescription(), pair.Value.GetDescription());
} }
File.WriteAllText(Path.Combine(GetAssetDir(AssetType.Dumps), "travel_buffs.json"), JsonSerializer.Serialize(dumpedTravelBuffs, new JsonSerializerOptions File.WriteAllText(Path.Combine(GetAssetDir(AssetType.Dumps), "travel_buffs.json"), SerializeWithIndentation(dumpedTravelBuffs));
{
WriteIndented = true,
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
}));
string translatedTravelBuffsPath = Path.Combine(GetAssetDir(AssetType.Strings, Utils.Language), "travel_buffs.json"); string translatedTravelBuffsPath = Path.Combine(GetAssetDir(AssetType.Strings, Utils.Language), "travel_buffs.json");
if (!File.Exists(translatedTravelBuffsPath)) if (!File.Exists(translatedTravelBuffsPath))
{ {
File.WriteAllText(translatedTravelBuffsPath, JsonSerializer.Serialize(dumpedTravelBuffs, new JsonSerializerOptions File.WriteAllText(translatedTravelBuffsPath, SerializeWithIndentation(dumpedTravelBuffs));
{
WriteIndented = true,
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
}));
translatedTravelBuffs = dumpedTravelBuffs; translatedTravelBuffs = dumpedTravelBuffs;
} }
} }
//System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, SortedDictionary<int, string>>>(travelBuffsContent);
public static void GenerateTranslatedTravelBuffs(string travelBuffsContent)
{
if (!Core.isInitialized) return;
DumpTravelBuffs();
TravelBuffSet travelBuffs = Newtonsoft.Json.JsonConvert.DeserializeObject<TravelBuffSet>(travelBuffsContent);
translatedTravelBuffs = travelBuffs;
travelBuffString.Clear();
foreach(var i in travelBuffs)
{
var originalBuffSet = dumpedTravelBuffs.TryGet(i.Item1);
foreach(var j in originalBuffSet)
{
TravelBuffInfo originalBuff = j.Value;
var translatedBuffSet = travelBuffs.TryGet(i.Item1);
if (j.Value.desc == originalBuff.desc)
{
if (translatedBuffSet.ContainsKey(j.Key))
{
Utils.TryAdd(travelBuffString, originalBuff.desc, translatedBuffSet[j.Key].desc);
}
}
else if(j.Value.desc == RemoveBuffName(originalBuff.desc))
{
if (translatedBuffSet.ContainsKey(j.Key))
{
Utils.TryAdd(travelBuffString, originalBuff.desc, translatedBuffSet[j.Key].desc);
}
}
/*var translatedBuffSet = travelBuffs[i.Key];
if(translatedBuffSet.ContainsKey(j.Key))
{
string translatedBuff = travelBuffs[i.Key][j.Key];
travelBuffString[originalBuff] = translatedBuff;
}*/
}
}
string travelBuffsToSave = SerializeWithIndentation(TravelMgr_Patch.translatedTravelBuffs);
string stringDir = GetAssetDir(AssetType.Strings, Utils.Language);
File.WriteAllText(Path.Combine(stringDir, "travel_buffs.json"), travelBuffsToSave);
}
public static string MatchTravelBuff(string originalText) public static string MatchTravelBuff(string originalText)
{ {
string res = ""; string res = "";
foreach (var i in dumpedTravelBuffs) foreach (var i in dumpedTravelBuffs)
{ {
foreach (var j in dumpedTravelBuffs[i.Key]) foreach (var j in dumpedTravelBuffs.TryGet(i.Item1))
{ {
if (j.Value == originalText || j.Value == RemoveBuffName(originalText)) if (j.Value.desc == originalText || j.Value.desc == RemoveBuffName(originalText))
{ {
res = translatedTravelBuffs[i.Key][j.Key]; var translatedBuffSet = translatedTravelBuffs.TryGet(i.Item1);
if (translatedBuffSet.ContainsKey(j.Key))
{
res = translatedBuffSet[j.Key].desc;
}
break; break;
} }
} }
@ -122,5 +253,115 @@ namespace PvZ_Fusion_Translator.Patches.Modes.Odyssey
} }
return res; return res;
} }
public static Dictionary<string, string> modifierNameDict = new Dictionary<string, string>()
{
{ "advancedBuffs", "COMMON_MODIFIER_TAG" },
{ "ultimateBuffs", "EPIC_MODIFIER_TAG" },
{ "debuffs", "ZOMBIE_MODIFIER_TAG" },
{ "unlocks", "UNLOCK_MODIFIER_TAG" },
{ "investmentBuffs", "INVEST_MODIFIER_TAG" }
};
public static Dictionary<string, string> fallbackNameDict = new Dictionary<string, string>()
{
{ "COMMON_MODIFIER_TAG", "Common Modifier" },
{ "EPIC_MODIFIER_TAG", "Epic Modifier" },
{ "ZOMBIE_MODIFIER_TAG", "Zombie Modifier" },
{ "UNLOCK_MODIFIER_TAG", "Unlock Modifier" },
{ "INVEST_MODIFIER_TAG", "Investment Modifier" }
};
public static string TranslateNameTag(string originalText)
{
string res = originalText;
string nameTag = modifierNameDict[originalText];
res = StringStore.translationString.ContainsKey(nameTag) ? StringStore.TranslateText(nameTag) : fallbackNameDict[nameTag];
return res;
}
public static ValueTuple<string, int, string, bool> FindBuffData(string buffText)
{
ValueTuple<string, int, string, bool> res = new();
foreach(var pair1 in translatedTravelBuffs)
{
foreach(var pair2 in pair1.Item2)
{
if(buffText == pair2.Value.desc)
{
if(pair2.Value.name != "")
{
res.Item1 = pair2.Value.name;
res.Item4 = true;
}
else
{
res.Item1 = TranslateNameTag(pair1.Item1);
res.Item4 = false;
}
res.Item2 = pair2.Key;
}
}
}
foreach(var pair1 in dumpedTravelBuffs)
{
foreach(var pair2 in pair1.Item2)
{
if(buffText == pair2.Value.desc)
{
if(pair2.Value.name != "")
{
res.Item1 = pair2.Value.name;
res.Item4 = true;
}
else
{
res.Item1 = TranslateNameTag(pair1.Item1);
res.Item4 = false;
}
res.Item2 = pair2.Key;
}
}
}
string finalBuffText = buffText;
if(travelBuffString.ContainsKey(buffText))
{
finalBuffText = travelBuffString[buffText];
}
else
{
finalBuffText = StringStore.TranslateText(buffText);
}
res.Item3 = finalBuffText;
return res;
}
public static string fallbackFBuffStr = "{0}: {1}";
public static string AddBuffName(string buffText)
{
string translatedBuff = buffText;
if(Utils.CheckForUntranslatedText(buffText))
{
if(travelBuffString.ContainsKey(buffText))
{
translatedBuff = travelBuffString[buffText];
}
}
var buffData = FindBuffData(translatedBuff);
if(buffData.Item1 != null && buffData.Item3 != null)
{
string buffFStr = StringStore.translationStringRegex.ContainsKey("BUFF_NAME_FORMAT") ? StringStore.translationStringRegex["BUFF_NAME_FORMAT"] : "{0}: {1}";
string fBuffDesc = string.Format(buffFStr, buffData.Item1, buffData.Item3);
translatedBuff = fBuffDesc;
}
return translatedBuff;
}
} }
} }

View file

@ -2,9 +2,10 @@
using Il2Cpp; using Il2Cpp;
using Il2CppTMPro; using Il2CppTMPro;
using PvZ_Fusion_Translator.AssetStore; using PvZ_Fusion_Translator.AssetStore;
using static PvZ_Fusion_Translator.Patches.Modes.Odyssey.TravelMgr_Patch;
using UnityEngine;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using UnityEngine;
using static Il2CppSystem.Globalization.TimeSpanFormat;
using static PvZ_Fusion_Translator.Patches.Modes.Odyssey.TravelMgr_Patch;
namespace PvZ_Fusion_Translator.Patches.Modes.Odyssey namespace PvZ_Fusion_Translator.Patches.Modes.Odyssey
{ {
@ -15,14 +16,23 @@ namespace PvZ_Fusion_Translator.Patches.Modes.Odyssey
[HarmonyPostfix] [HarmonyPostfix]
private static void SetType(TravelStoreWindow __instance) private static void SetType(TravelStoreWindow __instance)
{ {
var buffSet = translatedTravelBuffs[buffLinks[__instance.buffType]]; /*var buffSet = translatedTravelBuffs[buffLinks[__instance.buffType]];
string buff = __instance.show != null && __instance.introduce.text != "词条已选完" ? buffSet[__instance.buffIndex] : StringStore.TranslateText("词条已选完"); string buff = __instance.show != null && __instance.introduce.text != "词条已选完" ? buffSet[__instance.buffIndex] : StringStore.TranslateText("词条已选完");*/
string originalText = __instance.introduce.text; string originalText = __instance.introduce.text;
string affinityPattern = "([\\s\\S]+)(\\\n<color=red>)([\\s\\S]+)(<\\/color>)";
string affinities = TranslateAffinities(originalText); if(Regex.IsMatch(__instance.introduce.text, affinityPattern, options: RegexOptions.Singleline))
{
__instance.introduce.text = buff + affinities; Match match = Regex.Match(__instance.introduce.text, affinityPattern, options: RegexOptions.Singleline);
string startText = match.Groups[1].Value;
string affinityText = match.Groups[3].Value;
string affinities = TranslateAffinities(affinityText);
__instance.introduce.text = AddBuffName(startText) + affinities;
}
else
{
__instance.introduce.text = AddBuffName(originalText);
}
foreach (var text in __instance.buttonText) foreach (var text in __instance.buttonText)
{ {
@ -42,55 +52,41 @@ namespace PvZ_Fusion_Translator.Patches.Modes.Odyssey
public static string TranslateAffinities(string originalText) public static string TranslateAffinities(string originalText)
{ {
string discolored = Utils.RemoveColorTags(originalText);
int firstNewlineIndex = discolored.IndexOf('\n');
string result = ""; string result = "";
List<string> translatedAffinities = []; List<string> translatedAffinities = [];
if(firstNewlineIndex >= 0) string[] lines = originalText.Split('\n');
foreach(string line in lines)
{ {
string affinityString = discolored.Substring(firstNewlineIndex); if (string.IsNullOrEmpty(line)) continue;
string[] affinities = affinityString.Split('\n');
string fStr = StringStore.translationStringRegex.ContainsKey("【([^\\s]+)】_IV") ? StringStore.translationStringRegex["【([^\\s]+)】_IV"] : "[{0}]"; string fStr = StringStore.translationStringRegex.ContainsKey("【([^\\s]+)】_IV") ? StringStore.translationStringRegex["【([^\\s]+)】_IV"] : "[{0}]";
string originalPattern = "【([^\\s]+)】";
foreach (string affinity in affinities) // Extract dynamic parts from the original text
var regex = new Regex("【([^\\s]+)】");
var match = regex.Match(line);
int groupCount = match.Groups.Count;
// List to hold formatted dynamic parts
List<string> dynamicParts = [];
// Loop through each group and determine its translation
for (int i = 1; i < groupCount; i++)
{ {
if(affinity != "") string groupValue = match.Groups[i].Value;
{ string translatedValue = StringStore.translationString.ContainsKey(groupValue)
string translatedAffinity = affinity; ? StringStore.translationString[groupValue]
if (StringStore.TestRegex(affinity, originalPattern)) : groupValue;
{ dynamicParts.Add(translatedValue);
// 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<string> 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" + "<color=red>" + String.Join("\n", translatedAffinities) + "</color>";
// Format the output string with dynamic parts
string translatedAffinity = string.Format(fStr, [.. dynamicParts]);
translatedAffinities.Add(translatedAffinity);
} }
result = "\n" + "<color=red>" + String.Join("\n", translatedAffinities) + "</color>";
return result; return result;
} }
} }

View file

@ -69,6 +69,11 @@ namespace PvZ_Fusion_Translator.Patches.Modes.Odyssey
{ {
string res = investText; string res = investText;
if(!Utils.CheckForUntranslatedText(res))
{
return res;
}
string[] investStats = investText.Split("\n\n"); string[] investStats = investText.Split("\n\n");
List<string> translatedInvestStats = new List<string>(); List<string> translatedInvestStats = new List<string>();
foreach(string investStat in investStats) foreach(string investStat in investStats)

View file

@ -0,0 +1,104 @@
using HarmonyLib;
using Il2Cpp;
using Il2CppGameLevel;
using Il2CppGameLevel.EventNodes;
using PvZ_Fusion_Translator.AssetStore;
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.VisualScripting.FullSerializer;
using UnityEngine;
using UnityEngine.UIElements;
namespace PvZ_Fusion_Translator.Patches.Modes.Super_Editor
{
[HarmonyPatch(typeof(CustomButton_enterGame))]
public static class CustomButton_enterGame_Patch
{
[HarmonyPatch(nameof(CustomButton_enterGame.LoadOnlineLevelAsync))]
[HarmonyPostfix]
public static void LoadOnlineLevelAsync(CustomButton_enterGame __instance)
{
string dumpPath = Path.Combine(FileLoader.GetAssetDir(FileLoader.AssetType.Dumps), "custom_level_data.json");
Dictionary<string, TranslatedLevelData> dumpData = new Dictionary<string, TranslatedLevelData>();
if (!File.Exists(dumpPath))
{
File.WriteAllText(dumpPath, System.Text.Json.JsonSerializer.Serialize(dumpData, new JsonSerializerOptions
{
WriteIndented = true,
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
}));
}
dumpData = JsonSerializer.Deserialize<Dictionary<string, TranslatedLevelData>>(File.ReadAllText(dumpPath));
string dumpStringsPath = Path.Combine(FileLoader.GetAssetDir(FileLoader.AssetType.Dumps), "custom_level_strings.json");
Dictionary<string, string> dumpStringsData = new Dictionary<string, string>();
if (!File.Exists(dumpStringsPath))
{
File.WriteAllText(dumpStringsPath, System.Text.Json.JsonSerializer.Serialize(dumpStringsData, new JsonSerializerOptions
{
WriteIndented = true,
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
}));
}
dumpStringsData = JsonSerializer.Deserialize<Dictionary<string, string>>(File.ReadAllText(dumpStringsPath));
var level = __instance;
if(level.onlineLevelInfo != null)
{
string levelId = level.onlineLevelInfo.levelId;
if(levelId != null)
{
SerializedLevelData serializedLevel = level.serializedLevel;
if(CustomLevelMenu_Patch.translatedLevelData.ContainsKey(levelId))
{
TranslatedLevelData levelData = CustomLevelMenu_Patch.translatedLevelData[levelId];
level.levelName.text = levelData.name;
serializedLevel.name = levelData.name;
serializedLevel.boardConfig.startTip = levelData.startTip;
}
else
{
TranslatedLevelData dumpedLevelData = new TranslatedLevelData(level.onlineLevelInfo.levelName, serializedLevel.boardConfig.startTip);
if (dumpData.ContainsKey(levelId))
{
dumpData[levelId] = dumpedLevelData;
}
else
{
dumpData.Add(levelId, dumpedLevelData);
}
}
/*level.levelData.SerializedLevelData
foreach()*/
}
}
else
{
level.levelName.text = StringStore.TranslateText(level.levelName.text);
}
File.WriteAllText(dumpPath, System.Text.Json.JsonSerializer.Serialize(dumpData, new JsonSerializerOptions
{
WriteIndented = true,
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
}));
File.WriteAllText(dumpStringsPath, System.Text.Json.JsonSerializer.Serialize(dumpStringsData, new JsonSerializerOptions
{
WriteIndented = true,
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
}));
}
}
}

View file

@ -36,13 +36,20 @@ namespace PvZ_Fusion_Translator.Patches.Modes.Super_Editor
} }
} }
[HarmonyPatch(nameof(CustomLevelMenu.InitWindows))] [HarmonyPatch(nameof(CustomLevelMenu.InitLocalWindows))]
[HarmonyPostfix] [HarmonyPostfix]
public static void InitWindows(CustomLevelMenu __instance) public static void InitWindows(CustomLevelMenu __instance)
{ {
TranslateLevelButtons(__instance); TranslateLevelButtons(__instance);
} }
[HarmonyPatch(nameof(CustomLevelMenu.InitOnlineWindow))]
[HarmonyPostfix]
public static void InitOnlineWindow(CustomLevelMenu __instance)
{
TranslateLevelButtons(__instance);
}
[HarmonyPatch(nameof(CustomLevelMenu.ReloadFiles))] [HarmonyPatch(nameof(CustomLevelMenu.ReloadFiles))]
[HarmonyPostfix] [HarmonyPostfix]
public static void ReloadFiles(CustomLevelMenu __instance) public static void ReloadFiles(CustomLevelMenu __instance)
@ -52,33 +59,45 @@ namespace PvZ_Fusion_Translator.Patches.Modes.Super_Editor
public static void TranslateLevelButtons(CustomLevelMenu __instance) public static void TranslateLevelButtons(CustomLevelMenu __instance)
{ {
string dumpPath = Path.Combine(FileLoader.GetAssetDir(FileLoader.AssetType.Dumps), "custom_level_data.json");
Dictionary<string, TranslatedLevelData> dumpData = new Dictionary<string, TranslatedLevelData>(); Dictionary<string, TranslatedLevelData> dumpData = new Dictionary<string, TranslatedLevelData>();
if (!File.Exists(dumpPath))
{
File.WriteAllText(dumpPath, System.Text.Json.JsonSerializer.Serialize(dumpData, new JsonSerializerOptions
{
WriteIndented = true,
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
}));
}
foreach(CustomButton_enterGame level in __instance.levels) foreach(CustomButton_enterGame level in __instance.levels)
{ {
string levelId = level.levelData.levelId; if(level.onlineLevelInfo != null)
if(levelId != null)
{ {
if(translatedLevelData.ContainsKey(levelId)) string levelId = level.onlineLevelInfo.levelId;
if(levelId != null)
{ {
TranslatedLevelData levelData = translatedLevelData[levelId]; if(translatedLevelData.ContainsKey(levelId))
level.levelName.text = levelData.name; {
level.levelData.Name = levelData.name; TranslatedLevelData levelData = translatedLevelData[levelId];
level.serializedLevel.boardConfig.startTip = levelData.startTip; level.levelName.text = levelData.name;
} level.serializedLevel.name = levelData.name;
else level.serializedLevel.boardConfig.startTip = levelData.startTip;
{ }
TranslatedLevelData dumpedLevelData = new TranslatedLevelData(level.levelData.Name, level.serializedLevel.boardConfig.startTip); else
dumpData.Add(levelId, dumpedLevelData); {
TranslatedLevelData dumpedLevelData = new TranslatedLevelData(level.onlineLevelInfo.levelName, level.serializedLevel.boardConfig.startTip);
dumpData.Add(levelId, dumpedLevelData);
}
} }
} }
else else
{ {
level.levelName.text = StringStore.TranslateText(level.levelData.Name); level.levelName.text = StringStore.TranslateText(level.levelName.text);
} }
} }
string dumpPath = Path.Combine(FileLoader.GetAssetDir(FileLoader.AssetType.Dumps), "custom_level_data.json");
File.WriteAllText(dumpPath, System.Text.Json.JsonSerializer.Serialize(dumpData, new JsonSerializerOptions File.WriteAllText(dumpPath, System.Text.Json.JsonSerializer.Serialize(dumpData, new JsonSerializerOptions
{ {
WriteIndented = true, WriteIndented = true,

View file

@ -0,0 +1,29 @@
/*using MelonLoader;
using HarmonyLib;
using UnityEngine;
using Il2Cpp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Il2CppTMPro;
using PvZ_Fusion_Translator.AssetStore;
using Il2CppGameLevel;
using PvZ_Fusion_Translator.Patches.Modes.Super_Editor.GameLevel.EventNodes;
namespace PvZ_Fusion_Translator.Patches.Modes.Super_Editor
{
[HarmonyPatch(typeof(CustomMenuPage_event))]
public static class CustomMenuPage_event_Patch
{
[HarmonyPatch(nameof(CustomMenuPage_event.InitializeNodeEditor))]
[HarmonyPostfix]
public static void InitializeNodeEditor(CustomMenuPage_event __instance)
{
RuntimeEventNodeEditor_Patch.Update(__instance.nodeEditor);
NodeInfoPanel_Patch.UpdatePanelContent(__instance.nodeInfoPanel);
}
}
}
*/

View file

@ -1,14 +1,17 @@
using MelonLoader; using HarmonyLib;
using HarmonyLib;
using UnityEngine;
using Il2Cpp; using Il2Cpp;
using Il2CppGameLevel;
using Il2CppTMPro;
using MelonLoader;
using PvZ_Fusion_Translator.AssetStore;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Threading.Tasks; using System.Threading.Tasks;
using Il2CppTMPro; using UnityEngine;
using PvZ_Fusion_Translator.AssetStore;
namespace PvZ_Fusion_Translator.Patches.Modes.Super_Editor namespace PvZ_Fusion_Translator.Patches.Modes.Super_Editor
{ {
@ -34,6 +37,44 @@ namespace PvZ_Fusion_Translator.Patches.Modes.Super_Editor
string translatedText = StringStore.TranslateText(__instance.title.text); string translatedText = StringStore.TranslateText(__instance.title.text);
__instance.title.text = translatedText; __instance.title.text = translatedText;
__instance.title2.text = translatedText; __instance.title2.text = translatedText;
TranslateLevelData(__instance.levelData);
}
public static void TranslateLevelData(CustomLevelData levelData)
{
Dictionary<string, TranslatedLevelData> dumpData = new Dictionary<string, TranslatedLevelData>();
if(levelData != null)
{
string levelId = levelData.levelId;
if(levelId != null)
{
if(CustomLevelMenu_Patch.translatedLevelData.ContainsKey(levelId))
{
TranslatedLevelData translatedLevelData = CustomLevelMenu_Patch.translatedLevelData[levelId];
levelData.Name = translatedLevelData.name;
levelData.SerializedLevelData.name = translatedLevelData.name;
levelData.SerializedLevelData.boardConfig.startTip = translatedLevelData.startTip;
}
else
{
TranslatedLevelData dumpedLevelData = new TranslatedLevelData(levelData.Name, levelData.SerializedLevelData.boardConfig.startTip);
dumpData.Add(levelId, dumpedLevelData);
}
}
}
else
{
levelData.Name = StringStore.TranslateText(levelData.Name);
}
string dumpPath = Path.Combine(FileLoader.GetAssetDir(FileLoader.AssetType.Dumps), "custom_level_data.json");
File.WriteAllText(dumpPath, System.Text.Json.JsonSerializer.Serialize(dumpData, new JsonSerializerOptions
{
WriteIndented = true,
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
}));
} }
} }
} }

View file

@ -0,0 +1,49 @@
using HarmonyLib;
using Il2CppGameLevel.EventNodes;
using Il2CppTMPro;
using PvZ_Fusion_Translator.AssetStore;
using PvZ_Fusion_Translator.Patches.BaseTextObjects;
using UnityEngine;
namespace PvZ_Fusion_Translator.Patches.Modes.Super_Editor.GameLevel.EventNodes
{
[HarmonyPatch(typeof(RuntimeEventNodeEditor))]
public static class RuntimeEventNodeEditor_Patch
{
public static TMP_FontAsset fontAsset => FontStore.LoadTMPFont(Utils.Language.ToString());
[HarmonyPatch(nameof(RuntimeEventNodeEditor.Update))]
[HarmonyPostfix]
public static void Update(RuntimeEventNodeEditor __instance)
{
// translate the new screens (3.7)
TranslateFullTransform(__instance.nodeInfoPanel.transform);
TranslateFullTransform(__instance.attributePanel.transform);
TranslateFullTransform(__instance.canvas.transform);
if(__instance.TryGetComponent<EventNodeContextMenu>(out EventNodeContextMenu eventNodeContextMenu))
{
TranslateFullTransform(eventNodeContextMenu.transform);
}
}
public static void TranslateFullTransform(Transform transform)
{
if (transform == null) return;
foreach(TextMeshProUGUI txt in transform.GetComponentsInChildren<TextMeshProUGUI>())
{
txt.text = RuntimeNodeUI_Patch.TranslateCodeText(txt.text);
txt.font = fontAsset;
}
foreach(TMP_InputField inputField in transform.GetComponentsInChildren<TMP_InputField>())
{
TMP_InputField_Patch.OnEnable(inputField);
foreach(TextMeshProUGUI txt in inputField.GetComponentsInChildren<TextMeshProUGUI>(true))
{
txt.text = RuntimeNodeUI_Patch.TranslateCodeText(txt.text);
}
}
}
}
}

View file

@ -0,0 +1,143 @@
using HarmonyLib;
using Il2CppGameLevel.EventNodes;
using Il2CppTMPro;
using PvZ_Fusion_Translator.AssetStore;
using PvZ_Fusion_Translator.Patches.BaseTextObjects;
namespace PvZ_Fusion_Translator.Patches.Modes.Super_Editor.GameLevel.EventNodes
{
[HarmonyPatch(typeof(RuntimeNodeUI))]
public static class RuntimeNodeUI_Patch
{
[HarmonyPatch(nameof(RuntimeNodeUI.Awake))]
[HarmonyPatch(nameof(RuntimeNodeUI.CreatePorts))]
[HarmonyPatch(nameof(RuntimeNodeUI.CreateValueEditUI))]
[HarmonyPatch(nameof(RuntimeNodeUI.GetPortUI))]
[HarmonyPatch(nameof(RuntimeNodeUI.UpdateDisplay))]
[HarmonyPatch(nameof(RuntimeNodeUI.UpdateSelectionVisual))]
[HarmonyPatch(nameof(RuntimeNodeUI.UpdateVisable))]
[HarmonyPostfix]
public static void Post_UpdateDisplay(RuntimeNodeUI __instance)
{
if (!__instance.isActiveAndEnabled) return;
if (__instance.Node == null) return;
TMP_FontAsset fontAsset = FontStore.LoadTMPFont(Utils.Language.ToString());
__instance.titleText.text = TranslateCodeText(__instance.titleText.text);
__instance.titleText.font = fontAsset;
foreach(TextMeshProUGUI txt in __instance.inputPortsContainer.GetComponentsInChildren<TextMeshProUGUI>())
{
txt.text = TranslateCodeText(txt.text);
txt.font = fontAsset;
}
foreach(TextMeshProUGUI txt in __instance.outputPortsContainer.GetComponentsInChildren<TextMeshProUGUI>())
{
txt.text = TranslateCodeText(txt.text);
txt.font = fontAsset;
}
if (
__instance.GetComponentsInChildren<TMP_Dropdown>().Count == 0
&& __instance.GetComponentsInChildren<TMP_InputField>().Count == 0
&& __instance.Node.nodeType != "PlantTypeValueNode"
&& __instance.Node.nodeType != "SinglePlantTypeListNode"
&& __instance.Node.nodeType != "ZombieTypeValueNode"
) return;
if (__instance.Node != null)
{
if(__instance.Node.nodeType == "PlantTypeValueNode")
{
foreach(TextMeshProUGUI txt in __instance.GetComponentsInChildren<TextMeshProUGUI>())
{
if(txt.gameObject.name.Contains("Label"))
{
if (Utils.CheckForUntranslatedText(txt.text))
{
PlantTypeValueNode castedNode = __instance.Node.TryCast<PlantTypeValueNode>();
if (castedNode != null)
{
string portName = castedNode.value_PortName;
string plantName = Utils.GetPlantNameFromAlmanac(castedNode.value, removeTags: true);
txt.text = (plantName != "") ? plantName : StringStore.TranslateText(txt.text);
txt.font = fontAsset;
}
}
}
}
}
if(__instance.Node.nodeType == "SinglePlantTypeListNode")
{
foreach(TextMeshProUGUI txt in __instance.GetComponentsInChildren<TextMeshProUGUI>())
{
if (txt.gameObject.name.Contains("Label"))
{
if (Utils.CheckForUntranslatedText(txt.text))
{
SinglePlantTypeListNode castedNode = __instance.Node.TryCast<SinglePlantTypeListNode>();
if (castedNode != null)
{
string portName = castedNode.plantTypeList_PortName;
string plantName = Utils.GetPlantNameFromAlmanac(castedNode.plantType, removeTags: true);
txt.text = (plantName != "") ? plantName : StringStore.TranslateText(txt.text);
txt.font = fontAsset;
}
}
}
}
}
if(__instance.Node.nodeType == "ZombieTypeValueNode")
{
foreach(TextMeshProUGUI txt in __instance.GetComponentsInChildren<TextMeshProUGUI>())
{
if(txt.gameObject.name.Contains("Label"))
{
if(Utils.CheckForUntranslatedText(txt.text))
{
ZombieTypeValueNode castedNode = __instance.Node.TryCast<ZombieTypeValueNode>();
if(castedNode != null)
{
string portName = castedNode.value_PortName;
string zombieName = Utils.GetZombieNameFromAlmanac(castedNode.value, removeTags: true);
txt.text = (zombieName != "") ? zombieName : StringStore.TranslateText(txt.text);
txt.font = fontAsset;
}
}
}
}
}
}
if(__instance.GetComponentsInChildren<TMP_Dropdown>().Count > 0)
{
foreach(TMP_Dropdown dropdown in __instance.GetComponentsInChildren<TMP_Dropdown>())
{
TMP_Dropdown_Patch.CreateDropdownList(dropdown);
}
}
if(__instance.GetComponentsInChildren<TMP_InputField>().Count > 0)
{
foreach(TMP_InputField inputField in __instance.GetComponentsInChildren<TMP_InputField>())
{
TMP_InputField_Patch.OnEnable(inputField);
foreach(TextMeshProUGUI txt in inputField.GetComponentsInChildren<TextMeshProUGUI>(true))
{
txt.text = TranslateCodeText(txt.text);
}
}
}
}
public static string TranslateCodeText(string originalText)
{
return StringStore.translationString.ContainsKey(originalText + "_code") ? StringStore.TranslateText(originalText + "_code") : StringStore.TranslateText(originalText);
}
}
}

View file

@ -0,0 +1,280 @@
using HarmonyLib;
using Il2Cpp;
using Il2CppGameLevel;
using Il2CppGameLevel.EventNodes;
using MelonLoader;
using PvZ_Fusion_Translator.AssetStore;
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 UnityEngine;
namespace PvZ_Fusion_Translator.Patches.Modes.Super_Editor.GameLevel
{
[HarmonyPatch(typeof(LevelManager))]
public static class LevelManager_Patch
{
[HarmonyPatch(nameof(LevelManager.SaveLevelData))]
[HarmonyPrefix]
public static void Pre_SaveLevelData(LevelManager __instance, ref SerializedLevelData serializedLevelData)
{
if (serializedLevelData.name == "未命名关卡")
{
serializedLevelData.name = StringStore.translationString.ContainsKey("LEVEL_UNNAMED") ? StringStore.TranslateText("LEVEL_UNNAMED") : "Unnamed";
}
}
public static void ExportLevelStrings(SerializedLevelData serializedLevelData)
{
string levelDataString = JsonUtility.ToJson(serializedLevelData);
ReferenceLevelData referenceLevelData = Newtonsoft.Json.JsonConvert.DeserializeObject<ReferenceLevelData>(levelDataString);
EventNodeGraph eventNodeGraph = serializedLevelData.eventNodeGraph;
eventNodeGraph.BuildCache();
List<string> stringValueNodeIds = new List<string>();
List<string> stringConcatNodeIds = new List<string>();
List<string> showTextNodeIds = new List<string>();
List<string> addOptionNodeIds = new List<string>();
foreach (var reference in referenceLevelData.references.RefIds)
{
string nodeType = reference.data.nodeType;
string nodeId = reference.data.nodeId;
if (nodeType == "ShowTextNode")
{
if(!showTextNodeIds.Contains(nodeId))
{
showTextNodeIds.Add(nodeId);
}
}
else if (nodeType == "AddMultipleChoiceOptionNode")
{
if(!addOptionNodeIds.Contains(nodeId))
{
addOptionNodeIds.Add(nodeId);
}
}
}
foreach (var reference in referenceLevelData.references.RefIds)
{
string nodeType = reference.data.nodeType;
string nodeId = reference.data.nodeId;
switch(nodeType)
{
case "StringValueNode":
case "FloatToStringNode":
case "StringConcatNode":
stringValueNodeIds.Add(nodeId);
if(nodeType == "StringConcatNode")
{
stringConcatNodeIds.Add(nodeId);
}
break;
default:
break;
}
}
Dictionary<string, ValueTuple<string, string>> stringConcatNodePairs = new();
foreach(var connection in eventNodeGraph.connections)
{
string sourceNodeId = connection.sourceNodeId;
string sourcePortName = connection.sourcePortName;
string targetNodeId = connection.targetNodeId;
string targetPortName = connection.targetPortName;
if(stringValueNodeIds.Contains(sourceNodeId))
{
if(stringConcatNodeIds.Contains(targetNodeId))
{
if(stringConcatNodePairs.ContainsKey(targetNodeId))
{
ValueTuple<string, string> temp = stringConcatNodePairs[targetNodeId];
switch(targetPortName)
{
case "A":
temp.Item1 = sourceNodeId;
stringConcatNodePairs[targetNodeId] = temp;
break;
case "B":
temp.Item2 = sourceNodeId;
stringConcatNodePairs[targetNodeId] = temp;
break;
default:
break;
}
}
else
{
stringConcatNodePairs.Add(targetNodeId, new ValueTuple<string, string>());
ValueTuple<string, string> temp = stringConcatNodePairs[targetNodeId];
switch(targetPortName)
{
case "A":
temp.Item1 = sourceNodeId;
stringConcatNodePairs[targetNodeId] = temp;
break;
case "B":
temp.Item2 = sourceNodeId;
stringConcatNodePairs[targetNodeId] = temp;
break;
default:
break;
}
}
}
}
}
string GetStringNodeValue(EventNodeBase eventNodeBase)
{
string stringValue = "";
switch(eventNodeBase.nodeType)
{
case "StringValueNode":
StringValueNode stringNode = eventNodeBase.TryCast<StringValueNode>();
stringValue = stringNode.value;
break;
case "FloatToStringNode":
stringValue = "([^\\s]+)";
break;
case "StringConcatNode":
StringConcatNode stringConcatNode = eventNodeBase.TryCast<StringConcatNode>();
stringConcatNode.InitializeConnections(eventNodeGraph);
stringValue = GetStringNodeValue(stringConcatNode.aSourceNode) + GetStringNodeValue(stringConcatNode.bSourceNode);
break;
default:
break;
}
return stringValue;
}
string baseDumpDir = FileLoader.GetAssetDir(FileLoader.AssetType.Dumps);
string levelDumpDir = Path.Combine(baseDumpDir, "CustomLevels.json");
if (!File.Exists(levelDumpDir)) File.WriteAllText(levelDumpDir, "{}");
Dictionary<string, string> dump = JsonSerializer.Deserialize<Dictionary<string, string>>(File.ReadAllText(levelDumpDir));
foreach(string showTextNodeId in showTextNodeIds)
{
ShowTextNode showTextNode = eventNodeGraph.GetNodeById(showTextNodeId).TryCast<ShowTextNode>();
showTextNode.InitializeConnections(eventNodeGraph);
string value = GetStringNodeValue(showTextNode.textSourceNode);
if (!dump.ContainsKey(value))
{
dump.Add(value, value);
}
}
foreach(string addOptionId in addOptionNodeIds)
{
AddMultipleChoiceOptionNode addOptionNode = eventNodeGraph.GetNodeById(addOptionId).TryCast<AddMultipleChoiceOptionNode>();
addOptionNode.InitializeConnections(eventNodeGraph);
string titleValue = GetStringNodeValue(addOptionNode.titleSourceNode);
if (!dump.ContainsKey(titleValue))
{
dump.Add(titleValue, titleValue);
}
string descriptionValue = GetStringNodeValue(addOptionNode.descriptionSourceNode);
if (!dump.ContainsKey(descriptionValue))
{
dump.Add(descriptionValue, descriptionValue);
}
}
File.WriteAllText(levelDumpDir, JsonSerializer.Serialize(dump, new JsonSerializerOptions
{
WriteIndented = true,
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
}));
}
// reference level data classes
public class ReferenceLevelData
{
public References references { get; set; }
}
public class Data
{
public string nodeId { get; set; }
public string nodeType { get; set; }
public Position position { get; set; }
public string nodeName { get; set; }
public string plant_PortName { get; set; }
public string column_PortName { get; set; }
public string row_PortName { get; set; }
public string plantType_PortName { get; set; }
public object value { get; set; }
public string value_PortName { get; set; }
public string plantTypeA_PortName { get; set; }
public string plantTypeB_PortName { get; set; }
public string equal_PortName { get; set; }
public string trigger_PortName { get; set; }
public string count_PortName { get; set; }
public string output_PortName { get; set; }
public string index_PortName { get; set; }
public string plants_PortName { get; set; }
public string plantList_PortName { get; set; }
public string loopBody_PortName { get; set; }
public string currentPlant_PortName { get; set; }
public string currentIndex_PortName { get; set; }
public string onCompleted_PortName { get; set; }
public string condition_PortName { get; set; }
public string then_PortName { get; set; }
public string else_PortName { get; set; }
public string a_PortName { get; set; }
public string b_PortName { get; set; }
public string result_PortName { get; set; }
public string shouldReset_PortName { get; set; }
public string onCount_PortName { get; set; }
public int? startValue { get; set; }
public string valueA_PortName { get; set; }
public string valueB_PortName { get; set; }
public string greater_PortName { get; set; }
public string less_PortName { get; set; }
public string displayText { get; set; }
public double? duration { get; set; }
public string text_PortName { get; set; }
public string duration_PortName { get; set; }
public string int_PortName { get; set; }
public string float_PortName { get; set; }
}
public class Position
{
public double x { get; set; }
public double y { get; set; }
}
public class References
{
public int version { get; set; }
public List<RefId> RefIds { get; set; }
}
public class RefId
{
public int rid { get; set; }
public Type type { get; set; }
public Data data { get; set; }
}
public class Type
{
public string @class { get; set; }
public string ns { get; set; }
public string asm { get; set; }
}
}
}

View file

@ -0,0 +1,95 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Il2Cpp;
using Il2CppRhythmGameEditor;
using Il2CppRhythmGame;
using HarmonyLib;
using UnityEngine;
using Il2CppTMPro;
using PvZ_Fusion_Translator.AssetStore;
namespace PvZ_Fusion_Translator.Patches.Modes.Super_Editor.RhythmGameEditor
{
[HarmonyPatch(typeof(RhythmGameChartEditorUI))]
public static class RhythmGameChartEditorUI_Patch
{
[HarmonyPatch(nameof(RhythmGameChartEditorUI.Awake))]
[HarmonyPostfix]
public static void Awake(RhythmGameChartEditorUI __instance)
{
TMP_FontAsset fontAsset = FontStore.LoadTMPFont(Utils.Language.ToString());
foreach(TextMeshProUGUI txt in __instance.GetComponentsInChildren<TextMeshProUGUI>())
{
txt.font = fontAsset;
if (!Utils.CheckForUntranslatedText(txt.text)) continue;
txt.text = StringStore.TranslateText(txt.text);
}
foreach(TextMeshProUGUI txt in __instance.dropdown.GetComponentsInChildren<TextMeshProUGUI>(true))
{
txt.text = StringStore.TranslateText(txt.text);
}
}
[HarmonyPatch(nameof(RhythmGameChartEditorUI.Start))]
[HarmonyPostfix]
public static void Start(RhythmGameChartEditorUI __instance)
{
Awake(__instance);
}
[HarmonyPatch(nameof(RhythmGameChartEditorUI.InitializeSubSystems))]
[HarmonyPostfix]
public static void InitializeSubSystems(RhythmGameChartEditorUI __instance)
{
Awake(__instance);
}
[HarmonyPatch(nameof(RhythmGameChartEditorUI.Update))]
[HarmonyPostfix]
public static void Update(RhythmGameChartEditorUI __instance)
{
TMP_FontAsset fontAsset = FontStore.LoadTMPFont(Utils.Language.ToString());
foreach(TextMeshProUGUI txt in __instance.transform.Find("TopPanel").GetComponentsInChildren<TextMeshProUGUI>())
{
txt.font = fontAsset;
txt.text = StringStore.TranslateText(txt.text);
}
foreach(TheButton btn in __instance.transform.GetComponentsInChildren<TheButton>())
{
foreach(TextMeshProUGUI txt in btn.GetComponentsInChildren<TextMeshProUGUI>())
{
if (!Utils.CheckForUntranslatedText(txt.text)) continue;
txt.text = StringStore.TranslateText(txt.text);
}
}
foreach(TextMeshProUGUI txt in __instance.dropdown.GetComponentsInChildren<TextMeshProUGUI>(true))
{
if (!Utils.CheckForUntranslatedText(txt.text)) continue;
txt.text = Utils.RemoveSizeTags(StringStore.TranslateText(txt.text));
}
}
[HarmonyPatch(nameof(RhythmGameChartEditorUI.UpdateUI))]
[HarmonyPostfix]
public static void UpdateUI(RhythmGameChartEditorUI __instance)
{
foreach(TextMeshProUGUI txt in __instance.dropdown.GetComponentsInChildren<TextMeshProUGUI>(true))
{
txt.text = StringStore.TranslateText(txt.text);
}
}
[HarmonyPatch(nameof(RhythmGameChartEditorUI.UpdateSelectedNoteInfo))]
[HarmonyPostfix]
public static void UpdateSelectedNoteInfo(RhythmGameChartEditorUI __instance)
{
__instance.selectedNoteInfoText.text = StringStore.TranslateText(__instance.selectedNoteInfoText.text);
}
}
}

View file

@ -0,0 +1,51 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HarmonyLib;
using Il2Cpp;
using Il2CppRhythmGame;
using Il2CppTMPro;
using PvZ_Fusion_Translator.AssetStore;
using UnityEngine;
namespace PvZ_Fusion_Translator.Patches.Modes.Super_Editor.RhythmGameEditor
{
[HarmonyPatch(typeof(RhythmGameManager))]
public static class RhythmGameManager_Patch
{
[HarmonyPatch(nameof(RhythmGameManager.Awake))]
[HarmonyPatch(nameof(RhythmGameManager.ComboUpdate))]
[HarmonyPostfix]
public static void Awake(RhythmGameManager __instance)
{
if(__instance.comboText)
{
__instance.comboText.autoSizeTextContainer = false;
__instance.comboText.ForceMeshUpdate();
}
}
[HarmonyPatch(nameof(RhythmGameManager.OnNoteClicked))]
[HarmonyPostfix]
public static void OnNoteClicked(RhythmGameManager __instance)
{
if (!__instance.particle) return;
TextParticle txtParticle = __instance.particle.GetComponent<TextParticle>();
if(txtParticle)
{
TextMeshPro txt = txtParticle.text.GetComponent<TextMeshPro>();
if(txt)
{
string originalKey = StringStore.translationString.FirstOrDefault(x => x.Value == txt.text).Key;
txt.text = StringStore.translationString.ContainsKey(originalKey + "_RG") ? StringStore.TranslateText(originalKey + "_RG") : StringStore.TranslateText(txt.text);
txt.autoSizeTextContainer = false;
txt.ForceMeshUpdate();
}
}
}
}
}

View file

@ -1,4 +1,4 @@
using HarmonyLib; /*using HarmonyLib;
using Il2Cpp; using Il2Cpp;
using Il2CppTMPro; using Il2CppTMPro;
using Newtonsoft.Json; using Newtonsoft.Json;
@ -68,3 +68,4 @@ namespace PvZ_Fusion_Translator.Patches.OtherManagers
} }
} }
} }
*/

View file

@ -2,6 +2,7 @@
using Il2Cpp; using Il2Cpp;
using PvZ_Fusion_Translator.AssetStore; using PvZ_Fusion_Translator.AssetStore;
using UnityEngine; using UnityEngine;
using Il2CppZenGarden;
namespace PvZ_Fusion_Translator.Patches.OtherManagers namespace PvZ_Fusion_Translator.Patches.OtherManagers
{ {
@ -13,7 +14,6 @@ namespace PvZ_Fusion_Translator.Patches.OtherManagers
public static void Update(GardenUI __instance) public static void Update(GardenUI __instance)
{ {
__instance.currentPageText = StringStore.TranslateText(__instance.currentPageText, false); __instance.currentPageText = StringStore.TranslateText(__instance.currentPageText, false);
__instance.currentPageText2 = StringStore.TranslateText(__instance.currentPageText2, false);
// Transform PageText = __instance.transform.Find("PageText"); // Transform PageText = __instance.transform.Find("PageText");
// StringStore.TranslateTextTransform(PageText.transform); // StringStore.TranslateTextTransform(PageText.transform);

View file

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
@ -306,6 +306,9 @@
<Reference Include="Il2CppInterop.Common"> <Reference Include="Il2CppInterop.Common">
<HintPath>$(GamePath)\MelonLoader\net6\Il2CppInterop.Common.dll</HintPath> <HintPath>$(GamePath)\MelonLoader\net6\Il2CppInterop.Common.dll</HintPath>
</Reference> </Reference>
<Reference Include="Il2CppCore">
<HintPath>$(GamePath)\MelonLoader\Il2CppAssemblies\Il2CppCore.dll</HintPath>
</Reference>
</ItemGroup> </ItemGroup>
@ -392,6 +395,7 @@
<ItemGroup> <ItemGroup>
<Compile Include="AssetStore\CheckSumStore.cs" /> <Compile Include="AssetStore\CheckSumStore.cs" />
<Compile Include="AssetStore\DllStore.cs" />
<Compile Include="AssetStore\FontStore.cs" /> <Compile Include="AssetStore\FontStore.cs" />
<Compile Include="AssetStore\StringStore.cs" /> <Compile Include="AssetStore\StringStore.cs" />
<Compile Include="AssetStore\TextureStore.cs" /> <Compile Include="AssetStore\TextureStore.cs" />
@ -402,15 +406,32 @@
<Compile Include="Log.cs" /> <Compile Include="Log.cs" />
<Compile Include="ModFeatures.cs" /> <Compile Include="ModFeatures.cs" />
<Compile Include="AssetStore\AudioStore.cs" /> <Compile Include="AssetStore\AudioStore.cs" />
<Compile Include="Patches\BaseTextObjects\TMP_Dropdown_Patch.cs" />
<Compile Include="Patches\GameObjects\GardenStoreMenu_Patch.cs" />
<Compile Include="Patches\GameObjects\AlmanacCardUI_Patch.cs" />
<Compile Include="Patches\GameObjects\AlmanacBuffMenu_Patch.cs" />
<Compile Include="Patches\GameObjects\AlmanacSelectMenu_Patch.cs" />
<Compile Include="Patches\GameObjects\ButtonObjects\LevelSaveEnter_Patch.cs" />
<Compile Include="Patches\GameObjects\ConfirmMenu_Patch.cs" /> <Compile Include="Patches\GameObjects\ConfirmMenu_Patch.cs" />
<Compile Include="Patches\GameObjects\LevelResultMenu_Patch.cs" />
<Compile Include="Patches\GameObjects\LoseMenu_Patch.cs" /> <Compile Include="Patches\GameObjects\LoseMenu_Patch.cs" />
<Compile Include="Patches\GameObjects\MinorObjects\GameLose_Patch.cs" />
<Compile Include="Patches\GameObjects\MinorObjects\HealthSlider_Patch.cs" />
<Compile Include="Patches\GameObjects\MinorObjects\PumpinerChestMenu_Patch.cs" />
<Compile Include="Patches\GameObjects\MinorObjects\SpecialCard_Patch.cs" />
<Compile Include="Patches\GameObjects\PlayerSaveMenu_Patch.cs" /> <Compile Include="Patches\GameObjects\PlayerSaveMenu_Patch.cs" />
<Compile Include="Patches\GameObjects\PVPRandomManager_Patch.cs" /> <Compile Include="Patches\GameObjects\PVPRandomManager_Patch.cs" />
<Compile Include="Patches\GameObjects\GodShootingMenu_Patch.cs" /> <Compile Include="Patches\GameObjects\GodShootingMenu_Patch.cs" />
<Compile Include="Patches\GameObjects\ButtonObjects\GodShootingLevelButton_Patch.cs" /> <Compile Include="Patches\GameObjects\ButtonObjects\GodShootingLevelButton_Patch.cs" />
<Compile Include="Patches\GameObjects\PlantDataMenu_Patch.cs" /> <Compile Include="Patches\GameObjects\PlantDataMenu_Patch.cs" />
<Compile Include="Patches\GameObjects\ReNameMenu_Patch.cs" />
<Compile Include="Patches\GameObjects\PlantCardPackageBuilder_Patch.cs" />
<Compile Include="Patches\GameObjects\WarningMenu_Patch.cs" /> <Compile Include="Patches\GameObjects\WarningMenu_Patch.cs" />
<Compile Include="Patches\Managers\PVPScareyPot_Patch.cs" />
<Compile Include="Patches\Modes\Abyss\AbyssBuffMenu_Patch.cs" /> <Compile Include="Patches\Modes\Abyss\AbyssBuffMenu_Patch.cs" />
<Compile Include="Patches\Modes\Odyssey\MultipleChoiceMenu_Patch.cs" />
<Compile Include="Patches\Modes\Odyssey\ShootingManager_Patch.cs" />
<Compile Include="Patches\Modes\Odyssey\TravelAdvantureMenu_Patch.cs" />
<Compile Include="Patches\Modes\Odyssey\TravelInvestMenu_Patch.cs" /> <Compile Include="Patches\Modes\Odyssey\TravelInvestMenu_Patch.cs" />
<Compile Include="Patches\Modes\Odyssey\SynergyDisplay_Patch.cs" /> <Compile Include="Patches\Modes\Odyssey\SynergyDisplay_Patch.cs" />
<Compile Include="Patches\Modes\Odyssey\TravelStoreWindow_Patch.cs" /> <Compile Include="Patches\Modes\Odyssey\TravelStoreWindow_Patch.cs" />
@ -430,7 +451,7 @@
<Compile Include="Patches\GameObjects\PlantDamageMenu_Patch.cs" /> <Compile Include="Patches\GameObjects\PlantDamageMenu_Patch.cs" />
<Compile Include="Patches\GameObjects\EveBuffMenu_Patch.cs" /> <Compile Include="Patches\GameObjects\EveBuffMenu_Patch.cs" />
<Compile Include="Patches\GameObjects\EveOptionWindow_Patch.cs" /> <Compile Include="Patches\GameObjects\EveOptionWindow_Patch.cs" />
<Compile Include="Patches\Managers\GameAPP_Patch.cs" /> <Compile Include="Patches\Managers\Screen_Patch.cs" />
<Compile Include="Patches\Modes\Odyssey\OppositeBuffManager_Patch.cs" /> <Compile Include="Patches\Modes\Odyssey\OppositeBuffManager_Patch.cs" />
<Compile Include="Patches\GameObjects\ButtonObjects\ExploreMakeSceneButton_Patch.cs" /> <Compile Include="Patches\GameObjects\ButtonObjects\ExploreMakeSceneButton_Patch.cs" />
<Compile Include="Patches\GameObjects\ButtonObjects\ExploreMakeZombieButton_Patch.cs" /> <Compile Include="Patches\GameObjects\ButtonObjects\ExploreMakeZombieButton_Patch.cs" />
@ -507,11 +528,18 @@
<Compile Include="Patches\Managers\TowerManager_Patch.cs" /> <Compile Include="Patches\Managers\TowerManager_Patch.cs" />
<Compile Include="Patches\Managers\SaveMenu_Patch.cs" /> <Compile Include="Patches\Managers\SaveMenu_Patch.cs" />
<Compile Include="Patches\Modes\Odyssey\TravelBuffOptionButton_Patch.cs" /> <Compile Include="Patches\Modes\Odyssey\TravelBuffOptionButton_Patch.cs" />
<Compile Include="Patches\Modes\Super Editor\CustomButton_enterGame_Patch.cs" />
<Compile Include="Patches\Modes\Super Editor\CustomMenuPage_event_Patch_B.cs" />
<Compile Include="Patches\Modes\Super Editor\CustomOnlineMenu_Patch.cs" /> <Compile Include="Patches\Modes\Super Editor\CustomOnlineMenu_Patch.cs" />
<Compile Include="Patches\Modes\Super Editor\CustomMenuPage_shooting_Patch.cs" /> <Compile Include="Patches\Modes\Super Editor\CustomMenuPage_shooting_Patch.cs" />
<Compile Include="Patches\Modes\Super Editor\CustomLevelMenu_Patch.cs" /> <Compile Include="Patches\Modes\Super Editor\CustomLevelMenu_Patch.cs" />
<Compile Include="Patches\Modes\Super Editor\CustomMenuPage_page3_Patch.cs" /> <Compile Include="Patches\Modes\Super Editor\CustomMenuPage_page3_Patch.cs" />
<Compile Include="Patches\Modes\Super Editor\CustomMenuPage_initZombies_Patch.cs" /> <Compile Include="Patches\Modes\Super Editor\CustomMenuPage_initZombies_Patch.cs" />
<Compile Include="Patches\Modes\Super Editor\GameLevel\EventNodes\RuntimeEventNodeEditor_Patch.cs" />
<Compile Include="Patches\Modes\Super Editor\GameLevel\EventNodes\RuntimeNodeUI_Patch.cs" />
<Compile Include="Patches\Modes\Super Editor\GameLevel\LevelManager_Patch.cs" />
<Compile Include="Patches\Modes\Super Editor\RhythmGame\RhythmGameChartEditorUI_Patch.cs" />
<Compile Include="Patches\Modes\Super Editor\RhythmGame\RhythmGameManager_Patch.cs" />
<Compile Include="Patches\OtherManagers\AchievementClip_Patch.cs" /> <Compile Include="Patches\OtherManagers\AchievementClip_Patch.cs" />
<Compile Include="Patches\GameObjects\ButtonObjects\Advanture_Btn_Patch.cs" /> <Compile Include="Patches\GameObjects\ButtonObjects\Advanture_Btn_Patch.cs" />
<Compile Include="Patches\Managers\AlmanacMgrZombie_Patch.cs" /> <Compile Include="Patches\Managers\AlmanacMgrZombie_Patch.cs" />
@ -555,9 +583,14 @@
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Folder Include="Resources\" />
</ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent"> <Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="COPY &quot;$(TargetPath)&quot; &quot;$(GamePath)\Mods\&quot;" /> <Exec Command="COPY &quot;$(TargetPath)&quot; &quot;$(GamePath)\Mods\&quot;" />
<Exec Command="COPY &quot;$(TargetPath)&quot; &quot;$(GamePath)\Translation Builds\&quot;" /> <Exec Command="COPY &quot;$(TargetPath)&quot; &quot;$(GamePath)\Translation Builds\&quot;" />
<Exec Command="COPY &quot;$(TargetPath)&quot; &quot;C:\Users\rainb\Documents\GitHub\PVZF-Translation\&quot;" /> <Exec Command="COPY &quot;$(TargetPath)&quot; &quot;C:\Users\rainb\Documents\GitHub\PVZF-Translation\&quot;" />
<Exec Command="COPY &quot;$(TargetPath)&quot; &quot;C:\Users\rainb\Documents\GitHub\PvZF-Translation-DLLs\&quot;" />
</Target> </Target>
</Project> </Project>

View file

@ -10,13 +10,13 @@ using PvZ_Fusion_Translator.Patches.GameObjects.ButtonObjects;
using PvZ_Fusion_Translator.Patches.GameObjects.MinorObjects; using PvZ_Fusion_Translator.Patches.GameObjects.MinorObjects;
using PvZ_Fusion_Translator.Patches.Modes.Super_Editor; using PvZ_Fusion_Translator.Patches.Modes.Super_Editor;
using System.Diagnostics; using System.Diagnostics;
using System.Reflection;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using Unity.Burst.Intrinsics; using Unity.Burst.Intrinsics;
using UnityEngine; using UnityEngine;
using UnityEngine.Events; using UnityEngine.Events;
using UnityEngine.Experimental.Rendering; using UnityEngine.Experimental.Rendering;
using UnityEngine.UI; using UnityEngine.UI;
using static Il2Cpp.AlmanacPlantBank;
using static MelonLoader.MelonLogger; using static MelonLoader.MelonLogger;
using static PvZ_Fusion_Translator.FileLoader; using static PvZ_Fusion_Translator.FileLoader;
@ -28,11 +28,11 @@ namespace PvZ_Fusion_Translator
{ {
if (ogTexture != null) if (ogTexture != null)
{ {
if (TextureStore.textureDict.TryGetValue(ogTexture.name, out string texturePath)) if (TextureStore.textureDict.TryGetValue(ogTexture.name, out byte[] textureData))
{ {
try try
{ {
ImageConversion.LoadImage(ogTexture, File.ReadAllBytes(texturePath)); ImageConversion.LoadImage(ogTexture, textureData);
Log.LogDebug("OK! Replaced Texture " + ogTexture.name); Log.LogDebug("OK! Replaced Texture " + ogTexture.name);
@ -41,7 +41,7 @@ namespace PvZ_Fusion_Translator
} }
catch (Exception ex) catch (Exception ex)
{ {
Log.LogError("Failed to replace texture: " + ogTexture.name + " at path: " + texturePath); Log.LogError("Failed to replace texture: " + ogTexture.name);
Log.LogError(ex.ToString()); Log.LogError(ex.ToString());
} }
} }
@ -62,6 +62,19 @@ namespace PvZ_Fusion_Translator
return texture2D; return texture2D;
} }
internal static Texture2D LoadImage(byte[] bytes)
{
if (bytes == null)
{
throw new FileNotFoundException($"Byte array was null.");
}
byte[] array = bytes;
Texture2D texture2D = new(2, 2, GraphicsFormat.R8G8B8A8_UNorm, TextureCreationFlags.None, 1, IntPtr.Zero, null);
ImageConversion.LoadImage(texture2D, array);
return texture2D;
}
public static Color HexToColor(string hex) public static Color HexToColor(string hex)
{ {
@ -80,9 +93,9 @@ namespace PvZ_Fusion_Translator
Process.Start("explorer.exe", saveDirectory); Process.Start("explorer.exe", saveDirectory);
} }
public static void OpenTrello() public static void OpenOnlineAlmanac()
{ {
string website = "https://trello.com/b/DcdT1kUp"; string website = "https://carroti4ch.itch.io/almanac";
Process.Start(new ProcessStartInfo(website) { UseShellExecute = true }); Process.Start(new ProcessStartInfo(website) { UseShellExecute = true });
} }
@ -103,13 +116,34 @@ namespace PvZ_Fusion_Translator
if (string.IsNullOrEmpty(text)) if (string.IsNullOrEmpty(text))
return text ?? string.Empty; return text ?? string.Empty;
// Remove opening color tags like <color=#FF0000> // Remove opening size tags like <color=#FF0000>
string withoutOpenTags = Regex.Replace(text, @"<size=[^>]+>", string.Empty, RegexOptions.IgnoreCase); string withoutOpenTags = Regex.Replace(text, @"<size=[^>]+>", string.Empty, RegexOptions.IgnoreCase);
// Remove closing color tags like </color> // Remove closing size tags like </color>
string withoutCloseTags = Regex.Replace(withoutOpenTags, @"</size>", string.Empty, RegexOptions.IgnoreCase); string withoutCloseTags = Regex.Replace(withoutOpenTags, @"</size>", string.Empty, RegexOptions.IgnoreCase);
return withoutCloseTags; return withoutCloseTags;
} }
public static string RemoveFormatTags(string text)
{
if (string.IsNullOrEmpty(text))
return text ?? string.Empty;
string withoutUnderlineTags = Regex.Replace(text, @"<u>", string.Empty, RegexOptions.IgnoreCase);
string withoutUnderlineCloseTags = Regex.Replace(withoutUnderlineTags, @"</u>", string.Empty, RegexOptions.IgnoreCase);
string withoutItalicTags = Regex.Replace(withoutUnderlineCloseTags, @"<i>", string.Empty, RegexOptions.IgnoreCase);
string withoutItalicCloseTags = Regex.Replace(withoutItalicTags, @"</i>", string.Empty, RegexOptions.IgnoreCase);
return withoutItalicCloseTags;
}
public static string RemoveAllTags(string text)
{
if (string.IsNullOrEmpty(text))
return text ?? string.Empty;
return RemoveColorTags(RemoveSizeTags(RemoveFormatTags(text)));
}
public static GameObject ConvertToTextMeshProUGUI(GameObject originalText, Transform parent, string name) public static GameObject ConvertToTextMeshProUGUI(GameObject originalText, Transform parent, string name)
{ {
GameObject newObj = new GameObject(name); GameObject newObj = new GameObject(name);
@ -140,81 +174,57 @@ namespace PvZ_Fusion_Translator
newGoBackText.color = color; newGoBackText.color = color;
} }
public static string GetPlantNameFromAlmanac(PlantType thePlantType) public static string GetPlantNameFromAlmanac(PlantType thePlantType, bool removeTags = false, bool log = false)
{ {
string json; bool foundPlantName = false;
string thePlantName = ""; string thePlantName = "";
json = AlmanacPlantMenu_Patch.almanacJson; if(plantIndices.ContainsKey((int)thePlantType))
AlmanacPlantBank.PlantData plantData = JsonUtility.FromJson<AlmanacPlantBank.PlantData>(json); {
foundPlantName = true;
thePlantName = plantIndices[(int)thePlantType].Value;
}
foreach (AlmanacPlantBank.PlantInfo plantInfo in plantData.plants) if (!foundPlantName)
{
if (plantInfo.seedType == (int)thePlantType)
{
thePlantName = plantInfo.name;
}
}
return thePlantName;
}
public static string GetPlantNameFromAlmanac(string theOriginalPlantName, bool log = false)
{
string originalJson;
string translatedJson;
string thePlantName = "";
string currentLanguage = Utils.Language.ToString();
string almanacDir = GetAssetDir(AssetType.Almanac, Utils.Language);
string dumpDir = GetAssetDir(AssetType.Dumps);
string originalPath = Path.Combine(dumpDir, "LawnStrings.json");
string path = Path.Combine(almanacDir, "LawnStringsTranslate.json");
if ((!File.Exists(originalPath)))
{ {
if(log) if(log)
{ {
Log.LogError($"LawnStringsTranslate.json file not found at path: {path}"); Log.LogInfo("Couldn't find plant name!");
Log.LogError("Plant name could not be found!");
} }
thePlantName = ""; thePlantName = "";
} }
else
{
bool foundPlantName = false;
originalJson = File.ReadAllText(originalPath); thePlantName = (removeTags) ? RemoveAllTags(thePlantName) : thePlantName;
translatedJson = AlmanacPlantMenu_Patch.almanacJson;
AlmanacPlantBank.PlantData originalPlantData = JsonUtility.FromJson<AlmanacPlantBank.PlantData>(originalJson);
AlmanacPlantBank.PlantData translatedPlantData = JsonUtility.FromJson<AlmanacPlantBank.PlantData>(translatedJson);
for(int i = 0; i < originalPlantData.plants.Count; i++)
{
AlmanacPlantBank.PlantInfo originalPlantInfo = originalPlantData.plants[i];
KeyValuePair<int, string> translatedPlantInfo = plantIndices[originalPlantInfo.seedType];
if (originalPlantInfo.name == theOriginalPlantName)
{
thePlantName = translatedPlantInfo.Value;
foundPlantName = true;
}
}
if (!foundPlantName)
{
if(log)
{
Log.LogInfo("Couldn't find plant name!");
}
thePlantName = "";
}
}
return thePlantName; return thePlantName;
} }
public static string GetZombieNameFromAlmanac(ZombieType theZombieType) public static string GetPlantNameFromAlmanac(string theOriginalPlantName, bool removeTags = false, bool log = false)
{
bool foundPlantName = false;
string thePlantName = "";
if(plantIndiceString.ContainsKey(theOriginalPlantName))
{
foundPlantName = true;
thePlantName = plantIndiceString[theOriginalPlantName];
}
if (!foundPlantName)
{
if(log)
{
Log.LogInfo("Couldn't find plant name!");
}
thePlantName = "";
}
thePlantName = (removeTags) ? RemoveAllTags(thePlantName) : thePlantName;
return thePlantName;
}
public static string GetZombieNameFromAlmanac(ZombieType theZombieType, bool removeTags = false)
{ {
string json; string json;
string theZombieName = ""; string theZombieName = "";
@ -222,9 +232,9 @@ namespace PvZ_Fusion_Translator
string currentLanguage = Utils.Language.ToString(); string currentLanguage = Utils.Language.ToString();
json = AlmanacZombieMenu_Patch.almanacJson; json = AlmanacZombieMenu_Patch.almanacJson;
ZombieAlmanacData zombieData = JsonUtility.FromJson<ZombieAlmanacData>(json); Il2CppAlmanacData.AlmanacData zombieData = JsonUtility.FromJson<Il2CppAlmanacData.AlmanacData>(json);
foreach (ZombieInfo zombieInfo in zombieData.zombies) foreach (Il2CppAlmanacData.ZombieInfo zombieInfo in zombieData.zombies)
{ {
if ((int)zombieInfo.theZombieType == (int)theZombieType) if ((int)zombieInfo.theZombieType == (int)theZombieType)
{ {
@ -232,14 +242,18 @@ namespace PvZ_Fusion_Translator
} }
} }
theZombieName = (removeTags) ? RemoveAllTags(theZombieName) : theZombieName;
return theZombieName; return theZombieName;
} }
public static Dictionary<int, KeyValuePair<int, string>> plantIndices = new Dictionary<int, KeyValuePair<int, string>>(); public static Dictionary<int, KeyValuePair<int, string>> plantIndices = new Dictionary<int, KeyValuePair<int, string>>();
public static Dictionary<string, string> plantIndiceString = new Dictionary<string, string>();
public static void RegisterPlantIndices() public static void RegisterPlantIndices()
{ {
plantIndices = new Dictionary<int, KeyValuePair<int, string>>(); plantIndices = new Dictionary<int, KeyValuePair<int, string>>();
plantIndiceString = new Dictionary<string, string>();
string originalJson; string originalJson;
string translatedJson; string translatedJson;
@ -255,33 +269,111 @@ namespace PvZ_Fusion_Translator
} }
else else
{ {
originalJson = File.ReadAllText(originalPath); try
translatedJson = AlmanacPlantMenu_Patch.almanacJson;
AlmanacPlantBank.PlantData originalPlantData = JsonUtility.FromJson<AlmanacPlantBank.PlantData>(originalJson);
AlmanacPlantBank.PlantData translatedPlantData = JsonUtility.FromJson<AlmanacPlantBank.PlantData>(translatedJson);
for (int i = 0; i < originalPlantData.plants.Count; i++)
{ {
PlantInfo originalPlantInfo = originalPlantData.plants[i]; originalJson = File.ReadAllText(originalPath);
PlantInfo translatedPlantInfo = null; translatedJson = AlmanacPlantMenu_Patch.almanacJson;
Il2CppAlmanacData.AlmanacData originalPlantData = JsonUtility.FromJson<Il2CppAlmanacData.AlmanacData>(originalJson);
Il2CppAlmanacData.AlmanacData translatedPlantData = JsonUtility.FromJson<Il2CppAlmanacData.AlmanacData>(translatedJson);
foreach (PlantInfo info in translatedPlantData.plants) foreach (Il2CppAlmanacData.PlantInfo originalPlantInfo in originalPlantData.plants)
{ {
if (info.seedType == originalPlantInfo.seedType) if(!plantIndiceString.ContainsKey(originalPlantInfo.name))
{ {
translatedPlantInfo = info; plantIndiceString.Add(originalPlantInfo.name, originalPlantInfo.name);
}
Il2CppAlmanacData.PlantInfo translatedPlantInfo = null;
foreach (Il2CppAlmanacData.PlantInfo info in translatedPlantData.plants)
{
if (info.seedType == originalPlantInfo.seedType)
{
translatedPlantInfo = info;
}
}
if (translatedPlantInfo != null)
{
if(translatedPlantInfo.name != null)
{
KeyValuePair<int, string> temp = new KeyValuePair<int, string>(translatedPlantInfo.seedType, translatedPlantInfo.name);
plantIndices.Add(originalPlantInfo.seedType, temp);
plantIndiceString[originalPlantInfo.name] = translatedPlantInfo.name;
}
} }
} }
}
if (translatedPlantInfo != null) catch (Exception e)
{ {
KeyValuePair<int, string> temp = new KeyValuePair<int, string>(translatedPlantInfo.seedType, translatedPlantInfo.name); Log.LogError(e);
plantIndices.Add(originalPlantInfo.seedType, temp);
}
} }
} }
} }
public static void TryAdd<A, B>(Dictionary<A, B> dict, A key, B val)
{
if (dict.ContainsKey(key))
{
dict[key] = val;
}
else
{
dict.Add(key, val);
}
}
public static void TryAdd<A, B>(SortedDictionary<A, B> dict, A key, B val)
{
if (dict.ContainsKey(key))
{
dict[key] = val;
}
else
{
dict.Add(key, val);
}
}
public static AssetBundle GetAssetBundle(Assembly assembly, string assetBundlePath, bool log = false)
{
try
{
if (assembly != null)
{
Stream manifestResourceStream = assembly.GetManifestResourceStream($"PvZ_Fusion_Translator.Resources.{assetBundlePath}");
using (manifestResourceStream)
{
if (manifestResourceStream == null)
{
throw new Exception("Stream was null.");
}
byte[] array = new byte[manifestResourceStream.Length];
manifestResourceStream.Read(array, 0, array.Length);
AssetBundle assetBundle = AssetBundle.LoadFromMemory(array);
ArgumentNullException.ThrowIfNull(assetBundle, "assetBundle");
if(log)
{
Log.LogDebug($"AssetBundle {assetBundlePath} has successfully been loaded.");
}
return assetBundle;
}
}
throw new Exception($"AssetBundle {assetBundlePath} was null.");
}
catch (Exception value)
{
throw new ArgumentException($"Failed to load {assetBundlePath}. \n{value}");
}
}
public static AssetBundle GetAssetBundle(string path)
{
AssetBundle assetBundle = AssetBundle.LoadFromFile(path);
return assetBundle;
}
/*public static Dictionary<int, List<int>> recipeLinks = new Dictionary<int, List<int>>(); /*public static Dictionary<int, List<int>> recipeLinks = new Dictionary<int, List<int>>();
public static void RegisterRecipeLinks() public static void RegisterRecipeLinks()
@ -325,12 +417,13 @@ namespace PvZ_Fusion_Translator
} }
}*/ }*/
public static Regex untranslatedRegex = new("\\p{IsCJKUnifiedIdeographs}+");
public static bool CheckForUntranslatedText(string text) public static bool CheckForUntranslatedText(string text)
{ {
Regex regex = new("\\p{IsCJKUnifiedIdeographs}+"); try
try
{ {
Match match = regex.Match(text); Match match = untranslatedRegex.Match(text);
return match.Success; return match.Success;
} }
catch(Exception e) catch(Exception e)
@ -355,6 +448,7 @@ namespace PvZ_Fusion_Translator
confirmButton.clickEvent = new UnityEvent(); confirmButton.clickEvent = new UnityEvent();
confirmButton.clickEvent.AddListener(new Action(() => SwapLocalData())); confirmButton.clickEvent.AddListener(new Action(() => SwapLocalData()));
confirmButton.clickEvent.AddListener(new Action(() => CursorChange.SetDefaultCursor()));
confirmButton.clickEvent.AddListener(new Action(() => GameAPP.UIManager.Pop())); confirmButton.clickEvent.AddListener(new Action(() => GameAPP.UIManager.Pop()));
} }
@ -362,9 +456,10 @@ namespace PvZ_Fusion_Translator
{ {
Utils.useLocal = (Utils.useLocal) ? false : true; Utils.useLocal = (Utils.useLocal) ? false : true;
MelonPreferences.SetEntryValue<bool>("PvZ_Fusion_Translator", "UseLocal", Utils.useLocal); MelonPreferences.SetEntryValue<bool>("PvZ_Fusion_Translator", "UseLocal", Utils.useLocal);
StringStore.Reload(); ChangeLanguage(Utils.Language.ToString());
string sourceMsg = "<size=10>" + (!(Utils.useLocal) ? "Translation Source:\nOnline" : "Translation Source:\nLocal"); string sourceMsg = "<size=10>" + (!(Utils.useLocal) ? "Translation Source:\nOnline" : "Translation Source:\nLocal");
OptLanguageBtn_Patch.FlashMessage(OptLanguageBtn_Patch.toggleSlots[2], sourceMsg, 0.1f, false); OptLanguageBtn_Patch.FlashMessage(OptLanguageBtn_Patch.toggleSlots[2], sourceMsg, 0.1f, false);
CursorChange.SetDefaultCursor();
} }
public static async Task<string> GetDataFromWeb(string url, bool isLog = true) public static async Task<string> GetDataFromWeb(string url, bool isLog = true)
@ -373,7 +468,99 @@ namespace PvZ_Fusion_Translator
{ {
Log.LogInfo($"Attempting to read {url}"); Log.LogInfo($"Attempting to read {url}");
} }
var dataRequest = await new HttpClient().GetAsync(url); HttpClient client = new HttpClient();
try
{
var dataRequest = await client.GetAsync(url);
if(dataRequest.StatusCode == System.Net.HttpStatusCode.OK)
{
if (isLog)
{
Log.LogInfo($"Successfully loaded data from {url}!");
}
string content = await dataRequest.Content.ReadAsStringAsync();
return content;
}
else
{
if (isLog)
{
Log.LogError($"Failed to load data from {url}! Falling back...");
Log.LogError($"Status code: {dataRequest.StatusCode}");
}
new CancellationTokenSource().Cancel();
return null;
}
}
catch(Exception ex)
{
Log.LogError($"Failed to load data from {url}! Falling back...");
Log.LogError(ex);
new CancellationTokenSource().Cancel();
return null;
}
}
public static async Task<byte[]> GetByteDataFromWeb(string url, bool isLog = true)
{
if (isLog)
{
Log.LogInfo($"Attempting to read {url}");
}
HttpClient client = new HttpClient();
try
{
var dataRequest = await client.GetAsync(url);
if (dataRequest.StatusCode == System.Net.HttpStatusCode.OK)
{
if (isLog)
{
Log.LogInfo($"Successfully loaded data from {url}!");
}
byte[] content = await dataRequest.Content.ReadAsByteArrayAsync();
return content;
}
else
{
if (isLog)
{
Log.LogError($"Failed to load data from {url}! Falling back...");
Log.LogError($"Status code: {dataRequest.StatusCode}");
}
new CancellationTokenSource().Cancel();
return null;
}
}
catch(Exception ex)
{
Log.LogError($"Failed to load data from {url}! Falling back...");
Log.LogError(ex);
new CancellationTokenSource().Cancel();
return null;
}
}
public static async Task<string> GetDataFromWebWithInput(string url, bool isLog = true)
{
if (isLog)
{
Log.LogInfo($"Attempting to read {url}");
}
HttpClient client = new HttpClient();
using var request = new HttpRequestMessage()
{
Method = HttpMethod.Get,
RequestUri = new Uri(url)
};
request.Headers.Add("Accept", "*/*");
request.Headers.Add("Accept-Encoding", "gzip, deflate, br");
request.Headers.Add("User-Agent", "TranslatorMod");
var dataRequest = await client.SendAsync(request);
if(dataRequest.StatusCode == System.Net.HttpStatusCode.OK) if(dataRequest.StatusCode == System.Net.HttpStatusCode.OK)
{ {
if (isLog) if (isLog)
@ -396,6 +583,26 @@ namespace PvZ_Fusion_Translator
} }
} }
public static int CalculateGameVersion(string gameVersion)
{
int res = 0;
string[] gameVersionParts = gameVersion.Split('.');
int startingPower = (int)Math.Max(gameVersionParts.Length, 3);
for (int i = 0; i < startingPower; i++)
{
int factor = 0;
if (i < gameVersionParts.Length)
{
factor = int.Parse(gameVersionParts[i]);
}
int power = startingPower - i;
res += factor * (int)Math.Pow(10, power - 1);
}
return res;
}
#if MULTI_LANGUAGE #if MULTI_LANGUAGE
internal static void ChangeLanguage(string language) internal static void ChangeLanguage(string language)
{ {
@ -437,7 +644,7 @@ namespace PvZ_Fusion_Translator
Chinese_cn, Chinese_cn,
French, French,
//Italian, //Italian,
//German, German,
Spanish, Spanish,
@ -446,7 +653,7 @@ namespace PvZ_Fusion_Translator
//Javanese, //Javanese,
//Filipino, //Filipino,
Vietnamese, Vietnamese,
//Indonesian, Indonesian,
//Russian, //NOTE: legacy language //Russian, //NOTE: legacy language
Japanese, Japanese,
@ -457,8 +664,8 @@ namespace PvZ_Fusion_Translator
// Slovak, // Slovak,
//Polish, //Polish,
//Turkish, //Turkish,
//Arabic, Arabic,
Romanian, Romanian,
LANG_END LANG_END
} }
@ -468,18 +675,21 @@ namespace PvZ_Fusion_Translator
{ LanguageEnum.English, "English"}, { LanguageEnum.English, "English"},
{ LanguageEnum.Chinese_cn, "简体中文"}, { LanguageEnum.Chinese_cn, "简体中文"},
{ LanguageEnum.French, "Français"}, { LanguageEnum.French, "Français"},
{ LanguageEnum.German, "Deutsch"},
{ LanguageEnum.Spanish, "Español"}, { LanguageEnum.Spanish, "Español"},
{ LanguageEnum.Vietnamese, "Tiếng Việt"}, { LanguageEnum.Vietnamese, "Tiếng Việt"},
{ LanguageEnum.Indonesian, "Bahasa Indonesia"},
{ LanguageEnum.Japanese, "日本語"}, { LanguageEnum.Japanese, "日本語"},
{ LanguageEnum.Korean, "한국어"}, { LanguageEnum.Korean, "한국어"},
{ LanguageEnum.Ukrainian, "українська"}, { LanguageEnum.Ukrainian, "українська"},
{ LanguageEnum.Arabic, "ﺔﻴﺑﺮﻌﻟا"},
{ LanguageEnum.Romanian, "Română"} { LanguageEnum.Romanian, "Română"}
}; };
public static Dictionary<ToggleEnum, string> ToggleNames = new Dictionary<ToggleEnum, string>() public static Dictionary<ToggleEnum, string> ToggleNames = new Dictionary<ToggleEnum, string>()
{ {
{ ToggleEnum.Textures, "Textures"}, { ToggleEnum.Textures, "<size=85%>Change Texture\nSource"},
{ ToggleEnum.Audio, "Audio"}, { ToggleEnum.Audio, "<size=85%>Change Audio\nSource"},
{ ToggleEnum.SwapLocal, "<size=85%>Change Translation\nSource"} { ToggleEnum.SwapLocal, "<size=85%>Change Translation\nSource"}
}; };

View file

@ -1,7 +1,7 @@
 
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17 # Visual Studio Version 18
VisualStudioVersion = 17.10.35122.118 VisualStudioVersion = 18.7.11911.148 stable
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8EC462FD-D22E-90A8-E5CE-7E832BA40C5D}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8EC462FD-D22E-90A8-E5CE-7E832BA40C5D}"
ProjectSection(SolutionItems) = preProject ProjectSection(SolutionItems) = preProject