Decompiled source of WheelOfWuck v1.0.0
WheelOfWuck.dll
Decompiled 9 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using Febucci.UI; using Febucci.UI.Core; using HarmonyLib; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("WheelOfWuck")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("WheelOfWuck")] [assembly: AssemblyTitle("WheelOfWuck")] [assembly: AssemblyVersion("1.0.0.0")] [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 WheelOfWuck { public class RunRecord { public DateTime ended; public string gamemode; public bool won; public float seconds; public float height; public float score; public List<WheelResult> results; public List<string> route; public List<string> visited; public List<string> offRoute; } public static class History { public static readonly string FilePath = Path.Combine(Paths.ConfigPath, "senkodev.whiteknuckle.wheelofwuck.history.json"); public static void Record(Roll roll, bool won, float seconds, float height, float score) { List<RunRecord> list = ((!File.Exists(FilePath)) ? new List<RunRecord>() : JsonConvert.DeserializeObject<List<RunRecord>>(File.ReadAllText(FilePath))); RunRecord runRecord = null; runRecord = new RunRecord(); runRecord.ended = DateTime.Now; runRecord.gamemode = CL_GameManager.GetBaseGamemode()?.gamemodeName.Trim() ?? roll.gamemode; runRecord.won = won; runRecord.seconds = seconds; runRecord.height = height; runRecord.score = score; runRecord.results = roll.results; runRecord.route = roll.route; runRecord.visited = roll.visited; runRecord.offRoute = roll.offRoute; list.Add(runRecord); string text = ""; text = JsonConvert.SerializeObject((object)list, (Formatting)1); File.WriteAllText(FilePath, text); Plugin.Logger.LogInfo((object)string.Format("run {0} written to the history: {1} after {2:0}s at {3:0}m", list.Count, won ? "won" : "died", seconds, height)); } } public static class MenuHook { public const string ButtonName = "WheelOfWuck_Button"; public static void AddButton(UI_TrinketPicker picker) { //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Expected O, but got Unknown //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Expected O, but got Unknown Transform parent = ((Component)picker.playButton).transform.parent; if (!((Object)(object)parent.Find("WheelOfWuck_Button") != (Object)null)) { GameObject val = Object.Instantiate<GameObject>(((Component)picker.playButton).gameObject, parent); string name = "WheelOfWuck_Button"; ((Object)val).name = name; val.transform.SetSiblingIndex(((Component)picker.playButton).transform.GetSiblingIndex() + 1); UI_FirstSelect[] components = val.GetComponents<UI_FirstSelect>(); for (int i = 0; i < components.Length; i++) { Object.Destroy((Object)(object)components[i]); } Button component = val.GetComponent<Button>(); _ = (Object)(object)component == (Object)null; component.onClick = new ButtonClickedEvent(); ((UnityEvent)component.onClick).AddListener((UnityAction)delegate { Open(picker); }); ((Selectable)component).interactable = true; val.GetComponentInChildren<TMP_Text>(true).text = "The Wheel"; val.SetActive(true); Plugin.Logger.LogInfo((object)("Wheel button added next to Play in " + ((Object)parent).name + ".")); } } private static void Open(UI_TrinketPicker picker) { M_Gamemode mode = Traverse.Create((object)picker).Field("currentGamemode").GetValue<M_Gamemode>(); if ((Object)(object)mode == (Object)null) { mode = CL_GameManager.GetBaseGamemode(); } WheelSet.Load(); WheelUI.Open(WheelSet.Current, mode, (Roll roll) => RunSetup.Apply(roll, mode)); } } [HarmonyPatch(typeof(UI_TrinketPicker), "Initialize")] internal class Patch_TrinketPicker_Initialize { private static void Postfix(UI_TrinketPicker __instance) { RunSetup.RevertOnce(); MenuHook.AddButton(__instance); } } [HarmonyPatch(typeof(UI_GamemodeScreen), "LoadGamemode")] internal class Patch_GamemodeScreen_LoadGamemode { private static bool Prefix(UI_GamemodeScreen __instance) { if (CL_SaveManager.loadSessionSaveOnLoad) { return true; } M_Gamemode value = Traverse.Create((object)__instance).Field("baseGamemode").GetValue<M_Gamemode>(); M_Gamemode val = RunSetup.ChimneyInstead(Roll.Current, value); if ((Object)(object)val == (Object)null) { return true; } Plugin.Logger.LogInfo((object)("the roll says Chimney first, loading the Chimney instead of " + value.gamemodeName.Trim())); CL_GameManager.gamemode = val; SceneManager.LoadScene(val.gamemodeScene); if ((Object)(object)__instance.loadingText != (Object)null) { __instance.loadingText.SetActive(true); } return false; } } [HarmonyPatch(typeof(CL_GameManager), "RestartScene")] internal class Patch_GameManager_RestartScene { private static void Prefix(CL_GameManager __instance) { Roll current = Roll.Current; if (current != null && current.inPlay && current.leg != 0 && current.route.Contains("chimney") && Utils.Same(CL_GameManager.GetBaseGamemode()?.gamemodeName, "Chimney")) { M_Gamemode val = RunSetup.FindGamemode(current.gamemode); if (!((Object)(object)val == (Object)null)) { Plugin.Logger.LogInfo((object)"the Chimney is done, this restart goes to the campaign run"); Traverse.Create((object)__instance).Field("baseGamemode").SetValue((object)val); CL_GameManager.gamemode = val; } } } } [HarmonyPatch(typeof(UI_CloseButtonOnBack), "Update")] internal class Patch_CloseButtonOnBack_Update { private static bool Prefix() { return !WheelUI.IsOpen; } } [HarmonyPatch(typeof(UT_BranchGenerator), "Generate")] internal class Patch_BranchGenerator_Generate { private static void Postfix(UT_BranchGenerator __instance) { if ((Object)(object)RunHud.Instance == (Object)null || __instance.branch == null) { return; } foreach (M_GenerationBranch item in __instance.branch) { if ((Object)(object)item != (Object)null) { RunHud.Instance.BranchTaken(((Object)item).name); } } } } [HarmonyPatch(typeof(UT_ZoneTitler), "Play")] internal class Patch_ZoneTitler_Play { private static void Postfix(UT_ZoneTitler __instance) { if (!((Object)(object)RunHud.Instance == (Object)null)) { RunHud.Instance.Titled(__instance.region, __instance.subRegion); } } } [HarmonyPatch(typeof(StatManager), "LoadStats")] internal class Patch_StatManager_LoadStats { private static void Postfix() { RunSetup.RevertOnce(); } } [HarmonyPatch(typeof(UI_TrinketPicker), "ReloadTrinkets")] internal class Patch_TrinketPicker_ReloadTrinkets { private static void Postfix(UI_TrinketPicker __instance) { MenuHook.AddButton(__instance); } } [HarmonyPatch(typeof(UI_TrinketPicker), "OnEnable")] internal class Patch_TrinketPicker_OnEnable { private static void Postfix(UI_TrinketPicker __instance) { MenuHook.AddButton(__instance); } } [HarmonyPatch(typeof(CL_GameManager))] [HarmonyPatch("Awake")] internal class Patch_GameManager_Awake { public static void Postfix() { Roll current = Roll.Current; if (current != null && !CL_SaveManager.loadSessionSaveOnLoad) { M_Gamemode baseGamemode = CL_GameManager.GetBaseGamemode(); if (!((Object)(object)baseGamemode == (Object)null)) { current.inPlay = current.AppliesTo(baseGamemode) && current.MatchesSave(baseGamemode); current.ResetProgress(); Plugin.Logger.LogInfo((object)(current.inPlay ? "the run uses the roll" : "the run doesn't match the roll, the wheel stays quiet")); } } } } [HarmonyPatch(typeof(M_Gamemode))] [HarmonyPatch("Finish")] internal class Patch_Gamemode_Finish { private static void Postfix(M_Gamemode __instance, float time, bool hasFinished) { Roll current = Roll.Current; if (current != null && current.inPlay && current.AppliesTo(CL_GameManager.GetBaseGamemode())) { History.Record(current, hasFinished, time, CL_GameManager.gMan.GetPlayerBestTravelDistance(), __instance.GetPlayerScore(hasFinished)); bool flag = false; if (hasFinished) { flag = true; } else if (current.ladderLooped && current.Route.Contains("ladder")) { flag = true; Plugin.Logger.LogInfo((object)"the Ladder was looped once, so this death still counts as beating it"); } if (flag && current.LegDone() && current.NextLeg()) { Plugin.Logger.LogInfo((object)string.Format("run {0} of the roll is done, the next run goes {1}", current.leg, string.Join(" > ", current.Route.ConvertAll<string>(Roll.Label)))); } } } } public static class MyPluginInfo { public const string PLUGIN_GUID = "senkodev.whiteknuckle.wheelofwuck"; public const string PLUGIN_NAME = "WheelOfWuck"; public const string PLUGIN_VERSION = "1.0.0"; } public enum HudCorner { TopLeft, TopRight, BottomLeft, BottomRight } [BepInPlugin("senkodev.whiteknuckle.wheelofwuck", "WheelOfWuck", "1.0.0")] public class Plugin : BaseUnityPlugin { internal static ManualLogSource Logger; public static Plugin Instance; private readonly Harmony harmony = new Harmony("senkodev.whiteknuckle.wheelofwuck"); public static ConfigEntry<KeyCode> HudKey; public static ConfigEntry<bool> ShowHud; public static ConfigEntry<HudCorner> HudPosition; public static ConfigEntry<float> HudScale; public static ConfigEntry<float> TickVolume; public static ConfigEntry<bool> RestartOnSkip; public static ConfigEntry<KeyCode> ChimneyStayKey; public static ConfigEntry<KeyCode> ChimneyGoKey; private void Awake() { //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Expected O, but got Unknown //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Expected O, but got Unknown //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Expected O, but got Unknown Logger = ((BaseUnityPlugin)this).Logger; Instance = this; HudKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("General", "HudKey", (KeyCode)289, "Shows or hides the panel during a wheel run."); ShowHud = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShowHud", true, "Show the wheel results during the run."); HudPosition = ((BaseUnityPlugin)this).Config.Bind<HudCorner>("General", "HudPosition", HudCorner.TopRight, "Corner of the screen for the results."); HudScale = ((BaseUnityPlugin)this).Config.Bind<float>("General", "HudScale", 0.75f, new ConfigDescription("Size of the results panel.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 1f), Array.Empty<object>())); TickVolume = ((BaseUnityPlugin)this).Config.Bind<float>("General", "TickVolume", 0.6f, new ConfigDescription("Volume of the ticking when the wheel spins.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); ChimneyStayKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("General", "ChimneyStayKey", (KeyCode)284, "After a loop of the Chimney: keep climbing."); ChimneyGoKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("General", "ChimneyGoKey", (KeyCode)287, "After a loop of the Chimney: end the run so the score counts, then Restart goes to the campaign run."); RestartOnSkip = ((BaseUnityPlugin)this).Config.Bind<bool>("General.Toggles", "RestartOnSkip", true, "Restart the run as soon as a shortcut the wheel picked can't be reached any more."); WheelSet.Load(); WheelPicks.Load(); Roll.Load(); harmony.PatchAll(); GameObject val = null; val = new GameObject("WheelOfWuck"); if ((Object)(object)val != (Object)null) { ((Object)val).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)(object)val); val.AddComponent<RunHud>(); } Logger.LogInfo((object)"Plugin senkodev.whiteknuckle.wheelofwuck is loaded!"); } } public class WheelResult { public string id; public string title; public List<string> winners = new List<string>(); } public class Roll { public static readonly string FilePath = Path.Combine(Paths.ConfigPath, "senkodev.whiteknuckle.wheelofwuck.roll.json"); public static Roll Current; public DateTime rolledAt; public string gamemode; public List<WheelResult> results = new List<WheelResult>(); public Dictionary<string, bool> settings = new Dictionary<string, bool>(); public List<string> trinkets = new List<string>(); public List<string> route = new List<string>(); public List<string> notes = new List<string>(); public List<string> visited = new List<string>(); public List<string> offRoute = new List<string>(); public List<string> skipped = new List<string>(); public List<List<string>> legs = new List<List<string>>(); public int leg; public List<string> activeSettings = new List<string>(); public List<string> activeTrinkets = new List<string>(); public List<string> beforeSettings; public List<string> beforeTrinkets; public List<string> chimneySettings = new List<string>(); public List<string> beforeChimneySettings; public List<string> beforeChimneyTrinkets; public bool chimneyLooped; public bool ladderLooped; public bool inPlay; private static readonly List<string> climbOrder = new List<string> { "chimney", "sink", "chute", "duct", "ladder", "diver", "hotzone", "infested" }; private static Dictionary<string, string[]> skipPoints = new Dictionary<string, string[]> { { "sink", new string[1] { "Deep Storage" } }, { "chute", new string[3] { "Drainage System", "Waste Heap", "Pipe Organ" } }, { "duct", new string[3] { "title:Service Shaft", "M3_Habitation_Shaft_0*", "M3_Habitation_Shaft_To_Pier" } }, { "ladder", new string[2] { "M3_Habitation_Lab_Ending", "abyss" } }, { "diver", new string[1] { "transit-scaffolds" } }, { "hotzone", new string[1] { "infested" } } }; private static Dictionary<string, string> routeKeys = new Dictionary<string, string> { { "sink", "sink" }, { "chute", "chute" }, { "ladder", "ladder" }, { "rotten-duct", "duct" }, { "hadal-diver", "diver" }, { "hotzone", "hotzone" }, { "infestedlabs", "infested" }, { "chimney", "chimney" } }; private static Dictionary<string, string> routeLabels = new Dictionary<string, string> { { "sink", "Sink" }, { "chute", "Chute" }, { "ladder", "Ladder" }, { "duct", "Duct" }, { "diver", "Diver" }, { "hotzone", "Hot Zone" }, { "infested", "Infested Labs" }, { "chimney", "Chimney" } }; private static Dictionary<string, string> routeUnlocks = new Dictionary<string, string> { { "sink", "unlockedsink" }, { "chute", "chutedoorunlocked" }, { "duct", "hasvisited-deadmans-handle" }, { "diver", "hadaldiverunlocked" } }; [JsonIgnore] public List<string> Route { get { if (legs.Count == 0) { return route; } return legs[Math.Min(leg, legs.Count - 1)]; } } public static void Load() { if (!File.Exists(FilePath)) { return; } Current = JsonConvert.DeserializeObject<Roll>(File.ReadAllText(FilePath)); if (Current != null) { Current.route = InClimbOrder(Current.route); for (int i = 0; i < Current.legs.Count; i++) { Current.legs[i] = InClimbOrder(Current.legs[i]); } } } private static int Rank(string key) { int num = climbOrder.IndexOf(key); if (num == -1) { num = 99; } return num; } public static List<string> InClimbOrder(List<string> keys) { List<string> list = new List<string>(); list.AddRange(keys); list.Sort((string a, string b) => Rank(a) - Rank(b)); return list; } public void Save() { File.WriteAllText(FilePath, JsonConvert.SerializeObject((object)this, (Formatting)1)); } public void PlanLegs() { legs.Clear(); leg = 0; List<string> list = new List<string>(route); list.Remove("chimney"); if (route.Contains("chimney")) { legs.Add(new List<string> { "chimney" }); } if (list.Contains("hotzone") && list.Contains("ladder")) { List<string> list2 = new List<string>(list); list2.Remove("hotzone"); legs.Add(list2); legs.Add(new List<string> { "hotzone" }); } else if (legs.Count > 0) { legs.Add(list); } } public bool LegDone() { bool flag = true; foreach (string item in Route) { if (!(item == "chimney") && !visited.Contains(item)) { flag = false; } } if (flag) { return true; } return false; } public bool NextLeg() { if (leg >= legs.Count - 1) { return false; } leg++; ResetProgress(); return true; } public bool HasRoute(string key) { return route.Contains(key); } public bool AppliesTo(M_Gamemode mode) { if (Utils.Same(mode.gamemodeName, gamemode)) { return true; } if (route.Contains("chimney") && Utils.Same(mode.gamemodeName, "Chimney")) { return true; } return false; } public bool MatchesSave(M_Gamemode mode) { SaveData saveData = StatManager.saveData; List<string> collection = saveData.GetGameMode(mode.gamemodeName)?.activeSettings ?? new List<string>(); List<string> list = (Utils.Same(mode.gamemodeName, "Chimney") ? chimneySettings : activeSettings); if (!new HashSet<string>(collection).SetEquals(list)) { return false; } return new HashSet<string>(saveData.GetGamemodeTrinkets(mode.GetGamemodeName(true))).SetEquals(activeTrinkets); } public void ResetProgress() { visited.Clear(); offRoute.Clear(); skipped.Clear(); chimneyLooped = false; ladderLooped = false; Save(); } public bool Visit(string key) { if (key == null) { return false; } if (visited.Contains(key)) { return false; } visited.Add(key); if ((!(key == "infested")) ? (!Route.Contains(key)) : Route.Contains("hotzone")) { offRoute.Add(key); } Save(); return true; } public List<string> Arrive(string place) { List<string> list = new List<string>(); if (place == null) { return list; } foreach (string item in Route) { if (!skipPoints.TryGetValue(item, out var value)) { continue; } bool flag = false; string[] array = value; foreach (string text in array) { flag = ((!text.EndsWith("*")) ? Utils.Same(text, place) : place.StartsWith(text.TrimEnd('*'), StringComparison.OrdinalIgnoreCase)); if (flag) { break; } } if (flag && !visited.Contains(item) && !skipped.Contains(item)) { skipped.Add(item); list.Add(item); } } if (list.Count > 0) { Save(); } return list; } public static string Label(string key) { if (routeLabels.TryGetValue(key, out var value)) { return value; } return key; } public static bool RouteUnlocked(string key) { if (key == "chimney") { return RunSetup.GamemodeUnlocked(RunSetup.FindGamemode("Chimney")); } if (!routeUnlocks.TryGetValue(key, out var value)) { return true; } return StatManager.saveData.GetFlag(value)?.value ?? false; } public static string RouteKey(string regionName, string subregionName, string gamemodeName) { if (gamemodeName == "Ladder") { return "ladder"; } if (regionName != null && routeKeys.TryGetValue(regionName, out var value)) { return value; } if (subregionName != null && routeKeys.TryGetValue(subregionName, out value)) { return value; } return null; } } public class RunHud : MonoBehaviour { public static RunHud Instance; private GameObject canvas; private GameObject notice; private CanvasGroup noticeGroup; private bool restarting; private int asked; private bool inLoopRoom; private bool asking; private TextMeshProUGUI text; private HudCorner builtCorner; private float builtScale; private CL_GameManager seenManager; private static string Compose(Roll roll) { List<string> list = new List<string>(); list.Add("<b><color=#EEB211>WHEEL OF WUCK</color></b>"); foreach (WheelResult result in roll.results) { if (result.winners.Count <= 0) { continue; } string text = ""; foreach (string winner in result.winners) { if (text != "") { text += ", "; } text += winner; } list.Add("<color=#AAAAAA>" + result.title + ":</color> " + text); } if (roll.legs.Count > 1) { for (int i = 0; i < roll.legs.Count; i++) { List<string> list2 = new List<string>(); foreach (string item in roll.legs[i]) { string text2 = ((i < roll.leg) ? "#55DD55" : ((i > roll.leg) ? "#777777" : (roll.visited.Contains(item) ? "#55DD55" : (roll.skipped.Contains(item) ? "#FF5555" : "#FFFFFF")))); list2.Add("<color=" + text2 + ">" + Roll.Label(item) + "</color>"); } string text3 = ((i == roll.leg) ? ("<color=#EEB211>Run " + (i + 1) + ":</color>") : ("<color=#AAAAAA>Run " + (i + 1) + ":</color>")); if (list2.Count == 0) { list2.Add((i < roll.leg) ? "<color=#55DD55>Campaign</color>" : ((i > roll.leg) ? "<color=#777777>Campaign</color>" : "<color=#FFFFFF>Campaign</color>")); } list.Add(text3 + " " + string.Join(" > ", list2)); } } else if (roll.Route.Count > 0) { List<string> list3 = new List<string>(); foreach (string item2 in roll.Route) { string text4 = (roll.visited.Contains(item2) ? "#55DD55" : (roll.skipped.Contains(item2) ? "#FF5555" : "#FFFFFF")); list3.Add("<color=" + text4 + ">" + Roll.Label(item2) + "</color>"); } list.Add("<color=#AAAAAA>Path:</color> " + string.Join(" > ", list3)); } if (roll.offRoute.Count > 0) { list.Add("<color=#FF5555>Off route: " + string.Join(", ", roll.offRoute.ConvertAll<string>(Roll.Label)) + "</color>"); } return string.Join("\n", list); } private void Awake() { Instance = this; } private void Update() { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) Roll current = Roll.Current; if (asking && ((Object)(object)CL_GameManager.gMan != (Object)(object)seenManager || !CL_GameManager.IsInGame())) { asked = 1; } seenManager = CL_GameManager.gMan; int num; if (current != null && current.inPlay && CL_GameManager.IsInGame()) { num = (current.AppliesTo(CL_GameManager.GetBaseGamemode()) ? 1 : 0); if (num != 0 && Input.GetKeyDown(Plugin.HudKey.Value)) { Plugin.ShowHud.Value = !Plugin.ShowHud.Value; } } else { num = 0; } if (num != 0) { Track(current); } if ((Object)(object)notice != (Object)null && asked == 0 && (Object)(object)noticeGroup != (Object)null && noticeGroup.alpha > 0.9f && !restarting) { if (Input.GetKeyDown(Plugin.ChimneyStayKey.Value)) { asked = 1; } if (Input.GetKeyDown(Plugin.ChimneyGoKey.Value)) { asked = 2; } } if (num == 0 || !Plugin.ShowHud.Value) { if ((Object)(object)canvas != (Object)null) { canvas.SetActive(false); } return; } if ((Object)(object)canvas == (Object)null || builtCorner != Plugin.HudPosition.Value || builtScale != Plugin.HudScale.Value) { Build(); } canvas.SetActive(!CL_GameManager.gMan.isPaused && !OS_Manager.inUse); string text = Compose(current); if (((TMP_Text)this.text).text != text) { ((TMP_Text)this.text).text = text; Transform parent = ((Transform)((TMP_Text)this.text).rectTransform).parent; LayoutRebuilder.ForceRebuildLayoutImmediate((RectTransform)(object)((parent is RectTransform) ? parent : null)); } } private void Build() { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown //IL_007f: 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_00db: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0118: 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_0148: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)canvas != (Object)null) { Object.Destroy((Object)(object)canvas); } builtCorner = Plugin.HudPosition.Value; builtScale = Plugin.HudScale.Value; canvas = new GameObject("WheelOfWuck_Hud"); Canvas obj = canvas.AddComponent<Canvas>(); obj.renderMode = (RenderMode)0; obj.sortingOrder = 100; CanvasScaler obj2 = canvas.AddComponent<CanvasScaler>(); obj2.uiScaleMode = (ScaleMode)1; obj2.referenceResolution = new Vector2(1920f, 1080f); obj2.matchWidthOrHeight = 0.5f; bool flag = builtCorner == HudCorner.TopRight || builtCorner == HudCorner.BottomRight; bool flag2 = builtCorner == HudCorner.TopLeft || builtCorner == HudCorner.TopRight; GameObject val = new GameObject("Panel", new Type[1] { typeof(RectTransform) }); RectTransform component = val.GetComponent<RectTransform>(); ((Transform)component).SetParent(canvas.transform, false); Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor((float)(flag ? 1 : 0), (float)(flag2 ? 1 : 0)); component.pivot = val2; Vector2 anchorMin = (component.anchorMax = val2); component.anchorMin = anchorMin; component.sizeDelta = new Vector2(320f, 100f); component.anchoredPosition = new Vector2((float)(flag ? (-24) : 24), (float)(flag2 ? (-24) : 24)); ((Transform)component).localScale = Vector3.one * builtScale; val.AddComponent<ContentSizeFitter>().verticalFit = (FitMode)2; VerticalLayoutGroup obj3 = val.AddComponent<VerticalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)obj3).childForceExpandHeight = false; ((HorizontalOrVerticalLayoutGroup)obj3).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)obj3).childControlWidth = true; text = new GameObject("Text", new Type[1] { typeof(RectTransform) }).AddComponent<TextMeshProUGUI>(); ((Transform)((TMP_Text)text).rectTransform).SetParent((Transform)(object)component, false); ((TMP_Text)text).rectTransform.sizeDelta = new Vector2(320f, 80f); ((TMP_Text)text).font = Utils.GetFont(); ((TMP_Text)text).fontSize = 14f; ((TMP_Text)text).alignment = (TextAlignmentOptions)(flag ? 260 : 257); ((Graphic)text).raycastTarget = false; } private void Track(Roll roll) { if ((Object)(object)WorldLoader.instance == (Object)null) { return; } Traverse obj = Traverse.Create((object)WorldLoader.instance); string text = obj.Field("currentRegion").GetValue<M_Region>()?.regionName; string text2 = obj.Field("currentSubregion").GetValue<M_Subregion>()?.subregionName; LevelInfo currentLevel = WorldLoader.instance.GetCurrentLevel(); string text3 = ((currentLevel == null) ? null : currentLevel.GetLevel()?.levelName); string text4 = Roll.RouteKey(text, text2, CL_GameManager.GetCurrentGamemode()?.gamemodeName); if (roll.Visit(text4)) { Plugin.Logger.LogInfo((object)("entered " + Roll.Label(text4) + (roll.offRoute.Contains(text4) ? " (off route)" : ""))); } Skipped(roll, roll.Arrive(text)); Skipped(roll, roll.Arrive(text2)); Skipped(roll, roll.Arrive(text3)); if (text4 != null) { Skipped(roll, roll.Arrive(text4)); } bool flag = text3 != null && text3.StartsWith("MX_Chimney_LoopRoom") && roll.route.Contains("chimney"); if (flag && !inLoopRoom) { if (!roll.chimneyLooped) { roll.chimneyLooped = true; roll.Save(); Plugin.Logger.LogInfo((object)"one loop of the Chimney is done"); roll.NextLeg(); } else { Plugin.Logger.LogInfo((object)"another loop of the Chimney is done"); } if (!asking) { ((MonoBehaviour)this).StartCoroutine(AskAfterLoop(roll)); } } inLoopRoom = flag; if (text3 != null && text3.StartsWith("M3_Habitation_LadderWarp_Loop") && roll.Route.Contains("ladder") && !roll.ladderLooped) { roll.ladderLooped = true; roll.Save(); Plugin.Logger.LogInfo((object)"one loop of the Ladder is done, dying from here still counts as beating it"); ((MonoBehaviour)this).StartCoroutine(Flash("ONE LOOP OF THE LADDER DONE.\n<size=60%>Walk out to end the run or keep climbing - this run counts as complete either way.</size>")); } } private IEnumerator AskAfterLoop(Roll roll) { asking = true; asked = 0; Notice("ONE LOOP OF THE CHIMNEY DONE.\n<size=60%>" + ((object)Plugin.ChimneyStayKey.Value/*cast due to .constrained prefix*/).ToString() + ": keep climbing " + ((object)Plugin.ChimneyGoKey.Value/*cast due to .constrained prefix*/).ToString() + ": end the run here and proceed to the campaign</size>"); yield return Fade(0f, 1f, 0.5f); while (asked == 0) { yield return null; } yield return Fade(1f, 0f, 0.5f); if ((Object)(object)notice != (Object)null) { Object.Destroy((Object)(object)notice); } if (asked == 2 && (Object)(object)CL_GameManager.gMan != (Object)null && CL_GameManager.IsInGame() && (Object)(object)ENT_Player.playerObject != (Object)null) { Plugin.Logger.LogInfo((object)"ending the Chimney run so the score counts, Restart goes to the campaign"); ((GameEntity)ENT_Player.playerObject).Kill("", (DamageInfo)null); } asked = 0; asking = false; } private IEnumerator Flash(string message) { Notice(message); yield return Fade(0f, 1f, 0.5f); yield return (object)new WaitForSecondsRealtime(5f); yield return Fade(1f, 0f, 0.8f); if ((Object)(object)notice != (Object)null) { Object.Destroy((Object)(object)notice); } } public void BranchTaken(string branchName) { Roll current = Roll.Current; if (current == null || !current.inPlay) { return; } string text = null; branchName = branchName ?? ""; if (branchName.Contains("TangledSink")) { text = "sink"; } else if (branchName.Contains("ExpulsionChute")) { text = "chute"; } else if (branchName.Contains("RottenDuct")) { text = "duct"; } else if (branchName.Contains("HadalDiver")) { text = "diver"; } else if (branchName.Contains("Ladder")) { text = "ladder"; } else if (branchName.Contains("Nest_HotZone")) { text = "hotzone"; } else if (branchName.Contains("InfestedLabs")) { text = "infested"; } if (text != null) { Plugin.Logger.LogInfo((object)("the game is building the " + Roll.Label(text) + " (" + branchName + ")")); if (current.Visit(text)) { Plugin.Logger.LogInfo((object)("entered " + Roll.Label(text) + (current.offRoute.Contains(text) ? " (off route)" : ""))); } if (text == "infested") { Skipped(current, current.Arrive("infested")); } } } public void Titled(string region, string subregion) { Roll current = Roll.Current; if (current != null && current.inPlay) { Plugin.Logger.LogInfo((object)("area title: " + region + " / " + subregion)); Skipped(current, current.Arrive("title:" + subregion)); Skipped(current, current.Arrive("title:" + region)); } } public void Skipped(Roll roll, List<string> keys) { if (keys.Count == 0) { return; } string text = ""; for (int i = 0; i < keys.Count; i++) { if (i > 0) { text += " and the "; } text += Roll.Label(keys[i]); } Plugin.Logger.LogInfo((object)("skipped the " + text)); if (Plugin.RestartOnSkip.Value && !restarting) { ((MonoBehaviour)this).StartCoroutine(Restart(text)); } } private IEnumerator Restart(string names) { restarting = true; Notice("YOU SKIPPED THE " + names.ToUpperInvariant() + ".\n<size=60%>The wheel restarts the run.</size>"); yield return Fade(0f, 1f, 0.5f); yield return (object)new WaitForSecondsRealtime(3.7f); yield return Fade(1f, 0f, 0.8f); if ((Object)(object)CL_GameManager.gMan != (Object)null && CL_GameManager.IsInGame()) { Plugin.Logger.LogInfo((object)"restarting the run"); AccessTools.Method(typeof(CL_SaveManager), "DeleteSessionSave", (Type[])null, (Type[])null).Invoke(null, new object[2] { CL_GameManager.GetGamemodeName(false, true), CL_GameManager.IsHardmode() }); CL_SaveManager.isSavedRun = false; CL_GameManager.ChangeState("restart"); } yield return (object)new WaitForSecondsRealtime(1.5f); if ((Object)(object)notice != (Object)null) { Object.Destroy((Object)(object)notice); } restarting = false; } private IEnumerator Fade(float from, float to, float seconds) { for (float t = 0f; t < seconds; t += Time.unscaledDeltaTime) { if (!((Object)(object)noticeGroup != (Object)null)) { break; } noticeGroup.alpha = Mathf.SmoothStep(from, to, t / seconds); yield return null; } if ((Object)(object)noticeGroup != (Object)null) { noticeGroup.alpha = to; } } private void Notice(string message) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)notice != (Object)null && Object.op_Implicit((Object)(object)notice)) { Object.Destroy((Object)(object)notice); } notice = new GameObject("WheelOfWuck_Notice"); Object.DontDestroyOnLoad((Object)(object)notice); Canvas obj = notice.AddComponent<Canvas>(); obj.renderMode = (RenderMode)0; obj.sortingOrder = 101; noticeGroup = notice.AddComponent<CanvasGroup>(); noticeGroup.alpha = 0f; CanvasScaler obj2 = notice.AddComponent<CanvasScaler>(); obj2.uiScaleMode = (ScaleMode)1; obj2.referenceResolution = new Vector2(1920f, 1080f); obj2.matchWidthOrHeight = 0.5f; TextMeshProUGUI obj3 = new GameObject("Text", new Type[1] { typeof(RectTransform) }).AddComponent<TextMeshProUGUI>(); ((Transform)((TMP_Text)obj3).rectTransform).SetParent(notice.transform, false); ((TMP_Text)obj3).rectTransform.sizeDelta = new Vector2(1400f, 200f); ((TMP_Text)obj3).rectTransform.anchoredPosition = new Vector2(0f, 280f); ((TMP_Text)obj3).font = Utils.GetFont("Ticketing SDF GreyGlow"); ((TMP_Text)obj3).fontSize = 48f; ((Graphic)obj3).color = Utils.Hex("#FF2F39"); ((TMP_Text)obj3).alignment = (TextAlignmentOptions)514; ((Graphic)obj3).raycastTarget = false; ((TMP_Text)obj3).text = message; } } public static class RunSetup { public static bool didRevert; public static List<string> Apply(Roll roll, M_Gamemode mode) { List<string> list = new List<string>(); string gamemodeName = mode.gamemodeName; SaveData saveData = StatManager.saveData; saveData.SetupGamemode(gamemodeName); Roll current = Roll.Current; if (current != null && current.beforeSettings != null && Utils.Same(current.gamemode, gamemodeName) && current.MatchesSave(mode)) { roll.beforeSettings = current.beforeSettings; roll.beforeTrinkets = current.beforeTrinkets; } else { roll.beforeSettings = new List<string>(saveData.GetGameMode(gamemodeName).activeSettings); roll.beforeTrinkets = new List<string>(saveData.GetGamemodeTrinkets(mode.GetGamemodeName(true))); } foreach (string clearSetting in WheelSet.Current.clearSettings) { saveData.SetSetting(gamemodeName, clearSetting, false); } foreach (KeyValuePair<string, bool> setting in roll.settings) { GamemodeSetting val = FindSetting(mode, setting.Key); if ((Object)(object)val == (Object)null) { list.Add(gamemodeName.Trim() + " has no setting called " + setting.Key + "."); continue; } if (setting.Value && !SettingUnlocked(val)) { list.Add(val.title + " is still locked"); saveData.SetSetting(gamemodeName, val.id, false); continue; } saveData.SetSetting(gamemodeName, val.id, setting.Value); if (!setting.Value) { continue; } foreach (string exclusiveSetting in val.exclusiveSettings) { saveData.SetSetting(gamemodeName, exclusiveSetting, false); } } List<string> list2 = new List<string>(); int num = 1; foreach (string trinket in roll.trinkets) { Trinket val2 = FindTrinket(mode, trinket); if ((Object)(object)val2 == (Object)null) { list.Add(trinket + " is not offered in " + gamemodeName.Trim() + "."); } else if (val2.comingSoon || !val2.IsUnlocked()) { list.Add(val2.title + " is still locked."); } else if (val2.settingBlacklist.Exists((Predicate<string>)mode.HasActiveSetting)) { list.Add(val2.title + " can't be used with the chosen settings."); } else if (!list2.Contains(((Object)val2).name)) { list2.Add(((Object)val2).name); num += (val2.isBinding ? val2.cost : (-val2.cost)); } } if (num < 0) { list?.Add("Too expensive! Take off some trinkets before playing the run."); } saveData.SetGamemodeTrinkets(mode.GetGamemodeName(true), list2); roll.gamemode = gamemodeName; roll.activeSettings = new List<string>(saveData.GetGameMode(gamemodeName).activeSettings); roll.activeTrinkets = list2; roll.chimneySettings = new List<string>(); if (roll.route.Contains("chimney")) { M_Gamemode val3 = FindGamemode("Chimney"); if ((Object)(object)val3 == (Object)null) { list.Add("The Chimney gamemode was not found, so the run stays in the campaign."); } else if (!GamemodeUnlocked(val3)) { list.Add("The Chimney is not unlocked yet, so the run stays in the campaign."); } else { string gamemodeName2 = val3.gamemodeName; saveData.SetupGamemode(gamemodeName2); if (current == null || current.beforeChimneyTrinkets == null || !current.route.Contains("chimney") || !current.MatchesSave(val3)) { roll.beforeChimneySettings = new List<string>(saveData.GetGameMode(gamemodeName2).activeSettings); roll.beforeChimneyTrinkets = new List<string>(saveData.GetGamemodeTrinkets(val3.GetGamemodeName(true))); } else { roll.beforeChimneySettings = current.beforeChimneySettings; roll.beforeChimneyTrinkets = current.beforeChimneyTrinkets; } foreach (string clearSetting2 in WheelSet.Current.clearSettings) { saveData.SetSetting(gamemodeName2, clearSetting2, false); } foreach (KeyValuePair<string, bool> setting2 in roll.settings) { GamemodeSetting val4 = FindSetting(val3, setting2.Key); if (!((Object)(object)val4 == (Object)null) && (!setting2.Value || SettingUnlocked(val4))) { saveData.SetSetting(gamemodeName2, val4.id, setting2.Value); } } saveData.SetGamemodeTrinkets(val3.GetGamemodeName(true), new List<string>(list2)); roll.chimneySettings = new List<string>(saveData.GetGameMode(gamemodeName2).activeSettings); } } roll.ResetProgress(); Roll.Current = roll; roll.Save(); RefreshMenus(mode); StatManager.instance.SaveStats(true); Plugin.Logger.LogInfo((object)("rolled " + gamemodeName.Trim() + ": route [" + string.Join(" > ", roll.route) + "], trinkets [" + string.Join(", ", list2) + "], settings [" + string.Join(", ", roll.activeSettings) + "]")); return list; } public static void RevertOnce() { if (didRevert) { return; } Roll roll = Roll.Current; if (roll == null || roll.beforeSettings == null || StatManager.saveData == null || CL_GameManager.IsInGame()) { return; } M_Gamemode val = Array.Find(Resources.FindObjectsOfTypeAll<M_Gamemode>(), (M_Gamemode m) => Utils.Same(m.gamemodeName, roll.gamemode)); if ((Object)(object)val == (Object)null) { return; } didRevert = true; if (!roll.MatchesSave(val)) { Plugin.Logger.LogInfo((object)"the menu was changed since the roll, leaving it alone"); return; } SaveData saveData = StatManager.saveData; foreach (GamemodeSetting gamemodeSetting in val.gamemodeSettings) { saveData.SetSetting(val.gamemodeName, gamemodeSetting.id, roll.beforeSettings.Contains(gamemodeSetting.id)); } saveData.SetGamemodeTrinkets(val.GetGamemodeName(true), new List<string>(roll.beforeTrinkets)); M_Gamemode val2 = ((roll.route.Contains("chimney") && roll.beforeChimneyTrinkets != null) ? FindGamemode("Chimney") : null); if ((Object)(object)val2 != (Object)null && roll.MatchesSave(val2)) { foreach (GamemodeSetting gamemodeSetting2 in val2.gamemodeSettings) { saveData.SetSetting(val2.gamemodeName, gamemodeSetting2.id, roll.beforeChimneySettings.Contains(gamemodeSetting2.id)); } saveData.SetGamemodeTrinkets(val2.GetGamemodeName(true), new List<string>(roll.beforeChimneyTrinkets)); } RefreshMenus(val); StatManager.instance.SaveStats(true); Plugin.Logger.LogInfo((object)"put the menu back the way it was before the wheel, the last roll is still on the wheel"); } private static void RefreshMenus(M_Gamemode mode) { //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) UI_GamemodeSetting[] array = Resources.FindObjectsOfTypeAll<UI_GamemodeSetting>(); foreach (UI_GamemodeSetting val in array) { Scene scene = ((Component)val).gameObject.scene; if (((Scene)(ref scene)).name != null) { val.toggle.SetIsOnWithoutNotify(StatManager.saveData.IsSettingActive(mode.gamemodeName, val.gamemodeSetting.id)); Traverse.Create((object)val).Method("UpdateColor", Array.Empty<object>()).GetValue(); } } UI_GamemodeScreen instance = UI_GamemodeScreen.instance; if ((Object)(object)instance != (Object)null && ((Component)instance).gameObject.activeInHierarchy && (Object)(object)instance.GetGamemode() == (Object)(object)mode) { instance.RefreshCurrentGamemode(); } UI_TrinketPicker[] array2 = Object.FindObjectsOfType<UI_TrinketPicker>(); for (int i = 0; i < array2.Length; i++) { array2[i].ReloadTrinkets(); } SettingsManager.RefreshSettings(""); } public static M_Gamemode FindGamemode(string name) { M_Gamemode[] array = Resources.FindObjectsOfTypeAll<M_Gamemode>(); foreach (M_Gamemode val in array) { if (Utils.Same(val.gamemodeName, name)) { return val; } } return null; } public static bool GamemodeUnlocked(M_Gamemode mode) { if ((Object)(object)mode == (Object)null) { return false; } if (mode.unlockAchievement == null || mode.unlockAchievement == "") { return true; } return CL_AchievementManager.GetAchievementValue(mode.unlockAchievement); } public static M_Gamemode ChimneyInstead(Roll roll, M_Gamemode mode) { if (roll == null || (Object)(object)mode == (Object)null) { return null; } if (!Utils.Same(mode.gamemodeName, roll.gamemode)) { return null; } if (!roll.Route.Contains("chimney")) { return null; } M_Gamemode val = FindGamemode("Chimney"); if ((Object)(object)val == (Object)null || !GamemodeUnlocked(val) || !roll.MatchesSave(val)) { return null; } return val; } public static Trinket FindTrinket(M_Gamemode mode, string name) { List<Trinket> list = new List<Trinket>(mode.availableTrinkets.trinkets); list.AddRange(mode.availableTrinkets.bindings); return list.Find((Trinket t) => Utils.Same(((Object)t).name, name) || Utils.Same(t.title, name)); } public static GamemodeSetting FindSetting(M_Gamemode mode, string id) { return mode.gamemodeSettings.Find((GamemodeSetting s) => Utils.Same(s.id, id)); } public static bool SettingUnlocked(GamemodeSetting setting) { if ((Object)(object)setting.unlock == (Object)null) { return true; } return setting.unlock.CheckUnlock(); } } public static class Utils { private static TMP_FontAsset _font; private static Dictionary<string, TMP_FontAsset> fonts = new Dictionary<string, TMP_FontAsset>(); private static Dictionary<string, Sprite> sprites = new Dictionary<string, Sprite>(); public static bool Same(string a, string b) { if (a == null || b == null) { if (a == null && b == null) { return true; } return false; } string a2 = a.Trim(); string b2 = b.Trim(); if (string.Equals(a2, b2, StringComparison.OrdinalIgnoreCase)) { return true; } return false; } public static TMP_FontAsset GetFont() { if ((Object)(object)_font != (Object)null) { return _font; } TMP_FontAsset[] array = Resources.FindObjectsOfTypeAll<TMP_FontAsset>(); foreach (TMP_FontAsset val in array) { if (((Object)val).name == "Ticketing SDF Smooth") { _font = val; break; } } if ((Object)(object)_font == (Object)null) { _font = TMP_Settings.defaultFontAsset; } return _font; } public static TMP_FontAsset GetFont(string name) { if (fonts.TryGetValue(name, out var value) && (Object)(object)value != (Object)null) { return value; } TMP_FontAsset[] array = Resources.FindObjectsOfTypeAll<TMP_FontAsset>(); foreach (TMP_FontAsset val in array) { if (((Object)val).name == name) { value = val; break; } } if ((Object)(object)value == (Object)null) { value = GetFont(); } fonts[name] = value; return value; } public static Sprite GetSprite(string name) { if (sprites.TryGetValue(name, out var value) && (Object)(object)value != (Object)null) { return value; } Sprite[] array = Resources.FindObjectsOfTypeAll<Sprite>(); foreach (Sprite val in array) { if (((Object)val).name == name) { value = val; break; } } if ((Object)(object)value == (Object)null) { Plugin.Logger.LogWarning((object)("no sprite called " + name)); } sprites[name] = value; return value; } public static string OneLine(string s) { return s.Replace("\n", " ").Trim(); } public static Color Hex(string hex) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) Color magenta = Color.magenta; if (!ColorUtility.TryParseHtmlString(hex, ref magenta)) { magenta = Color.magenta; } return magenta; } } public static class WheelLogic { public static List<(WheelDef wheel, EntryDef entry)> wins = new List<(WheelDef, EntryDef)>(); private static Random rng = new Random(); public static int SpinsFor(WheelDef wheel) { if (int.TryParse(wheel.spins, out var result)) { return result; } int num = 0; for (int i = 0; i < wins.Count; i++) { if (wins[i].wheel.id == wheel.spins) { num += wins[i].entry.count; } } return num; } public static int Slack(M_Gamemode mode) { int num = 1; for (int i = 0; i < wins.Count; i++) { (WheelDef, EntryDef) tuple = wins[i]; if (!string.IsNullOrEmpty(tuple.Item2.trinket)) { Trinket val = RunSetup.FindTrinket(mode, tuple.Item2.trinket); if (!((Object)(object)val == (Object)null)) { int cost = val.cost; num = ((!val.isBinding) ? (num - cost) : (num + cost)); } } } return num; } public static List<EntryDef> Live(WheelDef wheel, M_Gamemode mode) { List<EntryDef> list = new List<EntryDef>(); int num = Slack(mode); foreach (EntryDef entry in wheel.entries) { if (!WheelPicks.IsEnabled(wheel, entry) || entry.weight <= 0f || (wheel.unique && wins.Any(((WheelDef wheel, EntryDef entry) w) => w.wheel == wheel && w.entry == entry))) { continue; } if (!string.IsNullOrEmpty(entry.trinket)) { Trinket val = RunSetup.FindTrinket(mode, entry.trinket); if ((Object)(object)val != (Object)null && !val.isBinding && num - val.cost < 0) { Plugin.Logger.LogInfo((object)(entry.text + " stays off the " + wheel.title + " wheel: not enough bindings to afford it")); continue; } } string text = Locked(entry, mode); if (text != null) { Plugin.Logger.LogInfo((object)$"{entry.text} stays off the {wheel.title} wheel: {text}"); } else { list.Add(entry); } } return list; } public static string Locked(EntryDef entry, M_Gamemode mode) { if (!string.IsNullOrEmpty(entry.trinket)) { Trinket val = RunSetup.FindTrinket(mode, entry.trinket); if ((Object)(object)val == (Object)null) { return mode.gamemodeName + " offers no trinket or binding called " + entry.trinket; } if (val.comingSoon || !val.IsUnlocked()) { return val.title + " is not unlocked yet"; } } if (entry.settings != null) { foreach (KeyValuePair<string, bool> setting in entry.settings) { GamemodeSetting val2 = RunSetup.FindSetting(mode, setting.Key); if ((Object)(object)val2 == (Object)null) { return mode.gamemodeName + " has no setting called " + setting.Key; } if (setting.Value && !RunSetup.SettingUnlocked(val2)) { return val2.title + " is not unlocked yet"; } } } if (entry.route != null) { foreach (string item in entry.route) { if (!Roll.RouteUnlocked(item)) { return "the " + Roll.Label(item) + " is not unlocked yet"; } } } return null; } public static EntryDef Pick(List<EntryDef> live) { double num = 0.0; int count = live.Count; for (int i = 0; i < count; i++) { num += (double)live[i].weight; } double num2 = rng.NextDouble() * num; foreach (EntryDef item in live) { num2 -= (double)item.weight; if (num2 < 0.0) { return item; } } return live[live.Count - 1]; } public static Roll BuildRoll(List<WheelResult> results) { Roll roll = new Roll(); roll.rolledAt = DateTime.Now; roll.results = results; foreach (var win in wins) { EntryDef item = win.entry; if (item.settings != null) { foreach (KeyValuePair<string, bool> setting in item.settings) { roll.settings[setting.Key] = setting.Value; } } if (item.route != null) { foreach (string item2 in item.route) { if (!roll.route.Contains(item2)) { roll.route.Add(item2); } } } if (!string.IsNullOrEmpty(item.trinket) && !roll.trinkets.Contains(item.trinket)) { roll.trinkets.Add(item.trinket); } if (!string.IsNullOrEmpty(item.note)) { roll.notes.Add(item.note); } } roll.route = Roll.InClimbOrder(roll.route); roll.PlanLegs(); if (roll.legs.Count > 1) { List<string> list = new List<string>(); foreach (List<string> leg in roll.legs) { list.Add((leg.Count == 0) ? "the campaign" : string.Join(" > ", leg.ConvertAll<string>(Roll.Label))); } roll.notes.Add(list.Count + " runs: " + string.Join(", then ", list) + "."); } return roll; } } public class WheelPicks { public static readonly string FilePath = Path.Combine(Paths.ConfigPath, "senkodev.whiteknuckle.wheelofwuck.picks.json"); public static WheelPicks Current = new WheelPicks(); public Dictionary<string, Dictionary<string, bool>> enabled = new Dictionary<string, Dictionary<string, bool>>(); public static void Load() { if (!File.Exists(FilePath)) { return; } try { Current = JsonConvert.DeserializeObject<WheelPicks>(File.ReadAllText(FilePath)) ?? new WheelPicks(); } catch (Exception ex) { Plugin.Logger.LogWarning((object)("could not read " + FilePath + ", using the wheel defaults: " + ex.Message)); Current = new WheelPicks(); } } public void Save() { File.WriteAllText(FilePath, JsonConvert.SerializeObject((object)this, (Formatting)1)); } public static bool IsEnabled(WheelDef wheel, EntryDef entry) { if (Current.enabled.TryGetValue(wheel.id, out var value) && value.TryGetValue(entry.text, out var value2)) { return value2; } return entry.enabled; } public static void Set(WheelDef wheel, EntryDef entry, bool on) { if (!Current.enabled.TryGetValue(wheel.id, out var value)) { value = new Dictionary<string, bool>(); Current.enabled[wheel.id] = value; } if (on == entry.enabled) { value.Remove(entry.text); } else { value[entry.text] = on; } if (value.Count == 0) { Current.enabled.Remove(wheel.id); } Current.Save(); } public static void Clear() { Current.enabled.Clear(); Current.Save(); } } public class WheelSet { public static readonly string FilePath = Path.Combine(Paths.ConfigPath, "senkodev.whiteknuckle.wheelofwuck.wheels.json"); public static WheelSet Current; private static DateTime loadedAt; public string title = "Wheel of Wuck"; public List<string> colors = new List<string> { "#3369E8", "#D50F25", "#EEB211", "#009925" }; public List<string> clearSettings = new List<string> { "ironknuckle", "competitive" }; public List<WheelDef> wheels = new List<WheelDef>(); public static void Load() { if (!File.Exists(FilePath)) { try { File.WriteAllText(FilePath, Default()); } catch { } } DateTime lastWriteTimeUtc = File.GetLastWriteTimeUtc(FilePath); if (Current != null && lastWriteTimeUtc == loadedAt) { return; } loadedAt = lastWriteTimeUtc; try { Current = JsonConvert.DeserializeObject<WheelSet>(File.ReadAllText(FilePath)); } catch (Exception ex) { Plugin.Logger.LogWarning((object)("could not read " + FilePath + ", using the shipped wheels: " + ex.Message)); Current = JsonConvert.DeserializeObject<WheelSet>(Default()); } } private static string Default() { using StreamReader streamReader = new StreamReader(typeof(WheelSet).Assembly.GetManifestResourceStream("wheels.json")); return streamReader.ReadToEnd(); } } public class WheelDef { public string id; public string title; public string spins = "1"; public bool unique = true; public List<EntryDef> entries = new List<EntryDef>(); } [JsonObject(/*Could not decode attribute arguments.*/)] public class EntryDef { public string text; public float weight = 1f; public bool enabled = true; public Dictionary<string, bool> settings; public List<string> route; public string trinket; [JsonProperty(/*Could not decode attribute arguments.*/)] public int count; public string note; } public class WheelSettings : MonoBehaviour { private static readonly Color Box = Utils.Hex("#FF7800"); private static readonly Color Faded = Utils.Hex("#A66922"); private static readonly Color Grey = Utils.Hex("#575757"); private WheelSet set; private M_Gamemode mode; private Action onClose; public List<Toggle> toggles = new List<Toggle>(); public List<(WheelDef wheel, EntryDef entry)> rows = new List<(WheelDef, EntryDef)>(); private bool _built; private AudioClip tickOn; private AudioClip tickOff; private TextMeshProUGUI hint; private const string HintText = "Tick what can land on each wheel."; public static WheelSettings Current { get; private set; } public static bool IsOpen => (Object)(object)Current != (Object)null; public static void Open(Transform parent, WheelSet set, M_Gamemode mode, Action onClose) { //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_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004c: 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) if (!((Object)(object)Current != (Object)null)) { RectTransform obj = WheelUI.Rect("Settings", parent, Vector2.zero, Vector2.zero); obj.anchorMin = Vector2.zero; obj.anchorMax = Vector2.one; obj.offsetMin = Vector2.zero; obj.offsetMax = Vector2.zero; Current = ((Component)obj).gameObject.AddComponent<WheelSettings>(); Current.set = set; Current.mode = mode; Current.onClose = onClose; Current.Build(); Current._built = true; } } public void Close() { Object.Destroy((Object)(object)((Component)this).gameObject); onClose?.Invoke(); } public void Defaults() { if ((Object)(object)tickOff != (Object)null) { AudioManager.PlayUISound(tickOff, 0.8f, 1f); } WheelPicks.Clear(); int count = toggles.Count; for (int i = 0; i < count; i++) { bool enabled = rows[i].entry.enabled; Toggle obj = toggles[i]; obj.SetIsOnWithoutNotify(enabled); Tint(obj, enabled); } } private void OnDestroy() { if ((Object)(object)Current == (Object)(object)this) { Current = null; } } private void Build() { //IL_0087: 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_00b6: 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_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_010e: 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_0152: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Expected O, but got Unknown //IL_02c8: Unknown result type (might be due to invalid IL or missing references) //IL_02cd: Unknown result type (might be due to invalid IL or missing references) //IL_02e8: Unknown result type (might be due to invalid IL or missing references) //IL_0330: Unknown result type (might be due to invalid IL or missing references) //IL_0335: Unknown result type (might be due to invalid IL or missing references) //IL_034e: Unknown result type (might be due to invalid IL or missing references) //IL_0387: Unknown result type (might be due to invalid IL or missing references) //IL_038c: Unknown result type (might be due to invalid IL or missing references) //IL_03c3: Unknown result type (might be due to invalid IL or missing references) //IL_03d8: Unknown result type (might be due to invalid IL or missing references) //IL_03e7: Unknown result type (might be due to invalid IL or missing references) //IL_03f1: Expected O, but got Unknown //IL_0480: Unknown result type (might be due to invalid IL or missing references) //IL_0485: Unknown result type (might be due to invalid IL or missing references) //IL_0491: Unknown result type (might be due to invalid IL or missing references) //IL_0496: Unknown result type (might be due to invalid IL or missing references) //IL_04c3: Unknown result type (might be due to invalid IL or missing references) //IL_04c8: Unknown result type (might be due to invalid IL or missing references) //IL_04d4: Unknown result type (might be due to invalid IL or missing references) //IL_04d9: Unknown result type (might be due to invalid IL or missing references) Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(0.5f, 1f); AudioClip[] array = Resources.FindObjectsOfTypeAll<AudioClip>(); foreach (AudioClip val2 in array) { if (((Object)val2).name == "mbutton4") { tickOn = val2; } if (((Object)val2).name == "mbutton5") { tickOff = val2; } } ((Graphic)WheelUI.Fill("Dim", ((Component)this).transform, new Color(0f, 0f, 0f, 0.6f))).raycastTarget = true; Transform parent = WheelUI.Panel("Panel", ((Component)this).transform, new Vector2(1100f, 920f), Vector2.zero, "WHEEL SETTINGS", Utils.Hex("#606060"), Utils.Hex("#959595")); hint = WheelUI.Text("Hint", parent, new Vector2(1000f, 30f), new Vector2(0f, -54f), "Tick what can land on each wheel.", 18f, (TextAlignmentOptions)514, WheelUI.Dim, val); ((TMP_Text)hint).font = Utils.GetFont("Ticketing SDF"); RectTransform val3 = WheelUI.Rect("View", parent, new Vector2(1040f, 740f), new Vector2(0f, -90f), val); ((Graphic)((Component)val3).gameObject.AddComponent<Image>()).color = new Color(0f, 0f, 0f, 0.45f); ((Component)val3).gameObject.AddComponent<RectMask2D>(); RectTransform val4 = WheelUI.Rect("Content", (Transform)(object)val3, Vector2.zero, Vector2.zero, val); val4.anchorMin = new Vector2(0f, 1f); val4.anchorMax = new Vector2(1f, 1f); val4.pivot = val; val4.sizeDelta = Vector2.zero; VerticalLayoutGroup obj = ((Component)val4).gameObject.AddComponent<VerticalLayoutGroup>(); ((LayoutGroup)obj).padding = new RectOffset(16, 16, 6, 10); ((HorizontalOrVerticalLayoutGroup)obj).spacing = 4f; ((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = true; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = false; ((Component)val4).gameObject.AddComponent<ContentSizeFitter>().verticalFit = (FitMode)2; ScrollRect obj2 = ((Component)val3).gameObject.AddComponent<ScrollRect>(); obj2.content = val4; obj2.horizontal = false; obj2.vertical = true; obj2.movementType = (MovementType)2; obj2.scrollSensitivity = 30f; foreach (WheelDef wheel in set.wheels) { TextMeshProUGUI obj3 = WheelUI.Text("Header", (Transform)(object)val4, new Vector2(0f, 34f), Vector2.zero, wheel.title.ToUpperInvariant(), 24f, (TextAlignmentOptions)1025, WheelUI.Orange); ((TMP_Text)obj3).font = Utils.GetFont("Ticketing SDF GreyGlow"); ((Component)obj3).gameObject.AddComponent<LayoutElement>().preferredHeight = 34f; ((Component)WheelUI.Image("Rule", (Transform)(object)val4, Vector2.zero, Vector2.zero, new Color(0.58f, 0.58f, 0.58f, 0.6f))).gameObject.AddComponent<LayoutElement>().preferredHeight = 2f; RectTransform val5 = WheelUI.Rect("Grid", (Transform)(object)val4, Vector2.zero, Vector2.zero); GridLayoutGroup obj4 = ((Component)val5).gameObject.AddComponent<GridLayoutGroup>(); obj4.cellSize = new Vector2(246f, 34f); obj4.spacing = new Vector2(8f, 2f); ((LayoutGroup)obj4).padding = new RectOffset(0, 0, 4, 2); obj4.constraint = (Constraint)1; obj4.constraintCount = 4; ((LayoutGroup)obj4).childAlignment = (TextAnchor)0; foreach (EntryDef entry in wheel.entries) { AddRow((Transform)(object)val5, wheel, entry); } } Vector2 val6 = default(Vector2); ((Vector2)(ref val6))..ctor(0f, -416f); WheelUI.Button("Defaults", parent, new Vector2(170f, 48f), val6 + new Vector2(-100f, 0f), "DEFAULTS", Defaults, primary: false); WheelUI.Button("Done", parent, new Vector2(170f, 48f), val6 + new Vector2(100f, 0f), "DONE", Close); } private void AddRow(Transform parent, WheelDef wheel, EntryDef entry) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: 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_007b: 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_008f: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_0179: 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_01af: Unknown result type (might be due to invalid IL or missing references) //IL_021a: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_0242: Unknown result type (might be due to invalid IL or missing references) //IL_0247: Unknown result type (might be due to invalid IL or missing references) //IL_024b: Unknown result type (might be due to invalid IL or missing references) //IL_025c: Unknown result type (might be due to invalid IL or missing references) //IL_026d: Unknown result type (might be due to invalid IL or missing references) //IL_0279: Unknown result type (might be due to invalid IL or missing references) //IL_028a: Unknown result type (might be due to invalid IL or missing references) //IL_029a: Unknown result type (might be due to invalid IL or missing references) //IL_0305: Unknown result type (might be due to invalid IL or missing references) //IL_030a: Unknown result type (might be due to invalid IL or missing references) //IL_030f: Unknown result type (might be due to invalid IL or missing references) //IL_0339: Unknown result type (might be due to invalid IL or missing references) //IL_0345: Unknown result type (might be due to invalid IL or missing references) RectTransform val = WheelUI.Rect("Entry", parent, Vector2.zero, Vector2.zero); ((Graphic)((Component)val).gameObject.AddComponent<Image>()).color = Color.clear; Vector2 value = default(Vector2); ((Vector2)(ref value))..ctor(0f, 0.5f); Image val2 = WheelUI.Image("Box", (Transform)(object)val, new Vector2(26f, 26f), new Vector2(6f, 0f), Box, Utils.GetSprite("window_outline_02"), value, value); val2.type = (Type)1; val2.pixelsPerUnitMultiplier = 0.5f; Image val3 = WheelUI.Image("Check", ((Component)val2).transform, new Vector2(30f, 30f), Vector2.zero, WheelUI.Orange, Utils.GetSprite("window_X_02")); TextMeshProUGUI val4 = WheelUI.Text("Label", (Transform)(object)val, Vector2.zero, Vector2.zero, entry.text, 20f, (TextAlignmentOptions)4097, WheelUI.Ink); ((TMP_Text)val4).font = Utils.GetFont("Ticketing SDF"); ((TMP_Text)val4).rectTransform.anchorMin = Vector2.zero; ((TMP_Text)val4).rectTransform.anchorMax = Vector2.one; ((TMP_Text)val4).rectTransform.offsetMin = new Vector2(42f, 0f); ((TMP_Text)val4).rectTransform.offsetMax = new Vector2(-4f, 0f); ((TMP_Text)val4).enableAutoSizing = true; ((TMP_Text)val4).fontSizeMin = 12f; ((TMP_Text)val4).fontSizeMax = 20f; ((TMP_Text)val4).textWrappingMode = (TextWrappingModes)0; ((TMP_Text)val4).overflowMode = (TextOverflowModes)1; Toggle toggle = ((Component)val).gameObject.AddComponent<Toggle>(); ((Selectable)toggle).targetGraphic = (Graphic)(object)val2; toggle.graphic = (Graphic)(object)val3; toggle.toggleTransition = (ToggleTransition)0; Toggle obj = toggle; Navigation navigation = default(Navigation); ((Navigation)(ref navigation)).mode = (Mode)0; ((Selectable)obj).navigation = navigation; ColorBlock colors = ((Selectable)toggle).colors; ((ColorBlock)(ref colors)).normalColor = Color.white; ((ColorBlock)(ref colors)).highlightedColor = Utils.Hex("#FF0000"); ((ColorBlock)(ref colors)).pressedColor = Utils.Hex("#C8C8C8"); ((ColorBlock)(ref colors)).selectedColor = Color.white; ((ColorBlock)(ref colors)).disabledColor = Utils.Hex("#7D7D7D80"); ((Selectable)toggle).colors = colors; bool flag = WheelPicks.IsEnabled(wheel, entry); toggle.SetIsOnWithoutNotify(flag); if (WheelLogic.Locked(entry, mode) != null) { ((Selectable)toggle).interactable = false; ((Component)val3).gameObject.SetActive(false); WheelUI.Image("Lock", ((Component)val2).transform, new Vector2(28f, 28f), Vector2.zero, Grey, Utils.GetSprite("Icon_Lock")); ((Graphic)val2).color = Grey; ((Graphic)val4).color = Grey; ((TMP_Text)val4).text = entry.text + " <size=65%>locked</size>"; } else { Tint(toggle, flag); ((UnityEvent<bool>)(object)toggle.onValueChanged).AddListener((UnityAction<bool>)delegate(bool flag2) { if (!flag2 && !AnotherOn(wheel, toggle)) { toggle.SetIsOnWithoutNotify(true); Tint(toggle, on: true); if ((Object)(object)tickOff != (Object)null) { AudioManager.PlayUISound(tickOff, 0.8f, 1f); } Warn("At least one entry has to stay on for " + wheel.title + "."); } else { WheelPicks.Set(wheel, entry, flag2); Tint(toggle, flag2); AudioClip val5 = (flag2 ? tickOn : tickOff); if ((Object)(object)val5 != (Object)null) { AudioManager.PlayUISound(val5, 0.8f, 1f); } } }); } toggles.Add(toggle); rows.Add((wheel, entry)); } public bool AnotherOn(WheelDef wheel, Toggle except) { int num = 0; for (int i = 0; i < toggles.Count; i++) { if (rows[i].wheel == wheel) { Toggle val = toggles[i]; if (!((Object)(object)val == (Object)(object)except) && ((Selectable)val).interactable && val.isOn) { num++; } } } return num > 0; } private void Warn(string message) { if (!((Object)(object)hint == (Object)null)) { ((MonoBehaviour)this).StopAllCoroutines(); ((MonoBehaviour)this).StartCoroutine(WarnFor(message, 2.5f)); } } private IEnumerator WarnFor(string message, float seconds) { ((TMP_Text)hint).text = message; ((Graphic)hint).color = WheelUI.Red; yield return (object)new WaitForSecondsRealtime(seconds); if ((Object)(object)hint != (Object)null) { ((TMP_Text)hint).text = "Tick what can land on each wheel."; ((Graphic)hint).color = WheelUI.Dim; } } private static void Tint(Toggle toggle, bool on) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0012: 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) //IL_0028: 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) if (((Selectable)toggle).interactable) { ((Graphic)((Component)toggle).GetComponentInChildren<TMP_Text>()).color = (on ? WheelUI.Ink : Faded); Color box = Box; box.a = (on ? 1f : 0.55f); ((Selectable)toggle).targetGraphic.color = box; } } } public class WheelUI : MonoBehaviour { private const float Radius = 290f; private static readonly Vector2 WheelCentre = new Vector2(-290f, -50f); private static readonly Vector2 PanelCentre = new Vector2(335f, -50f); private static readonly Vector2 PanelSize = new Vector2(440f, 560f); private static readonly Vector2 Middle = new Vector2(0.5f, 0.5f); public static readonly Color Ink = Color.white; public static readonly Color Frame = Utils.Hex("#A1A1A1"); public static readonly Color Orange = Utils.Hex("#FF9D00"); public static readonly Color Red = Utils.Hex("#FF2F39"); public static readonly Color Magenta = Utils.Hex("#B43EA8"); public static readonly Color Dim = Utils.Hex("#9F9F9F"); public static float SpinSeconds = 6f; public static int SpinTurns = 5; private WheelSet set; private M_Gamemode mode; private Func<Roll, List<string>> apply; private RectTransform wheelGroup; private RectTransform wheel; private RectTransform pointer; private Image wheelImage; private TextMeshProUGUI resultsText; private TextMeshProUGUI hint; private GameObject winnerPanel; private TextAnimator_TMP winnerText; private Button actionButton; private Button resetButton; private Button settingsButton; private Button cancelButton; private Button lastButton; private GameObject selectedBefore; private AudioClip tickClip; private AudioClip winClip; private float[] starts; private float[] spans; private Color[] sliceColors; private Sprite highlight; private int lastSlice; private float pointerKick; private float pointerReturn = 160f; private float lastDegrees; private float lastDegreesTime; private float wheelSpeed; private int spinCount; private bool actionPressed; private bool resetPressed; private bool useLast; private bool previewLast; private bool wasReset; private List<WheelResult> results = new List<WheelResult>(); private const float launchPart = 0.06f; private const float friction = 1.45f; public static WheelUI Current { get; private set; } public static bool IsOpen => (Object)(object)Current != (Object)null; public static void Open(WheelSet set, M_Gamemode mode, Func<Roll, List<string>> apply) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: 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_0047: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)Current != (Object)null)) { GameObject val = new GameObject("WheelOfWuck_Overlay"); Canvas obj = val.AddComponent<Canvas>(); obj.renderMode = (RenderMode)0; obj.sortingOrder = 32000; CanvasScaler obj2 = val.AddComponent<CanvasScaler>(); obj2.uiScaleMode = (ScaleMode)1; obj2.referenceResolution = new Vector2(1920f, 1080f); obj2.matchWidthOrHeight = 0.5f; val.AddComponent<GraphicRaycaster>(); Current = val.AddComponent<WheelUI>(); Current.set = set; Current.mode = mode; Current.apply = apply; } } public void Press() { if (((Selectable)actionButton).interactable) { actionPressed = true; } } public void Reset() { if (((Selectable)resetButton).interactable) { resetPressed = true; actionPressed = true; } } private void Start() { Build(); selectedBefore = EventSystem.current.currentSelectedGameObject; AudioClip[] array = Resources.FindObjectsOfTypeAll<AudioClip>(); foreach (AudioClip val in array) { if (((Object)val).name == "click_01") { tickClip = val; } if (((Object)val).name == "mbutton1") { winClip = val; } } ((MonoBehaviour)this).StartCoroutine(Run()); } private void OnDestroy() { ClearWheel(); EventSystem current = EventSystem.current; if (current != null) { current.SetSelectedGameObject(selectedBefore); } if ((Object)(object)Current == (Object)(object)this) { Current = null; } } public void Back() { if (WheelSettings.IsOpen) { WheelSettings.Current.Close(); } else { Cancel(); } } private void Update() { //IL_0064: Unknown result type (might be due to invalid IL or missing references) if (Input.GetKeyDown((KeyCode)27)) { Back(); } if ((Object)(object)EventSystem.current.currentSelectedGameObject != (Object)null) { EventSystem.current.SetSelectedGameObject((GameObject)null); } pointerKick = Mathf.MoveTowards(pointerKick, 0f, Time.unscaledDeltaTime * pointerReturn); ((Transform)pointer).localRotation = Quaternion.Euler(0f, 0f, pointerKick); } private void Build() { //IL_0041: 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_007a: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_022f: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_0275: Unknown result type (might be due to invalid IL or missing references) //IL_0284: Unknown result type (might be due to invalid IL or missing references) //IL_0298: Unknown result type (might be due to invalid IL or missing references) //IL_029d: Unknown result type (might be due to invalid IL or missing references) //IL_02e8: Unknown result type (might be due to invalid IL or missing references) //IL_02f7: Unknown result type (might be due to invalid IL or missing references) //IL_030b: Unknown result type (might be due to invalid IL or missing references) //IL_0310: Unknown result type (might be due to invalid IL or missing references) //IL_0359: Unknown result type (might be due to invalid IL or missing references) //IL_0389: Unknown result type (might be due to invalid IL or missing references) //IL_03f1: Unknown result type (might be due to invalid IL or missing references) //IL_03f6: Unknown result type (might be due to invalid IL or missing references) //IL_0428: Unknown result type (might be due to invalid IL or missing references) //IL_042d: Unknown result type (might be due to invalid IL or missing references) //IL_045f: Unknown result type (might be due to invalid IL or missing references) //IL_0464: Unknown result type (might be due to invalid IL or missing references) //IL_0496: Unknown result type (might be due to invalid IL or missing references) //IL_049b: Unknown result type (might be due to invalid IL or missing references) //IL_04d1: Unknown result type (might be due to invalid IL or missing references) //IL_04d6: Unknown result type (might be due to invalid IL or missing references) //IL_0507: Unknown result type (might be due to invalid IL or missing references) //IL_050c: Unknown result type (might be due to invalid IL or missing references) //IL_0516: Unknown result type (might be due to invalid IL or missing references) //IL_051b: Unknown result type (might be due to invalid IL or missing references) //IL_0545: Unknown result type (might be due to invalid IL or missing references) //IL_0554: Unknown result type (might be due to invalid IL or missing references) //IL_0568: Unknown result type (might be due to invalid IL or missing references) //IL_056d: Unknown result type (might be due to invalid IL or missing references) Vector2 value = default(Vector2); ((Vector2)(ref value))..ctor(0.5f, 1f); Vector2 value2 = default(Vector2); ((Vector2)(ref value2))..ctor(0.5f, 0f); ((Graphic)Fill("Dim", ((Component)this).transform, new Color(0.02f, 0.02f, 0.03f, 0.92f))).raycastTarget = true; ((TAnimCore)Shaky(Text("Title", ((Component)this).transform, new Vector2(1200f, 80f), new Vector2(0f, -10f), "", 56f, (TextAlignmentOptions)514, Ink, value))).SetText(set.title.ToUpperInvariant()); wheelGroup = Rect("WheelGroup", ((Component)this).transform, Vector2.zero, Vector2.zero); wheel = Rect("Wheel", (Transform)(object)wheelGroup, new Vector2(580f, 580f), WheelCentre); wheelImage = ((Component)wheel).gameObject.AddComponent<Image>(); ((Graphic)wheelImage).raycastTarget = false; pointer = ((Graphic)Image("Pointer", (Transform)(object)wheelGroup, new Vector2(60f, 42f), WheelCentre + new Vector2(342f, 0f), Color.white, PointerSprite(120, 84, Color.white, Color.black, 5f), (Vector2?)null, (Vector2?)new Vector2(1f, 0.5f))).rectTransform; lastButton = Button("Last", (Transform)(object)wheelGroup, new Vector2(240f, 48f), WheelCentre + new Vector2(0f, -334f), "LAST ROLL", delegate { useLast = true; actionPressed = true; }, primary: false); Transform parent = Panel("Results", ((Component)this).transform, PanelSize, PanelCentre, "THE RUN", Magenta, Magenta); resultsText = Text("ResultsText", parent, new Vector2(PanelSize.x - 44f, PanelSize.y - 150f), new Vector2(0f, -62f), "", 22f, (TextAlignmentOptions)257, Ink, value); ((TMP_Text)resultsText).font = Utils.GetFont("Ticketing SDF"); hint = Text("Hint", parent, new Vector2(PanelSize.x - 44f, 60f), new Vector2(0f, 16f), "", 18f, (TextAlignmentOptions)1026, Dim, value2); ((TMP_Text)hint).font = Utils.GetFont("Ticketing SDF"); RectTransform val = Rect("Buttons", ((Component)this).transform, new Vector2(PanelSize.x, 50f), new Vector2(PanelCentre.x, PanelCentre.y - PanelSize.y / 2f - 40f)); HorizontalLayoutGroup obj = ((Component)val).gameObject.AddComponent<HorizontalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)obj).spacing = 16f; ((LayoutGroup)obj).childAlignment = (TextAnchor)4; ((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = false; ((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = false; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = false; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = false; actionButton = Button("Action", (Transform)(object)val, new Vector2(136f, 50f), Vector2.zero, "SPIN", Press); resetButton = Button("Reset", (Transform)(object)val, new Vector2(136f, 50f), Vector2.zero, "RESET", Reset, primary: false); settingsButton = Button("Settings", (Transform)(object)val, new Vector2(136f, 50f), Vector2.zero, "SETTINGS", OpenSettings, primary: false); cancelButton = Button("Cancel", (Transform)(object)val, new Vector2(136f, 50f), Vector2.zero, "CANCEL", Cancel, primary: false); RectTransform val2 = Rect("Winner", ((Component)this).transform, new Vector2(520f, 160f), WheelCentre); Panel("Frame", (Transform)(object)val2, new Vector2(520f, 160f), Vector2.zero, "THE WHEEL SAYS", Red, Red); winnerPanel = ((Component)val2).gameObject; winnerText = Shaky(Text("WinnerText", (Transform)(object)val2, new Vector2(500f, 90f), new Vector2(0f, 12f), "", 40f, (TextAlignmentOptions)514, Ink, value2)); winnerPanel.SetActive(false); } private static TextAnimator_TMP Shaky(TextMeshProUGUI text) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) TextAnimator_TMP val = ((Component)text).gameObject.AddComponent<TextAnimator_TMP>(); ((TAnimCore)val).DefaultBehaviorsTags = new string[1] { "shake" }; ((TAnimCore)val).DefaultAppearancesTags = new string[0]; ((TAnimCore)val).defaultTagsMode = (DefaultTagsMode)1; ((TAnimCore)val).useDynamicScaling = true; ((TAnimCore)val).referenceFontSize = 250f; return val; } private void OpenSettings() { if (!WheelSettings.IsOpen) { WheelSettings.Open(((Component)this).transform, set, mode, delegate { resetPressed = true; actionPressed = true; }); } } private IEnumerator Run() { while (true) { resetPressed = false; useLast = false; WheelLogic.wins.Clear(); results = new List<WheelResult>(); previewLast = Roll.Current != null && !wasReset; ((Component)lastButton).gameObject.SetActive(Roll.Current != null); ((Component)resetButton).gameObject.SetActive(false); ((Component)settingsButton).gameObject.SetActive(true); ((Component)wheelGroup).gameObject.SetActive(true); ((Component)cancelButton).gameObject.SetActive(true); ((TMP_Text)hint).text = ""; foreach (WheelDef wheelDef in set.wheels) { int spins = WheelLogic.SpinsFor(wheelDef); WheelResult result = new WheelResult { id = wheelDef.id, title = wheelDef.title }; for (int spin = 0; spin < spins; spin++) { List<EntryDef> live = WheelLogic.Live(wheelDef, mode); if (live.Count == 0) { Plugin.Logger.LogWarning((object)("nothing left to spin on the " + wheelDef.title + " wheel")); break; } if (live.Count == 1) { EntryDef entryDef = live[0]; Plugin.Logger.LogInfo((object)("only " + entryDef.text + " can land on the " + wheelDef.title + " wheel, no spin needed")); WheelLogic.wins.Add((wheelDef, entryDef)); result.winners.Add(entryDef.text); if (!results.Contains(result)) { results.Add(result); } RefreshResults(wheelDef); continue; } EntryDef winner = WheelLogic.Pick(live); ShowWheel(live); RefreshResults(wheelDef); yield return WaitForAction("SPIN"); if (useLast || resetPressed) { break; } previewLast = false; ((Component)lastButton).gameObject.SetActive(false); ((Component)settingsButton).gameObject.SetActive(false); RefreshResults(wheelDef); ((Selectable)resetButton).interactable = false; yield return Spin(live.IndexOf(winner)); WheelLogic.wins.Add((wheelDef, winner)); result.winners.Add(winner.text); if (!results.Contains(result)) { results.Add(result); } RefreshResults(wheelDef); ((Component)resetButton).gameObject.SetActive(true); winnerPanel.SetActive(true); ((TAnimCore)winnerText).SetText(winner.text); yield return PopIn(winnerPanel.transform); AudioManager.PlayUISound(winClip, 0.8f, 1f); yield return WaitForAction("NEXT"); winnerPanel.SetActive(false); if (resetPressed) { break; } } if (useLast || resetPressed) { break; } } if (resetPressed) { wasReset = true; continue; } ClearWheel(); ((Component)wheelGroup).gameObject.SetActive(false); ((Component)cancelButton).gameObject.SetActive(false); ((Component)settingsButton).gameObject.SetActive(false); Roll roll = (useLast ? Roll.Current : WheelLogic.BuildRoll(results)); results = roll.results; previewLast = false; List<string> list = apply(roll); list.InsertRange(0, roll.notes); RefreshResults(null, list); ((TMP_Text)hint).text = "Everything is picked. Press Play when you're ready, or Reset to spin again."; ((Component)resetButton).gameObject.SetActive(true); yield return WaitForAction("DONE"); if (!resetPressed) { break; } } Object.Destroy((Object)(object)((Component)this).gameObject); } private void Cancel() { Plugin.Logger.LogInfo((object)"wheel cancelled, nothing changed"); Object.Destroy((Object)(object)((Component)this).gameObject); } private IEnumerator WaitForAction(string label) { actionPressed = false; ((Selectable)actionButton).interactable = true; ((Selectable)resetButton).interactable = true; SetLabel(actionButton, label); while (!actionPressed) { yield return null; } actionPressed = false; } private void RefreshResults(WheelDef current, List<string> notes = null) { List<string> list = new List<string>(); foreach (WheelDef wheelDef in set.wheels) { WheelResult wheelResult = results.Find((WheelResult r) => r.id == wheelDef.id); WheelResult wheelResult2 = null; if (previewLast) { wheelResult2 = Roll.Current.results.Find((WheelResult r) => r.id == wheelDef.id); } if (wheelDef == current) { list.Add("<color=#FF9D00>" + wheelDef.title + ":</color> " + Winners(wheelResult)); } else if (wheelResult != null) { list.Add("<color=#AAAAAA>" + wheelDef.title + ":</color> " + Winners(wheelResult)); } else if (wheelResult2 != null) { list.Add("<color=#555555>" + wheelDef.title + ": " + Winners(wheelResult2) + "</color>"); } else { list.Add("<color=#555555>" + wheelDef.title + "</color>"); } } if (notes != null) { foreach (string note in notes) { list.Add("<color=#FF9D00>" + note + "</color>"); } } ((TMP_Text)resultsText).text = string.Join("\n", list); } private static string Winners(WheelResult result) { if (result == null) { return ""; } string text = ""; for (int i = 0; i < result.winners.Count; i++) { if (i != 0) { text += ", "; } text += result.winners[i]; } return text; } private void ShowWheel(List<EntryDef> live) { //IL_0124: 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_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_025b: Unknown result type (might be due to invalid IL or missing references) //IL_0260: Unknown result type (might be due to invalid IL or missing references) //IL_0267: Unknown result type (might be due to invalid IL or missing references) //IL_0283: Unknown result type (might be due to invalid IL or missing references) //IL_029c: Unknown result type (might be due to invalid IL or missing references) //IL_02bd: Unknown result type (might be due to invalid IL or missing references) //IL_0307: Unknown result type (might be due to invalid IL or missing references) //IL_030c: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) ClearWheel(); float num = 0f; for (int i = 0; i < live.Count; i++) { num += live[i].weight; } starts = new float[live.Count]; spans = new float[live.Count]; for (int j = 0; j < live.Count; j++) { starts[j] = ((j == 0) ? 0f : (starts[j - 1] + spans[j - 1])); spans[j] = 360f * live[j].weight / num; } spans[live.Count - 1] = 360f - starts[live.Count - 1]; List<Color> list = set.colors.ConvertAll<Color>(Utils.Hex); sliceColors = (Color[])(object)new Color[live.Count]; for (int k = 0; k < live.Count; k++) { sliceColors[k] = list[k % list.Count]; } int num2 = live.Count - 1; if (num2 > 1 && list.Count > 2 && sliceColors[num2] == sliceColors[0]) { sliceColors[num2] = list[1]; } wheelImage.sprite = WheelSprite(1024, starts, spans, sliceColors); ((Graphic)wheelImage).color = Color.white; ((Transform)wheel).localRotation = Quaternion.identity; lastSlice = -1; Vector2 val = default(Vector2); for (int l = 0; l < live.Count; l++) { float num3 = starts[l] + spans[l] / 2f; float num4 = Mathf.Clamp(348f * Mathf.Sin(spans[l] * (MathF.PI / 180f) / 2f), 16f, 64f); ((Vector2)(ref val))..ctor(Mathf.Cos(num3 * (MathF.PI / 180f)), Mathf.Sin(num3 * (MathF.PI / 180f))); TextMeshProUGUI obj = Text("Label", (Transform)(object)wheel, new Vector2(214.6f, num4), val * 272.6f, live[l].text, 24f, (TextAlignmentOptions)4100, Color.white, (Vector2?)null, (Vector2?)new Vector2(1f, 0.5f)); ((Transform)((TMP_Text)obj).rectTransform).localRotation = Quaternion.Euler(0f, 0f, num3); ((TMP_Text)obj).enableAutoSizing = true; ((TMP_Text)obj).fontSizeMin = 11f; ((TMP_Text)obj).fontSizeMax = Mathf.Min(26f, num4 * 0.8f); ((TMP_Text)obj).textWrappingMode = (TextWrappingModes)0; ((TMP_Text)obj).overflowMode = (TextOverflowModes)1; ((TMP_Text)obj).fontStyle = (FontStyles)1; ((TMP_Text)obj).outlineColor = Color32.op_Implicit(Color.black); ((TMP_Text)obj).outlineWidth = 0.25f; } } private void ClearWheel() { //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_00a3: Unknown result type (might be due to invalid IL or missing references) foreach (Transform item in (Transform)wheel) { Object.Destroy((Object)(object)((Component)item).GetComponent<TMP_Text>().fontMaterial); Object.Destroy((Object)(object)((Component)item).gameObject); } if ((Object)(object)highlight != (Object)null) { DestroySprite(highlight); } highlight = null; if ((Object)(object)wheelImage.sprite != (Object)null) { DestroySprite(wheelImage.sprite); } wheelImage.sprite = null; ((Graphic)wheelImage).color = Color.clear; } private IEnumerator Spin(int winner) { ((Selectable)actionButton).interactable = false; spinCount++; Color[] array = (Color[])sliceColors.Clone(); for (int i = 0; i < array.Length; i++) { if (i != winner) { array[i] = Color.Lerp(array[i], Color.black, 0.6f); } } highlight = WheelSprite(1024, starts, spans, array); float num = starts[winner] + spans[winner] * Random.Range(0.15f, 0.85f); float start = ((Transform)wheel).localEulerAngles.z; int num2 = Mathf.Max(2, SpinTurns + Random.Range(-1, 2)); float delta = (float)num2 * 360f + Mathf.Repeat(start + num, 360f); float duration = SpinSeconds; float pullBack = Mathf.Min(14f, spans[winner] * 0.4f); float pullTime = Mathf.Min(0.3f, duration * 0.05f); float[] travel = SpinProfile(512); lastDegrees = start; lastDegreesTime = Time.unscaledTime; for (float elapsed = 0f; elapsed < pullTime; elapsed += Time.unscaledDeltaTime) { float num3 = elapsed / pullTime; float num4 = 1f - num3; SetRotation(start + pullBack * (1f - num4 * num4)); yield return null; } float spinFrom = start + pullBack; float spinDelta = delta + pullBack; for (float elapsed = 0f; elapsed < duration; elapsed += Time.unscaledDeltaTime) { SetRotation(spinFrom - spinDelta * Sample(travel, elapsed / duration)); yield return null; } float settle = Mathf.Min(1.5f, spans[winner] * 0.08f); for (float elapsed = 0f; elapsed < 0.35f; elapsed += Time.unscaledDeltaTime) { float num5 = elapsed / 0.35f; SetRotation(start - delta - settle * Mathf.Sin(num5 * MathF.PI)); yield return null; } SetRotation(start - delta); wheelSpeed = 0f; DestroySprite(wheelImage.sprite); wheelImage.sprite = highlight; highlight = null; for (int j = 0; j < ((Transform)wheel).childCount; j++) { if (j != winner) { ((Graphic)((Component)((Transform)wheel).GetChild(j)).GetComponent<TMP_Text>()).color = new Color(0.55f, 0.55f, 0.55f); } } yield return (object)new WaitForSecondsRealtime(0.6f); } private static float[] SpinProfile(int samples) { float[] array = new float[samples + 1]; float num = 0f; array[0] = 0f; for (int i = 1; i <= samples; i++) { float num2 = (float)i / (float)samples; float num3 = 0f; if (num2 < 0.06f) { num3 = Mathf.Sin(num2 / 0.06f * MathF.PI * 0.5f); } else { float num4 = (num2 - 0.06f) / 0.94f; num3 = Mathf.Pow(1f - num4, 1.45f); } num = (array[i] = num + num3); } for (int j = 0; j <= samples; j++) { array[j] /= num; } array[samples] = 1f; return array; } private static float Sample(float[] table, float t) { if (t <= 0f) { return 0f; } if (t >= 1f) { return 1f; } float num = t * (float)(table.Length - 1); int num2 = Mathf.FloorToInt(num); float num3 = num - (float)num2; if (num2 >= table.Length - 1) { return 1f; } float num4 = table[num2]; float num5 = table[num2 + 1]; return num4 + (num5 - num4) * num3; } private static float Ease(float t) { float num = 0.1f; float num2 = 0.05f; if (t < num) { return num2 * (t / num) * (t / num); } return num2 + (1f - num2) * (1f - Mathf.Pow(1f - (t - num) / (1f - num), 4f)); } private void SetRotation(float degrees) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) ((Transform)wheel).localRotation = Quaternion.Euler(0f, 0f, degrees); float unscaledTime = Time.uns