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 BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using HarmonyLib;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem.Collections.Generic;
using Microsoft.CodeAnalysis;
using TMPro;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("MoreSpellSlots")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+a9352b86c54d6fad225c6e20c794c2fa03c16fff")]
[assembly: AssemblyProduct("MoreSpellSlots")]
[assembly: AssemblyTitle("MoreSpellSlots")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.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 MoreSpellSlots
{
internal static class HostConfig
{
private static ConfigFile cfg;
private static string messageName;
private static string[] personal;
private static Dictionary<string, string> whenHostLacksMod;
private static Func<bool> active;
private static HandleNamedMessageDelegate handler;
private static IntPtr registeredOn;
private static float nextSend;
private static float joinedAt;
private static string lastSent;
private static string lastApplied;
private static bool overriding;
private static bool heardFromHost;
private static bool warnedMissing;
private static bool savedFlag;
private static bool savingPersonal;
private static readonly Dictionary<ConfigEntryBase, string> originals = new Dictionary<ConfigEntryBase, string>();
internal static bool FromHost
{
get
{
if (overriding)
{
return heardFromHost;
}
return false;
}
}
internal static void Init(BasePlugin plugin, string guid, string[] personalKeys, Dictionary<string, string> offWithoutHost, Func<bool> isActive = null)
{
cfg = plugin.Config;
messageName = guid + ".HostConfig";
personal = personalKeys ?? Array.Empty<string>();
whenHostLacksMod = offWithoutHost ?? new Dictionary<string, string>();
active = isActive;
cfg.SettingChanged += OnSettingChanged;
plugin.AddComponent<HostConfigRunner>();
}
private static void OnSettingChanged(object sender, SettingChangedEventArgs e)
{
try
{
if (overriding && !savingPersonal && IsPersonal(e.ChangedSetting.Definition))
{
SavePersonal();
}
}
catch
{
}
}
private static string Id(ConfigDefinition d)
{
return d.Section + "." + d.Key;
}
private static bool IsPersonal(ConfigDefinition d)
{
string[] array = personal;
foreach (string text in array)
{
if (text.EndsWith(".*") ? (d.Section == text.Substring(0, text.Length - 2)) : (Id(d) == text))
{
return true;
}
}
return false;
}
internal static void Tick()
{
//IL_007c: Unknown result type (might be due to invalid IL or missing references)
//IL_0082: Expected O, but got Unknown
try
{
NetworkManager singleton = NetworkManager.Singleton;
bool flag = (Object)(object)singleton != (Object)null && singleton.IsListening;
if (!flag || singleton.IsServer || (active != null && !active()))
{
if (overriding)
{
Restore();
}
if (flag && singleton.IsServer)
{
HostTick(singleton);
}
if (!flag)
{
registeredOn = IntPtr.Zero;
}
}
else
{
ClientTick(singleton);
}
}
catch (Exception ex)
{
ManualLogSource log = Plugin.Log;
bool flag2 = default(bool);
BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(15, 1, ref flag2);
if (flag2)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Host settings: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
}
log.LogError(val);
}
}
private static void HostTick(NetworkManager nm)
{
//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
if (Time.unscaledTime < nextSend || nm.CustomMessagingManager == null)
{
return;
}
nextSend = Time.unscaledTime + 1.5f;
List<string> list = new List<string>();
foreach (KeyValuePair<ConfigDefinition, ConfigEntryBase> item in cfg)
{
if (!IsPersonal(item.Key))
{
list.Add(item.Key.Section + "\u001f" + item.Key.Key + "\u001f" + item.Value.GetSerializedValue());
}
}
string text = string.Join("\u001e", list);
FastBufferWriter val = default(FastBufferWriter);
((FastBufferWriter)(ref val))..ctor(text.Length * 2 + 64, (Allocator)2, -1);
try
{
((FastBufferWriter)(ref val)).WriteValueSafe(text, false);
nm.CustomMessagingManager.SendNamedMessageToAll(messageName, val, (NetworkDelivery)4);
}
finally
{
((FastBufferWriter)(ref val)).Dispose();
}
if (text != lastSent)
{
lastSent = text;
Plugin.Log.LogInfo((object)"Sending this game's settings to all players.");
}
}
private static void ClientTick(NetworkManager nm)
{
//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
//IL_00e2: Expected O, but got Unknown
CustomMessagingManager customMessagingManager = nm.CustomMessagingManager;
if (customMessagingManager != null && registeredOn != ((Il2CppObjectBase)customMessagingManager).Pointer)
{
if (handler == null)
{
handler = DelegateSupport.ConvertDelegate<HandleNamedMessageDelegate>((Delegate)new Action<ulong, FastBufferReader>(OnReceived));
}
customMessagingManager.RegisterNamedMessageHandler(messageName, handler);
registeredOn = ((Il2CppObjectBase)customMessagingManager).Pointer;
}
if (!overriding)
{
Begin();
joinedAt = Time.unscaledTime;
foreach (KeyValuePair<string, string> item in whenHostLacksMod)
{
Set(item.Key, item.Value);
}
}
if (!heardFromHost && !warnedMissing && Time.unscaledTime - joinedAt > 15f)
{
warnedMissing = true;
ManualLogSource log = Plugin.Log;
bool flag = default(bool);
BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(88, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("No settings from the host: the host doesn't seem to have ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("MoreSpellSlots");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", so it stays off in this game.");
}
log.LogWarning(val);
}
}
private static void OnReceived(ulong sender, FastBufferReader reader)
{
//IL_00da: Unknown result type (might be due to invalid IL or missing references)
//IL_00e1: Expected O, but got Unknown
//IL_009a: Unknown result type (might be due to invalid IL or missing references)
//IL_00a1: Expected O, but got Unknown
//IL_0060: Unknown result type (might be due to invalid IL or missing references)
//IL_0067: Expected O, but got Unknown
bool flag = default(bool);
try
{
string text = default(string);
((FastBufferReader)(ref reader)).ReadValueSafe(ref text, false);
if (!overriding)
{
Begin();
}
heardFromHost = true;
if (text == lastApplied)
{
return;
}
lastApplied = text;
int num = 0;
string[] array = text.Split('\u001e');
for (int i = 0; i < array.Length; i++)
{
string[] array2 = array[i].Split('\u001f');
if (array2.Length == 3)
{
ConfigDefinition d = new ConfigDefinition(array2[0], array2[1]);
if (!IsPersonal(d) && Set(Id(d), array2[2]))
{
num++;
}
}
}
ManualLogSource log = Plugin.Log;
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(36, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Using the host's settings (");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(num);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" values).");
}
log.LogInfo(val);
}
catch (Exception ex)
{
ManualLogSource log2 = Plugin.Log;
BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(25, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Host settings (receive): ");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex.Message);
}
log2.LogError(val2);
}
}
private static void Begin()
{
overriding = true;
heardFromHost = false;
warnedMissing = false;
lastApplied = null;
savedFlag = cfg.SaveOnConfigSet;
cfg.SaveOnConfigSet = false;
}
private static bool Set(string id, string value)
{
foreach (KeyValuePair<ConfigDefinition, ConfigEntryBase> item in cfg)
{
if (!(Id(item.Key) != id))
{
ConfigEntryBase value2 = item.Value;
if (!originals.ContainsKey(value2))
{
originals[value2] = value2.GetSerializedValue();
}
if (value2.GetSerializedValue() != value)
{
value2.SetSerializedValue(value);
}
return true;
}
}
return false;
}
private static void SavePersonal()
{
savingPersonal = true;
Dictionary<ConfigEntryBase, string> dictionary = new Dictionary<ConfigEntryBase, string>();
try
{
foreach (KeyValuePair<ConfigEntryBase, string> original in originals)
{
dictionary[original.Key] = original.Key.GetSerializedValue();
original.Key.SetSerializedValue(original.Value);
}
cfg.Save();
}
finally
{
foreach (KeyValuePair<ConfigEntryBase, string> item in dictionary)
{
try
{
item.Key.SetSerializedValue(item.Value);
}
catch
{
}
}
savingPersonal = false;
}
}
private static void Restore()
{
foreach (KeyValuePair<ConfigEntryBase, string> original in originals)
{
try
{
original.Key.SetSerializedValue(original.Value);
}
catch
{
}
}
originals.Clear();
overriding = false;
heardFromHost = false;
lastApplied = null;
cfg.SaveOnConfigSet = savedFlag;
try
{
cfg.Save();
}
catch
{
}
Plugin.Log.LogInfo((object)"Left the game; back to this computer's own settings.");
}
}
public class HostConfigRunner : MonoBehaviour
{
public HostConfigRunner(IntPtr ptr)
: base(ptr)
{
}
private void Update()
{
HostConfig.Tick();
}
}
[HarmonyPatch]
internal static class HostSettings
{
private const string MessageName = "girthy_mods.MoreSpellSlots.Settings";
private static HandleNamedMessageDelegate handler;
private static Dictionary<string, string> synced;
internal static bool Enabled
{
get
{
if (synced == null || !synced.TryGetValue("Enabled", out var value) || !bool.TryParse(value, out var result))
{
return Plugin.Enabled.Value;
}
return result;
}
}
internal static int ExtraSlots
{
get
{
if (!Enabled)
{
return 0;
}
return Math.Clamp(Int("ExtraSlots", Plugin.ExtraSlots.Value), 0, 6);
}
}
internal static int LevelsBetween => Math.Max(1, Int("LevelsBetween", Plugin.LevelsBetween.Value));
internal static int FirstExtraLevel => Math.Max(0, Int("FirstExtraLevel", Plugin.FirstExtraLevel.Value));
private static int Int(string key, int local)
{
if (synced == null || !synced.TryGetValue(key, out var value) || !int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result))
{
return local;
}
return result;
}
[HarmonyPatch(typeof(RunManager), "OnNetworkSpawn")]
[HarmonyPostfix]
private static void Listen()
{
//IL_0060: Unknown result type (might be due to invalid IL or missing references)
//IL_0066: Expected O, but got Unknown
try
{
NetworkManager singleton = NetworkManager.Singleton;
if (!((Object)(object)singleton == (Object)null) && !singleton.IsServer && singleton.CustomMessagingManager != null)
{
if (handler == null)
{
handler = DelegateSupport.ConvertDelegate<HandleNamedMessageDelegate>((Delegate)new Action<ulong, FastBufferReader>(OnReceived));
}
singleton.CustomMessagingManager.RegisterNamedMessageHandler("girthy_mods.MoreSpellSlots.Settings", handler);
}
}
catch (Exception ex)
{
ManualLogSource log = Plugin.Log;
bool flag = default(bool);
BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(24, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Host settings (listen): ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
}
log.LogError(val);
}
}
private static void OnReceived(ulong sender, FastBufferReader reader)
{
//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
//IL_00a8: Expected O, but got Unknown
//IL_0068: Unknown result type (might be due to invalid IL or missing references)
//IL_006f: Expected O, but got Unknown
bool flag = default(bool);
try
{
string text = default(string);
((FastBufferReader)(ref reader)).ReadValueSafe(ref text, false);
Dictionary<string, string> dictionary = new Dictionary<string, string>();
string[] array = text.Split(';');
foreach (string text2 in array)
{
int num = text2.IndexOf('=');
if (num > 0)
{
dictionary[text2.Substring(0, num)] = text2.Substring(num + 1);
}
}
synced = dictionary;
ManualLogSource log = Plugin.Log;
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(38, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Using the host's spell slot settings: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(text);
}
log.LogInfo(val);
HudPatches.RefreshAll();
}
catch (Exception ex)
{
ManualLogSource log2 = Plugin.Log;
BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(25, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Host settings (receive): ");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<Exception>(ex);
}
log2.LogError(val2);
}
}
[HarmonyPatch(typeof(RunManager), "StartRunOnServerRpc")]
[HarmonyPrefix]
private static void StartRun_Prefix(RunManager __instance, out bool __state)
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Invalid comparison between Unknown and I4
__state = false;
try
{
__state = (int)((NetworkBehaviour)__instance).__rpc_exec_stage == 1;
}
catch
{
}
}
[HarmonyPatch(typeof(RunManager), "StartRunOnServerRpc")]
[HarmonyPostfix]
private static void StartRun_Postfix(bool __state)
{
//IL_010f: Unknown result type (might be due to invalid IL or missing references)
//IL_0116: Expected O, but got Unknown
//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
if (!__state)
{
return;
}
bool value = default(bool);
try
{
NetworkManager singleton = NetworkManager.Singleton;
if ((Object)(object)singleton == (Object)null || !singleton.IsServer || singleton.CustomMessagingManager == null)
{
return;
}
CultureInfo invariantCulture = CultureInfo.InvariantCulture;
string[] array = new string[4];
value = Plugin.Enabled.Value;
array[0] = "Enabled=" + value;
array[1] = "ExtraSlots=" + Plugin.ExtraSlots.Value.ToString(invariantCulture);
array[2] = "LevelsBetween=" + Plugin.LevelsBetween.Value.ToString(invariantCulture);
array[3] = "FirstExtraLevel=" + Plugin.FirstExtraLevel.Value.ToString(invariantCulture);
string text = string.Join(";", array);
FastBufferWriter val = default(FastBufferWriter);
((FastBufferWriter)(ref val))..ctor(Encoding.UTF8.GetByteCount(text) * 2 + 64, (Allocator)2, -1);
try
{
((FastBufferWriter)(ref val)).WriteValueSafe(text, false);
singleton.CustomMessagingManager.SendNamedMessageToAll("girthy_mods.MoreSpellSlots.Settings", val, (NetworkDelivery)4);
}
finally
{
((FastBufferWriter)(ref val)).Dispose();
}
}
catch (Exception ex)
{
ManualLogSource log = Plugin.Log;
BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(22, 1, ref value);
if (value)
{
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Host settings (send): ");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<Exception>(ex);
}
log.LogError(val2);
}
}
[HarmonyPatch(typeof(RunManager), "OnDestroy")]
[HarmonyPostfix]
private static void Clear()
{
synced = null;
}
}
[HarmonyPatch]
internal static class HudPatches
{
private sealed class State
{
public GameObject Template;
public int BaseCount;
public float Step;
public float Y;
public readonly List<Vector2> BasePos = new List<Vector2>();
public RectTransform Avoid;
public Vector2 AvoidSize;
public int LaidOutFor = -1;
}
private const float MaxRowWidth = 1600f;
private static readonly Dictionary<IntPtr, State> states = new Dictionary<IntPtr, State>();
private static float nextErrorLog;
private static bool Alive(Object o)
{
if (o != null && !((Il2CppObjectBase)o).WasCollected)
{
return o != (Object)null;
}
return false;
}
[HarmonyPatch(typeof(SpellSlotsDisplay), "SetSlotsForMaxAmountOfSpells")]
[HarmonyPostfix]
private static void SetSlots_Postfix(SpellSlotsDisplay __instance)
{
Ensure(__instance);
}
[HarmonyPatch(typeof(SpellSlotsDisplay), "OnSpellEquipped")]
[HarmonyPrefix]
private static void SpellEquipped_Prefix(SpellSlotsDisplay __instance)
{
Ensure(__instance);
}
[HarmonyPatch(typeof(SpellSlotsDisplay), "AssureSpellsEarlierGrantedIsShown")]
[HarmonyPostfix]
private static void EarlierGranted_Postfix(SpellSlotsDisplay __instance)
{
Ensure(__instance);
}
internal static void RefreshAll()
{
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_004a: Expected O, but got Unknown
try
{
foreach (SpellSlotsDisplay item in Object.FindObjectsOfType<SpellSlotsDisplay>())
{
if (Alive((Object)(object)item))
{
Ensure(item, reshow: true);
}
}
}
catch (Exception ex)
{
ManualLogSource log = Plugin.Log;
bool flag = default(bool);
BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(19, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Spell bar refresh: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
}
log.LogError(val);
}
}
private static void Ensure(SpellSlotsDisplay display, bool reshow = false)
{
//IL_0240: Unknown result type (might be due to invalid IL or missing references)
//IL_0247: Expected O, but got Unknown
try
{
if (!Alive((Object)(object)display))
{
return;
}
SpellSlotLayout activeLayout = display.activeLayout;
if (!Alive((Object)(object)activeLayout))
{
return;
}
List<SpellSlot> slots = activeLayout.slots;
if (slots == null || slots.Count == 0)
{
return;
}
if (!states.TryGetValue(((Il2CppObjectBase)activeLayout).Pointer, out var value) || !Alive((Object)(object)value.Template))
{
if (slots.Count < 2)
{
return;
}
value = Capture(activeLayout, slots);
if (value == null)
{
return;
}
states[((Il2CppObjectBase)activeLayout).Pointer] = value;
}
int num = 0;
try
{
num = display.GetEquippedSpells()?.Count ?? 0;
}
catch
{
}
int num2 = ((value.BaseCount >= 4 && StorePatches.NormalSpellCount() >= 4) ? HostSettings.ExtraSlots : 0);
int num3 = Math.Max(value.BaseCount + num2, Math.Min(num, value.BaseCount + 6));
bool flag = false;
while (slots.Count < num3)
{
GameObject val = Object.Instantiate<GameObject>(value.Template, value.Template.transform.parent);
((Object)val).name = $"SpellSlot{slots.Count + 1}";
val.SetActive(true);
SpellSlot component = val.GetComponent<SpellSlot>();
if ((Object)(object)component == (Object)null)
{
Object.Destroy((Object)(object)val);
break;
}
try
{
component.isStatApplicableChecker = slots[0].isStatApplicableChecker;
}
catch
{
}
slots.Add(component);
flag = true;
}
while (slots.Count > num3 && slots.Count > value.BaseCount)
{
SpellSlot val2 = slots[slots.Count - 1];
slots.RemoveAt(slots.Count - 1);
if (Alive((Object)(object)val2))
{
Object.Destroy((Object)(object)((Component)val2).gameObject);
}
flag = true;
}
if (flag || value.LaidOutFor != slots.Count)
{
Arrange(value, slots);
}
Label(value, slots, num);
if (!(flag || reshow) || num <= 0)
{
return;
}
try
{
display.ShowSpells(display.GetEquippedSpells());
}
catch
{
}
}
catch (Exception ex)
{
if (!(Time.unscaledTime < nextErrorLog))
{
nextErrorLog = Time.unscaledTime + 10f;
ManualLogSource log = Plugin.Log;
bool flag2 = default(bool);
BepInExErrorLogInterpolatedStringHandler val3 = new BepInExErrorLogInterpolatedStringHandler(11, 1, ref flag2);
if (flag2)
{
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Spell bar: ");
((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<Exception>(ex);
}
log.LogError(val3);
}
}
}
private static State Capture(SpellSlotLayout layout, List<SpellSlot> slots)
{
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
//IL_0143: Unknown result type (might be due to invalid IL or missing references)
//IL_0148: Unknown result type (might be due to invalid IL or missing references)
State state = new State
{
BaseCount = slots.Count
};
for (int i = 0; i < slots.Count; i++)
{
RectTransform component = ((Component)slots[i]).GetComponent<RectTransform>();
if ((Object)(object)component == (Object)null)
{
return null;
}
state.BasePos.Add(component.anchoredPosition);
}
state.Step = Math.Abs(state.BasePos[state.BaseCount - 1].x - state.BasePos[state.BaseCount - 2].x);
if (state.Step < 50f)
{
state.Step = 228f;
}
state.Y = state.BasePos[state.BaseCount - 1].y;
GameObject gameObject = ((Component)slots[state.BaseCount - 1]).gameObject;
state.Template = Object.Instantiate<GameObject>(gameObject, gameObject.transform.parent);
state.Template.SetActive(false);
((Object)state.Template).name = "MoreSpellSlots_Template";
Transform val = ((Component)layout).transform.Find("AvoidanceRect");
if ((Object)(object)val != (Object)null)
{
state.Avoid = ((Component)val).GetComponent<RectTransform>();
if ((Object)(object)state.Avoid != (Object)null)
{
state.AvoidSize = state.Avoid.sizeDelta;
}
}
try
{
TMP_Text spellSlotLevelText = slots[state.BaseCount - 1].spellSlotLevelText;
if ((Object)(object)spellSlotLevelText != (Object)null && int.TryParse(spellSlotLevelText.text?.Trim(), out var result) && result > 0)
{
StorePatches.HudHint = result;
}
}
catch
{
}
return state;
}
private static void Arrange(State st, List<SpellSlot> slots)
{
//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
//IL_0129: 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_002f: Unknown result type (might be due to invalid IL or missing references)
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
int num = (st.LaidOutFor = slots.Count);
if (num <= st.BaseCount)
{
for (int i = 0; i < num && i < st.BasePos.Count; i++)
{
RectTransform component = ((Component)slots[i]).GetComponent<RectTransform>();
component.anchoredPosition = st.BasePos[i];
((Transform)component).localScale = Vector3.one;
}
if ((Object)(object)st.Avoid != (Object)null)
{
st.Avoid.sizeDelta = st.AvoidSize;
}
return;
}
float num2 = Mathf.Min(1f, 1600f / ((float)num * st.Step));
float num3 = st.Step * num2;
for (int j = 0; j < num; j++)
{
RectTransform component2 = ((Component)slots[j]).GetComponent<RectTransform>();
component2.anchoredPosition = new Vector2(((float)j - (float)(num - 1) / 2f) * num3, st.Y);
((Transform)component2).localScale = new Vector3(num2, num2, 1f);
}
if ((Object)(object)st.Avoid != (Object)null)
{
st.Avoid.sizeDelta = new Vector2(st.AvoidSize.x * ((float)num * num3) / ((float)st.BaseCount * st.Step), st.AvoidSize.y);
}
}
private static void Label(State st, List<SpellSlot> slots, int equipped)
{
if (slots.Count <= st.BaseCount)
{
return;
}
try
{
TMP_Text spellSlotLevelText = slots[st.BaseCount - 1].spellSlotLevelText;
if ((Object)(object)spellSlotLevelText != (Object)null && int.TryParse(spellSlotLevelText.text?.Trim(), out var result) && result > 0)
{
StorePatches.HudHint = result;
}
}
catch
{
}
List<int> list = StorePatches.ExtraLevels();
for (int i = st.BaseCount; i < slots.Count; i++)
{
if (i < equipped)
{
continue;
}
int num = i - st.BaseCount;
try
{
TMP_Text spellSlotLevelText2 = slots[i].spellSlotLevelText;
if (!((Object)(object)spellSlotLevelText2 == (Object)null))
{
string text = ((num < list.Count) ? list[num].ToString() : "");
if (spellSlotLevelText2.text != text)
{
spellSlotLevelText2.SetText(text);
}
}
}
catch
{
}
}
}
}
[HarmonyPatch]
internal static class Owed
{
private const string MessageName = "girthy_mods.MoreSpellSlots.Owed";
private static HandleNamedMessageDelegate handler;
private static IntPtr registeredOn;
private static List<ulong> hostOwed;
private static bool storeSeenOpen;
private static float offeredAt;
private static float nextCheck;
private static float runSeenAt = -1f;
private static int lastLevel;
private static float armedUntil;
private static float levelChangedAt;
private static float nextLevelLook;
private static IntPtr runPtr;
private static readonly Dictionary<ulong, (int count, float since)> stable = new Dictionary<ulong, (int, float)>();
private static HashSet<ulong> local;
private static bool localWaitingShown;
private static float localSince;
internal const string SpecialStoreFlag = "girthy_mods.SpecialStore";
private static StoreManager store;
private static StoreManager Store
{
get
{
if (!Alive((Object)(object)store))
{
store = Object.FindObjectOfType<StoreManager>();
}
return store;
}
}
internal static bool ForceSpellShop
{
get
{
if (local != null)
{
return local.Contains(Me());
}
return false;
}
}
private static void SetFlag(bool on)
{
try
{
AppDomain.CurrentDomain.SetData("girthy_mods.SpecialStore", on ? ((object)Time.realtimeSinceStartup) : null);
}
catch
{
}
}
private static bool FlagSet()
{
try
{
return AppDomain.CurrentDomain.GetData("girthy_mods.SpecialStore") is float num && Time.realtimeSinceStartup - num < 180f;
}
catch
{
return false;
}
}
private static bool Alive(Object o)
{
if (o != null && !((Il2CppObjectBase)o).WasCollected)
{
return o != (Object)null;
}
return false;
}
private static ulong Me()
{
try
{
return NetworkManager.Singleton.LocalClientId;
}
catch
{
return ulong.MaxValue;
}
}
internal static void Tick()
{
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Expected O, but got Unknown
Listen();
LocalTick();
try
{
HostTick();
}
catch (Exception ex)
{
ManualLogSource log = Plugin.Log;
bool flag = default(bool);
BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(13, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Owed spells: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
}
log.LogError(val);
nextCheck = Time.unscaledTime + 10f;
}
}
private static bool StoreBusy(StoreManager s)
{
try
{
return s.showStoresCoroutine != null || s.IsShopPanelActive || s.IsExitingStore;
}
catch
{
return true;
}
}
private static void HostTick()
{
//IL_031c: Unknown result type (might be due to invalid IL or missing references)
//IL_0323: Expected O, but got Unknown
NetworkManager singleton = NetworkManager.Singleton;
if ((Object)(object)singleton == (Object)null || !singleton.IsListening || !singleton.IsServer || !HostSettings.Enabled)
{
hostOwed = null;
return;
}
StoreManager val = Store;
if ((Object)(object)val == (Object)null)
{
hostOwed = null;
return;
}
if (((Il2CppObjectBase)val).Pointer != runPtr)
{
runPtr = ((Il2CppObjectBase)val).Pointer;
runSeenAt = Time.unscaledTime;
stable.Clear();
hostOwed = null;
SetFlag(on: false);
lastLevel = 0;
armedUntil = 0f;
}
WatchLevel();
if (hostOwed != null)
{
if (StoreBusy(val))
{
storeSeenOpen = true;
}
else if (storeSeenOpen || Time.unscaledTime - offeredAt > 20f)
{
hostOwed = null;
SetFlag(on: false);
Announce(null);
nextCheck = Time.unscaledTime + 2f;
}
}
else
{
if (Time.unscaledTime >= armedUntil || Time.unscaledTime < nextCheck)
{
return;
}
nextCheck = Time.unscaledTime + 2f;
if (Time.unscaledTime - levelChangedAt < 10f || Time.unscaledTime - runSeenAt < 20f || StoreBusy(val) || Time.timeScale <= 0.01f || FlagSet())
{
return;
}
PartyLevelManager val2 = Object.FindObjectOfType<PartyLevelManager>();
if ((Object)(object)val2 == (Object)null)
{
return;
}
if (StorePatches.Checker == null)
{
try
{
ISpellStoreAvailabilityChecker spellStoreAvailabilityChecker = val.spellStoreAvailabilityChecker;
StorePatches.Checker = ((spellStoreAvailabilityChecker != null) ? ((Il2CppObjectBase)spellStoreAvailabilityChecker).TryCast<SpellStoreAvailabilityChecker>() : null);
}
catch
{
}
}
int num = StorePatches.SpellsEarnedAt(val2.level);
if (num <= 1)
{
return;
}
List<ulong> list = new List<ulong>();
int num2 = 0;
foreach (GameplayPlayerIdentity item in Object.FindObjectsOfType<GameplayPlayerIdentity>())
{
if (!((Object)(object)item == (Object)null) && ((NetworkBehaviour)item).IsSpawned)
{
int valueOrDefault;
try
{
SpellEquipper spellEquipper = item.spellEquipper;
valueOrDefault = ((spellEquipper == null) ? ((int?)null) : spellEquipper.equippedSpells?.Count).GetValueOrDefault();
}
catch
{
continue;
}
(int, float) value;
if (valueOrDefault <= 0)
{
num2++;
}
else if (!stable.TryGetValue(((NetworkBehaviour)item).OwnerClientId, out value) || value.Item1 != valueOrDefault)
{
stable[((NetworkBehaviour)item).OwnerClientId] = (valueOrDefault, Time.unscaledTime);
num2++;
}
else if (Time.unscaledTime - value.Item2 < 8f)
{
num2++;
}
else if (valueOrDefault < num)
{
list.Add(((NetworkBehaviour)item).OwnerClientId);
}
}
}
if (list.Count == 0)
{
if (num2 == 0 && stable.Count > 0)
{
armedUntil = 0f;
Plugin.Log.LogInfo((object)"Everyone has the spells their level has earned.");
}
return;
}
hostOwed = list;
SetFlag(on: true);
storeSeenOpen = false;
offeredAt = Time.unscaledTime;
Announce(list);
ManualLogSource log = Plugin.Log;
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val3 = new BepInExInfoLogInterpolatedStringHandler(62, 3, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Owed spell shop for ");
((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(list.Count);
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" player(s) (party level ");
((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(val2.level);
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(", ");
((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(num);
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" spells earned).");
}
log.LogInfo(val3);
val.OfferStoreToAllPlayers((StoreType)0);
}
}
private static void WatchLevel()
{
//IL_0073: Unknown result type (might be due to invalid IL or missing references)
//IL_0079: Expected O, but got Unknown
if (Time.unscaledTime < nextLevelLook)
{
return;
}
nextLevelLook = Time.unscaledTime + 0.5f;
PartyLevelManager val = Object.FindObjectOfType<PartyLevelManager>();
if ((Object)(object)val == (Object)null)
{
return;
}
int level = val.level;
if (level == lastLevel)
{
return;
}
if (lastLevel > 0 && level - lastLevel >= 2)
{
armedUntil = Time.unscaledTime + 300f;
stable.Clear();
ManualLogSource log = Plugin.Log;
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(71, 2, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Party level jumped ");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(lastLevel);
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" -> ");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(level);
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" (resumed save): checking for spells nobody got.");
}
log.LogInfo(val2);
}
lastLevel = level;
levelChangedAt = Time.unscaledTime;
}
[HarmonyPatch(typeof(StoreManager), "PrepareChoosingPlayers")]
[HarmonyPostfix]
private static void PrepareChoosing_Postfix(StoreManager __instance)
{
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: Expected O, but got Unknown
List<ulong> list = hostOwed;
if (list == null)
{
return;
}
try
{
__instance.SetChoosingPlayersRpc(new Il2CppStructArray<ulong>(list.ToArray()));
}
catch (Exception ex)
{
ManualLogSource log = Plugin.Log;
bool flag = default(bool);
BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(24, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Owed spells (choosers): ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
}
log.LogError(val);
}
}
[HarmonyPatch(typeof(StoreManager), "StartCountdown")]
[HarmonyPrefix]
private static bool StartCountdown_Prefix()
{
if (hostOwed == null)
{
return local == null;
}
return false;
}
[HarmonyPatch(typeof(StoreManager), "KickPlayer")]
[HarmonyPrefix]
private static bool Kick_Prefix()
{
if (hostOwed == null)
{
return local == null;
}
return false;
}
[HarmonyPatch(typeof(StoreManager), "ChooseShopItem")]
[HarmonyPrefix]
private static bool Choose_Prefix()
{
if (local != null)
{
return local.Contains(Me());
}
return true;
}
[HarmonyPatch(typeof(StoreManager), "Reroll")]
[HarmonyPrefix]
private static bool Reroll_Prefix()
{
if (local != null)
{
return local.Contains(Me());
}
return true;
}
private static void LocalTick()
{
if (local == null)
{
return;
}
if (Time.unscaledTime - localSince > 120f)
{
local = null;
return;
}
StoreManager val = Store;
if ((Object)(object)val == (Object)null)
{
return;
}
bool flag = false;
try
{
flag = val.IsShopPanelActive;
}
catch
{
}
if (!flag || localWaitingShown || local.Contains(Me()))
{
return;
}
localWaitingShown = true;
try
{
StorePanel storePanel = val.storePanel;
if (storePanel != null)
{
storePanel.SetAsWaitingForOtherPlayers();
}
}
catch
{
}
}
private static void Listen()
{
try
{
NetworkManager singleton = NetworkManager.Singleton;
if ((Object)(object)singleton == (Object)null || !singleton.IsListening || singleton.IsServer || singleton.CustomMessagingManager == null)
{
if ((Object)(object)singleton == (Object)null || !singleton.IsListening)
{
registeredOn = IntPtr.Zero;
}
return;
}
CustomMessagingManager customMessagingManager = singleton.CustomMessagingManager;
if (!(registeredOn == ((Il2CppObjectBase)customMessagingManager).Pointer))
{
if (handler == null)
{
handler = DelegateSupport.ConvertDelegate<HandleNamedMessageDelegate>((Delegate)new Action<ulong, FastBufferReader>(OnMessage));
}
customMessagingManager.RegisterNamedMessageHandler("girthy_mods.MoreSpellSlots.Owed", handler);
registeredOn = ((Il2CppObjectBase)customMessagingManager).Pointer;
}
}
catch
{
}
}
private static void Announce(List<ulong> ids)
{
//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
//IL_00b1: Expected O, but got Unknown
//IL_008c: Unknown result type (might be due to invalid IL or missing references)
SetLocal(ids);
try
{
NetworkManager singleton = NetworkManager.Singleton;
if ((Object)(object)singleton == (Object)null || !singleton.IsServer || singleton.CustomMessagingManager == null)
{
return;
}
string text = ((ids == null) ? "end" : string.Join(",", ids.ConvertAll((ulong i) => i.ToString(CultureInfo.InvariantCulture))));
FastBufferWriter val = default(FastBufferWriter);
((FastBufferWriter)(ref val))..ctor(text.Length * 2 + 64, (Allocator)2, -1);
try
{
((FastBufferWriter)(ref val)).WriteValueSafe(text, false);
singleton.CustomMessagingManager.SendNamedMessageToAll("girthy_mods.MoreSpellSlots.Owed", val, (NetworkDelivery)4);
}
finally
{
((FastBufferWriter)(ref val)).Dispose();
}
}
catch (Exception ex)
{
ManualLogSource log = Plugin.Log;
bool flag = default(bool);
BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(20, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Owed spells (send): ");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex.Message);
}
log.LogError(val2);
}
}
private static void OnMessage(ulong sender, FastBufferReader reader)
{
//IL_006b: Unknown result type (might be due to invalid IL or missing references)
//IL_0072: Expected O, but got Unknown
try
{
string text = default(string);
((FastBufferReader)(ref reader)).ReadValueSafe(ref text, false);
if (text == "end")
{
SetLocal(null);
return;
}
List<ulong> list = new List<ulong>();
string[] array = text.Split(',');
for (int i = 0; i < array.Length; i++)
{
if (ulong.TryParse(array[i], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result))
{
list.Add(result);
}
}
SetLocal(list);
}
catch (Exception ex)
{
ManualLogSource log = Plugin.Log;
bool flag = default(bool);
BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(23, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Owed spells (receive): ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
}
log.LogError(val);
}
}
private static void SetLocal(List<ulong> ids)
{
local = ((ids == null) ? null : new HashSet<ulong>(ids));
localWaitingShown = false;
localSince = Time.unscaledTime;
}
}
public class Runner : MonoBehaviour
{
public Runner(IntPtr ptr)
: base(ptr)
{
}
private void Update()
{
Owed.Tick();
}
}
[BepInPlugin("girthy_mods.MoreSpellSlots", "MoreSpellSlots", "1.1.4")]
public class Plugin : BasePlugin
{
public const string Guid = "girthy_mods.MoreSpellSlots";
public const string Name = "MoreSpellSlots";
public const string Version = "1.1.4";
internal static ManualLogSource Log;
internal static ConfigEntry<bool> Enabled;
internal static ConfigEntry<int> ExtraSlots;
internal static ConfigEntry<int> LevelsBetween;
internal static ConfigEntry<int> FirstExtraLevel;
public override void Load()
{
//IL_0073: Unknown result type (might be due to invalid IL or missing references)
//IL_007d: Expected O, but got Unknown
//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
//IL_00af: Expected O, but got Unknown
//IL_00da: Unknown result type (might be due to invalid IL or missing references)
//IL_00e4: Expected O, but got Unknown
//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
//IL_0103: 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_0123: Unknown result type (might be due to invalid IL or missing references)
//IL_0152: Unknown result type (might be due to invalid IL or missing references)
//IL_0158: Expected O, but got Unknown
Log = ((BasePlugin)this).Log;
HostConfig.Init((BasePlugin)(object)this, "girthy_mods.MoreSpellSlots", Array.Empty<string>(), new Dictionary<string, string> { ["Spell Slots.Enabled"] = "false" });
Enabled = ((BasePlugin)this).Config.Bind<bool>("Spell Slots", "Enabled", true, "Add extra spell slots.");
ExtraSlots = ((BasePlugin)this).Config.Bind<int>("Spell Slots", "ExtraSlots", 2, new ConfigDescription("How many spells you can have on top of the normal 4.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 6), Array.Empty<object>()));
LevelsBetween = ((BasePlugin)this).Config.Bind<int>("Spell Slots", "LevelsBetweenExtraSpells", 6, new ConfigDescription("Party levels between each extra spell shop.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 50), Array.Empty<object>()));
FirstExtraLevel = ((BasePlugin)this).Config.Bind<int>("Spell Slots", "FirstExtraSpellLevel", 0, new ConfigDescription("Party level of the first extra spell shop. 0 = the last normal spell level + LevelsBetweenExtraSpells.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 200), Array.Empty<object>()));
Harmony val = new Harmony("girthy_mods.MoreSpellSlots");
val.PatchAll(typeof(StorePatches));
val.PatchAll(typeof(FifthSpellRarity));
val.PatchAll(typeof(HudPatches));
val.PatchAll(typeof(HostSettings));
val.PatchAll(typeof(Owed));
((BasePlugin)this).AddComponent<Runner>();
ManualLogSource log = Log;
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(8, 2, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>("MoreSpellSlots");
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" ");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>("1.1.4");
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" ready.");
}
log.LogInfo(val2);
}
}
[HarmonyPatch]
internal static class StorePatches
{
private static SpellStoreAvailabilityChecker checker;
private static int lastNormalLevel;
private static readonly HashSet<int> logged = new HashSet<int>();
internal static int HudHint;
internal static SpellStoreAvailabilityChecker Checker
{
get
{
return checker;
}
set
{
checker = value;
}
}
[HarmonyPatch(typeof(SpellStoreAvailabilityChecker), "SpellStoreShouldBeOffered")]
[HarmonyPostfix]
private static void ShouldBeOffered_Postfix(SpellStoreAvailabilityChecker __instance, int partyLevel, ref bool __result)
{
//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
//IL_00d0: Expected O, but got Unknown
//IL_0064: Unknown result type (might be due to invalid IL or missing references)
//IL_006a: Expected O, but got Unknown
bool flag = default(bool);
try
{
checker = __instance;
if (Owed.ForceSpellShop)
{
__result = true;
}
else
{
if (__result || HostSettings.ExtraSlots <= 0 || NormalSpellCount() < 4)
{
return;
}
List<int> list = ExtraLevels();
int num = list.IndexOf(partyLevel);
if (num < 0)
{
return;
}
__result = true;
if (logged.Add(partyLevel))
{
ManualLogSource log = Plugin.Log;
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(48, 3, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Extra spell shop at party level ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(partyLevel);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" (extra slot ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(num + 1);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("/");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(list.Count);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(").");
}
log.LogInfo(val);
}
}
}
catch (Exception ex)
{
ManualLogSource log2 = Plugin.Log;
BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(18, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Spell shop check: ");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<Exception>(ex);
}
log2.LogError(val2);
}
}
[HarmonyPatch(typeof(RunManager), "OnDestroy")]
[HarmonyPostfix]
private static void RunEnded()
{
checker = null;
lastNormalLevel = 0;
logged.Clear();
}
internal static int NormalSpellCount()
{
try
{
SpellStoreAvailabilityChecker val = checker;
if (val != null && !((Il2CppObjectBase)val).WasCollected && val.spellAmountProvider != null)
{
return val.spellAmountProvider.GetAmountOfSpellsForRun();
}
}
catch
{
}
return 4;
}
internal static int LastNormalLevel(int fromHud)
{
try
{
SpellStoreAvailabilityChecker val = checker;
if (val != null && !((Il2CppObjectBase)val).WasCollected)
{
Il2CppStructArray<int> val2 = (val.ShouldUseAdjustedSpellLevels() ? val.adjustedLevels : val.baseLevels);
int num = Math.Min(((Il2CppArrayBase<int>)(object)val2)?.Length ?? 0, NormalSpellCount() - 1);
if (val2 != null && num > 0)
{
int num2 = 0;
for (int i = 0; i < num; i++)
{
num2 = Math.Max(num2, ((Il2CppArrayBase<int>)(object)val2)[i]);
}
if (num2 > 0)
{
lastNormalLevel = num2;
}
}
}
}
catch
{
}
if (lastNormalLevel > 0)
{
return lastNormalLevel;
}
if (fromHud <= 0)
{
return 19;
}
return fromHud;
}
internal static int SpellsEarnedAt(int partyLevel)
{
int num = 1;
try
{
SpellStoreAvailabilityChecker val = checker;
if (val == null || ((Il2CppObjectBase)val).WasCollected)
{
return 0;
}
Il2CppStructArray<int> val2 = (val.ShouldUseAdjustedSpellLevels() ? val.adjustedLevels : val.baseLevels);
int num2 = Math.Min(((Il2CppArrayBase<int>)(object)val2)?.Length ?? 0, NormalSpellCount() - 1);
for (int i = 0; i < num2; i++)
{
if (((Il2CppArrayBase<int>)(object)val2)[i] <= partyLevel)
{
num++;
}
}
}
catch
{
return 0;
}
foreach (int item in ExtraLevels())
{
if (item <= partyLevel)
{
num++;
}
}
return num;
}
internal static List<int> ExtraLevels()
{
int num = ((NormalSpellCount() >= 4) ? HostSettings.ExtraSlots : 0);
int levelsBetween = HostSettings.LevelsBetween;
int num2 = HostSettings.FirstExtraLevel;
int num3 = LastNormalLevel(HudHint);
if (num2 <= num3)
{
num2 = num3 + levelsBetween;
}
List<int> list = new List<int>(num);
for (int i = 0; i < num; i++)
{
list.Add(num2 + i * levelsBetween);
}
return list;
}
}
[HarmonyPatch]
internal static class FifthSpellRarity
{
[HarmonyPatch(typeof(CatchUpImprovementInventoryGenerator), "TryIncreaseMinimumRarityForNewlyEquippedSpell")]
[HarmonyPrefix]
private static void Rarity_Prefix(CatchUpImprovementInventoryGenerator __instance)
{
Trim(__instance);
}
[HarmonyPatch(typeof(CatchUpImprovementInventoryGenerator), "FilterForSpellImprovementAfterEquippingNewSpell")]
[HarmonyPrefix]
private static void Filter_Prefix(CatchUpImprovementInventoryGenerator __instance)
{
Trim(__instance);
}
private static void Trim(CatchUpImprovementInventoryGenerator g)
{
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: Expected O, but got Unknown
try
{
List<SpellType> spellsThatHaveBeenOfferedAnImprovement = g.spellsThatHaveBeenOfferedAnImprovement;
if (spellsThatHaveBeenOfferedAnImprovement != null)
{
int num = (g.shouldOfferImprovementForNewlyEquippedSpell ? 4 : 3);
while (spellsThatHaveBeenOfferedAnImprovement.Count > num)
{
spellsThatHaveBeenOfferedAnImprovement.RemoveAt(0);
}
}
}
catch (Exception ex)
{
ManualLogSource log = Plugin.Log;
bool flag = default(bool);
BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(20, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Spell bonus rarity: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
}
log.LogError(val);
}
}
}
}