Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of GambitPopQuiz v1.0.3
MathTeacherPlugin.dll
Decompiled 5 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using TMPro; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: IgnoresAccessChecksTo("")] [assembly: AssemblyCompany("FJX")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("MathTeacherPlugin")] [assembly: AssemblyTitle("MathTeacherPlugin")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [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 MathTeacherPlugin { public enum MathTeacherAnswerChoice { Left, Right } internal static class MathTeacherGameplayEffects { public static void ApplyToLocalPlayer(MathTeacherQuizResult result) { PlayerAvatar instance = PlayerAvatar.instance; if ((Object)(object)instance == (Object)null) { MathTeacherPlugin.Logger.LogWarning((object)"MathTeacher could not apply quiz result because local player was not found."); } else { Apply(result, instance); } } public static void Apply(MathTeacherQuizResult result, PlayerAvatar player) { switch (result.Outcome) { case MathTeacherQuizOutcome.Correct: SpawnReward(player, result.RewardValue); break; case MathTeacherQuizOutcome.Wrong: case MathTeacherQuizOutcome.Timeout: HurtPlayer(player, result.Damage); break; } } private static void HurtPlayer(PlayerAvatar player, int damage) { if (damage > 0) { player.playerHealth.Hurt(damage, false, -1, false); MathTeacherPlugin.Logger.LogInfo((object)$"MathTeacher dealt {damage} damage to {((Object)player).name}."); } } private static void SpawnReward(PlayerAvatar player, int rewardValue) { //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_009a: 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_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: 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) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) if (rewardValue <= 0) { return; } if ((Object)(object)AssetManager.instance == (Object)null || (Object)(object)AssetManager.instance.surplusValuableSmall == (Object)null) { MathTeacherPlugin.Logger.LogWarning((object)"MathTeacher could not spawn reward because surplusValuableSmall was not available."); return; } if (SemiFunc.IsMultiplayer() && !PhotonNetwork.IsMasterClient) { MathTeacherPlugin.Logger.LogWarning((object)"MathTeacher reward spawn skipped because this client is not the multiplayer master client."); return; } GameObject surplusValuableSmall = AssetManager.instance.surplusValuableSmall; Vector3 val = ((Component)player).transform.position + ((Component)player).transform.forward * 1.4f + Vector3.up * 0.6f; GameObject val2 = (SemiFunc.IsMultiplayer() ? PhotonNetwork.InstantiateRoomObject("Valuables/" + ((Object)surplusValuableSmall).name, val, Quaternion.identity, (byte)0, (object[])null) : Object.Instantiate<GameObject>(surplusValuableSmall, val, Quaternion.identity)); ValuableObject component = val2.GetComponent<ValuableObject>(); if ((Object)(object)component != (Object)null) { component.dollarValueOverride = rewardValue; } MathTeacherPlugin.Logger.LogInfo((object)$"MathTeacher spawned reward valuable worth {rewardValue}."); } } [BepInPlugin("FJX.MathTeacherPlugin", "MathTeacherPlugin", "1.0")] public class MathTeacherPlugin : BaseUnityPlugin { internal static MathTeacherPlugin Instance { get; private set; } internal static ManualLogSource Logger => Instance._logger; private ManualLogSource _logger => ((BaseUnityPlugin)this).Logger; internal Harmony? Harmony { get; set; } private void Awake() { Instance = this; ((Component)this).gameObject.transform.parent = null; ((Object)((Component)this).gameObject).hideFlags = (HideFlags)61; Patch(); Logger.LogInfo((object)$"{((BaseUnityPlugin)this).Info.Metadata.GUID} v{((BaseUnityPlugin)this).Info.Metadata.Version} has loaded!"); } internal void Patch() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_0026: Expected O, but got Unknown if (Harmony == null) { Harmony val = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID); Harmony val2 = val; Harmony = val; } Harmony.PatchAll(); } internal void Unpatch() { Harmony? harmony = Harmony; if (harmony != null) { harmony.UnpatchSelf(); } } private void OnDestroy() { MathTeacherSpinnyQuizController.DestroyActiveHud(); Unpatch(); } } public readonly struct MathTeacherQuestion { public string Prompt { get; } public int LeftAnswer { get; } public int RightAnswer { get; } public MathTeacherAnswerChoice CorrectChoice { get; } public int CorrectAnswer => (CorrectChoice == MathTeacherAnswerChoice.Left) ? LeftAnswer : RightAnswer; public MathTeacherQuestion(string prompt, int leftAnswer, int rightAnswer, MathTeacherAnswerChoice correctChoice) { Prompt = prompt; LeftAnswer = leftAnswer; RightAnswer = rightAnswer; CorrectChoice = correctChoice; } public bool IsCorrect(MathTeacherAnswerChoice choice) { return choice == CorrectChoice; } } public static class MathTeacherQuizHudLayout { public const float PromptX = 0f; public const float PromptY = 92f; public const float LeftChoiceX = -115f; public const float RightChoiceX = 115f; public const float ChoiceY = 32f; public const float ResultX = 0f; public const float ResultY = -24f; } public readonly struct MathTeacherQuizHudText { private const string AccentColor = "F2D56B"; private const string CorrectColor = "78F28B"; private const string WrongColor = "FF6B6B"; public string Title { get; } public string Prompt { get; } public string LeftChoice { get; } public string RightChoice { get; } public string Result { get; } private MathTeacherQuizHudText(string title, string prompt, string leftChoice, string rightChoice, string result) { Title = title; Prompt = prompt; LeftChoice = leftChoice; RightChoice = rightChoice; Result = result; } public static MathTeacherQuizHudText Build(MathTeacherQuestion question, MathTeacherAnswerChoice? selectedChoice) { string result = string.Empty; if (selectedChoice.HasValue) { result = (question.IsCorrect(selectedChoice.Value) ? string.Format("<color=#{0}>CORRECT +{1}</color>", "78F28B", 10000) : string.Format("<color=#{0}>WRONG -{1} HP</color>", "FF6B6B", 50)); } return new MathTeacherQuizHudText(string.Empty, question.Prompt, FormatChoice("A", question.LeftAnswer), FormatChoice("D", question.RightAnswer), result); } public static MathTeacherQuizHudText Build(MathTeacherQuizSession session) { string result = (session.Result.HasValue ? FormatResult(session.Result.Value) : $"TIME {session.RemainingSeconds:0.0}"); return new MathTeacherQuizHudText(string.Empty, session.Question.Prompt, FormatChoice("A", session.Question.LeftAnswer), FormatChoice("D", session.Question.RightAnswer), result); } private static string FormatResult(MathTeacherQuizResult result) { MathTeacherQuizOutcome outcome = result.Outcome; if (1 == 0) { } string result2 = outcome switch { MathTeacherQuizOutcome.Correct => string.Format("<color=#{0}>CORRECT +{1}</color>", "78F28B", result.RewardValue), MathTeacherQuizOutcome.Timeout => string.Format("<color=#{0}>TIME UP -{1} HP</color>", "FF6B6B", result.Damage), _ => string.Format("<color=#{0}>WRONG -{1} HP</color>", "FF6B6B", result.Damage), }; if (1 == 0) { } return result2; } private static string FormatChoice(string key, int answer) { return string.Format("<color=#{0}>[{1}]</color> {2}", "F2D56B", key, answer); } } internal sealed class MathTeacherQuizHudView { private static readonly Color TitleColor = new Color(0.79f, 0.91f, 0.9f, 1f); private static readonly Color PromptColor = Color.white; private static readonly Color ChoiceColor = new Color(1f, 0.86f, 0.42f, 1f); private GameObject? root; private TextMeshProUGUI? promptText; private TextMeshProUGUI? leftChoiceText; private TextMeshProUGUI? rightChoiceText; private TextMeshProUGUI? resultText; public bool IsAlive => (Object)(object)root != (Object)null; public static bool TryCreate(out MathTeacherQuizHudView view) { view = new MathTeacherQuizHudView(); return view.Create(); } public void Render(MathTeacherQuizHudText text) { if (!((Object)(object)root == (Object)null)) { ((TMP_Text)promptText).text = text.Prompt; ((TMP_Text)leftChoiceText).text = text.LeftChoice; ((TMP_Text)rightChoiceText).text = text.RightChoice; ((TMP_Text)resultText).text = text.Result; ((Component)resultText).gameObject.SetActive(!string.IsNullOrEmpty(text.Result)); } } public void Destroy() { if ((Object)(object)root != (Object)null) { Object.Destroy((Object)(object)root); root = null; } } private bool Create() { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected O, but got Unknown //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Expected O, but got Unknown //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00af: 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_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0163: 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_0198: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: 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) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Unknown result type (might be due to invalid IL or missing references) Transform val = FindHudParent(); if ((Object)(object)val == (Object)null) { return false; } TMP_FontAsset val2 = FindHudFont(); if ((Object)(object)val2 == (Object)null) { return false; } root = new GameObject("MathTeacher Quiz HUD", new Type[1] { typeof(RectTransform) }); root.SetActive(true); root.transform.SetParent(val, false); root.layer = ((Component)val).gameObject.layer; RectTransform val3 = (RectTransform)root.transform; val3.anchorMin = Vector2.zero; val3.anchorMax = Vector2.one; val3.pivot = new Vector2(0.5f, 0.5f); val3.offsetMin = Vector2.zero; val3.offsetMax = Vector2.zero; ((Transform)val3).localScale = Vector3.one; promptText = CreateCenteredText("Prompt", val2, root.transform, new Vector2(0f, 92f), new Vector2(620f, 52f), PromptColor, 34f); leftChoiceText = CreateCenteredText("Left Choice", val2, root.transform, new Vector2(-115f, 32f), new Vector2(230f, 42f), ChoiceColor, 26f); rightChoiceText = CreateCenteredText("Right Choice", val2, root.transform, new Vector2(115f, 32f), new Vector2(230f, 42f), ChoiceColor, 26f); resultText = CreateCenteredText("Result", val2, root.transform, new Vector2(0f, -24f), new Vector2(520f, 42f), PromptColor, 24f); return true; } private static Transform? FindHudParent() { GameObject val = GameObject.Find("Game Hud"); return ((Object)(object)val != (Object)null) ? val.transform : null; } private static TMP_FontAsset? FindHudFont() { GameObject val = GameObject.Find("Tax Haul"); if ((Object)(object)val != (Object)null) { TMP_Text component = val.GetComponent<TMP_Text>(); if ((Object)(object)((component != null) ? component.font : null) != (Object)null) { return component.font; } } HealthUI instance = HealthUI.instance; object obj; if (instance == null) { obj = null; } else { TextMeshProUGUI uiText = ((SemiUI)instance).uiText; obj = ((uiText != null) ? ((TMP_Text)uiText).font : null); } if ((Object)obj != (Object)null) { return ((TMP_Text)((SemiUI)HealthUI.instance).uiText).font; } TextMeshProUGUI obj2 = Object.FindObjectOfType<TextMeshProUGUI>(); return (obj2 != null) ? ((TMP_Text)obj2).font : null; } private static TextMeshProUGUI CreateCenteredText(string name, TMP_FontAsset font, Transform parent, Vector2 position, Vector2 size, Color color, float fontSize) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_007e: 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_0092: Unknown result type (might be due to invalid IL or missing references) //IL_009b: 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) GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) }); val.transform.SetParent(parent, false); val.layer = ((Component)parent).gameObject.layer; RectTransform val2 = (RectTransform)val.transform; val2.anchorMin = new Vector2(0.5f, 0.5f); val2.anchorMax = new Vector2(0.5f, 0.5f); val2.pivot = new Vector2(0.5f, 0.5f); val2.anchoredPosition = position; val2.sizeDelta = size; ((Transform)val2).localScale = Vector3.one; TextMeshProUGUI val3 = val.AddComponent<TextMeshProUGUI>(); ((TMP_Text)val3).font = font; ((Graphic)val3).color = color; ((TMP_Text)val3).fontSize = fontSize; ((TMP_Text)val3).enableAutoSizing = true; ((TMP_Text)val3).fontSizeMin = 12f; ((TMP_Text)val3).fontSizeMax = fontSize; ((TMP_Text)val3).enableWordWrapping = false; ((TMP_Text)val3).overflowMode = (TextOverflowModes)1; ((TMP_Text)val3).alignment = (TextAlignmentOptions)514; ((Graphic)val3).raycastTarget = false; ((TMP_Text)val3).richText = true; return val3; } } public enum MathTeacherQuizOutcome { Correct, Wrong, Timeout } public readonly struct MathTeacherQuizResult { public const int CorrectRewardValue = 10000; public const int WrongDamage = 50; public MathTeacherQuizOutcome Outcome { get; } public int RewardValue { get; } public int Damage { get; } private MathTeacherQuizResult(MathTeacherQuizOutcome outcome, int rewardValue, int damage) { Outcome = outcome; RewardValue = rewardValue; Damage = damage; } public static MathTeacherQuizResult FromAnswer(MathTeacherQuestion question, MathTeacherAnswerChoice answer) { return question.IsCorrect(answer) ? new MathTeacherQuizResult(MathTeacherQuizOutcome.Correct, 10000, 0) : new MathTeacherQuizResult(MathTeacherQuizOutcome.Wrong, 0, 50); } public static MathTeacherQuizResult Timeout() { return new MathTeacherQuizResult(MathTeacherQuizOutcome.Timeout, 0, 50); } } public sealed class MathTeacherQuizService { private readonly struct Problem { public int LeftOperand { get; } public string OperatorSymbol { get; } public int RightOperand { get; } public int CorrectAnswer { get; } public Problem(int leftOperand, string operatorSymbol, int rightOperand, int correctAnswer) { LeftOperand = leftOperand; OperatorSymbol = operatorSymbol; RightOperand = rightOperand; CorrectAnswer = correctAnswer; } } private readonly Random random; public MathTeacherQuizService(Random? random = null) { this.random = random ?? new Random(); } public MathTeacherQuestion CreateQuestion() { Problem problem = CreateProblem(); int num = CreateWrongAnswer(problem.CorrectAnswer); MathTeacherAnswerChoice mathTeacherAnswerChoice = ((random.Next(0, 2) != 0) ? MathTeacherAnswerChoice.Right : MathTeacherAnswerChoice.Left); int leftAnswer = ((mathTeacherAnswerChoice == MathTeacherAnswerChoice.Left) ? problem.CorrectAnswer : num); int rightAnswer = ((mathTeacherAnswerChoice == MathTeacherAnswerChoice.Right) ? problem.CorrectAnswer : num); return new MathTeacherQuestion($"{problem.LeftOperand} {problem.OperatorSymbol} {problem.RightOperand} = ?", leftAnswer, rightAnswer, mathTeacherAnswerChoice); } private Problem CreateProblem() { int num = random.Next(0, 3); if (1 == 0) { } Problem result = num switch { 0 => CreateAdditionProblem(), 1 => CreateSubtractionProblem(), _ => CreateMultiplicationProblem(), }; if (1 == 0) { } return result; } private Problem CreateAdditionProblem() { int num = random.Next(2, 31); int num2 = random.Next(2, 31); return new Problem(num, "+", num2, num + num2); } private Problem CreateSubtractionProblem() { int num = random.Next(8, 51); int num2 = random.Next(2, num); return new Problem(num, "-", num2, num - num2); } private Problem CreateMultiplicationProblem() { int num = random.Next(2, 13); int num2 = random.Next(2, 13); return new Problem(num, "x", num2, num * num2); } private int CreateWrongAnswer(int correctAnswer) { int num = random.Next(1, 7); if (random.Next(0, 2) == 0) { num = -num; } int num2 = correctAnswer + num; if (num2 < 0) { num2 = correctAnswer + Math.Abs(num) + 1; } if (num2 == correctAnswer) { num2++; } return num2; } } public sealed class MathTeacherQuizSession { public MathTeacherQuestion Question { get; } public float TimeLimitSeconds { get; } public float RemainingSeconds { get; private set; } public MathTeacherAnswerChoice? SelectedChoice { get; private set; } public MathTeacherQuizResult? Result { get; private set; } public bool IsFinished => Result.HasValue; public MathTeacherQuizSession(MathTeacherQuestion question, float timeLimitSeconds) { Question = question; TimeLimitSeconds = Math.Max(0.1f, timeLimitSeconds); RemainingSeconds = TimeLimitSeconds; } public void Tick(float deltaSeconds) { if (!IsFinished) { RemainingSeconds = Math.Max(0f, RemainingSeconds - Math.Max(0f, deltaSeconds)); if (RemainingSeconds <= 0f) { Result = MathTeacherQuizResult.Timeout(); } } } public void Choose(MathTeacherAnswerChoice choice) { if (!IsFinished) { SelectedChoice = choice; Result = MathTeacherQuizResult.FromAnswer(Question, choice); } } } internal sealed class MathTeacherResolvedInteractions { private readonly HashSet<int> resolvedIds = new HashSet<int>(); public bool Contains(int id) { return resolvedIds.Contains(id); } public void MarkResolved(int id) { resolvedIds.Add(id); } public void Clear(int id) { resolvedIds.Remove(id); } public void ClearAll() { resolvedIds.Clear(); } } [HarmonyPatch(typeof(EnemySpinnyAnim), "Update")] internal static class MathTeacherSpinnyAnimPatch { [HarmonyPostfix] private static void Postfix(EnemySpinnyAnim __instance) { if ((Object)(object)__instance.enemySpinny != (Object)null) { MathTeacherSpinnyQuizController.SuppressWheelGlow(__instance.enemySpinny); } } } [HarmonyPatch(typeof(EnemySpinny), "GetCurrentColorColor")] internal static class MathTeacherSpinnyColorPatch { [HarmonyPostfix] private static void Postfix(EnemySpinny __instance, ref Color __result) { //IL_000d: 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) if (MathTeacherSpinnyQuizController.ShouldHandle(__instance)) { __result = MathTeacherSpinnyQuizController.WheelHighlightColor; } } } [HarmonyPatch(typeof(EnemySpinny), "Update")] internal static class MathTeacherSpinnyPatch { [HarmonyPrefix] private static void Prefix(EnemySpinny __instance) { MathTeacherSpinnyQuizController.BeforeSpinnyUpdate(__instance); } [HarmonyPostfix] private static void Postfix(EnemySpinny __instance) { MathTeacherSpinnyQuizController.AfterSpinnyUpdate(__instance); } } internal static class MathTeacherSpinnyQuizController { private const string MathTeacherEnemyName = "MathTeacher"; private const float TimeLimitSeconds = 8f; private const float HoldRouletteStateSeconds = 0.25f; private static readonly MathTeacherQuizService QuizService = new MathTeacherQuizService(); private static readonly Dictionary<int, MathTeacherQuizSession> Sessions = new Dictionary<int, MathTeacherQuizSession>(); private static readonly MathTeacherResolvedInteractions ResolvedInteractions = new MathTeacherResolvedInteractions(); private static readonly FieldInfo? StateTimerField = AccessTools.Field(typeof(EnemySpinny), "stateTimer"); private static readonly MethodInfo? UpdateStateMethod = AccessTools.Method(typeof(EnemySpinny), "UpdateState", (Type[])null, (Type[])null); internal static readonly Color WheelHighlightColor = new Color(0f, 0f, 0f, 1f); private static MathTeacherQuizHudView? hudView; public static void BeforeSpinnyUpdate(EnemySpinny spinny) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Invalid comparison between Unknown and I4 if (ShouldHandle(spinny) && (int)spinny.currentState == 8 && IsLocalTarget(spinny) && !IsResolved(spinny)) { MathTeacherQuizSession orCreateSession = GetOrCreateSession(spinny); if (!orCreateSession.IsFinished) { HoldRouletteState(spinny); } } } public static void AfterSpinnyUpdate(EnemySpinny spinny) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Invalid comparison between Unknown and I4 if (!ShouldHandle(spinny)) { CleanupInteraction(spinny); return; } SuppressWheelGlow(spinny); if (IsResolved(spinny)) { CleanupResolvedInteractionIfRouletteEnded(spinny); return; } if ((int)spinny.currentState != 8 || !IsLocalTarget(spinny)) { CleanupIfInteractionEnded(spinny); return; } MathTeacherQuizSession orCreateSession = GetOrCreateSession(spinny); if (!orCreateSession.IsFinished) { orCreateSession.Tick(Time.deltaTime); HandleAnswerInput(orCreateSession); } Render(orCreateSession); if (orCreateSession.Result.HasValue) { MathTeacherGameplayEffects.Apply(orCreateSession.Result.Value, spinny.playerTarget); ResolvedInteractions.MarkResolved(((Object)spinny).GetInstanceID()); ForceCloseMouth(spinny); CleanupSession(spinny); } } public static void DestroyActiveHud() { hudView?.Destroy(); hudView = null; Sessions.Clear(); ResolvedInteractions.ClearAll(); } internal static bool ShouldHandle(EnemySpinny spinny) { Enemy component = ((Component)spinny).GetComponent<Enemy>(); return (Object)(object)component?.EnemyParent != (Object)null && component.EnemyParent.enemyName == "MathTeacher"; } internal static void SuppressWheelGlow(EnemySpinny spinny) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_013a: 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) if (!ShouldHandle(spinny)) { return; } if (spinny.colors != null) { for (int i = 0; i < spinny.colors.Length; i++) { spinny.colors[i] = WheelHighlightColor; } } if (spinny.pieces != null) { Transform[] pieces = spinny.pieces; foreach (Transform val in pieces) { MeshRenderer val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<MeshRenderer>() : null); Material val3 = (((Object)(object)val2 != (Object)null) ? ((Renderer)val2).material : null); if (!((Object)(object)val3 == (Object)null)) { val3.DisableKeyword("_EMISSION"); if (val3.HasProperty("_EmissionColor")) { val3.SetColor("_EmissionColor", WheelHighlightColor); } } } } if (MathTeacherWheelVisualPolicy.DisablePointLight) { Light val4 = (((Object)(object)spinny.enemySpinnyAnim != (Object)null) ? spinny.enemySpinnyAnim.pointLight : null); if (!((Object)(object)val4 == (Object)null)) { val4.color = WheelHighlightColor; val4.intensity = 0f; val4.range = 0f; ((Behaviour)val4).enabled = false; } } } private static bool IsLocalTarget(EnemySpinny spinny) { return (Object)(object)spinny.playerTarget != (Object)null && spinny.playerTarget.isLocal; } private static bool IsResolved(EnemySpinny spinny) { return ResolvedInteractions.Contains(((Object)spinny).GetInstanceID()); } private static MathTeacherQuizSession GetOrCreateSession(EnemySpinny spinny) { int instanceID = ((Object)spinny).GetInstanceID(); if (Sessions.TryGetValue(instanceID, out MathTeacherQuizSession value)) { return value; } value = new MathTeacherQuizSession(QuizService.CreateQuestion(), 8f); Sessions[instanceID] = value; MathTeacherPlugin.Logger.LogInfo((object)$"MathTeacher question started: {value.Question.Prompt} A={value.Question.LeftAnswer} D={value.Question.RightAnswer}"); return value; } private static void HandleAnswerInput(MathTeacherQuizSession session) { if (Input.GetKeyDown((KeyCode)97)) { session.Choose(MathTeacherAnswerChoice.Left); } else if (Input.GetKeyDown((KeyCode)100)) { session.Choose(MathTeacherAnswerChoice.Right); } } private static void Render(MathTeacherQuizSession session) { if (EnsureHud()) { hudView?.Render(MathTeacherQuizHudText.Build(session)); } } private static bool EnsureHud() { MathTeacherQuizHudView mathTeacherQuizHudView = hudView; if (mathTeacherQuizHudView != null && mathTeacherQuizHudView.IsAlive) { return true; } hudView?.Destroy(); hudView = null; if (!MathTeacherQuizHudView.TryCreate(out MathTeacherQuizHudView view)) { return false; } hudView = view; return true; } private static void ForceCloseMouth(EnemySpinny spinny) { if (UpdateStateMethod == null) { MathTeacherPlugin.Logger.LogWarning((object)"MathTeacher could not force Spinny close-mouth state because UpdateState was not found."); return; } UpdateStateMethod.Invoke(spinny, new object[1] { (object)(State)12 }); } private static void HoldRouletteState(EnemySpinny spinny) { if (StateTimerField == null) { MathTeacherPlugin.Logger.LogWarning((object)"MathTeacher could not hold Spinny roulette state because stateTimer was not found."); } else { StateTimerField.SetValue(spinny, 0.25f); } } private static void CleanupIfInteractionEnded(EnemySpinny spinny) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Invalid comparison between Unknown and I4 //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Invalid comparison between Unknown and I4 State currentState = spinny.currentState; if (((int)currentState != 7 && currentState - 9 > 2) || 1 == 0) { CleanupInteraction(spinny); } } private static void CleanupResolvedInteractionIfRouletteEnded(EnemySpinny spinny) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 if ((int)spinny.currentState != 8) { CleanupInteraction(spinny); } } private static void CleanupInteraction(EnemySpinny spinny) { int instanceID = ((Object)spinny).GetInstanceID(); Sessions.Remove(instanceID); ResolvedInteractions.Clear(instanceID); DestroyHud(); } private static void CleanupSession(EnemySpinny spinny) { Sessions.Remove(((Object)spinny).GetInstanceID()); DestroyHud(); } private static void DestroyHud() { hudView?.Destroy(); hudView = null; } } public static class MathTeacherWheelVisualPolicy { public const float HighlightRed = 0f; public const float HighlightGreen = 0f; public const float HighlightBlue = 0f; public static bool DisablePointLight => true; } }