using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using AvatarStatsChanger;
using BoneLib;
using BoneLib.BoneMenu;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppSLZ.VRMK;
using MelonLoader;
using MelonLoader.Preferences;
using Microsoft.CodeAnalysis;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(Main), "AvatarStatsChanger", "1.0.1", "kamonkus", null)]
[assembly: MelonGame("Stress Level Zero", "BONELAB")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[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 AvatarStatsChanger
{
internal static class AvatarEditor
{
public const int Count = 11;
public static readonly string[] Labels = new string[11]
{
"Agility", "Strength Upper", "Strength Lower", "Vitality", "Speed", "Intelligence", "Chest Mass", "Pelvis Mass", "Head Mass", "Arm Mass",
"Leg Mass"
};
private static readonly string[] Names = new string[11]
{
"agility", "strengthupper", "strengthlower", "vitality", "speed", "intelligence", "masschest", "masspelvis", "masshead", "massarm",
"massleg"
};
private static readonly string[][] Tokens = new string[11][]
{
new string[1] { "agility" },
new string[2] { "strength", "upper" },
new string[2] { "strength", "lower" },
new string[1] { "vitality" },
new string[1] { "speed" },
new string[1] { "intelligence" },
new string[2] { "mass", "chest" },
new string[2] { "mass", "pelvis" },
new string[2] { "mass", "head" },
new string[2] { "mass", "arm" },
new string[2] { "mass", "leg" }
};
private static readonly PropertyInfo[] _loaded = new PropertyInfo[11];
private static readonly PropertyInfo[] _computed = new PropertyInfo[11];
private static bool _resolved;
private static PropertyInfo _massTotalProp;
private static float _nextWatch;
private static readonly Dictionary<long, float[]> _orig = new Dictionary<long, float[]>();
private static readonly List<float> _schedule = new List<float>();
private static readonly HashSet<string> _noted = new HashSet<string>();
private static float _refreshAt = -1f;
private static bool _uiDirty;
private static bool IsFloat(PropertyInfo pi)
{
if (pi.PropertyType == typeof(float) && pi.CanRead)
{
return pi.GetIndexParameters().Length == 0;
}
return false;
}
private static void Resolve()
{
if (_resolved)
{
return;
}
_resolved = true;
PropertyInfo[] properties = typeof(Avatar).GetProperties(BindingFlags.Instance | BindingFlags.Public);
PropertyInfo[] array = properties;
foreach (PropertyInfo propertyInfo in array)
{
if (propertyInfo.CanWrite && IsFloat(propertyInfo) && propertyInfo.Name.ToLowerInvariant() == "_masstotal")
{
_massTotalProp = propertyInfo;
break;
}
}
for (int j = 0; j < 11; j++)
{
PropertyInfo propertyInfo2 = null;
PropertyInfo propertyInfo3 = null;
array = properties;
foreach (PropertyInfo propertyInfo4 in array)
{
if (!IsFloat(propertyInfo4))
{
continue;
}
string text = propertyInfo4.Name.ToLowerInvariant();
bool flag = text.StartsWith("_");
if (!(text.TrimStart('_') != Names[j]))
{
if (flag && propertyInfo4.CanWrite && propertyInfo2 == null)
{
propertyInfo2 = propertyInfo4;
}
if (!flag && propertyInfo3 == null)
{
propertyInfo3 = propertyInfo4;
}
}
}
if (propertyInfo2 == null)
{
int num = int.MaxValue;
array = properties;
foreach (PropertyInfo propertyInfo5 in array)
{
if (!IsFloat(propertyInfo5) || !propertyInfo5.CanWrite)
{
continue;
}
string text2 = propertyInfo5.Name.ToLowerInvariant();
bool flag2 = true;
string[] array2 = Tokens[j];
foreach (string value in array2)
{
if (!text2.Contains(value))
{
flag2 = false;
}
}
if (flag2 && text2.Length < num)
{
num = text2.Length;
propertyInfo2 = propertyInfo5;
}
}
}
_loaded[j] = propertyInfo2;
_computed[j] = propertyInfo3;
if (propertyInfo2 == null)
{
MelonLogger.Warning("[AvatarStatsChanger] stat not found on the avatar: " + Labels[j]);
}
}
}
private static Avatar CurrentAvatar()
{
try
{
return Player.Avatar;
}
catch (Exception)
{
return null;
}
}
private static float[] OriginalsFor(Avatar av)
{
Resolve();
long key = ((Il2CppObjectBase)av).Pointer.ToInt64();
if (_orig.TryGetValue(key, out var value))
{
return value;
}
value = new float[12];
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < 11; i++)
{
value[i] = float.NaN;
if (!(_loaded[i] == null))
{
try
{
value[i] = (float)_loaded[i].GetValue(av, null);
stringBuilder.Append(Labels[i]).Append('=').Append(value[i].ToString("0.###"))
.Append(" ");
}
catch (Exception)
{
}
}
}
value[11] = float.NaN;
if (_massTotalProp != null)
{
try
{
value[11] = (float)_massTotalProp.GetValue(av, null);
}
catch (Exception)
{
}
}
if (_orig.Count > 20)
{
_orig.Clear();
}
_orig[key] = value;
return value;
}
public static float GetOriginal(int index)
{
Avatar val = CurrentAvatar();
if ((Object)(object)val == (Object)null)
{
return float.NaN;
}
if (_orig.TryGetValue(((Il2CppObjectBase)val).Pointer.ToInt64(), out var value))
{
return value[index];
}
try
{
return OriginalsFor(val)[index];
}
catch (Exception)
{
return float.NaN;
}
}
public static void ApplyToCurrent()
{
Avatar val = CurrentAvatar();
if ((Object)(object)val == (Object)null || !Settings.Enabled.Value)
{
return;
}
try
{
if (ApplyTo(val, restore: false))
{
_refreshAt = Time.unscaledTime + 0.35f;
}
}
catch (Exception ex)
{
MelonLogger.Error("[AvatarStatsChanger] apply failed: " + ex);
}
}
public static void RestoreOriginals()
{
Avatar val = CurrentAvatar();
if ((Object)(object)val == (Object)null)
{
return;
}
try
{
if (ApplyTo(val, restore: true))
{
_refreshAt = Time.unscaledTime + 0.35f;
}
}
catch (Exception ex)
{
MelonLogger.Error("[AvatarStatsChanger] restore failed: " + ex);
}
}
private static bool AnyTouched()
{
for (int i = 0; i < 11; i++)
{
if (Settings.Touched[i].Value)
{
return true;
}
}
return false;
}
private static bool ApplyTo(Avatar av, bool restore)
{
float[] array = OriginalsFor(av);
float[] array2 = new float[11];
bool result = false;
for (int i = 0; i < 11; i++)
{
array2[i] = array[i];
if (_loaded[i] == null || float.IsNaN(array[i]))
{
continue;
}
if (!restore && Settings.Touched[i].Value)
{
array2[i] = Settings.Value[i].Value;
}
if (i >= 6 && i <= 10 && array2[i] < 0.001f)
{
array2[i] = 0.001f;
}
try
{
if (!Mathf.Approximately((float)_loaded[i].GetValue(av, null), array2[i]))
{
_loaded[i].SetValue(av, array2[i], null);
result = true;
}
}
catch (Exception ex)
{
Note("set " + Labels[i], "[AvatarStatsChanger] could not set " + Labels[i] + ": " + ex.Message);
}
}
bool flag = _massTotalProp != null && !float.IsNaN(array[11]);
for (int j = 6; j <= 10; j++)
{
if (float.IsNaN(array[j]))
{
flag = false;
}
}
if (flag)
{
bool flag2 = false;
for (int k = 6; k <= 10; k++)
{
if (!Mathf.Approximately(array2[k], array[k]))
{
flag2 = true;
}
}
float num = array[11];
if (flag2)
{
num = array2[6] + array2[7] + array2[8] + 2f * array2[9] + 2f * array2[10];
}
try
{
if (!Mathf.Approximately((float)_massTotalProp.GetValue(av, null), num))
{
_massTotalProp.SetValue(av, num, null);
result = true;
}
}
catch (Exception ex2)
{
Note("set masstotal", "[AvatarStatsChanger] could not set total mass: " + ex2.Message);
}
}
return result;
}
private static void Note(string key, string message)
{
if (_noted.Add(key))
{
MelonLogger.Warning(message);
}
}
private static bool TryInvoke(object target, string method, params object[] args)
{
try
{
Type[] array = new Type[args.Length];
for (int i = 0; i < args.Length; i++)
{
array[i] = args[i].GetType();
}
MethodInfo methodInfo = null;
MethodInfo[] methods = target.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public);
foreach (MethodInfo methodInfo2 in methods)
{
if (methodInfo2.Name != method)
{
continue;
}
ParameterInfo[] parameters = methodInfo2.GetParameters();
if (parameters.Length != args.Length)
{
continue;
}
bool flag = true;
for (int k = 0; k < parameters.Length; k++)
{
if (!parameters[k].ParameterType.IsAssignableFrom(array[k]))
{
flag = false;
}
}
if (flag)
{
methodInfo = methodInfo2;
break;
}
}
if (methodInfo == null)
{
return false;
}
methodInfo.Invoke(target, args);
return true;
}
catch (Exception ex)
{
Note("invoke " + method, "[AvatarStatsChanger] " + target.GetType().Name + "." + method + " failed: " + ex.Message);
return false;
}
}
private static void Refresh(Avatar av)
{
if (Settings.RigRefresh.Value)
{
object[] array = null;
try
{
array = new object[3]
{
Player.PhysicsRig,
Player.RemapRig,
Player.ControllerRig
};
}
catch (Exception)
{
}
if (array != null)
{
object[] array2 = array;
foreach (object obj in array2)
{
if (obj != null)
{
TryInvoke(obj, "SetAvatar", av);
}
}
}
}
try
{
ApplyTo(av, !Settings.Enabled.Value);
}
catch (Exception)
{
}
if (!Settings.RigRefresh.Value)
{
return;
}
try
{
object physicsRig = Player.PhysicsRig;
if (physicsRig != null)
{
TryInvoke(physicsRig, "CalibrateJoints", av);
TryInvoke(physicsRig, "SetBodyMassDistribution");
TryInvoke(physicsRig, "UpdateTotalDerivatives");
}
}
catch (Exception)
{
}
}
public static void OnAvatarSwitched(Avatar newAvatar)
{
try
{
if (!((Object)(object)newAvatar == (Object)null))
{
Avatar val = CurrentAvatar();
if (!((Object)(object)val != (Object)null) || !(((Il2CppObjectBase)val).Pointer != ((Il2CppObjectBase)newAvatar).Pointer))
{
ScheduleApply();
}
}
}
catch (Exception ex)
{
MelonLogger.Error("[AvatarStatsChanger] avatar switch error: " + ex);
}
}
public static void ScheduleApply()
{
float unscaledTime = Time.unscaledTime;
_schedule.Add(unscaledTime + 0.1f);
_schedule.Add(unscaledTime + 0.8f);
_schedule.Add(unscaledTime + 2.5f);
_uiDirty = true;
}
public static void Tick()
{
float unscaledTime = Time.unscaledTime;
for (int num = _schedule.Count - 1; num >= 0; num--)
{
if (!(_schedule[num] > unscaledTime))
{
_schedule.RemoveAt(num);
if (Settings.AutoApply.Value)
{
ApplyToCurrent();
}
if (_uiDirty && _schedule.Count == 0)
{
_uiDirty = false;
Settings.RefreshElements();
}
}
}
if (_refreshAt > 0f && unscaledTime >= _refreshAt)
{
_refreshAt = -1f;
Avatar val = CurrentAvatar();
if ((Object)(object)val != (Object)null && Settings.Enabled.Value)
{
try
{
Refresh(val);
}
catch (Exception ex)
{
MelonLogger.Error("[AvatarStatsChanger] refresh failed: " + ex);
}
}
}
if (unscaledTime >= _nextWatch)
{
_nextWatch = unscaledTime + 1f;
if (Settings.Enabled.Value && AnyTouched())
{
ApplyToCurrent();
}
}
}
}
public class Main : MelonMod
{
private float _nextErrorLog;
public override void OnInitializeMelon()
{
Settings.Init();
Hooking.OnSwitchAvatarPostfix += AvatarEditor.OnAvatarSwitched;
Hooking.OnLevelLoaded += delegate
{
AvatarEditor.ScheduleApply();
};
Settings.BuildMenu();
MelonLogger.Msg("AvatarStatsChanger loaded. Open BoneMenu -> AvatarStatsChanger.");
}
public override void OnUpdate()
{
try
{
AvatarEditor.Tick();
Settings.Tick();
}
catch (Exception ex)
{
float realtimeSinceStartup = Time.realtimeSinceStartup;
if (realtimeSinceStartup > _nextErrorLog)
{
_nextErrorLog = realtimeSinceStartup + 5f;
MelonLogger.Error("[AvatarStatsChanger] tick error: " + ex);
}
}
}
}
public static class Settings
{
public const int SlotCount = 6;
private static MelonPreferences_Category _cat;
private static float _saveAt = -1f;
private static bool _suppress;
public static MelonPreferences_Entry<bool> Enabled;
public static MelonPreferences_Entry<bool> AutoApply;
public static MelonPreferences_Entry<bool> RigRefresh;
public static MelonPreferences_Entry<float>[] Value = new MelonPreferences_Entry<float>[11];
public static MelonPreferences_Entry<bool>[] Touched = new MelonPreferences_Entry<bool>[11];
public static MelonPreferences_Entry<string>[] Slots = new MelonPreferences_Entry<string>[6];
private static readonly float[] Steps = new float[4] { 1f, 10f, 50f, 100f };
private static readonly FloatElement[][] _rows = new FloatElement[11][];
private static readonly FunctionElement[] _slotInfo = (FunctionElement[])(object)new FunctionElement[6];
private static readonly string[] _slotNameEdit = new string[6];
private static readonly string[] PrefIds = new string[11]
{
"Agility", "StrengthUpper", "StrengthLower", "Vitality", "Speed", "Intelligence", "ChestMass", "PelvisMass", "HeadMass", "ArmMass",
"LegMass"
};
public static void Init()
{
_cat = MelonPreferences.CreateCategory("AvatarStatsChanger");
Enabled = _cat.CreateEntry<bool>("Enabled", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
AutoApply = _cat.CreateEntry<bool>("ApplyOnAvatarChange", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
RigRefresh = _cat.CreateEntry<bool>("RefreshRigAfterChange", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
for (int i = 0; i < 11; i++)
{
Value[i] = _cat.CreateEntry<float>("Value_" + PrefIds[i], 1f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
Touched[i] = _cat.CreateEntry<bool>("Override_" + PrefIds[i], false, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
}
for (int j = 0; j < 6; j++)
{
Slots[j] = _cat.CreateEntry<string>("PresetV2_" + (j + 1), "", (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
}
}
public static void BuildMenu()
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
//IL_0074: Unknown result type (might be due to invalid IL or missing references)
//IL_009f: Unknown result type (might be due to invalid IL or missing references)
//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
//IL_0113: Unknown result type (might be due to invalid IL or missing references)
//IL_014d: Unknown result type (might be due to invalid IL or missing references)
Page val = Page.Root.CreatePage("AvatarStatsChanger", Color.cyan, 0, true);
Page parent = val.CreatePage("Avatar Stats", Color.green, 0, true);
for (int i = 0; i <= 5; i++)
{
BuildStatPage(parent, i);
}
Page parent2 = val.CreatePage("Avatar Mass", Color.red, 0, true);
for (int j = 6; j <= 10; j++)
{
BuildStatPage(parent2, j);
}
Page parent3 = val.CreatePage("Presets", Color.magenta, 0, true);
for (int k = 0; k < 6; k++)
{
BuildPresetPage(parent3, k);
}
val.CreateBool("Enabled", Color.white, Enabled.Value, (Action<bool>)delegate(bool v)
{
Enabled.Value = v;
Dirty();
if (v)
{
AvatarEditor.ApplyToCurrent();
}
else
{
AvatarEditor.RestoreOriginals();
}
});
val.CreateBool("Apply on avatar change", Color.white, AutoApply.Value, (Action<bool>)delegate(bool v)
{
AutoApply.Value = v;
Dirty();
});
val.CreateBool("Refresh body after change", Color.white, RigRefresh.Value, (Action<bool>)delegate(bool v)
{
RigRefresh.Value = v;
Dirty();
});
val.CreateFunction("Reset everything", Color.yellow, (Action)ResetAll);
RefreshElements();
}
private static void BuildStatPage(Page parent, int index)
{
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_006e: Unknown result type (might be due to invalid IL or missing references)
//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
Page val = parent.CreatePage(AvatarEditor.Labels[index], Color.white, 0, true);
_rows[index] = (FloatElement[])(object)new FloatElement[Steps.Length];
float num = DisplayValue(index);
for (int i = 0; i < Steps.Length; i++)
{
_rows[index][i] = val.CreateFloat(((int)Steps[i]).ToString(), Color.white, num, Steps[i], -100000f, 100000f, (Action<float>)delegate(float v)
{
OnRowChanged(index, v);
});
}
val.CreateFunction("Set to 1.0", Color.white, (Action)delegate
{
SetValue(index, 1f);
});
val.CreateFunction("Load from avatar's loaded value", Color.white, (Action)delegate
{
LoadOriginal(index);
});
}
private static float DisplayValue(int idx)
{
if (Touched[idx].Value)
{
return Value[idx].Value;
}
float original = AvatarEditor.GetOriginal(idx);
if (!float.IsNaN(original))
{
return original;
}
return Value[idx].Value;
}
private static void SyncRows(int idx, float v)
{
if (_rows[idx] == null)
{
return;
}
bool suppress = _suppress;
_suppress = true;
try
{
for (int i = 0; i < _rows[idx].Length; i++)
{
FloatElement val = _rows[idx][i];
if (val != null && !Mathf.Approximately(val.Value, v))
{
val.Value = v;
}
}
}
finally
{
_suppress = suppress;
}
}
public static void RefreshElements()
{
for (int i = 0; i < 11; i++)
{
SyncRows(i, DisplayValue(i));
}
}
private static void OnRowChanged(int idx, float v)
{
if (!_suppress)
{
Value[idx].Value = v;
Touched[idx].Value = true;
SyncRows(idx, v);
Dirty();
AvatarEditor.ApplyToCurrent();
}
}
private static void SetValue(int idx, float v)
{
Value[idx].Value = v;
Touched[idx].Value = true;
SyncRows(idx, v);
Dirty();
AvatarEditor.ApplyToCurrent();
}
private static void LoadOriginal(int idx)
{
float original = AvatarEditor.GetOriginal(idx);
if (!float.IsNaN(original))
{
Touched[idx].Value = false;
Value[idx].Value = original;
SyncRows(idx, original);
Dirty();
AvatarEditor.ApplyToCurrent();
}
}
private static void ResetAll()
{
for (int i = 0; i < 11; i++)
{
Touched[i].Value = false;
}
Dirty();
AvatarEditor.ApplyToCurrent();
RefreshElements();
}
private static void BuildPresetPage(Page parent, int slot)
{
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_0081: Unknown result type (might be due to invalid IL or missing references)
//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
//IL_00da: Unknown result type (might be due to invalid IL or missing references)
//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
//IL_0114: Unknown result type (might be due to invalid IL or missing references)
Page val = parent.CreatePage("Preset " + (slot + 1), Color.white, 0, true);
_slotNameEdit[slot] = SlotName(slot) ?? ("Preset " + (slot + 1));
_slotInfo[slot] = val.CreateFunction(SlotLabel(slot), Color.gray, (Action)delegate
{
});
val.CreateString("Name", Color.white, _slotNameEdit[slot], (Action<string>)delegate(string v)
{
_slotNameEdit[slot] = v;
});
val.CreateFunction("Save current values here", Color.green, (Action)delegate
{
SavePreset(slot);
});
val.CreateFunction("Load this preset", Color.cyan, (Action)delegate
{
LoadPreset(slot);
});
val.CreateFunction("Clear this slot", Color.red, (Action)delegate
{
ClearPreset(slot);
});
}
private static string SlotName(int s)
{
string value = Slots[s].Value;
if (string.IsNullOrEmpty(value))
{
return null;
}
int num = value.IndexOf('|');
if (num <= 0)
{
return value;
}
return value.Substring(0, num);
}
private static string SlotLabel(int s)
{
string text = SlotName(s);
return "Slot " + (s + 1) + ": " + ((text != null) ? text : "(empty)");
}
private static void SavePreset(int s)
{
string text = (string.IsNullOrWhiteSpace(_slotNameEdit[s]) ? ("Preset " + (s + 1)) : _slotNameEdit[s].Replace("|", " ").Trim());
string[] array = new string[11];
for (int i = 0; i < 11; i++)
{
array[i] = DisplayValue(i).ToString("0.####", CultureInfo.InvariantCulture) + ":" + (Touched[i].Value ? "1" : "0");
}
Slots[s].Value = text + "|" + string.Join(";", array);
Dirty();
if (_slotInfo[s] != null)
{
((Element)_slotInfo[s]).ElementName = SlotLabel(s) + " (saved)";
}
}
private static void LoadPreset(int s)
{
string value = Slots[s].Value;
if (string.IsNullOrEmpty(value))
{
if (_slotInfo[s] != null)
{
((Element)_slotInfo[s]).ElementName = SlotLabel(s) + " (nothing to load)";
}
return;
}
int num = value.IndexOf('|');
string[] array = ((num >= 0) ? value.Substring(num + 1) : value).Split(';');
for (int i = 0; i < 11 && i < array.Length; i++)
{
string[] array2 = array[i].Split(':');
if (!float.TryParse(array2[0], NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
{
result = 1f;
}
bool value2 = array2.Length > 1 && array2[1] == "1";
Value[i].Value = Mathf.Clamp(result, -100000f, 100000f);
Touched[i].Value = value2;
}
Dirty();
AvatarEditor.ApplyToCurrent();
RefreshElements();
if (_slotInfo[s] != null)
{
((Element)_slotInfo[s]).ElementName = SlotLabel(s) + " (loaded)";
}
}
private static void ClearPreset(int s)
{
Slots[s].Value = "";
Dirty();
if (_slotInfo[s] != null)
{
((Element)_slotInfo[s]).ElementName = SlotLabel(s) + " (cleared)";
}
}
public static void Tick()
{
if (_saveAt > 0f && Time.realtimeSinceStartup >= _saveAt)
{
_saveAt = -1f;
MelonPreferences.Save();
}
}
public static void Dirty()
{
_saveAt = Time.realtimeSinceStartup + 1.5f;
}
}
}