using 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(surplusValuableSmall, val, Quaternion.identity)); ValuableObject component = val2.GetComponent(); 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("CORRECT +{1}", "78F28B", 10000) : string.Format("WRONG -{1} HP", "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("CORRECT +{1}", "78F28B", result.RewardValue), MathTeacherQuizOutcome.Timeout => string.Format("TIME UP -{1} HP", "FF6B6B", result.Damage), _ => string.Format("WRONG -{1} HP", "FF6B6B", result.Damage), }; if (1 == 0) { } return result2; } private static string FormatChoice(string key, int answer) { return string.Format("[{1}] {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(); 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(); 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(); ((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 resolvedIds = new HashSet(); 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 Sessions = new Dictionary(); 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(); 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() : 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; } }