using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("Phosphor")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Phosphor")]
[assembly: AssemblyTitle("Phosphor")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Phosphor;
public class DebugTester : MonoBehaviour
{
private static DebugTester _instance;
private bool _awaitingNumber = false;
private float _messageTimer = 0f;
private string _lastMessage = "";
private void Start()
{
if (!((Object)(object)_instance != (Object)null))
{
_instance = this;
Init.Logger.LogInfo((object)"DebugTester active – press F1 then a number key (1-9) for actions.");
}
}
private void Update()
{
//IL_007e: Unknown result type (might be due to invalid IL or missing references)
//IL_0080: Unknown result type (might be due to invalid IL or missing references)
if (_messageTimer > 0f)
{
_messageTimer -= Time.unscaledDeltaTime;
if (_messageTimer <= 0f)
{
_lastMessage = "";
}
}
if (Input.GetKeyDown((KeyCode)282))
{
_awaitingNumber = true;
ShowMessage("F1 pressed – now press a number key (1-9)");
}
if (!_awaitingNumber)
{
return;
}
for (int i = 1; i <= 9; i++)
{
KeyCode val = (KeyCode)(48 + i);
if (Input.GetKeyDown(val))
{
_awaitingNumber = false;
ExecuteAction(i);
break;
}
}
if (Input.GetKeyDown((KeyCode)27))
{
_awaitingNumber = false;
ShowMessage("Action cancelled.");
}
}
private void ExecuteAction(int action)
{
switch (action)
{
case 1:
ListAllParticleSystems();
break;
case 2:
SpawnTestParticleSystem();
break;
case 3:
LoadCampScene();
break;
case 4:
LoadBattleScene();
break;
case 5:
TestLinqReplacement();
break;
case 6:
TestFarUnitSkip();
break;
case 7:
ToggleParticleBlocking();
break;
case 8:
PrintPatchStatus();
break;
case 9:
TestLogSuppression();
break;
default:
ShowMessage("Unknown action");
break;
}
}
private void ListAllParticleSystems()
{
ParticleSystem[] array = Object.FindObjectsOfType<ParticleSystem>(true);
ShowMessage($"Found {array.Length} particle systems.");
ParticleSystem[] array2 = array;
foreach (ParticleSystem val in array2)
{
Init.Logger.LogDebug((object)$" - {((Object)val).name} (active: {((Component)val).gameObject.activeInHierarchy})");
}
}
private void SpawnTestParticleSystem()
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Expected O, but got Unknown
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
//IL_0063: Unknown result type (might be due to invalid IL or missing references)
//IL_0068: Unknown result type (might be due to invalid IL or missing references)
//IL_0070: Unknown result type (might be due to invalid IL or missing references)
GameObject val = new GameObject("TestParticle");
ParticleSystem val2 = val.AddComponent<ParticleSystem>();
MainModule main = val2.main;
((MainModule)(ref main)).startLifetime = MinMaxCurve.op_Implicit(2f);
((MainModule)(ref main)).startSpeed = MinMaxCurve.op_Implicit(5f);
((MainModule)(ref main)).startSize = MinMaxCurve.op_Implicit(0.5f);
((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(Color.red);
EmissionModule emission = val2.emission;
((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(20f);
val2.Play();
ShowMessage("Spawned test particle system '" + ((Object)val2).name + "'. Should be visible for a moment.");
Object.Destroy((Object)(object)val, 3f);
}
private void LoadCampScene()
{
ShowMessage("Loading camp scene...");
SceneManager.LoadScene("Camp");
}
private void LoadBattleScene()
{
ShowMessage("Loading battle scene...");
SceneManager.LoadScene("Battle");
}
private void TestLinqReplacement()
{
ShowMessage("Testing LINQ replacement... (see console)");
if ((Object)(object)PlayerMgr.Inst != (Object)null && PlayerMgr.Inst.Wands.Count > 0)
{
Wand val = PlayerMgr.Inst.Wands[0];
if (val.WandCfg != null)
{
FieldInfo field = ((object)val).GetType().GetField("normalSlots", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (field != null)
{
if (field.GetValue(val) is SlotData[] array && array.Length != 0 && array[0] != null)
{
int id = array[0].id;
if (SpellConfig.dic != null && SpellConfig.dic.TryGetValue(id, out var value))
{
RatioValue damage_FinalPlayerValue = CanShootSpellUtils.GetDamage_FinalPlayerValue(value.damage, (SpellConfig[])(object)new SpellConfig[1] { value }, (SpellConfig)null, val);
Init.Logger.LogInfo((object)$"Test damage: {damage_FinalPlayerValue.Result}");
}
else
{
Init.Logger.LogInfo((object)$"SpellConfig.dic not found or spell {id} not found.");
}
}
else
{
Init.Logger.LogInfo((object)"No spells in wand slots to test.");
}
}
else
{
Init.Logger.LogInfo((object)"Could not access wand slots via reflection.");
}
}
else
{
Init.Logger.LogInfo((object)"Wand config is null.");
}
}
else
{
Init.Logger.LogInfo((object)"No player or wand available to test LINQ replacement.");
}
}
private void TestFarUnitSkip()
{
ShowMessage("Creating far-away dummy unit... (see console)");
if ((Object)(object)PlayerMgr.Inst == (Object)null)
{
Init.Logger.LogInfo((object)"Player not available.");
}
else
{
Init.Logger.LogInfo((object)"To test far unit skip, enter a battle and move away from enemies. Check console for unit skip logs.");
}
}
private void ToggleParticleBlocking()
{
//IL_005a: Unknown result type (might be due to invalid IL or missing references)
//IL_005f: Unknown result type (might be due to invalid IL or missing references)
bool flag = !Init.DisableParticles.Value;
Init.DisableParticles.Value = flag;
ShowMessage($"Particle blocking toggled to {flag}. Reload scene to see full effect.");
if (flag)
{
ParticleSystem[] array = Object.FindObjectsOfType<ParticleSystem>(true);
ParticleSystem[] array2 = array;
foreach (ParticleSystem val in array2)
{
val.Stop(true, (ParticleSystemStopBehavior)0);
EmissionModule emission = val.emission;
((EmissionModule)(ref emission)).enabled = false;
}
Init.Logger.LogInfo((object)"Stopped all existing particles.");
}
}
private void PrintPatchStatus()
{
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
//IL_0028: Expected O, but got Unknown
ShowMessage("Checking patch status... (see console)");
Init.Logger.LogInfo((object)"Patch status: Check for 'Harmony patches applied' earlier in log.");
GameObject val = new GameObject("PatchTestParticle");
ParticleSystem val2 = val.AddComponent<ParticleSystem>();
val2.Play();
if (val2.isPlaying && Init.DisableParticles.Value)
{
Init.Logger.LogWarning((object)"Particle system Play was NOT blocked – patch may not be working.");
}
else if (!val2.isPlaying && Init.DisableParticles.Value)
{
Init.Logger.LogInfo((object)"Particle system Play was blocked – patch working.");
}
else if (val2.isPlaying && !Init.DisableParticles.Value)
{
Init.Logger.LogInfo((object)"Particle system Play allowed (as expected).");
}
Object.Destroy((Object)(object)val);
}
private void TestLogSuppression()
{
ShowMessage("Testing log suppression... (see console)");
Debug.Log((object)"This is a test Debug.Log. It should be suppressed if EnableLogRemoval is true.");
Debug.LogWarning((object)"This is a test Debug.LogWarning. It should be suppressed if EnableLogRemoval is true.");
Debug.LogError((object)"This is a test Debug.LogError. It should always appear.");
Init.Logger.LogInfo((object)"If you see the above 'LogError' but not the other two, suppression works.");
}
private void ShowMessage(string msg)
{
_lastMessage = msg;
_messageTimer = 3f;
Init.Logger.LogInfo((object)("DEBUG: " + msg));
}
private void OnGUI()
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_006b: Unknown result type (might be due to invalid IL or missing references)
//IL_007f: Unknown result type (might be due to invalid IL or missing references)
//IL_0084: Unknown result type (might be due to invalid IL or missing references)
//IL_008a: Unknown result type (might be due to invalid IL or missing references)
//IL_009a: Expected O, but got Unknown
if (!string.IsNullOrEmpty(_lastMessage))
{
GUI.Label(new Rect(10f, (float)(Screen.height - 60), 400f, 30f), "[DEBUG] " + _lastMessage);
}
if (_awaitingNumber)
{
Rect val = new Rect(10f, (float)(Screen.height - 90), 300f, 30f);
GUIStyle val2 = new GUIStyle(GUI.skin.label);
val2.normal.textColor = Color.yellow;
GUI.Label(val, "Press 1-9 or ESC", val2);
}
}
}
[BepInPlugin("com.ngeorge.phosphor", "Phosphor", "1.1.1")]
public class Init : BaseUnityPlugin
{
internal static ManualLogSource Logger;
public static ConfigEntry<bool> EnableOptimizations;
public static ConfigEntry<bool> EnableLogRemoval;
public static ConfigEntry<bool> EnableLinqReplacement;
public static ConfigEntry<bool> EnableFarAwareDisable;
public static ConfigEntry<float> FarDistance;
public static ConfigEntry<bool> DisableParticles;
public static ConfigEntry<bool> VerboseLogging;
private void Awake()
{
//IL_0129: Unknown result type (might be due to invalid IL or missing references)
//IL_012f: Expected O, but got Unknown
Logger = ((BaseUnityPlugin)this).Logger;
Logger.LogInfo((object)"Phosphor loading...");
EnableOptimizations = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableOptimizations", true, "Master switch for all optimizations.");
EnableLogRemoval = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableLogRemoval", true, "Removes Debug.Log calls in performance-critical paths.");
EnableLinqReplacement = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableLinqReplacement", true, "Replaces LINQ queries with loops.");
EnableFarAwareDisable = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableFarAwareDisable", true, "Disables Update for units far from the player.");
FarDistance = ((BaseUnityPlugin)this).Config.Bind<float>("General", "FarDistance", 30f, "Distance beyond which units are considered far.");
DisableParticles = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "DisableParticles", true, "Disables all particle effects. Improves performance drastically but removes visual effects.");
VerboseLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "VerboseLogging", true, "Enable verbose debug logging.");
if (!EnableOptimizations.Value)
{
Logger.LogInfo((object)"Optimizations disabled. Exiting.");
return;
}
GameObject val = new GameObject("PhosphorRunner");
Object.DontDestroyOnLoad((Object)(object)val);
((Object)val).hideFlags = (HideFlags)61;
val.AddComponent<PhosphorBehaviour>();
}
}
public class PhosphorBehaviour : MonoBehaviour
{
private static FieldInfo _unitCfgField;
private static PropertyInfo _unitTypeProperty;
private static bool _patched;
private static int _unitSkipCounter;
private static float _lastUnitSkipLogTime;
private static float _lastHeartbeatTime;
private static float _lastPatchLogTime;
private static int _patchCallCount;
private static float _lastParticleLogTime;
private static int _particleBlockCount;
static PhosphorBehaviour()
{
_patched = false;
_unitSkipCounter = 0;
_lastUnitSkipLogTime = 0f;
_lastHeartbeatTime = 0f;
_lastPatchLogTime = 0f;
_patchCallCount = 0;
_lastParticleLogTime = 0f;
_particleBlockCount = 0;
Type typeFromHandle = typeof(UnitBase);
_unitCfgField = typeFromHandle.GetField("UnitCfg", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (_unitCfgField != null)
{
Type fieldType = _unitCfgField.FieldType;
_unitTypeProperty = fieldType.GetProperty("unitType", BindingFlags.Instance | BindingFlags.Public);
Init.Logger.LogInfo((object)"Reflection: UnitCfg field found.");
}
else
{
Init.Logger.LogError((object)"Reflection: UnitCfg field NOT found!");
}
}
private void Start()
{
//IL_009c: Unknown result type (might be due to invalid IL or missing references)
//IL_00a2: Expected O, but got Unknown
Init.Logger.LogInfo((object)($"Phosphor started. Features: FarDisable={Init.EnableFarAwareDisable.Value}, " + $"Distance={Init.FarDistance.Value}, LogRemoval={Init.EnableLogRemoval.Value}, " + $"LinqReplacement={Init.EnableLinqReplacement.Value}, DisableParticles={Init.DisableParticles.Value}"));
UIManager.Create();
if (Init.DisableParticles.Value)
{
DisableAllExistingParticleSystems();
}
GameObject val = new GameObject("PerformanceUI");
Object.DontDestroyOnLoad((Object)(object)val);
val.AddComponent<PerformanceUI>();
if (Init.VerboseLogging.Value)
{
((Component)this).gameObject.AddComponent<DebugTester>();
}
}
private void DisableAllExistingParticleSystems()
{
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
int num = 0;
ParticleSystem[] array = Object.FindObjectsOfType<ParticleSystem>(true);
foreach (ParticleSystem val in array)
{
val.Stop(true, (ParticleSystemStopBehavior)0);
EmissionModule emission = val.emission;
((EmissionModule)(ref emission)).enabled = false;
num++;
}
Init.Logger.LogInfo((object)$"Disabled {num} existing particle systems.");
}
private void Update()
{
if (Time.unscaledTime - _lastHeartbeatTime > 10f)
{
_lastHeartbeatTime = Time.unscaledTime;
Init.Logger.LogInfo((object)"Phosphor heartbeat – active.");
}
}
private void Awake()
{
//IL_019c: Unknown result type (might be due to invalid IL or missing references)
//IL_01a3: Expected O, but got Unknown
//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
//IL_01df: Expected O, but got Unknown
//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
//IL_020a: Expected O, but got Unknown
//IL_022a: Unknown result type (might be due to invalid IL or missing references)
//IL_0235: Expected O, but got Unknown
//IL_0255: Unknown result type (might be due to invalid IL or missing references)
//IL_0260: Expected O, but got Unknown
//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
//IL_02b4: Expected O, but got Unknown
//IL_02fe: Unknown result type (might be due to invalid IL or missing references)
//IL_0309: Expected O, but got Unknown
//IL_0346: Unknown result type (might be due to invalid IL or missing references)
//IL_0351: Expected O, but got Unknown
//IL_039b: Unknown result type (might be due to invalid IL or missing references)
//IL_03a6: Expected O, but got Unknown
//IL_03e3: Unknown result type (might be due to invalid IL or missing references)
//IL_03ee: Expected O, but got Unknown
//IL_0438: Unknown result type (might be due to invalid IL or missing references)
//IL_0443: Expected O, but got Unknown
//IL_048d: Unknown result type (might be due to invalid IL or missing references)
//IL_0498: Expected O, but got Unknown
//IL_04d1: Unknown result type (might be due to invalid IL or missing references)
//IL_04db: Expected O, but got Unknown
//IL_050a: Unknown result type (might be due to invalid IL or missing references)
//IL_0515: Expected O, but got Unknown
//IL_0552: Unknown result type (might be due to invalid IL or missing references)
//IL_055d: Expected O, but got Unknown
//IL_05a7: Unknown result type (might be due to invalid IL or missing references)
//IL_05b2: Expected O, but got Unknown
//IL_05ef: Unknown result type (might be due to invalid IL or missing references)
//IL_05fa: Expected O, but got Unknown
//IL_0637: Unknown result type (might be due to invalid IL or missing references)
//IL_0642: Expected O, but got Unknown
//IL_067f: Unknown result type (might be due to invalid IL or missing references)
//IL_068a: Expected O, but got Unknown
//IL_06d4: Unknown result type (might be due to invalid IL or missing references)
//IL_06de: Expected O, but got Unknown
if (_patched)
{
return;
}
_patched = true;
try
{
Type typeFromHandle = typeof(CampMgr);
Type typeFromHandle2 = typeof(UnitBase);
Type typeFromHandle3 = typeof(CanShootSpellUtils);
Init.Logger.LogInfo((object)$"Target types: CampMgr={typeFromHandle != null}, UnitBase={typeFromHandle2 != null}, CanShootSpellUtils={typeFromHandle3 != null}");
MethodInfo method = typeFromHandle.GetMethod("Start", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
Init.Logger.LogInfo((object)$"CampMgr.Start method found: {method != null}");
MethodInfo method2 = typeFromHandle2.GetMethod("Update", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
Init.Logger.LogInfo((object)$"UnitBase.Update method found: {method2 != null}");
MethodInfo method3 = typeFromHandle3.GetMethod("GetDamage", new Type[3]
{
typeof(float),
typeof(IEnumerable<SpellConfig>),
typeof(SpellConfig)
});
Init.Logger.LogInfo((object)$"CanShootSpellUtils.GetDamage method found: {method3 != null}");
MethodInfo method4 = typeFromHandle3.GetMethod("GetDamage_FinalPlayerValue", new Type[4]
{
typeof(float),
typeof(SpellConfig[]),
typeof(SpellConfig),
typeof(Wand)
});
Init.Logger.LogInfo((object)$"CanShootSpellUtils.GetDamage_FinalPlayerValue method found: {method4 != null}");
Harmony val = new Harmony("com.ngeorge.phosphor");
Init.Logger.LogInfo((object)"Applying manual patches...");
List<(MethodBase, HarmonyMethod, HarmonyMethod)> list = new List<(MethodBase, HarmonyMethod, HarmonyMethod)>();
list.Add(((MethodBase)method, (HarmonyMethod)null, new HarmonyMethod(typeof(PhosphorBehaviour).GetMethod("CampMgr_Start_Postfix", BindingFlags.Static | BindingFlags.NonPublic))));
list.Add(((MethodBase)method2, new HarmonyMethod(typeof(PhosphorBehaviour).GetMethod("UnitBase_Update_Prefix", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null));
list.Add(((MethodBase)method3, new HarmonyMethod(typeof(PhosphorBehaviour).GetMethod("CanShootSpellUtils_GetDamage_Prefix", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null));
list.Add(((MethodBase)method4, new HarmonyMethod(typeof(PhosphorBehaviour).GetMethod("CanShootSpellUtils_GetDamage_FinalPlayerValue_Prefix", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null));
Type typeFromHandle4 = typeof(Debug);
list.Add(((MethodBase)typeFromHandle4.GetMethod("Log", new Type[1] { typeof(object) }), new HarmonyMethod(typeof(PhosphorBehaviour).GetMethod("Log_Object", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null));
list.Add(((MethodBase)typeFromHandle4.GetMethod("Log", new Type[2]
{
typeof(object),
typeof(Object)
}), new HarmonyMethod(typeof(PhosphorBehaviour).GetMethod("Log_Object_Object", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null));
list.Add(((MethodBase)typeFromHandle4.GetMethod("LogWarning", new Type[1] { typeof(object) }), new HarmonyMethod(typeof(PhosphorBehaviour).GetMethod("LogWarning_Object", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null));
list.Add(((MethodBase)typeFromHandle4.GetMethod("LogWarning", new Type[2]
{
typeof(object),
typeof(Object)
}), new HarmonyMethod(typeof(PhosphorBehaviour).GetMethod("LogWarning_Object_Object", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null));
list.Add(((MethodBase)typeFromHandle4.GetMethod("LogError", new Type[1] { typeof(object) }), new HarmonyMethod(typeof(PhosphorBehaviour).GetMethod("LogError_Object", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null));
list.Add(((MethodBase)typeFromHandle4.GetMethod("LogError", new Type[2]
{
typeof(object),
typeof(Object)
}), new HarmonyMethod(typeof(PhosphorBehaviour).GetMethod("LogError_Object_Object", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null));
list.Add(((MethodBase)typeFromHandle4.GetMethod("LogFormat", new Type[2]
{
typeof(string),
typeof(object[])
}), new HarmonyMethod(typeof(PhosphorBehaviour).GetMethod("LogFormat", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null));
Type typeFromHandle5 = typeof(ParticleSystem);
list.Add(((MethodBase)typeFromHandle5.GetMethod("Awake", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic), (HarmonyMethod)null, new HarmonyMethod(typeof(PhosphorBehaviour).GetMethod("ParticleSystem_Awake_Postfix", BindingFlags.Static | BindingFlags.NonPublic))));
list.Add(((MethodBase)typeFromHandle5.GetMethod("Play", Type.EmptyTypes), new HarmonyMethod(typeof(PhosphorBehaviour).GetMethod("ParticleSystem_Play_Prefix", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null));
list.Add(((MethodBase)typeFromHandle5.GetMethod("Play", new Type[1] { typeof(bool) }), new HarmonyMethod(typeof(PhosphorBehaviour).GetMethod("ParticleSystem_Play_Bool_Prefix", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null));
list.Add(((MethodBase)typeFromHandle5.GetMethod("Emit", new Type[2]
{
typeof(EmitParams),
typeof(int)
}), new HarmonyMethod(typeof(PhosphorBehaviour).GetMethod("ParticleSystem_Emit_Prefix", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null));
list.Add(((MethodBase)typeFromHandle5.GetMethod("Emit", new Type[1] { typeof(EmitParams) }), new HarmonyMethod(typeof(PhosphorBehaviour).GetMethod("ParticleSystem_EmitSingle_Prefix", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null));
list.Add(((MethodBase)typeFromHandle5.GetMethod("Emit", new Type[1] { typeof(int) }), new HarmonyMethod(typeof(PhosphorBehaviour).GetMethod("ParticleSystem_EmitInt_Prefix", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null));
list.Add(((MethodBase)typeFromHandle5.GetMethod("Simulate", new Type[1] { typeof(float) }), new HarmonyMethod(typeof(PhosphorBehaviour).GetMethod("ParticleSystem_Simulate_Prefix", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null));
Type typeFromHandle6 = typeof(GameObject);
list.Add(((MethodBase)typeFromHandle6.GetMethod("SetActive", new Type[1] { typeof(bool) }), (HarmonyMethod)null, new HarmonyMethod(typeof(PhosphorBehaviour).GetMethod("GameObject_SetActive_Postfix", BindingFlags.Static | BindingFlags.NonPublic))));
foreach (var (methodBase, val2, val3) in list)
{
if (methodBase == null)
{
Init.Logger.LogWarning((object)"Skipping null target method.");
continue;
}
try
{
val.Patch(methodBase, val2, val3, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
Init.Logger.LogInfo((object)("Patched: " + methodBase.DeclaringType.Name + "." + methodBase.Name));
}
catch (Exception arg)
{
Init.Logger.LogError((object)$"Failed to patch {methodBase.DeclaringType.Name}.{methodBase.Name}: {arg}");
}
}
IEnumerable<MethodBase> patchedMethods = val.GetPatchedMethods();
foreach (MethodBase item in patchedMethods)
{
Init.Logger.LogInfo((object)("Verified patched: " + item.DeclaringType?.Name + "." + item.Name));
}
Init.Logger.LogInfo((object)$"Total patched methods: {patchedMethods.Count()}");
}
catch (Exception arg2)
{
Init.Logger.LogError((object)$"Failed to apply Harmony patches: {arg2}");
}
}
private static void LogPatchCall(string patchName)
{
if (Init.VerboseLogging.Value)
{
_patchCallCount++;
if (Time.unscaledTime - _lastPatchLogTime > 5f && _patchCallCount > 0)
{
Init.Logger.LogDebug((object)$"Patch calls in last 5s: {_patchCallCount} ({patchName})");
_patchCallCount = 0;
_lastPatchLogTime = Time.unscaledTime;
}
}
}
[HarmonyPatch]
private static void CampMgr_Start_Postfix()
{
LogPatchCall("CampMgr.Start");
Init.Logger.LogInfo((object)"CampMgr.Start patched – this should appear when camp loads.");
}
[HarmonyPatch]
private static bool UnitBase_Update_Prefix(UnitBase __instance)
{
//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
LogPatchCall("UnitBase.Update");
if (!Init.EnableFarAwareDisable.Value)
{
return true;
}
if (false)
{
return true;
}
if ((Object)(object)PlayerMgr.Inst == (Object)null)
{
return true;
}
int num = -1;
if (_unitCfgField != null && _unitTypeProperty != null)
{
object value = _unitCfgField.GetValue(__instance);
if (value != null)
{
num = (int)_unitTypeProperty.GetValue(value);
}
}
if (num == 5 || num == 4)
{
return true;
}
Vector3 val = ((Component)__instance).transform.position - PlayerMgr.Inst.PlayerPoint;
float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
float num2 = Init.FarDistance.Value * Init.FarDistance.Value;
if (sqrMagnitude > num2)
{
_unitSkipCounter++;
if (Time.unscaledTime - _lastUnitSkipLogTime > 5f && _unitSkipCounter > 0)
{
Init.Logger.LogInfo((object)$"Unit update skip: {_unitSkipCounter} skipped in last 5 seconds.");
_unitSkipCounter = 0;
_lastUnitSkipLogTime = Time.unscaledTime;
}
return false;
}
return true;
}
[HarmonyPatch]
private static bool CanShootSpellUtils_GetDamage_Prefix(float baseDamage, IEnumerable<SpellConfig> enhances, SpellConfig stopTarget, ref RatioValue __result)
{
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_005a: Unknown result type (might be due to invalid IL or missing references)
//IL_0061: Invalid comparison between Unknown and I4
//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
//IL_00f7: Expected O, but got Unknown
//IL_0079: Unknown result type (might be due to invalid IL or missing references)
//IL_0080: Invalid comparison between Unknown and I4
//IL_0063: Unknown result type (might be due to invalid IL or missing references)
//IL_006a: Invalid comparison between Unknown and I4
//IL_0084: Unknown result type (might be due to invalid IL or missing references)
//IL_008b: Invalid comparison between Unknown and I4
//IL_006e: Unknown result type (might be due to invalid IL or missing references)
//IL_0075: Invalid comparison between Unknown and I4
LogPatchCall("CanShootSpellUtils.GetDamage");
if (!Init.EnableLinqReplacement.Value)
{
return true;
}
double num = baseDamage;
foreach (SpellConfig enhance in enhances)
{
if (enhance == stopTarget)
{
break;
}
SpellAbilityType abilityType = enhance.abilityType;
SpellAbilityType val = abilityType;
if ((int)val <= 3104)
{
if ((int)val != 3102)
{
if ((int)val == 3104)
{
num *= (double)enhance.float3 / 100.0;
}
continue;
}
}
else if ((int)val != 3111)
{
if ((int)val == 3121)
{
num *= (double)enhance.float2 / 100.0;
}
continue;
}
num += num * ((double)enhance.float1 / 100.0);
}
__result = new RatioValue(num);
return false;
}
[HarmonyPatch]
private static bool CanShootSpellUtils_GetDamage_FinalPlayerValue_Prefix(float baseDamage, SpellConfig[] enhances, SpellConfig stopTarget, Wand wand, ref RatioValue __result)
{
//IL_0117: Unknown result type (might be due to invalid IL or missing references)
//IL_011d: Expected O, but got Unknown
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
//IL_005d: Invalid comparison between Unknown and I4
//IL_0075: Unknown result type (might be due to invalid IL or missing references)
//IL_007c: Invalid comparison between Unknown and I4
//IL_005f: Unknown result type (might be due to invalid IL or missing references)
//IL_0066: Invalid comparison between Unknown and I4
//IL_0080: Unknown result type (might be due to invalid IL or missing references)
//IL_0087: Invalid comparison between Unknown and I4
//IL_006a: Unknown result type (might be due to invalid IL or missing references)
//IL_0071: Invalid comparison between Unknown and I4
LogPatchCall("CanShootSpellUtils.GetDamage_FinalPlayerValue");
if (!Init.EnableLinqReplacement.Value)
{
return true;
}
double num = baseDamage;
foreach (SpellConfig val in enhances)
{
if (val == stopTarget)
{
break;
}
SpellAbilityType abilityType = val.abilityType;
SpellAbilityType val2 = abilityType;
if ((int)val2 <= 3104)
{
if ((int)val2 != 3102)
{
if ((int)val2 == 3104)
{
num *= (double)val.float3 / 100.0;
}
continue;
}
}
else if ((int)val2 != 3111)
{
if ((int)val2 == 3121)
{
num *= (double)val.float2 / 100.0;
}
continue;
}
num += num * ((double)val.float1 / 100.0);
}
num += (double)PlayerMgr.Inst.ExtraDamageRatio;
num *= (double)wand.passiveDamageRatio;
num *= (double)wand.WandCfg.damageCorrection / 100.0;
__result = new RatioValue(num);
return false;
}
[HarmonyPatch]
private static bool Log_Object(object message)
{
return !Init.EnableLogRemoval.Value;
}
[HarmonyPatch]
private static bool Log_Object_Object(object message, Object context)
{
return !Init.EnableLogRemoval.Value;
}
[HarmonyPatch]
private static bool LogWarning_Object(object message)
{
return !Init.EnableLogRemoval.Value;
}
[HarmonyPatch]
private static bool LogWarning_Object_Object(object message, Object context)
{
return !Init.EnableLogRemoval.Value;
}
[HarmonyPatch]
private static bool LogError_Object(object message)
{
return true;
}
[HarmonyPatch]
private static bool LogError_Object_Object(object message, Object context)
{
return true;
}
[HarmonyPatch]
private static bool LogFormat(string format, object[] args)
{
return !Init.EnableLogRemoval.Value;
}
[HarmonyPatch]
private static void ParticleSystem_Awake_Postfix(ParticleSystem __instance)
{
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
if (Init.DisableParticles.Value)
{
__instance.Stop(true, (ParticleSystemStopBehavior)0);
EmissionModule emission = __instance.emission;
((EmissionModule)(ref emission)).enabled = false;
LogParticleBlock(((Object)__instance).name);
}
}
[HarmonyPatch]
private static bool ParticleSystem_Play_Prefix(ParticleSystem __instance)
{
if (Init.DisableParticles.Value)
{
LogParticleBlock(((Object)__instance).name);
return false;
}
return true;
}
[HarmonyPatch]
private static bool ParticleSystem_Play_Bool_Prefix(ParticleSystem __instance, bool withChildren)
{
if (Init.DisableParticles.Value)
{
LogParticleBlock(((Object)__instance).name);
return false;
}
return true;
}
[HarmonyPatch]
private static bool ParticleSystem_Emit_Prefix(ParticleSystem __instance)
{
if (Init.DisableParticles.Value)
{
LogParticleBlock(((Object)__instance).name);
return false;
}
return true;
}
[HarmonyPatch]
private static bool ParticleSystem_EmitSingle_Prefix(ParticleSystem __instance)
{
if (Init.DisableParticles.Value)
{
LogParticleBlock(((Object)__instance).name);
return false;
}
return true;
}
[HarmonyPatch]
private static bool ParticleSystem_EmitInt_Prefix(ParticleSystem __instance, int count)
{
if (Init.DisableParticles.Value)
{
LogParticleBlock(((Object)__instance).name);
return false;
}
return true;
}
[HarmonyPatch]
private static bool ParticleSystem_Simulate_Prefix(ParticleSystem __instance, float t)
{
if (Init.DisableParticles.Value)
{
LogParticleBlock(((Object)__instance).name);
return false;
}
return true;
}
[HarmonyPatch]
private static void GameObject_SetActive_Postfix(GameObject __instance, bool value)
{
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
if (!(Init.DisableParticles.Value && value))
{
return;
}
ParticleSystem[] componentsInChildren = __instance.GetComponentsInChildren<ParticleSystem>(true);
ParticleSystem[] array = componentsInChildren;
foreach (ParticleSystem val in array)
{
if (val.isPlaying)
{
val.Stop(true, (ParticleSystemStopBehavior)0);
EmissionModule emission = val.emission;
((EmissionModule)(ref emission)).enabled = false;
LogParticleBlock(((Object)val).name);
}
}
}
private static void LogParticleBlock(string name)
{
_particleBlockCount++;
if (Time.unscaledTime - _lastParticleLogTime > 5f && _particleBlockCount > 0)
{
Init.Logger.LogInfo((object)$"Particle system blocked: {_particleBlockCount} blocks in last 5 seconds.");
_particleBlockCount = 0;
_lastParticleLogTime = Time.unscaledTime;
}
if (Init.VerboseLogging.Value)
{
Init.Logger.LogDebug((object)("Blocked particle on " + name));
}
}
}
public class PerformanceUI : MonoBehaviour
{
private const string Version = "1.1.0";
private bool _visible = true;
private Rect _windowRect = new Rect(10f, 10f, 360f, 400f);
private int _windowId = "PerformanceUI".GetHashCode();
private float[] _fpsBuffer = new float[60];
private int _fpsIndex = 0;
private float _fpsMin = float.MaxValue;
private float _fpsMax = float.MinValue;
private float _fpsAvg = 0f;
private int _drawCalls;
private int _batches;
private int _setPassCalls;
private float _lastFpsUpdate = 0f;
private long _lastMemory = 0L;
private float _memoryUpdateTime = 0f;
private int _totalGameObjects = 0;
private int _totalParticleSystems = 0;
private int _totalUnitBases = 0;
private float _objectCountUpdateTime = 0f;
private float _statsTimer = 0f;
private void Start()
{
for (int i = 0; i < _fpsBuffer.Length; i++)
{
_fpsBuffer[i] = 60f;
}
_fpsAvg = 60f;
}
private void Update()
{
if (Input.GetKeyDown((KeyCode)283))
{
_visible = !_visible;
}
if (!_visible)
{
return;
}
float unscaledDeltaTime = Time.unscaledDeltaTime;
if (unscaledDeltaTime > 0f)
{
float num = 1f / unscaledDeltaTime;
_fpsBuffer[_fpsIndex] = num;
_fpsIndex = (_fpsIndex + 1) % _fpsBuffer.Length;
_lastFpsUpdate += unscaledDeltaTime;
if (_lastFpsUpdate >= 0.5f)
{
_lastFpsUpdate = 0f;
_fpsMin = float.MaxValue;
_fpsMax = float.MinValue;
float num2 = 0f;
float[] fpsBuffer = _fpsBuffer;
foreach (float num3 in fpsBuffer)
{
num2 += num3;
if (num3 < _fpsMin)
{
_fpsMin = num3;
}
if (num3 > _fpsMax)
{
_fpsMax = num3;
}
}
_fpsAvg = num2 / (float)_fpsBuffer.Length;
}
}
_memoryUpdateTime += unscaledDeltaTime;
if (_memoryUpdateTime >= 1f)
{
_memoryUpdateTime = 0f;
_lastMemory = GC.GetTotalMemory(forceFullCollection: false);
}
_objectCountUpdateTime += unscaledDeltaTime;
if (_objectCountUpdateTime >= 2f)
{
_objectCountUpdateTime = 0f;
_totalGameObjects = Object.FindObjectsOfType<GameObject>().Length;
_totalParticleSystems = Object.FindObjectsOfType<ParticleSystem>().Length;
_totalUnitBases = Object.FindObjectsOfType<UnitBase>().Length;
}
if (_statsTimer <= 0f)
{
_statsTimer = 1f;
UpdateRenderStats();
}
else
{
_statsTimer -= unscaledDeltaTime;
}
}
private void UpdateRenderStats()
{
RenderPipeline currentPipeline = RenderPipelineManager.currentPipeline;
if (currentPipeline == null)
{
_drawCalls = (_batches = (_setPassCalls = 0));
return;
}
try
{
Type type = ((object)currentPipeline).GetType().Assembly.GetType("UnityEngine.Rendering.RenderPipeline+Statistics");
if (type != null)
{
MethodInfo method = ((object)currentPipeline).GetType().GetMethod("GetStatistics", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (method != null)
{
object obj = method.Invoke(currentPipeline, null);
if (obj != null)
{
_drawCalls = (int)type.GetField("drawCalls").GetValue(obj);
_batches = (int)type.GetField("batches").GetValue(obj);
_setPassCalls = (int)type.GetField("setPassCalls").GetValue(obj);
return;
}
}
}
_drawCalls = (_batches = (_setPassCalls = 0));
}
catch
{
_drawCalls = (_batches = (_setPassCalls = 0));
}
}
private void OnGUI()
{
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_0033: Expected O, but got Unknown
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
if (_visible)
{
_windowRect = GUI.Window(_windowId, _windowRect, new WindowFunction(DrawWindow), "Phosphor Performance");
}
}
private void DrawWindow(int id)
{
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_008d: Unknown result type (might be due to invalid IL or missing references)
//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
//IL_014f: Unknown result type (might be due to invalid IL or missing references)
//IL_0194: Unknown result type (might be due to invalid IL or missing references)
//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
//IL_023c: Unknown result type (might be due to invalid IL or missing references)
//IL_026a: Unknown result type (might be due to invalid IL or missing references)
//IL_02b5: Unknown result type (might be due to invalid IL or missing references)
//IL_0300: Unknown result type (might be due to invalid IL or missing references)
//IL_034b: Unknown result type (might be due to invalid IL or missing references)
//IL_03a5: Unknown result type (might be due to invalid IL or missing references)
//IL_03f0: Unknown result type (might be due to invalid IL or missing references)
GUI.color = new Color(0f, 0f, 0f, 0.85f);
GUI.DrawTexture(new Rect(0f, 0f, ((Rect)(ref _windowRect)).width, ((Rect)(ref _windowRect)).height), (Texture)(object)Texture2D.whiteTexture);
GUI.color = Color.white;
float num = 18f;
float num2 = 2f;
float num3 = 5f;
GUI.Label(new Rect(5f, 5f, ((Rect)(ref _windowRect)).width - 10f, 20f), "Phosphor v1.1.0 | " + Application.productName);
float num4 = 30f;
GUI.Label(new Rect(5f, num4, ((Rect)(ref _windowRect)).width - 10f, num), $"FPS: Current: {Mathf.Round(1f / Time.unscaledDeltaTime)} Min: {Mathf.Round(_fpsMin)} Max: {Mathf.Round(_fpsMax)} Avg: {Mathf.Round(_fpsAvg)}");
num4 += num + num2;
GUI.Label(new Rect(5f, num4, ((Rect)(ref _windowRect)).width - 10f, num), $"Memory: {(float)_lastMemory / 1048576f:F1} MB");
num4 += num + num2;
GUI.Label(new Rect(5f, num4, ((Rect)(ref _windowRect)).width - 10f, num), $"Objects: Total: {_totalGameObjects} Units: {_totalUnitBases} Particles: {_totalParticleSystems}");
num4 += num + num3;
GUI.Label(new Rect(5f, num4, ((Rect)(ref _windowRect)).width - 10f, num), $"Draw Calls: {_drawCalls} Batches: {_batches} SetPass: {_setPassCalls}");
num4 += num + num3;
GUI.Label(new Rect(5f, num4, ((Rect)(ref _windowRect)).width - 10f, num), "Mod Config:");
num4 += num + num2;
GUI.Label(new Rect(15f, num4, ((Rect)(ref _windowRect)).width - 20f, num), " Optimizations: " + (Init.EnableOptimizations.Value ? "Enabled" : "Disabled"));
num4 += num + num2;
GUI.Label(new Rect(15f, num4, ((Rect)(ref _windowRect)).width - 20f, num), " Log Removal: " + (Init.EnableLogRemoval.Value ? "On" : "Off"));
num4 += num + num2;
GUI.Label(new Rect(15f, num4, ((Rect)(ref _windowRect)).width - 20f, num), " LINQ Replacement: " + (Init.EnableLinqReplacement.Value ? "On" : "Off"));
num4 += num + num2;
GUI.Label(new Rect(15f, num4, ((Rect)(ref _windowRect)).width - 20f, num), string.Format(" Far Disable: {0} (Distance: {1:F1})", Init.EnableFarAwareDisable.Value ? "On" : "Off", Init.FarDistance.Value));
num4 += num + num2;
GUI.Label(new Rect(15f, num4, ((Rect)(ref _windowRect)).width - 20f, num), " Disable Particles: " + (Init.DisableParticles.Value ? "On" : "Off"));
num4 += num + num3;
GUI.Label(new Rect(5f, num4, ((Rect)(ref _windowRect)).width - 10f, num), "Press F2 to toggle this UI");
GUI.DragWindow();
}
private void OnEnable()
{
_fpsMin = float.MaxValue;
_fpsMax = float.MinValue;
_fpsAvg = 60f;
_fpsIndex = 0;
for (int i = 0; i < _fpsBuffer.Length; i++)
{
_fpsBuffer[i] = 60f;
}
}
}
public class UIManager : MonoBehaviour
{
private static UIManager _instance;
private const string Version = "1.1.0";
private GUIStyle _guiStyle;
public static void Create()
{
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_001d: Expected O, but got Unknown
if (!((Object)(object)_instance != (Object)null))
{
GameObject val = new GameObject("PhosphorUI");
Object.DontDestroyOnLoad((Object)(object)val);
_instance = val.AddComponent<UIManager>();
}
}
private void Awake()
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Expected O, but got Unknown
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
_guiStyle = new GUIStyle();
_guiStyle.fontSize = 18;
_guiStyle.normal.textColor = Color.white;
_guiStyle.alignment = (TextAnchor)6;
_guiStyle.fontStyle = (FontStyle)1;
}
private void OnGUI()
{
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
GUI.Label(new Rect(10f, (float)(Screen.height - 30), 200f, 30f), "Phosphor v1.1.0", _guiStyle);
}
}