using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using Microsoft.CodeAnalysis;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("ValhATYLSS")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("ValhATYLSS")]
[assembly: AssemblyTitle("ValhATYLSS")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace Atlyss.Uncap.StatLogics
{
[BepInPlugin("com.cconx.valhatylss", "ValhATYLSS", "0.1.0")]
public class Plugin : BaseUnityPlugin
{
private enum RepeatMode
{
Constant,
PatternEveryN
}
[CompilerGenerated]
private sealed class <ApplyTweaksWhenReady>d__7 : IEnumerator<object>, IDisposable, IEnumerator
{
private int <>1__state;
private object <>2__current;
public Plugin <>4__this;
private float <deadline>5__2;
private Assembly <asm>5__3;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <ApplyTweaksWhenReady>d__7(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<asm>5__3 = null;
<>1__state = -2;
}
private bool MoveNext()
{
//IL_0080: Unknown result type (might be due to invalid IL or missing references)
//IL_008a: Expected O, but got Unknown
int num = <>1__state;
Plugin plugin = <>4__this;
switch (num)
{
default:
return false;
case 0:
<>1__state = -1;
<deadline>5__2 = Time.realtimeSinceStartup + 15f;
<asm>5__3 = null;
break;
case 1:
<>1__state = -1;
break;
}
if (Time.realtimeSinceStartup < <deadline>5__2)
{
<asm>5__3 = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => a.GetName().Name == "Assembly-CSharp");
if (!(<asm>5__3 != null))
{
<>2__current = (object)new WaitForSeconds(0.25f);
<>1__state = 1;
return true;
}
}
if (<asm>5__3 == null)
{
Logger.LogError((object)"[ValhATYLSS] Assembly-CSharp not found; aborting.");
return false;
}
Type type = <asm>5__3.GetTypes().FirstOrDefault((Type t) => t.Name == "StatLogics") ?? <asm>5__3.GetTypes().FirstOrDefault((Type t) => t.Name.EndsWith("StatLogics", StringComparison.OrdinalIgnoreCase));
if (type == null)
{
Logger.LogError((object)"[ValhATYLSS] StatLogics type not found; aborting.");
return false;
}
object obj = FindSingletonInstance(type) ?? FindAnyStaticReferenceTo(type) ?? FindUnityObjectOfType(type);
if (obj != null)
{
Logger.LogInfo((object)("[ValhATYLSS] StatLogics instance acquired via " + ((obj is Object) ? "UnityObject" : "reflection") + "."));
}
else
{
Logger.LogWarning((object)"[ValhATYLSS] StatLogics instance not found (will patch static fields only).");
}
plugin.TrySetIntField(type, obj, "_maxMainLevel", NewLevelCap);
plugin.TryExtendCurve(type, obj, "_experienceCurve");
plugin.TryExtendRewardTables(<asm>5__3);
Logger.LogInfo((object)"[ValhATYLSS] reflection tweaks applied");
return false;
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
internal static ManualLogSource Logger;
public static int NewLevelCap = 64;
public static int AnchorWindow = 4;
public static int AttributePerLevel = 3;
public static int SkillEveryNLevels = 2;
public static int SkillPointsGrant = 4;
private void Awake()
{
Logger = ((BaseUnityPlugin)this).Logger;
Logger.LogInfo((object)"[ValhATYLSS] boot (reflection-only mode, instance-safe)");
((MonoBehaviour)this).StartCoroutine(ApplyTweaksWhenReady());
}
[IteratorStateMachine(typeof(<ApplyTweaksWhenReady>d__7))]
private IEnumerator ApplyTweaksWhenReady()
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <ApplyTweaksWhenReady>d__7(0)
{
<>4__this = this
};
}
private void TryExtendCurve(Type owner, object ownerInstance, string fieldName)
{
FieldInfo field = GetField(owner, fieldName);
if (field == null)
{
Logger.LogWarning((object)("[ValhATYLSS] Field '" + fieldName + "' not found on " + owner.Name + "."));
return;
}
object obj = null;
try
{
obj = field.GetValue(field.IsStatic ? null : ownerInstance);
}
catch (Exception ex)
{
Logger.LogError((object)("[ValhATYLSS] Failed reading " + owner.Name + "." + fieldName + ": " + ex.Message));
return;
}
if (obj == null)
{
Logger.LogWarning((object)("[ValhATYLSS] " + owner.Name + "." + fieldName + " is null at patch time."));
return;
}
try
{
if (obj is int[] array)
{
double r;
int[] array2 = ExtendCurveArray(array, NewLevelCap, AnchorWindow, out r);
if (array != array2)
{
field.SetValue(field.IsStatic ? null : ownerInstance, array2);
Logger.LogInfo((object)$"[ValhATYLSS] Extended int[] {fieldName} {array.Length} -> {array2.Length} (r≈{r:F4})");
}
}
else if (obj is float[] array3)
{
double r2;
float[] array4 = ExtendCurveArray(array3, NewLevelCap, AnchorWindow, out r2);
if (array3 != array4)
{
field.SetValue(field.IsStatic ? null : ownerInstance, array4);
Logger.LogInfo((object)$"[ValhATYLSS] Extended float[] {fieldName} {array3.Length} -> {array4.Length} (r≈{r2:F4})");
}
}
else if (obj is IList list)
{
int count = list.Count;
ExtendCurveList(list, NewLevelCap, AnchorWindow, out var r3);
if (list.Count != count)
{
Logger.LogInfo((object)$"[ValhATYLSS] Extended List {fieldName} {count} -> {list.Count} (r≈{r3:F4})");
}
}
else
{
Logger.LogWarning((object)("[ValhATYLSS] " + fieldName + " type " + obj.GetType().FullName + " not handled."));
}
}
catch (Exception arg)
{
Logger.LogError((object)$"[ValhATYLSS] Failed extending {owner.Name}.{fieldName}: {arg}");
}
}
private static int[] ExtendCurveArray(int[] src, int targetLevelCap, int anchor, out double r)
{
int num = Math.Max(src.Length, targetLevelCap + 1);
r = EstimateGeometricRatio(src, Math.Max(1, src.Length - anchor));
if (src.Length >= num)
{
return src;
}
int[] array = new int[num];
Array.Copy(src, array, src.Length);
int num2 = src[^1];
for (int i = src.Length; i < num; i++)
{
num2 = (int)Math.Round((double)num2 * r);
if (i > 0 && num2 <= array[i - 1])
{
num2 = array[i - 1] + 1;
}
array[i] = num2;
}
return array;
}
private static float[] ExtendCurveArray(float[] src, int targetLevelCap, int anchor, out double r)
{
int num = Math.Max(src.Length, targetLevelCap + 1);
r = EstimateGeometricRatio(src, Math.Max(1, src.Length - anchor));
if (src.Length >= num)
{
return src;
}
float[] array = new float[num];
Array.Copy(src, array, src.Length);
double num2 = src[^1];
for (int i = src.Length; i < num; i++)
{
num2 *= r;
array[i] = (float)num2;
}
return array;
}
private static void ExtendCurveList(IList list, int targetLevelCap, int anchor, out double r)
{
int count = list.Count;
int num = Math.Max(1, count - anchor);
List<double> list2 = new List<double>();
for (int i = num; i < count - 1; i++)
{
double num2 = ToDouble(list[i]);
double num3 = ToDouble(list[i + 1]);
if (num2 > 0.0 && num3 > 0.0)
{
double num4 = num3 / num2;
if (num4 > 0.1 && num4 < 10.0)
{
list2.Add(num4);
}
}
}
r = ((list2.Count == 0) ? 1.15 : Math.Pow(list2.Aggregate(1.0, (double p, double x) => p * x), 1.0 / (double)list2.Count));
int num5 = Math.Max(count, targetLevelCap + 1);
if (count >= num5)
{
return;
}
double num6 = ToDouble(list[count - 1]);
while (list.Count < num5)
{
num6 = Math.Max(1.0, num6 * r);
if (list[0] is int)
{
list.Add((int)Math.Round(num6));
}
else
{
list.Add((float)num6);
}
}
}
private static double ToDouble(object o)
{
try
{
return Convert.ToDouble(o);
}
catch
{
return 0.0;
}
}
private static double EstimateGeometricRatio(int[] arr, int startIdx)
{
double num = 1.0;
int num2 = 0;
for (int i = startIdx; i < arr.Length - 1; i++)
{
if (arr[i] > 0)
{
double num3 = (double)arr[i + 1] / (double)arr[i];
if (num3 > 0.1 && num3 < 10.0)
{
num *= num3;
num2++;
}
}
}
if (num2 != 0)
{
return Math.Pow(num, 1.0 / (double)num2);
}
return 1.15;
}
private static double EstimateGeometricRatio(float[] arr, int startIdx)
{
double num = 1.0;
int num2 = 0;
for (int i = startIdx; i < arr.Length - 1; i++)
{
if (!(arr[i] <= 0f))
{
double num3 = (double)arr[i + 1] / (double)arr[i];
if (num3 > 0.1 && num3 < 10.0)
{
num *= num3;
num2++;
}
}
}
if (num2 != 0)
{
return Math.Pow(num, 1.0 / (double)num2);
}
return 1.15;
}
private void TryExtendRewardTables(Assembly asm)
{
int num = 0;
Type[] types = asm.GetTypes();
foreach (Type type in types)
{
string text = type.FullName ?? "";
if (!text.StartsWith("System") && !text.Contains("Unity"))
{
num += TryExtendIntArrayField(type, null, "_attributePointsEachLevel", NewLevelCap, AttributePerLevel, RepeatMode.Constant);
num += TryExtendIntArrayField(type, null, "_skillPointsEachLevel", NewLevelCap, 0, RepeatMode.PatternEveryN, SkillEveryNLevels, SkillPointsGrant);
}
}
if (num == 0)
{
Logger.LogInfo((object)"[ValhATYLSS] No obvious reward arrays found. (If points past 32 don’t grant, we’ll hook the LevelUp method next.)");
}
}
private int TryExtendIntArrayField(Type owner, object instance, string fieldName, int targetLen, int constant, RepeatMode mode, int n = 2, int grant = 4)
{
try
{
FieldInfo field = GetField(owner, fieldName);
if (field == null)
{
return 0;
}
if (!field.IsStatic && instance == null)
{
instance = FindSingletonInstance(owner) ?? FindAnyStaticReferenceTo(owner) ?? FindUnityObjectOfType(owner);
}
if (!(field.GetValue(field.IsStatic ? null : instance) is int[] array))
{
return 0;
}
if (array.Length >= targetLen)
{
return 0;
}
int[] array2 = new int[targetLen];
Array.Copy(array, array2, array.Length);
if (mode == RepeatMode.Constant)
{
for (int i = array.Length; i < targetLen; i++)
{
array2[i] = constant;
}
}
else
{
for (int j = array.Length; j < targetLen; j++)
{
int num = j + 1;
array2[j] = ((num % n == 0) ? grant : 0);
}
}
field.SetValue(field.IsStatic ? null : instance, array2);
Logger.LogInfo((object)$"[ValhATYLSS] Extended {owner.Name}.{fieldName} {array.Length} -> {array2.Length}");
return 1;
}
catch (Exception ex)
{
Logger.LogWarning((object)("[ValhATYLSS] Failed to extend " + owner.Name + "." + fieldName + ": " + ex.Message));
return 0;
}
}
private static FieldInfo GetField(Type t, string name)
{
return t.GetField(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
}
private void TrySetIntField(Type owner, object instance, string fieldName, int value)
{
FieldInfo field = GetField(owner, fieldName);
if (field == null || field.FieldType != typeof(int))
{
return;
}
try
{
object obj = (field.IsStatic ? null : (instance ?? FindSingletonInstance(owner) ?? FindAnyStaticReferenceTo(owner) ?? FindUnityObjectOfType(owner)));
if (!field.IsStatic && obj == null)
{
Logger.LogWarning((object)("[ValhATYLSS] " + owner.Name + "." + fieldName + " is instance but no instance was found."));
}
else
{
int num = (int)field.GetValue(obj);
field.SetValue(obj, value);
Logger.LogInfo((object)$"[ValhATYLSS] {owner.Name}.{fieldName}: {num} -> {value}");
}
}
catch (Exception ex)
{
Logger.LogError((object)("[ValhATYLSS] Failed to set " + owner.Name + "." + fieldName + ": " + ex.Message));
}
}
private static object FindSingletonInstance(Type t)
{
string[] array = new string[8] { "Instance", "instance", "_instance", "s_instance", "Singleton", "singleton", "Inst", "inst" };
foreach (string name in array)
{
FieldInfo field = t.GetField(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
if (field != null && field.FieldType == t)
{
object value = field.GetValue(null);
if (value != null)
{
return value;
}
}
PropertyInfo property = t.GetProperty(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
if (property != null && property.PropertyType == t)
{
object value2 = property.GetValue(null, null);
if (value2 != null)
{
return value2;
}
}
}
return null;
}
private static object FindAnyStaticReferenceTo(Type targetType)
{
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (Assembly assembly in assemblies)
{
Type[] types;
try
{
types = assembly.GetTypes();
}
catch
{
continue;
}
Type[] array = types;
foreach (Type type in array)
{
FieldInfo[] fields;
try
{
fields = type.GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
}
catch
{
continue;
}
FieldInfo[] array2 = fields;
foreach (FieldInfo fieldInfo in array2)
{
try
{
if (targetType.IsAssignableFrom(fieldInfo.FieldType))
{
object value = fieldInfo.GetValue(null);
if (value != null)
{
return value;
}
}
}
catch
{
}
}
}
}
return null;
}
private static object FindUnityObjectOfType(Type t)
{
try
{
if (typeof(Object).IsAssignableFrom(t))
{
MethodInfo methodInfo = typeof(Resources).GetMethods(BindingFlags.Static | BindingFlags.Public).FirstOrDefault((MethodInfo m) => m.Name == "FindObjectsOfTypeAll" && m.IsGenericMethodDefinition && m.GetParameters().Length == 0);
if (methodInfo != null && methodInfo.MakeGenericMethod(t).Invoke(null, null) is Array array && array.Length > 0)
{
return array.GetValue(0);
}
}
}
catch
{
}
return null;
}
}
}