Update BepInEx to the current progress.

Credit: Moon & JustNull
This commit is contained in:
TuanAnh2901 2025-07-31 20:17:08 +07:00
parent ae707d7b06
commit 7be9b8c514
36 changed files with 1305 additions and 772 deletions

379
.gitignore vendored
View file

@ -1,368 +1,11 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Oo]ut/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd
PvZ-Fusion-Blooms-master/MelonLoader/PvZ Fusion Translator \[MelonLoader\].csproj
PvZ-Fusion-Translator 2.zip
MelonLoader/PvZ Fusion Translator \[MelonLoader].csproj
################################################################################
# This .gitignore file was automatically created by Microsoft(R) Visual Studio.
################################################################################
/.vs/BepInEx/copilot-chat/bff105b7/sessions
/.vs
/bin
/obj
/MelonLoader/obj
/BepInEx/obj/Debug/net6.0
/BepInEx/obj

View file

@ -40,29 +40,36 @@ namespace PvZ_Fusion_Translator__BepInEx_
}
public static void LoadAudios()
{
if (!Directory.Exists(customAudioPath))
Directory.CreateDirectory(customAudioPath);
string[] audioFiles = Directory.GetFiles(customAudioPath, "*", SearchOption.AllDirectories);
var ovrClip = audioFiles.SingleOrDefault(f => Path.GetFileNameWithoutExtension(f) == "REPLACE_ALL");
if (ovrClip == null)
try
{
foreach (string file in audioFiles)
{
if (!allowedExts.Contains(Path.GetExtension(file)))
continue;
if (!Directory.Exists(customAudioPath))
Directory.CreateDirectory(customAudioPath);
AudioClip clip = AudioImportLib.BepInEx.API.LoadAudioClip(file);
string[] audioFiles = Directory.GetFiles(customAudioPath, "*", SearchOption.AllDirectories);
var ovrClip = audioFiles.SingleOrDefault(f => Path.GetFileNameWithoutExtension(f) == "REPLACE_ALL");
if (ovrClip == null)
{
foreach (string file in audioFiles)
{
if (!allowedExts.Contains(Path.GetExtension(file)))
continue;
AudioClip clip = AudioImportLib.BepInEx.API.LoadAudioClip(file);
AudioClips.Add(clip.name, clip);
Log.LogInfo("Added Override: " + clip.name);
}
}
else
{
AudioClip clip = AudioImportLib.BepInEx.API.LoadAudioClip(ovrClip);
AudioClips.Add(clip.name, clip);
overrideEnabled = true;
Log.LogInfo("Added Override: " + clip.name);
}
}
else
catch (Exception ex)
{
AudioClip clip = AudioImportLib.BepInEx.API.LoadAudioClip(ovrClip);
AudioClips.Add(clip.name, clip);
overrideEnabled = true;
Log.LogInfo("Added Override: " + clip.name);
Log.LogError($"Error loading audio clips: {ex.Message}");
}
}

View file

@ -4,169 +4,169 @@ using System.IO;
namespace PvZ_Fusion_Translator__BepInEx_.AssetStore
{
public static class FontStore
{
internal static Dictionary<string, TMP_FontAsset> fontAssetDict = [];
internal static Dictionary<string, TMP_FontAsset> fontAssetDictSecondary = [];
public static class FontStore
{
internal static Dictionary<string, TMP_FontAsset> fontAssetDict = [];
internal static Dictionary<string, TMP_FontAsset> fontAssetDictSecondary = [];
internal static void Init()
{
string fontsDir = Path.Combine(Core.Instance.modsDirectory, "[Custom Fonts]");
internal static void Init()
{
string fontsDir = Path.Combine(Core.Instance.modsDirectory, "[Custom Fonts]");
#if MULTI_LANGUAGE
foreach (string file in Directory.GetFiles(fontsDir))
{
string fileName = Path.GetFileNameWithoutExtension(file);
string fileExtension = Path.GetExtension(file);
#if MULTI_LANGUAGE
foreach (string file in Directory.GetFiles(fontsDir))
{
string fileName = Path.GetFileNameWithoutExtension(file);
string fileExtension = Path.GetExtension(file);
if (fileExtension == ".ttf" || fileExtension == ".otf")
{
if (!fileName.EndsWith("_Almanac") && !fileName.EndsWith("_Fallback"))
{
string fontPath = Path.Combine("PvZ_Fusion_Translator", "[Custom Fonts]", fileName + fileExtension);
if (fileExtension == ".ttf" || fileExtension == ".otf")
{
if (!fileName.EndsWith("_Almanac") && !fileName.EndsWith("_Fallback"))
{
string fontPath = Path.Combine("PvZ_Fusion_Translator", "[Custom Fonts]", fileName + fileExtension);
TMP_FontAsset fontAsset = FontHandler.LoadTMPFont(fontPath, true);
fontAsset.name = fileName;
fontAssetDict.Add(fileName, fontAsset);
TMP_FontAsset fontAsset = FontHandler.LoadTMPFont(fontPath, true);
fontAsset.name = fileName;
fontAssetDict.Add(fileName, fontAsset);
Log.LogInfo($"Font for language '{fileName}' loaded");
}
}
}
InitFallback();
#else
Log.LogInfo($"Font for language '{fileName}' loaded");
}
}
}
InitFallback();
#else
string defaultFontDir = Path.Combine("PvZ_Fusion_Translator", "[Custom Fonts]", "English.ttf");
TMP_FontAsset defaultFont = FontHandler.LoadTMPFont(defaultFontDir, true);
fontAssetDict.Add("English", defaultFont);
#endif
}
#endif
}
internal static void InitFallback()
{
string fontsDir = Path.Combine(Core.Instance.modsDirectory, "[Custom Fonts]");
foreach (string file in Directory.GetFiles(fontsDir))
{
string fileName = Path.GetFileNameWithoutExtension(file);
string fileExtension = Path.GetExtension(file);
internal static void InitFallback()
{
string fontsDir = Path.Combine(Core.Instance.modsDirectory, "[Custom Fonts]");
foreach (string file in Directory.GetFiles(fontsDir))
{
string fileName = Path.GetFileNameWithoutExtension(file);
string fileExtension = Path.GetExtension(file);
if (fileExtension == ".ttf" || fileExtension == ".otf")
{
if (fileName.EndsWith("_Almanac") || fileName.EndsWith("_Fallback"))
{
string fallbackPath = Path.Combine("PvZ_Fusion_Translator", "[Custom Fonts]", fileName + fileExtension);
TMP_FontAsset fallbackFont = FontHandler.LoadTMPFont(fallbackPath, true);
fallbackFont.name = fileName;
if (fileExtension == ".ttf" || fileExtension == ".otf")
{
if (fileName.EndsWith("_Almanac") || fileName.EndsWith("_Fallback"))
{
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))
{
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);
if (fontAssetDictSecondary.ContainsKey(fileNameLanguage))
{
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");
}
}
}
AddFallback();
}
// Log.LogInfo($"Fallback font for language '{fileNameLanguage}' loaded");
}
}
}
AddFallback();
}
public static void AddFallback()
{
foreach (var lang in fontAssetDict.Keys)
{
if (fontAssetDict[lang].fallbackFontAssetTable == null)
{
fontAssetDict[lang].fallbackFontAssetTable = new Il2CppSystem.Collections.Generic.List<TMP_FontAsset>();
}
public static void AddFallback()
{
foreach (var lang in fontAssetDict.Keys)
{
if (fontAssetDict[lang].fallbackFontAssetTable == null)
{
fontAssetDict[lang].fallbackFontAssetTable = new Il2CppSystem.Collections.Generic.List<TMP_FontAsset>();
}
if (fontAssetDictSecondary.ContainsKey(lang))
{
fontAssetDict[lang].fallbackFontAssetTable.Add(fontAssetDictSecondary[lang]);
Log.LogInfo("Fallback font for language '" + lang + "' added");
continue;
}
if (fontAssetDictSecondary.ContainsKey(lang + "_Almanac"))
{
fontAssetDict[lang].fallbackFontAssetTable.Add(fontAssetDictSecondary[lang + "_Almanac"]);
Log.LogInfo("Fallback font for language '" + lang + "' added");
continue;
}
if (fontAssetDictSecondary.ContainsKey(lang + "_Fallback"))
{
fontAssetDict[lang].fallbackFontAssetTable.Add(fontAssetDictSecondary[lang + "_Fallback"]);
Log.LogInfo("Fallback font for language '" + lang + "' added");
continue;
}
}
}
if (fontAssetDictSecondary.ContainsKey(lang))
{
fontAssetDict[lang].fallbackFontAssetTable.Add(fontAssetDictSecondary[lang]);
Log.LogInfo("Fallback font for language '" + lang + "' added");
continue;
}
if (fontAssetDictSecondary.ContainsKey(lang + "_Almanac"))
{
fontAssetDict[lang].fallbackFontAssetTable.Add(fontAssetDictSecondary[lang + "_Almanac"]);
Log.LogInfo("Fallback font for language '" + lang + "' added");
continue;
}
if (fontAssetDictSecondary.ContainsKey(lang + "_Fallback"))
{
fontAssetDict[lang].fallbackFontAssetTable.Add(fontAssetDictSecondary[lang + "_Fallback"]);
Log.LogInfo("Fallback font for language '" + lang + "' added");
continue;
}
}
}
#if MULTI_LANGUAGE
public static TMP_FontAsset LoadTMPFont(string language)
{
if (fontAssetDict.TryGetValue(language, out TMP_FontAsset font))
{
TMP_FontAsset fontAsset = font;
if (fontAsset.fallbackFontAssetTable != null)
{
// Log.LogInfo("Fallback font for language '" + language + "' loaded. The name of the FB Font is" + fontAsset.fallbackFontAssetTable[0].name);
}
return fontAsset;
}
return fontAssetDict.GetValueOrDefault("English");
}
#else
#if MULTI_LANGUAGE
public static TMP_FontAsset LoadTMPFont(string language)
{
if (fontAssetDict.TryGetValue(language, out TMP_FontAsset font))
{
TMP_FontAsset fontAsset = font;
if (fontAsset.fallbackFontAssetTable != null)
{
// Log.LogInfo("Fallback font for language '" + language + "' loaded. The name of the FB Font is" + fontAsset.fallbackFontAssetTable[0].name);
}
return fontAsset;
}
return fontAssetDict.GetValueOrDefault("English");
}
#else
public static TMP_FontAsset LoadTMPFont()
{
TMP_FontAsset defaultFont = fontAssetDict["English"];
return defaultFont;
}
#endif
#endif
public static TMP_FontAsset LoadTMPFontAlmanac(string language)
{
if (fontAssetDictSecondary.ContainsKey(language))
{
if (fontAssetDictSecondary.TryGetValue(language, out TMP_FontAsset almanacAsset))
{
return almanacAsset;
}
}
if (fontAssetDictSecondary.ContainsKey(language + "_Almanac"))
{
if (fontAssetDictSecondary.TryGetValue(language + "_Almanac", out TMP_FontAsset almanacAsset))
{
return almanacAsset;
}
}
public static TMP_FontAsset LoadTMPFontAlmanac(string language)
{
if (fontAssetDictSecondary.ContainsKey(language))
{
if (fontAssetDictSecondary.TryGetValue(language, out TMP_FontAsset almanacAsset))
{
return almanacAsset;
}
}
if (fontAssetDictSecondary.ContainsKey(language + "_Almanac"))
{
if (fontAssetDictSecondary.TryGetValue(language + "_Almanac", out TMP_FontAsset almanacAsset))
{
return almanacAsset;
}
}
return fontAssetDict.GetValueOrDefault("English");
}
return fontAssetDict.GetValueOrDefault("English");
}
#if MULTI_LANGUAGE
public static void Reload()
{
// Get the current language
string currentLanguage = Utils.Language.ToString();
#if MULTI_LANGUAGE
public static void Reload()
{
// Get the current language
string currentLanguage = Utils.Language.ToString();
// Load the font for the current language
_ = LoadTMPFont(currentLanguage);
}
#endif
// Load the font for the current language
_ = LoadTMPFont(currentLanguage);
}
#endif
}
}
}
}

View file

@ -1252,7 +1252,7 @@ namespace PvZ_Fusion_Translator__BepInEx_.AssetStore
};
}
static TextMeshProUGUI ConvertToTextMeshPro(UnityEngine.UI.Text oldText, TMP_FontAsset fontAsset, bool isLog = false)
public static TextMeshProUGUI ConvertToTextMeshPro(UnityEngine.UI.Text oldText, TMP_FontAsset fontAsset, bool isLog = false)
{
if (oldText == null)
{

View file

@ -9,6 +9,8 @@ namespace PvZ_Fusion_Translator__BepInEx_.AssetStore
{
internal static Dictionary<string, string> textureDict = [];
internal static Dictionary<string, string> spriteDict = [];
internal static void Init() => FileLoader.LoadTextures();
internal static void Reload()

View file

@ -21,7 +21,7 @@ public class Core : BasePlugin
private static DateTime? dtStartToast;
private static string toast_txt;
public static ManualLogSource Log;
public new static ManualLogSource Log;
public static Core Instance { get; private set; }
public static MonoBehaviour MonoInstance { get; private set; }

Binary file not shown.

View file

@ -18,6 +18,7 @@ namespace PvZ_Fusion_Translator__BepInEx_
Strings,
Dumps,
Almanac,
Sprites
}
public static string GetAssetDir(AssetType assetType, Utils.LanguageEnum? language = null)
@ -91,7 +92,7 @@ namespace PvZ_Fusion_Translator__BepInEx_
Log.LogInfo("Strings loaded successfully.");
}
internal static void LoadTextures()
{
@ -101,7 +102,8 @@ namespace PvZ_Fusion_Translator__BepInEx_
if (Utils.customTextures)
{
LoadCustomTextures();
} else
}
else
{
LoadDefaultTextures();
}
@ -183,13 +185,13 @@ namespace PvZ_Fusion_Translator__BepInEx_
foreach (string filepath in Directory.EnumerateFiles(textureDefaultDir, "*.png", SearchOption.AllDirectories))
{
#if OBFUSCATE
#if OBFUSCATE
if (CheckSumStore.IsModified(filepath))
{
Log.LogError("File {0} was modified!" , filepath);
continue;
}
#endif
#endif
Texture2D texture2D = Utils.LoadImage(filepath);
TextureStore.textureDict[Path.GetFileNameWithoutExtension(filepath)] = filepath;
@ -279,9 +281,11 @@ namespace PvZ_Fusion_Translator__BepInEx_
File.WriteAllText(Path.Combine(dumpDir, "ZombieStrings.json"), ZombieStrings);
Dictionary<Achievement, AchievementObject> achievementsList = new Dictionary<Achievement, AchievementObject>();
foreach (Il2CppSystem.Collections.Generic.KeyValuePair<Achievement, Il2CppSystem.Tuple<string, string>> entry in AchievementClip.achievementsText)
foreach (var entry in AchievementClip.achievementsText)
{
achievementsList.Add(entry.Key, new AchievementObject(entry.Key, entry.Value.Item1, entry.Value.Item2));
var key = entry.Key;
var value = entry.Value;
achievementsList.Add(key, new AchievementObject(key, value.Item1, value.Item2));
}
File.WriteAllText(Path.Combine(dumpDir, "AchievementsText.json"), JsonSerializer.Serialize(achievementsList, new JsonSerializerOptions
{
@ -290,7 +294,7 @@ namespace PvZ_Fusion_Translator__BepInEx_
}));
}
#if DEBUG
//#if DEBUG
public static void DumpUntranslatedStrings(string text)
{
string dumpDir = GetAssetDir(AssetType.Dumps);
@ -320,7 +324,7 @@ namespace PvZ_Fusion_Translator__BepInEx_
File.WriteAllText(jsonFile, JsonSerializer.Serialize(untranslatedStrings, options));
}
}
#endif
//#endif
#if MULTI_LANGUAGE
internal static void LoadLanguage()

View file

@ -6,40 +6,40 @@ using UnityEngine;
namespace PvZ_Fusion_Translator__BepInEx_
{
public static class FontHandler
{
public static Font LoadFont(this string pathFromModsFolder, bool throwException)
{
string fontFilePath = Path.Combine(Paths.PluginPath, pathFromModsFolder);
if (!File.Exists(fontFilePath))
{
if (throwException)
Log.LogWarning($"Font not found at path: '{fontFilePath}'.");
return null;
}
public static class FontHandler
{
public static Font LoadFont(this string pathFromModsFolder, bool throwException)
{
string fontFilePath = Path.Combine(Paths.PluginPath, pathFromModsFolder);
if (!File.Exists(fontFilePath))
{
if (throwException)
Log.LogWarning($"Font not found at path: '{fontFilePath}'.");
return null;
}
Font font = new Font();
Font.Internal_CreateFontFromPath(font, fontFilePath); // Default size, adjust as needed
return font;
}
Font font = new Font();
Font.Internal_CreateFontFromPath(font, fontFilePath); // Default size, adjust as needed
return font;
}
public static TMP_FontAsset ConvertToTMP(this Font font)
{
TMP_FontAsset fontAsset = TMP_FontAsset.CreateFontAsset(font);
if (fontAsset == null)
{
Log.LogWarning($"Failed to create TMP_FontAsset from font '{font.name}'.");
return null;
}
return fontAsset;
}
public static TMP_FontAsset ConvertToTMP(this Font font)
{
TMP_FontAsset fontAsset = TMP_FontAsset.CreateFontAsset(font);
if (fontAsset == null)
{
Log.LogWarning($"Failed to create TMP_FontAsset from font '{font.name}'.");
return null;
}
return fontAsset;
}
public static TMP_FontAsset LoadTMPFont(this string pathFromModsFolder, bool throwException)
{
Font font = pathFromModsFolder.LoadFont(throwException);
if (font == null)
return null;
return font.ConvertToTMP();
}
}
public static TMP_FontAsset LoadTMPFont(this string pathFromModsFolder, bool throwException)
{
Font font = pathFromModsFolder.LoadFont(throwException);
if (font == null)
return null;
return font.ConvertToTMP();
}
}
}

View file

@ -17,13 +17,13 @@ namespace PvZ_Fusion_Translator__BepInEx_.Patches.BaseTextObjects
private static void ShowText(InGameText __instance)
{
#if MULTI_LANGUAGE
TMP_FontAsset fontAsset = FontStore.LoadTMPFont(Utils.Language.ToString());
#else
#if MULTI_LANGUAGE
TMP_FontAsset fontAsset = FontStore.LoadTMPFont(Utils.Language.ToString());
#else
TMP_FontAsset fontAsset = FontStore.LoadTMPFont();
#endif
foreach (TextMeshProUGUI txt in __instance.textMeshes)
#endif
foreach (TextMeshProUGUI txt in __instance.textMeshes)
{
txt.text = StringStore.TranslateText(txt.text, true);
txt.font = fontAsset;

View file

@ -18,9 +18,11 @@ namespace PvZ_Fusion_Translator__BepInEx_.Patches.BaseTextObjects
__instance = StringStore.TranslateText(__instance);
__instance.autoSizeTextContainer = false;
return;
} else if (!(__instance.transform.name.Contains("AlmanacZombie") || __instance.transform.name.Contains("AlmanacPlant")))
{
__instance = StringStore.TranslateText(__instance);
__instance.autoSizeTextContainer = true;
}
__instance = StringStore.TranslateText(__instance);
__instance.autoSizeTextContainer = true;
}
}
}

View file

@ -108,7 +108,12 @@ namespace PvZ_Fusion_Translator__BepInEx_.Patches.GameObjects
foreach(TextMeshProUGUI txt in mainTransform.GetComponentsInChildren<TextMeshProUGUI>())
{
#if DEBUG
FileLoader.DumpUntranslatedStrings(txt.text);
txt.text = StringStore.TranslateText(txt.text);
#else
txt.text = StringStore.TranslateText(txt.text, true);
#endif
}
}
}

View file

@ -0,0 +1,27 @@
using HarmonyLib;
using TMPro;
using PvZ_Fusion_Translator__BepInEx_.AssetStore;
using UnityEngine;
namespace PvZ_Fusion_Translator__BepInEx_.Patches.GameObjects
{
[HarmonyPatch(typeof(Board))]
public static class Board_Patch
{
[HarmonyPatch(nameof(Board.Update))]
[HarmonyPostfix]
private static void Update(Board __instance)
{
foreach (SpriteRenderer spriteRenderer in __instance.GetComponentsInChildren<SpriteRenderer>())
{
if (spriteRenderer.sprite != null)
{
if (TextureStore.spriteDict.ContainsKey(spriteRenderer.sprite.name) && spriteRenderer.drawMode != SpriteDrawMode.Sliced)
{
spriteRenderer.drawMode = SpriteDrawMode.Sliced;
}
}
}
}
}
}

View file

@ -0,0 +1,73 @@
using HarmonyLib;
using System;
using TMPro;
using PvZ_Fusion_Translator__BepInEx_.AssetStore;
using UnityEngine;
using UnityEngine.UI;
namespace PvZ_Fusion_Translator__BepInEx_.Patches.GameObjects.ButtonObjects
{
[HarmonyPatch(typeof(UIButton))]
public static class UIButton_Patch
{
[HarmonyPatch(nameof(UIButton.Start))]
[HarmonyPostfix]
private static void Postfix_Start(UIButton __instance)
{
try
{
// Convert and translate legacy Text components
Text[] textComponents = __instance.GetComponentsInChildren<Text>(true);
TextMeshProUGUI[] textMeshComponents = __instance.GetComponentsInChildren<TextMeshProUGUI>(true);
foreach (Text textComponent in textComponents)
{
if (textComponent != null && !string.IsNullOrEmpty(textComponent.text))
{
string translatedText = StringStore.TranslateText(textComponent.text);
if (!string.IsNullOrEmpty(translatedText) && translatedText != textComponent.text)
{
TMP_FontAsset fontAsset = FontStore.LoadTMPFont(Utils.Language.ToString());
TextMeshProUGUI newTMP = StringStore.ConvertToTextMeshPro(textComponent, fontAsset, true);
if (newTMP != null)
{
newTMP.text = translatedText;
}
}
}
}
// Also handle TMP components directly under the button
if (__instance.transform.childCount >= 2)
{
TextMeshProUGUI text = __instance.transform.GetChild(0).GetComponent<TextMeshProUGUI>();
TextMeshProUGUI textShadow = __instance.transform.GetChild(1).GetComponent<TextMeshProUGUI>();
StringStore.TranslateTextUI(text, false);
StringStore.TranslateTextUI(textShadow, false);
text.autoSizeTextContainer = textShadow.autoSizeTextContainer = true;
}
}
catch (Exception) { }
}
[HarmonyPatch(nameof(UIButton.OnMouseUpAsButton))]
[HarmonyPostfix]
public static void Postfix_OnMouseUpAsButton(UIButton __instance)
{
try
{
if (__instance.transform.childCount >= 2)
{
TextMeshProUGUI text = __instance.transform.GetChild(0).GetComponent<TextMeshProUGUI>();
TextMeshProUGUI textShadow = __instance.transform.GetChild(1).GetComponent<TextMeshProUGUI>();
StringStore.TranslateTextUI(text, false);
StringStore.TranslateTextUI(textShadow, false);
text.autoSizeTextContainer = textShadow.autoSizeTextContainer = true;
}
}
catch (Exception) { }
}
}
}

View file

@ -0,0 +1,37 @@
using HarmonyLib;
using TMPro;
using PvZ_Fusion_Translator__BepInEx_.AssetStore;
using UnityEngine;
using System.Text.RegularExpressions;
namespace PvZ_Fusion_Translator__BepInEx_.Patches.GameObjects
{
[HarmonyPatch(typeof(CrisisZombieWindow))]
public static class CrisisZombieWindow_Patch
{
[HarmonyPatch(nameof(CrisisZombieWindow.Start))]
[HarmonyPostfix]
private static void Start(CrisisZombieWindow __instance)
{
Transform introduceTransform = __instance.transform.FindChild("Images").FindChild("Introduce");
TextMeshProUGUI introduceText = introduceTransform.GetComponent<TextMeshProUGUI>();
TMP_FontAsset fontAsset = FontStore.LoadTMPFont(Utils.Language.ToString());
introduceText.text = StringStore.TranslateText(introduceText.text);
introduceText.font = fontAsset;
}
[HarmonyPatch(nameof(CrisisZombieWindow.SetZombieType))]
[HarmonyPostfix]
private static void SetZombieType(CrisisZombieWindow __instance)
{
Transform introduceTransform = __instance.transform.FindChild("Images").FindChild("Introduce");
TextMeshProUGUI introduceText = introduceTransform.GetComponent<TextMeshProUGUI>();
TMP_FontAsset fontAsset = FontStore.LoadTMPFont(Utils.Language.ToString());
introduceText.text = StringStore.TranslateText(introduceText.text);
introduceText.font = fontAsset;
}
}
}

View file

@ -0,0 +1,37 @@
using HarmonyLib;
using TMPro;
using PvZ_Fusion_Translator__BepInEx_.AssetStore;
using UnityEngine;
using System.Text.RegularExpressions;
namespace PvZ_Fusion_Translator__BepInEx_.Patches.GameObjects
{
[HarmonyPatch(typeof(FruitNinjaSelectWindow))]
public static class FruitNinjaSelectWindow_Patch
{
[HarmonyPatch(nameof(FruitNinjaSelectWindow.SetType))]
[HarmonyPostfix]
private static void SetType(FruitNinjaSelectWindow __instance)
{
Transform introduceTransform = __instance.transform.FindChild("Images").FindChild("Introduce");
TextMeshProUGUI introduceText = introduceTransform.GetComponent<TextMeshProUGUI>();
TMP_FontAsset fontAsset = FontStore.LoadTMPFont(Utils.Language.ToString());
introduceText.text = StringStore.TranslateText(introduceText.text);
introduceText.font = fontAsset;
}
[HarmonyPatch(nameof(FruitNinjaSelectWindow.OnAnimOver))]
[HarmonyPostfix]
private static void OnAnimOver(FruitNinjaSelectWindow __instance)
{
Transform introduceTransform = __instance.transform.FindChild("Images").FindChild("Introduce");
TextMeshProUGUI introduceText = introduceTransform.GetComponent<TextMeshProUGUI>();
TMP_FontAsset fontAsset = FontStore.LoadTMPFont(Utils.Language.ToString());
introduceText.text = StringStore.TranslateText(introduceText.text);
introduceText.font = fontAsset;
}
}
}

View file

@ -11,14 +11,15 @@ namespace PvZ_Fusion_Translator__BepInEx_.Patches.GameObjects
private static bool _warningShown = false;
[HarmonyPostfix]
[HarmonyPatch(nameof(MainMenu.FixedUpdate))]
private static void FixedUpdate(MainMenu __instance)
{
if (_warningShown || NoticeMenu.Instance == null)
return;
WarningStore.WarningReload(Utils.Language, NoticeMenu.Instance);
_warningShown = true;
}
[HarmonyPatch("AnimOver")]
private static void AnimOver(MainMenu __instance)
{
bool flag = _warningShown || NoticeMenu.Instance == null;
if (!flag)
{
WarningStore.WarningReload(Utils.Language, NoticeMenu.Instance);
_warningShown = true;
}
}
}
}

View file

@ -0,0 +1,32 @@
using HarmonyLib;
// using Il2Cpp;
using TMPro;
using PvZ_Fusion_Translator__BepInEx_.AssetStore;
namespace PvZ_Fusion_Translator__BepInEx_.Patches.GameObjects.MinorObjects
{
[HarmonyPatch(typeof(JigsawClip))]
public static class JigsawClip_Patch
{
[HarmonyPostfix]
[HarmonyPatch(nameof(JigsawClip.Awake))]
private static void Postfix_Awake(JigsawClip __instance)
{
if (!__instance || !__instance.description) return;
StringStore.TranslateTextUI(__instance.description);
}
[HarmonyPostfix]
[HarmonyPatch(nameof(JigsawClip.Update))]
private static void Postfix_Update(JigsawClip __instance)
{
if (!__instance || !__instance.description) return;
if (__instance.description.text != StringStore.TranslateText(__instance.description.text))
{
StringStore.TranslateTextUI(__instance.description);
}
}
}
}

View file

@ -6,19 +6,45 @@ using UnityEngine;
namespace PvZ_Fusion_Translator__BepInEx_.Patches.GameObjects.MinorObjects
{
[HarmonyPatch(typeof(Plant))]
public static class Plant_Patch
{
[HarmonyPostfix]
[HarmonyPatch(nameof(Plant.UpdateHealthText))]
private static void UpdateHealthText(Plant __instance)
{
Transform healthTransform = __instance.transform.Find("health");
if (healthTransform != null)
{
StringStore.TranslateTextTransform(__instance.transform);
}
}
}
[HarmonyPatch(typeof(Plant))]
public static class Plant_Patch
{
[HarmonyPostfix]
[HarmonyPatch(nameof(Plant.Awake))]
private static void Awake(Plant __instance)
{
if (!(__instance.thePlantType == PlantType.SuperMachineNut || __instance.thePlantType == PlantType.MachineNut))
return;
__instance.healthSlider.healthText.text = __instance.healthSlider.healthTextShadow.text = ChangeHPText(__instance.healthSlider.healthTextShadow.text);
}
[HarmonyPostfix]
[HarmonyPatch(nameof(Plant.UpdateText))]
private static void Update(Plant __instance)
{
if (!(__instance.thePlantType == PlantType.SuperMachineNut || __instance.thePlantType == PlantType.MachineNut))
return;
if (__instance.thePlantHealth < __instance.thePlantMaxHealth)
return;
__instance.healthSlider.healthText.text = __instance.healthSlider.healthTextShadow.text = ChangeHPText(__instance.healthSlider.healthTextShadow.text);
}
static string ChangeHPText(string originalText)
{
var regex = new Regex(@"(\d+)\d\d\d/(\d)000");
if (regex.IsMatch(originalText))
{
var match = regex.Match(originalText);
int groupCount = match.Groups.Count;
List<string> dynamicParts = new List<string>();
for (int i = 1; i < groupCount; i++)
dynamicParts.Add(match.Groups[i].Value);
return originalText = string.Format("{0}k/{1}k", [.. dynamicParts]);
}
return originalText;
}
}
}
#endif

View file

@ -0,0 +1,16 @@
using HarmonyLib;
namespace PvZ_Fusion_Translator__BepInEx_.Patches.GameObjects.MinorObjects
{
[HarmonyPatch(typeof(TrainingDummy), nameof(TrainingDummy.UpdateHealthText))]
public static class TrainingDummy_Patch
{
[HarmonyPostfix]
public static void UpdateHealthText(TrainingDummy __instance)
{
Zombie_Patch.TranslateHpUI(__instance.healthText);
Zombie_Patch.TranslateHpUI(__instance.healthTextShadow);
}
}
}

View file

@ -0,0 +1,17 @@
using HarmonyLib;
using PvZ_Fusion_Translator__BepInEx_.AssetStore;
namespace PvZ_Fusion_Translator__BepInEx_.Patches.GameObjects.MinorObjects
{
[HarmonyPatch(typeof(UltimateChomper), nameof(UltimateChomper.UpdateText))]
public static class UltimateChomper_Patch
{
[HarmonyPostfix]
public static void UpdateText(UltimateChomper __instance)
{
StringStore.TranslateText(__instance.killingText);
StringStore.TranslateText(__instance.killingTextShadow);
}
}
}

View file

@ -1,12 +1,100 @@
using System;
using HarmonyLib;
using PvZ_Fusion_Translator__BepInEx_.AssetStore;
using System.Text.RegularExpressions;
using UnityEngine;
using TMPro;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PvZ_Fusion_Translator__BepInEx_.Patches.GameObjects.MinorObjects
{
class Zombie_Patch
[HarmonyPatch(typeof(Zombie))]
public static class Zombie_Patch
{
private static Dictionary<string, string> HPStrings = new Dictionary<string, string>()
{
{ "最后一击:(\\d+)\nDPS:(.+)$", "Last damage: {0}\nDPS: {1}" },
{ "^HP:(\\d+)/(\\d+)\n\\D+(\\d+)/(\\d+)\n\\D+(\\d+)/(\\d+)$", "HP: {0}/{1}\nType 1 armor: {2}/{3}\nType 2 armor: {4}/{5}" },
{ "^HP:(\\d+)/(\\d+)\n\\D+(\\d+)/(\\d+)$", "HP: {0}/{1}\nType 1 armor: {2}/{3}" },
{ "^HP:(\\d+)/(\\d+)$", "HP: {0}/{1}" },
};
public static void LoadHPStrings()
{
foreach (var hp in HPStrings)
if (StringStore.translationStringRegex.ContainsKey(hp.Key))
HPStrings[hp.Key] = StringStore.translationStringRegex[hp.Key];
}
[HarmonyPatch(nameof(Zombie.Start))]
[HarmonyPostfix]
public static void Start(Zombie __instance)
{
TranslateHpUI(__instance.healthText);
TranslateHpUI(__instance.healthTextShadow);
if (__instance.theFirstArmorHealth == 0 && __instance.theSecondArmorHealth != 0)
{
__instance.healthText.text = __instance.healthText.text.Replace("Type 1", "Type 2");
__instance.healthTextShadow.text = __instance.healthText.text.Replace("Type 1", "Type 2");
}
if (__instance.healthText.transform.rotation != Quaternion.Euler(0, 0, 0))
__instance.healthText.transform.rotation = Quaternion.Euler(0f, 0f, 0f);
}
[HarmonyPatch(nameof(Zombie.Update))]
[HarmonyPrefix]
public static void Update(Zombie __instance)
{
if (__instance.theZombieType == ZombieType.TrainingDummy || !Board.Instance.showZombieHealth)
return;
TranslateHpUI(__instance.healthText);
TranslateHpUI(__instance.healthTextShadow);
if (__instance.theFirstArmorHealth == 0 && __instance.theSecondArmorHealth != 0)
{
__instance.healthText.text = __instance.healthText.text.Replace("Type 1", "Type 2");
__instance.healthTextShadow.text = __instance.healthText.text.Replace("Type 1", "Type 2");
}
if (__instance.healthText.transform.rotation != Quaternion.Euler(0f, 0f, 0f))
__instance.healthText.transform.rotation = Quaternion.Euler(0f, 0f, 0f);
}
public static void TranslateHpUI(TextMeshPro textTMP)
{
if (textTMP)
{
string origText = textTMP.text;
string translatedText = TranslateHPText(origText);
textTMP.text = translatedText == origText ? origText : translatedText;
textTMP.autoSizeTextContainer = false;
if (translatedText != origText)
textTMP.font = FontStore.LoadTMPFont(Utils.Language.ToString());
}
}
public static string TranslateHPText(string originalText)
{
foreach (var entry in HPStrings)
{
var regex = new Regex(entry.Key);
if (regex.IsMatch(originalText))
{
var match = regex.Match(originalText);
int groupCount = match.Groups.Count;
List<string> dynamicParts = new List<string>();
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);
}
return originalText = string.Format(entry.Value, [.. dynamicParts]);
}
}
return originalText;
}
}
}
}

View file

@ -0,0 +1,37 @@
using HarmonyLib;
using TMPro;
using PvZ_Fusion_Translator__BepInEx_.AssetStore;
using UnityEngine;
using System.Text.RegularExpressions;
namespace PvZ_Fusion_Translator__BepInEx_.Patches.GameObjects
{
[HarmonyPatch(typeof(RogueCardWindow))]
public static class RogueCardWindow_Patch
{
[HarmonyPatch(nameof(RogueCardWindow.InitCard))]
[HarmonyPostfix]
private static void InitCard(RogueCardWindow __instance)
{
Transform introduceTransform = __instance.transform.FindChild("Images").FindChild("Introduce");
TextMeshProUGUI introduceText = introduceTransform.GetComponent<TextMeshProUGUI>();
TMP_FontAsset fontAsset = FontStore.LoadTMPFont(Utils.Language.ToString());
introduceText.text = StringStore.TranslateText(introduceText.text);
introduceText.font = fontAsset;
}
[HarmonyPatch(nameof(RogueCardWindow.OnAnimOver))]
[HarmonyPostfix]
private static void OnAnimOver(RogueCardWindow __instance)
{
Transform introduceTransform = __instance.transform.FindChild("Images").FindChild("Introduce");
TextMeshProUGUI introduceText = introduceTransform.GetComponent<TextMeshProUGUI>();
TMP_FontAsset fontAsset = FontStore.LoadTMPFont(Utils.Language.ToString());
introduceText.text = StringStore.TranslateText(introduceText.text);
introduceText.font = fontAsset;
}
}
}

View file

@ -0,0 +1,45 @@
using HarmonyLib;
// using Il2Cpp;
using TMPro;
// using MelonLoader;
using PvZ_Fusion_Translator__BepInEx_.AssetStore;
using UnityEngine;
using UnityEngine.TextCore.Text;
using UnityEngine.UI;
// using static MelonLoader.MelonLogger;
// using static BepInEx.BepInEx;
using static System.Net.Mime.MediaTypeNames;
namespace PvZ_Fusion_Translator__BepInEx_.Patches.GameObjects
{
[HarmonyPatch(typeof(RogueStartMenu))]
public static class RogueStartMenu_Patch
{
[HarmonyPatch(nameof(RogueStartMenu.SetLeader))]
[HarmonyPostfix]
private static void SetLeader(RogueStartMenu __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;
}
}
[HarmonyPatch(nameof(RogueStartMenu.EnterGame))]
[HarmonyPostfix]
private static void EnterGame(RogueStartMenu __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

@ -0,0 +1,25 @@
using HarmonyLib;
using TMPro;
using PvZ_Fusion_Translator__BepInEx_.AssetStore;
using UnityEngine;
namespace PvZ_Fusion_Translator__BepInEx_.Patches.GameObjects
{
[HarmonyPatch(typeof(ShootingMenu))]
public static class ShootingMenu_Patch
{
[HarmonyPatch(nameof(ShootingMenu.Update))]
[HarmonyPostfix]
private static void Update(ShootingMenu __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

@ -0,0 +1,73 @@
using HarmonyLib;
// using Il2Cpp;
using TMPro;
using PvZ_Fusion_Translator__BepInEx_.AssetStore;
using UnityEngine;
using System.Text.RegularExpressions;
namespace PvZ_Fusion_Translator__BepInEx_.Patches.GameObjects
{
[HarmonyPatch(typeof(ShootingSelectWindow))]
public static class ShootingSelectWindow_Patch
{
[HarmonyPatch(nameof(ShootingSelectWindow.InitPlantType))]
[HarmonyPostfix]
private static void InitCard(ShootingSelectWindow __instance)
{
Transform introduceTransform = __instance.transform.FindChild("Images").FindChild("Introduce");
TextMeshProUGUI introduceText = introduceTransform.GetComponent<TextMeshProUGUI>();
TMP_FontAsset fontAsset = FontStore.LoadTMPFont(Utils.Language.ToString());
introduceText.text = StringStore.TranslateText(introduceText.text);
introduceText.font = fontAsset;
}
[HarmonyPatch(nameof(ShootingSelectWindow.OnAnimOver))]
[HarmonyPostfix]
private static void OnAnimOver(ShootingSelectWindow __instance)
{
Transform introduceTransform = __instance.transform.FindChild("Images").FindChild("Introduce");
TextMeshProUGUI introduceText = introduceTransform.GetComponent<TextMeshProUGUI>();
TMP_FontAsset fontAsset = FontStore.LoadTMPFont(Utils.Language.ToString());
introduceText.text = StringStore.TranslateText(introduceText.text);
introduceText.font = fontAsset;
}
[HarmonyPatch(nameof(ShootingSelectWindow.SetUpgradePlantTypes))]
[HarmonyPostfix]
private static void SetUpgradePlantTypes(ShootingSelectWindow __instance)
{
Transform introduceTransform = __instance.transform.FindChild("Images").FindChild("Introduce");
TextMeshProUGUI introduceText = introduceTransform.GetComponent<TextMeshProUGUI>();
TMP_FontAsset fontAsset = FontStore.LoadTMPFont(Utils.Language.ToString());
introduceText.text = StringStore.TranslateText(introduceText.text);
introduceText.font = fontAsset;
}
[HarmonyPatch(nameof(ShootingSelectWindow.GetMaxIndexInRoutes))]
[HarmonyPostfix]
private static void GetMaxIndexInRoutes(ShootingSelectWindow __instance)
{
Transform introduceTransform = __instance.transform.FindChild("Images").FindChild("Introduce");
TextMeshProUGUI introduceText = introduceTransform.GetComponent<TextMeshProUGUI>();
TMP_FontAsset fontAsset = FontStore.LoadTMPFont(Utils.Language.ToString());
introduceText.text = StringStore.TranslateText(introduceText.text);
introduceText.font = fontAsset;
}
[HarmonyPatch(nameof(ShootingSelectWindow.Start))]
[HarmonyPostfix]
private static void Start(ShootingSelectWindow __instance)
{
Transform introduceTransform = __instance.transform.FindChild("Images").FindChild("Introduce");
TextMeshProUGUI introduceText = introduceTransform.GetComponent<TextMeshProUGUI>();
TMP_FontAsset fontAsset = FontStore.LoadTMPFont(Utils.Language.ToString());
introduceText.text = StringStore.TranslateText(introduceText.text);
introduceText.font = fontAsset;
}
}
}

View file

@ -0,0 +1,21 @@
using HarmonyLib;
using TMPro;
using PvZ_Fusion_Translator__BepInEx_.AssetStore;
using UnityEngine;
namespace PvZ_Fusion_Translator__BepInEx_.Patches.GameObjects
{
[HarmonyPatch(typeof(TowerOption))]
public static class TowerOption_Patch
{
[HarmonyPatch(nameof(TowerOption.Start))]
[HarmonyPostfix]
private static void Postfix_Start(TowerOption __instance)
{
//TextMeshProUGUI[] allTexts = __instance.GetComponentsInChildren<TextMeshProUGUI>(true);
__instance.introduce.text = StringStore.TranslateText(__instance.introduce.text);
__instance.introduce.font = FontStore.LoadTMPFont(Utils.Language.ToString());
}
}
}

View file

@ -0,0 +1,45 @@
using System;
using HarmonyLib;
using TMPro;
using PvZ_Fusion_Translator__BepInEx_.AssetStore;
using UnityEngine;
namespace PvZ_Fusion_Translator__BepInEx_.Patches.GameObjects
{
[HarmonyPatch(typeof(TravelLookBuff))]
public static class TravelLookBuff_Patch
{
private static void TranslateTexts(TravelLookBuff instance)
{
instance.introduce.text = StringStore.TranslateText(instance.introduce.text);
Transform transform = instance.rectTransform.transform;
var component1 = transform.GetChild(0).GetComponent<TextMeshProUGUI>();
var component2 = transform.GetChild(1).GetComponent<TextMeshProUGUI>();
if (component1 != null) component1.text = StringStore.TranslateText(component1.text);
if (component2 != null) component2.text = StringStore.TranslateText(component2.text);
}
[HarmonyPatch(nameof(TravelLookBuff.SetBuff))]
[HarmonyPostfix]
private static void SetBuff(TravelLookBuff __instance) => TranslateTexts(__instance);
[HarmonyPatch(nameof(TravelLookBuff.OnMouseUpAsButton))]
[HarmonyPostfix]
private static void OnMouseUpAsButton(TravelLookBuff __instance) => TranslateTexts(__instance);
[HarmonyPatch(nameof(TravelLookBuff.Clear))]
[HarmonyPostfix]
private static void Clear(TravelLookBuff __instance) => TranslateTexts(__instance);
[HarmonyPatch(nameof(TravelLookBuff.SetText), new Type[] { typeof(string) })]
[HarmonyPostfix]
private static void SetText_String(TravelLookBuff __instance) => TranslateTexts(__instance);
[HarmonyPatch(nameof(TravelLookBuff.SetText), new Type[] { typeof(bool), typeof(int) })]
[HarmonyPostfix]
private static void SetText_Bool(TravelLookBuff __instance) => TranslateTexts(__instance);
}
}

View file

@ -0,0 +1,34 @@
using HarmonyLib;
using TMPro;
using PvZ_Fusion_Translator__BepInEx_.AssetStore;
using UnityEngine;
namespace PvZ_Fusion_Translator__BepInEx_.Patches.GameObjects
{
[HarmonyPatch(typeof(TravelLookMenu))]
public static class TravelLookMenu_Patch
{
[HarmonyPatch(nameof(TravelLookMenu.Start))]
[HarmonyPostfix]
private static void Postfix_Start(TravelLookMenu __instance)
{
Transform quitButtonTransform = __instance.transform.Find("Quit");
if (quitButtonTransform != null)
{
TextMeshProUGUI[] allTexts = quitButtonTransform.GetComponentsInChildren<TextMeshProUGUI>(true);
foreach (var textComp in allTexts)
{
if (textComp != null && textComp.text == StringStore.TranslateText("关闭"))
{
textComp.text = StringStore.TranslateText("关闭_close");
TMP_FontAsset fontAsset = FontStore.LoadTMPFont(Utils.Language.ToString());
textComp.font = fontAsset;
}
}
}
}
}
}

View file

@ -1,181 +1,250 @@
using HarmonyLib;
using System.IO;
using TMPro;
using System.IO;
using HarmonyLib;
using Il2CppInterop.Runtime;
using PvZ_Fusion_Translator__BepInEx_;
using PvZ_Fusion_Translator__BepInEx_.AssetStore;
using TMPro;
using UnityEngine;
using static PvZ_Fusion_Translator__BepInEx_.FileLoader;
namespace PvZ_Fusion_Translator__BepInEx_.Patches.Managers
{
[HarmonyPatch(typeof(AlmanacPlantBank))]
public static partial class AlmanacPlantBank_Patch
{
[HarmonyPatch(nameof(AlmanacPlantBank.InitNameAndInfoFromJson))]
[HarmonyPostfix]
private static void InitNameAndInfoFromJson(AlmanacPlantBank __instance)
{
#if MULTI_LANGUAGE
string currentLanguage = Utils.Language.ToString();
string almanacDir = GetAssetDir(AssetType.Almanac, Utils.Language);
#else
[HarmonyPatch(typeof(AlmanacPlantBank))]
public static partial class AlmanacPlantBank_Patch
{
[HarmonyPatch(nameof(AlmanacPlantBank.InitNameAndInfoFromJson))]
[HarmonyPostfix]
private static void InitNameAndInfoFromJson(AlmanacPlantBank __instance)
{
#if MULTI_LANGUAGE
string currentLanguage = Utils.Language.ToString();
string almanacDir = GetAssetDir(AssetType.Almanac, Utils.Language);
#else
string almanacDir = GetAssetDir(AssetType.Almanac);
string currentLanguage = "English";
#endif
string path = Path.Combine(almanacDir, "LawnStringsTranslate.json");
string moddedPath = Path.Combine(almanacDir, "ModdedPlantsTranslate.json");
#endif
string path = Path.Combine(almanacDir, "LawnStringsTranslate.json");
string moddedPath = Path.Combine(almanacDir, "ModdedPlantsTranslate.json");
if (!File.Exists(path))
{
Log.LogError($"LawnStringsTranslate.json file not found at path: {path}");
return;
}
#if OBFUSCATE
if (CheckSumStore.IsModified(path))
{
Log.LogError("File {0} was modified!", path);
return;
}
#endif
string json;
json = File.ReadAllText(path);
bool hasAlmanacFont = false;
TMP_FontAsset almanacFontAsset = null;
if (FontStore.fontAssetDictSecondary.ContainsKey(currentLanguage + "_Almanac") || FontStore.fontAssetDictSecondary.ContainsKey(currentLanguage))
{
almanacFontAsset = FontStore.LoadTMPFontAlmanac(currentLanguage);
hasAlmanacFont = true;
}
#if MULTI_LANGUAGE
TMP_FontAsset fontAsset = FontStore.LoadTMPFont(currentLanguage);
#else
TMP_FontAsset fontAsset = FontStore.LoadTMPFont();
#endif
TextMeshPro component = __instance.introduce.GetComponent<TextMeshPro>();
TextMeshPro component2 = __instance.plantName.GetComponent<TextMeshPro>();
TextMeshPro component3 = __instance.plantName.transform.GetChild(0).GetComponent<TextMeshPro>();
TextMeshPro component4 = __instance.cost.GetComponent<TextMeshPro>();
AlmanacPlantBank.PlantData plantData = JsonUtility.FromJson<AlmanacPlantBank.PlantData>(json);
foreach (AlmanacPlantBank.PlantInfo plantInfo in plantData.plants)
{
if (plantInfo.seedType == __instance.theSeedType)
{
component.autoSizeTextContainer = false;
component.text = plantInfo.info + "\n\n" + plantInfo.introduce;
component.overflowMode = TextOverflowModes.Page;
// fix dimensions for cost text
component.rectTransform.offsetMax = new Vector2(component.rectTransform.offsetMax.x, 27.3839f);
component.rectTransform.offsetMin = new Vector2(component.rectTransform.offsetMin.x, -29.3079f);
component.rectTransform.sizeDelta = new Vector2(component.rectTransform.sizeDelta.x, 50.917f);
component.transform.localPosition = new Vector3(component.transform.localPosition.x, component.transform.localPosition.y + 0.15f, component.transform.localPosition.z);
component2.text = plantInfo.name;
component2.autoSizeTextContainer = true;
component3.text = Utils.RemoveColorTags(plantInfo.name);
component3.autoSizeTextContainer = true;
component4.text = plantInfo.cost;
if (hasAlmanacFont)
{
component.font = almanacFontAsset;
component4.font = almanacFontAsset;
}
else
{
component.font = fontAsset;
component4.font = fontAsset;
}
component2.font = fontAsset;
component3.font = fontAsset;
}
}
if (File.Exists(moddedPath))
{
string moddedJson;
moddedJson = File.ReadAllText(moddedPath);
AlmanacPlantBank.PlantData moddedPlantData = JsonUtility.FromJson<AlmanacPlantBank.PlantData>(moddedJson);
foreach (AlmanacPlantBank.PlantInfo plantInfo in moddedPlantData.plants)
{
if (plantInfo.seedType == __instance.theSeedType)
{
component.autoSizeTextContainer = false;
component.text = plantInfo.info + "\n\n" + plantInfo.introduce;
component.overflowMode = TextOverflowModes.Page;
// fix dimensions for cost text
component.rectTransform.offsetMax = new Vector2(component.rectTransform.offsetMax.x, 27.3839f);
component.rectTransform.offsetMin = new Vector2(component.rectTransform.offsetMin.x, -29.3079f);
component.rectTransform.sizeDelta = new Vector2(component.rectTransform.sizeDelta.x, 50.917f);
component.transform.localPosition = new Vector3(component.transform.localPosition.x, component.transform.localPosition.y + 0.15f, component.transform.localPosition.z);
component2.text = plantInfo.name;
component2.autoSizeTextContainer = true;
component3.text = Utils.RemoveColorTags(plantInfo.name);
component3.autoSizeTextContainer = true;
component4.text = plantInfo.cost;
if (hasAlmanacFont)
{
component.font = almanacFontAsset;
component4.font = almanacFontAsset;
}
else
{
component.font = fontAsset;
component4.font = fontAsset;
}
component2.font = fontAsset;
component3.font = fontAsset;
}
}
}
foreach (TextMeshPro textMeshPro in __instance.GetComponentsInChildren<TextMeshPro>())
TranslateTextAlmanac(__instance);
if (!File.Exists(path))
{
textMeshPro.text = StringStore.TranslateText(textMeshPro.text);
return;
}
#if OBFUSCATE
if (CheckSumStore.IsModified(path))
{
return;
}
#endif
string json = File.ReadAllText(path);
bool hasAlmanacFont = false;
TMP_FontAsset almanacFontAsset = null;
if (FontStore.fontAssetDictSecondary.ContainsKey(currentLanguage + "_Almanac") || FontStore.fontAssetDictSecondary.ContainsKey(currentLanguage))
{
almanacFontAsset = FontStore.LoadTMPFontAlmanac(currentLanguage);
hasAlmanacFont = true;
}
#if MULTI_LANGUAGE
TMP_FontAsset fontAsset = FontStore.LoadTMPFont(currentLanguage);
#else
TMP_FontAsset fontAsset = FontStore.LoadTMPFont();
#endif
TextMeshPro component = __instance.introduce.GetComponent<TextMeshPro>();
TextMeshPro component2 = __instance.plantName.GetComponent<TextMeshPro>();
TextMeshPro component3 = __instance.plantName.transform.GetChild(0).GetComponent<TextMeshPro>();
TextMeshPro component4 = __instance.cost.GetComponent<TextMeshPro>();
TextMeshPro component5 = __instance.introduce.GetComponentInChildren<TextMeshPro>();
#if DEBUG
Log.LogWarning($"Introduce text: {component?.text}");
Log.LogWarning($"Plant name: {component2?.text}");
#endif
component.text = Utils.RemoveColorTags(component.text);
AlmanacPlantBank.PlantData plantData = JsonUtility.FromJson<AlmanacPlantBank.PlantData>(json);
foreach (AlmanacPlantBank.PlantInfo plantInfo in plantData.plants)
{
if (plantInfo.seedType == __instance.theSeedType)
{
#if DEBUG
Log.LogInfo($"Processing plant type: {plantInfo.seedType}");
Log.LogInfo($"Plant info: {plantInfo.info}, Name: {plantInfo.name}, Cost: {plantInfo.cost}, Introduce: {plantInfo.introduce}");
#endif
component.autoSizeTextContainer = false;
component.text = plantInfo.info + "\n\n" + plantInfo.introduce;
component.overflowMode = TextOverflowModes.Page;
component.rectTransform.offsetMax = new Vector2(component.rectTransform.offsetMax.x, 27.3839f);
component.rectTransform.offsetMin = new Vector2(component.rectTransform.offsetMin.x, -29.3079f);
component.rectTransform.sizeDelta = new Vector2(component.rectTransform.sizeDelta.x, 50.917f);
component.transform.localPosition = new Vector3(component.transform.localPosition.x, component.transform.localPosition.y + 0.15f, component.transform.localPosition.z);
component2.text = plantInfo.name;
component2.autoSizeTextContainer = true;
component3.text = Utils.RemoveColorTags(plantInfo.name);
component3.autoSizeTextContainer = true;
component4.text = plantInfo.cost;
if (hasAlmanacFont)
{
component.font = almanacFontAsset;
component4.font = almanacFontAsset;
}
else
{
component.font = fontAsset;
component4.font = fontAsset;
}
component2.font = fontAsset;
component3.font = fontAsset;
TranslateTextAlmanac(__instance);
}
}
if (File.Exists(moddedPath))
{
string moddedJson = File.ReadAllText(moddedPath);
AlmanacPlantBank.PlantData moddedPlantData = JsonUtility.FromJson<AlmanacPlantBank.PlantData>(moddedJson);
foreach (AlmanacPlantBank.PlantInfo plantInfo in moddedPlantData.plants)
{
if (plantInfo.seedType == __instance.theSeedType)
{
component.autoSizeTextContainer = false;
component.text = plantInfo.info + "\n\n" + plantInfo.introduce;
component.overflowMode = TextOverflowModes.Page;
component.rectTransform.offsetMax = new Vector2(component.rectTransform.offsetMax.x, 27.3839f);
component.rectTransform.offsetMin = new Vector2(component.rectTransform.offsetMin.x, -29.3079f);
component.rectTransform.sizeDelta = new Vector2(component.rectTransform.sizeDelta.x, 50.917f);
component.transform.localPosition = new Vector3(component.transform.localPosition.x, component.transform.localPosition.y + 0.15f, component.transform.localPosition.z);
component2.text = plantInfo.name;
component2.autoSizeTextContainer = true;
component3.text = Utils.RemoveColorTags(plantInfo.name);
component3.autoSizeTextContainer = true;
component4.text = plantInfo.cost;
if (hasAlmanacFont)
{
component.font = almanacFontAsset;
component4.font = almanacFontAsset;
}
else
{
component.font = fontAsset;
component4.font = fontAsset;
}
component2.font = fontAsset;
component3.font = fontAsset;
}
}
}
foreach (TextMeshPro text in __instance.introduce.GetComponentsInChildren<TextMeshPro>())
{
if (text != null)
{
string originalText = text.text;
text.text = StringStore.TranslateText(text.text);
}
}
TranslateTextAlmanac(__instance);
return;
}
}
[HarmonyPatch(nameof(AlmanacPlantBank.OnMouseDown))]
[HarmonyPrefix]
private static bool OnMouseDown(AlmanacPlantBank __instance)
{
TextMeshPro component = __instance.introduce.GetComponent<TextMeshPro>();
if (component != null)
{
component.pageToDisplay = component.pageToDisplay > component.m_pageNumber ? 1 : component.pageToDisplay + 1;
return false;
}
return true;
}
[HarmonyPatch(nameof(AlmanacPlantBank.OnMouseDown))]
[HarmonyPrefix]
private static bool OnMouseDown(AlmanacPlantBank __instance)
{
TranslateTextAlmanac(__instance);
TextMeshPro component = __instance.introduce.GetComponent<TextMeshPro>();
if (component != null)
{
component.pageToDisplay = component.pageToDisplay > component.m_pageNumber ? 1 : component.pageToDisplay + 1;
return false;
}
return true;
}
[HarmonyPatch(nameof(AlmanacPlantBank.PVPInit))]
[HarmonyPostfix]
private static void PVPInit(AlmanacPlantBank __instance)
{
TextMeshPro component = __instance.introduce.GetComponent<TextMeshPro>();
if (component != null)
{
component.autoSizeTextContainer = false;
}
}
}
// This method is used to translate the text in the AlmanacPlantBank when it starts. And some plants like LibraHp plants have different text type in the Almanac.
[HarmonyPatch(nameof(AlmanacPlantBank.Start))]
[HarmonyPostfix]
public static void TranslateTextAlmanac(AlmanacPlantBank __instance)
{
string currentLanguage = Utils.Language.ToString();
__instance.introduce.text = StringStore.TranslateText(__instance.introduce.text);
__instance.introduce.font = FontStore.LoadTMPFont(currentLanguage);
TextMeshPro textMeshProComponent = __instance.introduce.GetComponent<TextMeshPro>();
foreach (TextMeshPro text in __instance.introduce.GetComponentsInChildren<TextMeshPro>())
{
if (text != null)
{
string originalText = text.text;
text.text = StringStore.TranslateText(text.text);
text.font = FontStore.LoadTMPFont(currentLanguage);
}
}
// IDK why this is needed, but put it here to avoid issues
foreach (TextMeshProUGUI text in __instance.introduce.GetComponentsInChildren<TextMeshProUGUI>())
{
if (text != null)
{
string originalText = text.text;
text.text = StringStore.TranslateText(text.text);
text.font = FontStore.LoadTMPFont(currentLanguage);
}
}
// IDK why this is needed, but put it here to avoid issues
foreach (TMPro.TMP_Text text in __instance.introduce.GetComponentsInChildren<TMPro.TMP_Text>())
{
if (text != null)
{
string originalText = text.text;
text.text = StringStore.TranslateText(text.text);
text.font = FontStore.LoadTMPFont(currentLanguage);
}
}
__instance.plantName.text = StringStore.TranslateText(__instance.plantName.text);
__instance.plantName.transform.GetChild(0).GetComponent<TextMeshPro>().text = StringStore.TranslateText(__instance.plantName.transform.GetChild(0).GetComponent<TextMeshPro>().text);
__instance.plantName.font = FontStore.LoadTMPFont(currentLanguage);
__instance.plantName.transform.GetChild(0).GetComponent<TextMeshPro>().font = FontStore.LoadTMPFont(currentLanguage);
__instance.cost.text = StringStore.TranslateText(__instance.cost.text);
__instance.cost.font = FontStore.LoadTMPFont(currentLanguage);
}
[HarmonyPatch(nameof(AlmanacPlantBank.PVPInit))]
[HarmonyPostfix]
private static void PVPInit(AlmanacPlantBank __instance)
{
TranslateTextAlmanac(__instance);
TextMeshPro component = __instance.introduce.GetComponent<TextMeshPro>();
if (component != null)
{
string originalText = component.text;
component.autoSizeTextContainer = false;
component.text = StringStore.TranslateText(component.text);
__instance.introduce.GetComponent<TextMeshPro>().text = component.text;
}
Transform banTransform = __instance.transform.FindChild("Ban").GetChild(0);
if (banTransform != null)
{
TextMeshPro banText = banTransform.GetComponent<TextMeshPro>();
string originalBanText = banText.text;
banText.text = StringStore.TranslateText(banText.text);
}
}
}
}

View file

@ -0,0 +1,38 @@
using HarmonyLib;
using TMPro;
using PvZ_Fusion_Translator__BepInEx_.AssetStore;
using UnityEngine;
using UnityEngine.TextCore.Text;
using UnityEngine.UI;
namespace PvZ_Fusion_Translator__BepInEx_.Patches.Managers
{
[HarmonyPatch(typeof(ChessManager))]
public static class ChessManager_Patch
{
[HarmonyPatch(nameof(ChessManager.Start))]
[HarmonyPostfix]
private static void Postfix_Start(ChessManager __instance)
{
__instance.textMesh.text = StringStore.TranslateText(__instance.textMesh.text);
__instance.textMesh.font = FontStore.LoadTMPFont(Utils.Language.ToString());
}
[HarmonyPatch(nameof(ChessManager.Update))]
[HarmonyPostfix]
private static void Postfix_Update(ChessManager __instance)
{
__instance.textMesh.text = StringStore.TranslateText(__instance.textMesh.text);
__instance.textMesh.font = FontStore.LoadTMPFont(Utils.Language.ToString());
}
[HarmonyPatch(nameof(ChessManager.UpdateText))]
[HarmonyPostfix]
private static void Postfix_UpdateText(ChessManager __instance)
{
__instance.textMesh.text = StringStore.TranslateText(__instance.textMesh.text);
__instance.textMesh.font = FontStore.LoadTMPFont(Utils.Language.ToString());
}
}
}

View file

@ -0,0 +1,45 @@
using HarmonyLib;
using TMPro;
using System.Collections.Generic;
using PvZ_Fusion_Translator__BepInEx_.AssetStore;
using UnityEngine;
namespace PvZ_Fusion_Translator__BepInEx_.Patches.Managers
{
[HarmonyPatch(typeof(DrawCardManager))]
public static class DrawCardManager_Patch
{
// Dùng chung xử lý cập nhật text
private static void TranslateAndApplyFont(Il2CppSystem.Collections.Generic.List<TextMeshProUGUI> texts)
{
if (texts == null || texts.Count == 0) return;
TMP_FontAsset fontAsset = FontStore.LoadTMPFont(Utils.Language.ToString());
foreach (var textComponent in texts)
{
if (textComponent == null) continue;
string translatedText = StringStore.TranslateText(textComponent.text);
textComponent.text = translatedText;
textComponent.font = fontAsset;
}
}
[HarmonyPostfix]
[HarmonyPatch(nameof(DrawCardManager.UpdateText))]
private static void Postfix_UpdateText(DrawCardManager __instance)
{
__instance.upName = StringStore.TranslateText(__instance.upName);
TranslateAndApplyFont(__instance.texts);
}
[HarmonyPostfix]
[HarmonyPatch(nameof(DrawCardManager.Update))]
private static void Postfix_Update(DrawCardManager __instance)
{
__instance.upName = StringStore.TranslateText(__instance.upName);
TranslateAndApplyFont(__instance.texts);
}
}
}

View file

@ -6,12 +6,12 @@ using UnityEngine;
namespace PvZ_Fusion_Translator__BepInEx_.Patches.Managers
{
[HarmonyPatch(typeof(IZEMgr))]
[HarmonyPatch(typeof(IZBottomMenu))]
public static class IZEMgr_Patch
{
[HarmonyPatch(nameof(IZEMgr.Start))]
[HarmonyPatch(nameof(IZBottomMenu.ChangeString))]
[HarmonyPostfix]
public static void Start(IZEMgr __instance)
public static void Start(IZBottomMenu __instance)
{
TextMeshProUGUI[] array =
[

View file

@ -0,0 +1,33 @@
using HarmonyLib;
using TMPro;
using PvZ_Fusion_Translator__BepInEx_.AssetStore;
namespace PvZ_Fusion_Translator__BepInEx_.Patches.Managers
{
[HarmonyPatch(typeof(InGameUI))]
public static class InGameUI_Patch
{
[HarmonyPatch(nameof(InGameUI.Start))]
[HarmonyPostfix]
private static void Start(InGameUI __instance)
{
TextMeshProUGUI[] array = new TextMeshProUGUI[]
{
__instance.transform.GetChild(4).GetComponent<TextMeshProUGUI>(),
__instance.transform.GetChild(4).GetChild(0).GetComponent<TextMeshProUGUI>(),
__instance.transform.GetChild(5).GetComponent<TextMeshProUGUI>(),
__instance.transform.GetChild(5).GetChild(0).GetComponent<TextMeshProUGUI>(),
__instance.transform.GetChild(6).GetComponent<TextMeshProUGUI>(),
__instance.transform.GetChild(6).GetChild(0).GetComponent<TextMeshProUGUI>()
};
TextMeshProUGUI[] array2 = array;
for (int i = 0; i < array2.Length; i++)
{
array2[i] = StringStore.TranslateText(array2[i]);
array2[i].text = array2[i].text.Replace("\n", " ");
}
}
}
}

View file

@ -13,7 +13,7 @@
https://nuget.samboy.dev/v3/index.json
</RestoreAdditionalProjectSources>
<RootNamespace>PvZ_Fusion_Translator__BepInEx_</RootNamespace>
<GamePath>C:\Users\rainb\Desktop\PC_PVZ-Fusion_2.5.1-BepInEx</GamePath>
<GamePath>D:\PvZ Fusion\BepInEx Game Files</GamePath>
<Configurations>Debug;DebugEnglish;ReleaseMulti;ReleaseEnglish;DebugTesting;ReleaseOther;DebugObfuscate;ReleaseObfuscate;DebugMulti</Configurations>
<Platforms>AnyCPU;x64</Platforms>
</PropertyGroup>
@ -21,6 +21,7 @@
<ItemGroup>
<PackageReference Include="BepInEx.Unity.IL2CPP" Version="6.0.0-be.*" IncludeAssets="compile" />
<PackageReference Include="BepInEx.PluginInfoProps" Version="2.*" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup>

View file

@ -10,6 +10,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
README.md = README.md
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PvZ Fusion Translator [BepInEx]", "BepInEx\PvZ Fusion Translator [BepInEx].csproj", "{395E60A0-A884-61F2-EF18-BC94BB7D9C69}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -86,6 +88,54 @@ Global
{90AA30F8-EFE7-6E1A-3859-0EE79252222A}.ReleaseOther|ARM64.Build.0 = ReleaseOther|ARM64
{90AA30F8-EFE7-6E1A-3859-0EE79252222A}.ReleaseOther|x64.ActiveCfg = ReleaseOther|x64
{90AA30F8-EFE7-6E1A-3859-0EE79252222A}.ReleaseOther|x64.Build.0 = ReleaseOther|x64
{395E60A0-A884-61F2-EF18-BC94BB7D9C69}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{395E60A0-A884-61F2-EF18-BC94BB7D9C69}.Debug|Any CPU.Build.0 = Debug|Any CPU
{395E60A0-A884-61F2-EF18-BC94BB7D9C69}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{395E60A0-A884-61F2-EF18-BC94BB7D9C69}.Debug|ARM64.Build.0 = Debug|Any CPU
{395E60A0-A884-61F2-EF18-BC94BB7D9C69}.Debug|x64.ActiveCfg = Debug|x64
{395E60A0-A884-61F2-EF18-BC94BB7D9C69}.Debug|x64.Build.0 = Debug|x64
{395E60A0-A884-61F2-EF18-BC94BB7D9C69}.DebugEnglish|Any CPU.ActiveCfg = DebugEnglish|Any CPU
{395E60A0-A884-61F2-EF18-BC94BB7D9C69}.DebugEnglish|Any CPU.Build.0 = DebugEnglish|Any CPU
{395E60A0-A884-61F2-EF18-BC94BB7D9C69}.DebugEnglish|ARM64.ActiveCfg = DebugEnglish|Any CPU
{395E60A0-A884-61F2-EF18-BC94BB7D9C69}.DebugEnglish|ARM64.Build.0 = DebugEnglish|Any CPU
{395E60A0-A884-61F2-EF18-BC94BB7D9C69}.DebugEnglish|x64.ActiveCfg = DebugEnglish|x64
{395E60A0-A884-61F2-EF18-BC94BB7D9C69}.DebugEnglish|x64.Build.0 = DebugEnglish|x64
{395E60A0-A884-61F2-EF18-BC94BB7D9C69}.DebugObfuscate|Any CPU.ActiveCfg = DebugObfuscate|Any CPU
{395E60A0-A884-61F2-EF18-BC94BB7D9C69}.DebugObfuscate|Any CPU.Build.0 = DebugObfuscate|Any CPU
{395E60A0-A884-61F2-EF18-BC94BB7D9C69}.DebugObfuscate|ARM64.ActiveCfg = DebugObfuscate|Any CPU
{395E60A0-A884-61F2-EF18-BC94BB7D9C69}.DebugObfuscate|ARM64.Build.0 = DebugObfuscate|Any CPU
{395E60A0-A884-61F2-EF18-BC94BB7D9C69}.DebugObfuscate|x64.ActiveCfg = DebugObfuscate|x64
{395E60A0-A884-61F2-EF18-BC94BB7D9C69}.DebugObfuscate|x64.Build.0 = DebugObfuscate|x64
{395E60A0-A884-61F2-EF18-BC94BB7D9C69}.DebugTesting|Any CPU.ActiveCfg = DebugTesting|Any CPU
{395E60A0-A884-61F2-EF18-BC94BB7D9C69}.DebugTesting|Any CPU.Build.0 = DebugTesting|Any CPU
{395E60A0-A884-61F2-EF18-BC94BB7D9C69}.DebugTesting|ARM64.ActiveCfg = DebugTesting|Any CPU
{395E60A0-A884-61F2-EF18-BC94BB7D9C69}.DebugTesting|ARM64.Build.0 = DebugTesting|Any CPU
{395E60A0-A884-61F2-EF18-BC94BB7D9C69}.DebugTesting|x64.ActiveCfg = DebugTesting|x64
{395E60A0-A884-61F2-EF18-BC94BB7D9C69}.DebugTesting|x64.Build.0 = DebugTesting|x64
{395E60A0-A884-61F2-EF18-BC94BB7D9C69}.ReleaseEnglish|Any CPU.ActiveCfg = ReleaseEnglish|Any CPU
{395E60A0-A884-61F2-EF18-BC94BB7D9C69}.ReleaseEnglish|Any CPU.Build.0 = ReleaseEnglish|Any CPU
{395E60A0-A884-61F2-EF18-BC94BB7D9C69}.ReleaseEnglish|ARM64.ActiveCfg = ReleaseEnglish|Any CPU
{395E60A0-A884-61F2-EF18-BC94BB7D9C69}.ReleaseEnglish|ARM64.Build.0 = ReleaseEnglish|Any CPU
{395E60A0-A884-61F2-EF18-BC94BB7D9C69}.ReleaseEnglish|x64.ActiveCfg = ReleaseEnglish|x64
{395E60A0-A884-61F2-EF18-BC94BB7D9C69}.ReleaseEnglish|x64.Build.0 = ReleaseEnglish|x64
{395E60A0-A884-61F2-EF18-BC94BB7D9C69}.ReleaseMulti|Any CPU.ActiveCfg = ReleaseMulti|Any CPU
{395E60A0-A884-61F2-EF18-BC94BB7D9C69}.ReleaseMulti|Any CPU.Build.0 = ReleaseMulti|Any CPU
{395E60A0-A884-61F2-EF18-BC94BB7D9C69}.ReleaseMulti|ARM64.ActiveCfg = ReleaseMulti|Any CPU
{395E60A0-A884-61F2-EF18-BC94BB7D9C69}.ReleaseMulti|ARM64.Build.0 = ReleaseMulti|Any CPU
{395E60A0-A884-61F2-EF18-BC94BB7D9C69}.ReleaseMulti|x64.ActiveCfg = ReleaseMulti|x64
{395E60A0-A884-61F2-EF18-BC94BB7D9C69}.ReleaseMulti|x64.Build.0 = ReleaseMulti|x64
{395E60A0-A884-61F2-EF18-BC94BB7D9C69}.ReleaseObfuscate|Any CPU.ActiveCfg = ReleaseObfuscate|Any CPU
{395E60A0-A884-61F2-EF18-BC94BB7D9C69}.ReleaseObfuscate|Any CPU.Build.0 = ReleaseObfuscate|Any CPU
{395E60A0-A884-61F2-EF18-BC94BB7D9C69}.ReleaseObfuscate|ARM64.ActiveCfg = ReleaseObfuscate|Any CPU
{395E60A0-A884-61F2-EF18-BC94BB7D9C69}.ReleaseObfuscate|ARM64.Build.0 = ReleaseObfuscate|Any CPU
{395E60A0-A884-61F2-EF18-BC94BB7D9C69}.ReleaseObfuscate|x64.ActiveCfg = ReleaseObfuscate|x64
{395E60A0-A884-61F2-EF18-BC94BB7D9C69}.ReleaseObfuscate|x64.Build.0 = ReleaseObfuscate|x64
{395E60A0-A884-61F2-EF18-BC94BB7D9C69}.ReleaseOther|Any CPU.ActiveCfg = ReleaseOther|Any CPU
{395E60A0-A884-61F2-EF18-BC94BB7D9C69}.ReleaseOther|Any CPU.Build.0 = ReleaseOther|Any CPU
{395E60A0-A884-61F2-EF18-BC94BB7D9C69}.ReleaseOther|ARM64.ActiveCfg = ReleaseOther|Any CPU
{395E60A0-A884-61F2-EF18-BC94BB7D9C69}.ReleaseOther|ARM64.Build.0 = ReleaseOther|Any CPU
{395E60A0-A884-61F2-EF18-BC94BB7D9C69}.ReleaseOther|x64.ActiveCfg = ReleaseOther|x64
{395E60A0-A884-61F2-EF18-BC94BB7D9C69}.ReleaseOther|x64.Build.0 = ReleaseOther|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE