using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using FlickRacingTimer;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppRUMBLE.Environment.Minigames;
using Il2CppRUMBLE.Managers;
using Il2CppRUMBLE.MoveSystem;
using Il2CppRUMBLE.Physics.Utility;
using Il2CppRUMBLE.Players.Subsystems;
using Il2CppRUMBLE.Utilities;
using Il2CppTMPro;
using MelonLoader;
using RumbleModUI;
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: MelonInfo(typeof(Mod), "FlickRacingTimer", "1.0.0", "Tortaneose and MasterMischief", null)]
[assembly: MelonGame("Buckethead Entertainment", "RUMBLE")]
[assembly: AssemblyTitle("FlickRacingTimer")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("FlickRacingTimer")]
[assembly: AssemblyCopyright("Copyright © 2024")]
[assembly: AssemblyTrademark("")]
[assembly: MelonColor(255, 0, 255, 0)]
[assembly: MelonAuthorColor(255, 0, 255, 0)]
[assembly: ComVisible(false)]
[assembly: Guid("d3e35beb-1a4f-42df-bda4-23a479aac4a2")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace FlickRacingTimer;
public class Mod : MelonMod
{
[HarmonyPatch(typeof(Stack), "Execute")]
private static class Stack_Execute_Patch
{
private static void Postfix(Stack __instance, IProcessor processor)
{
//IL_0087: Unknown result type (might be due to invalid IL or missing references)
if (__instance.cachedName == "Jump" && !isFlying && (Object)(object)((Il2CppObjectBase)processor).Cast<PlayerStackProcessor>() == (Object)(object)Singleton<PlayerManager>.instance.localPlayer.Controller.GetSubsystem<PlayerStackProcessor>())
{
isFlying = true;
takeoffChecked = false;
timer = 0.0;
if ((Object)(object)timerObject != (Object)null)
{
((TMP_Text)timerText).text = FormatTimeSpan(new TimeSpan(0L));
((Graphic)timerText).color = Color.white;
}
}
}
}
[HarmonyPatch(typeof(PlayerMovement), "OnBecameGrounded")]
private static class PlayerMovement_OnBecameGrounded_Patch
{
private static void Postfix(PlayerMovement __instance)
{
if (isFlying && (Object)(object)__instance == (Object)(object)Singleton<PlayerManager>.instance.localPlayer.Controller.GetSubsystem<PlayerMovement>())
{
HandleLanding();
}
}
}
[HarmonyPatch(typeof(PlayAudioOnImpact), "OnCollisionEnter")]
private static class PlayAudioOnImpact_OnCollisionEnter_Patch
{
private static void Postfix(PlayAudioOnImpact __instance, Collision collision)
{
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: 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_006d: Unknown result type (might be due to invalid IL or missing references)
//IL_0070: Unknown result type (might be due to invalid IL or missing references)
if (!isFlying)
{
return;
}
ContactPoint val = ((Il2CppArrayBase<ContactPoint>)(object)collision.contacts)[0];
if (!((Object)(object)((ContactPoint)(ref val)).thisCollider == (Object)(object)Singleton<PlayerManager>.instance.localPlayer.Controller.GetSubsystem<PlayerPhysics>().pillBodyCollider) || vehicles.Contains(((Object)collision.gameObject).name))
{
return;
}
for (int i = 0; i < collision.contactCount; i++)
{
val = ((Il2CppArrayBase<ContactPoint>)(object)collision.contacts)[i];
if (((ContactPoint)(ref val)).normal.y > maxNormalY)
{
HandleLanding();
}
}
}
}
[HarmonyPatch(typeof(ParkMinigame), "OnMiniGameEnded")]
private static class Patch
{
private static void Prefix()
{
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
if (isFlying)
{
if ((bool)((ModSetting)logTimes).Value)
{
MelonLogger.Msg("Flick Racing time: " + FormatTimeSpan(TimeSpan.FromSeconds(timer)));
}
isFlying = false;
if ((Object)(object)timerObject != (Object)null)
{
((Graphic)timerText).color = Color.red;
}
}
}
}
private static readonly Vector3 leftRelativeTranslate = new Vector3(-0.03f, -0.02f, 0f);
private static readonly Vector3 rightRelativeTranslate = new Vector3(0f - leftRelativeTranslate.x, leftRelativeTranslate.y, leftRelativeTranslate.z);
private static readonly Vector3 globalTranslate = new Vector3(0f, 0.15f, 0f);
private static readonly Vector3 healthRelativeTranslate = new Vector3(0f, 0.05f, 1f);
private static readonly HashSet<string> vehicles = new HashSet<string> { "Disc", "Pillar", "Ball", "RockCube", "Wall", "LargeRock", "SmallRock", "BoulderBall" };
private static readonly float maxNormalY = 0.5f;
private static Mod settings = new Mod();
private static ModSetting<bool> displayTimer;
private static ModSetting<bool> logTimes;
private static ModSetting<bool> swapHand;
private static ModSetting<bool> displayAboveHealth;
private static double timer = 0.0;
private static bool isFlying = false;
private static bool takeoffChecked = false;
private static GameObject timerObject;
private static TextMeshPro timerText;
private static GameObject healthBar;
public static string FormatTimeSpan(TimeSpan timeSpan)
{
List<string> list = new List<string>();
if (timeSpan.Days > 0)
{
list.Add(timeSpan.Days.ToString());
}
if (timeSpan.Hours > 0 || list.Count > 0)
{
list.Add(timeSpan.Hours.ToString("D2"));
}
if (timeSpan.Minutes > 0 || list.Count > 0)
{
list.Add(timeSpan.Minutes.ToString("D2"));
}
list.Add(timeSpan.Seconds.ToString((list.Count == 0) ? "D1" : "D2") + "." + timeSpan.Milliseconds.ToString("D3"));
if (list.Count == 1)
{
list[0] += "s";
}
return string.Join(":", list);
}
private static void HandleLanding()
{
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
if ((bool)((ModSetting)logTimes).Value)
{
MelonLogger.Msg("Flight time: " + FormatTimeSpan(TimeSpan.FromSeconds(timer)));
}
isFlying = false;
if ((Object)(object)timerObject != (Object)null)
{
((Graphic)timerText).color = Color.green;
}
}
private static void CreateTimer()
{
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_0023: Expected O, but got Unknown
//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)timerObject == (Object)null))
{
return;
}
timerObject = new GameObject("FlightTimer");
timerText = timerObject.AddComponent<TextMeshPro>();
((TMP_Text)timerText).text = FormatTimeSpan(new TimeSpan(0L));
foreach (TMP_FontAsset item in Resources.FindObjectsOfTypeAll<TMP_FontAsset>())
{
if (((Object)item).name == "GOODDP__ SDF Global Text Material")
{
((TMP_Text)timerText).font = item;
break;
}
}
((TMP_Text)timerText).fontSize = 0.5f;
((Graphic)timerText).color = Color.white;
((TMP_Text)timerText).alignment = (TextAlignmentOptions)514;
((TMP_Text)timerText).enableWordWrapping = false;
if (!(bool)((ModSetting)displayTimer).SavedValue)
{
((TMP_Text)timerText).maxVisibleCharacters = 0;
}
}
public override void OnLateInitializeMelon()
{
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
//IL_004c: Expected O, but got Unknown
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
//IL_006c: Expected O, but got Unknown
//IL_0082: Unknown result type (might be due to invalid IL or missing references)
//IL_008c: Expected O, but got Unknown
//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
//IL_00ac: Expected O, but got Unknown
settings.ModName = "FlightTimer";
settings.ModVersion = "1.0.0";
settings.SetFolder("FlightTimer");
displayTimer = settings.AddToList("Display Timer", true, 0, "Disable to hide the timer. Times will still be logged if \"Log Times\" is true.", new Tags());
logTimes = settings.AddToList("Log Times", true, 0, "Enable to log flight times to the console.", new Tags());
swapHand = settings.AddToList("Swap Hand", false, 0, "Enable to display the timer on the right hand instead of the left.", new Tags());
displayAboveHealth = settings.AddToList("Display Above Health", false, 0, "Enable to display the timer above the health bar instead of either hand.", new Tags());
settings.GetFromFile();
((ModSetting)displayTimer).SavedValueChanged += OnDisplayTimerChange;
((ModSetting)displayAboveHealth).SavedValueChanged += OnDisplayAboveHealthChanged;
UI.instance.UI_Initialized += OnUIInit;
}
public static void OnUIInit()
{
UI.instance.AddMod(settings);
}
public static void OnDisplayTimerChange(object sender, EventArgs args)
{
if ((Object)(object)timerObject != (Object)null)
{
if (((ValueChange<bool>)(object)args).Value)
{
((TMP_Text)timerText).maxVisibleCharacters = 999;
}
else
{
((TMP_Text)timerText).maxVisibleCharacters = 0;
}
}
}
public static void OnDisplayAboveHealthChanged(object sender, EventArgs args)
{
if ((Object)(object)timerObject != (Object)null)
{
if (((ValueChange<bool>)(object)args).Value)
{
healthBar = null;
}
else
{
timerObject.transform.parent = null;
}
}
}
public override void OnSceneWasInitialized(int buildIndex, string sceneName)
{
healthBar = null;
CreateTimer();
}
public override void OnUpdate()
{
//IL_0230: Unknown result type (might be due to invalid IL or missing references)
//IL_023f: Unknown result type (might be due to invalid IL or missing references)
//IL_0244: Unknown result type (might be due to invalid IL or missing references)
//IL_0249: Unknown result type (might be due to invalid IL or missing references)
//IL_020e: 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_0181: Unknown result type (might be due to invalid IL or missing references)
//IL_017a: 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)
if (isFlying)
{
timer += Time.deltaTime;
if ((Object)(object)timerObject != (Object)null)
{
((TMP_Text)timerText).text = FormatTimeSpan(TimeSpan.FromSeconds(timer));
}
if (!takeoffChecked && timer > 1.0)
{
takeoffChecked = true;
if (Singleton<PlayerManager>.instance.localPlayer.Controller.GetSubsystem<PlayerMovement>().IsGrounded())
{
HandleLanding();
}
}
}
if ((Object)(object)timerObject == (Object)null)
{
CreateTimer();
}
if (!((Object)(object)timerObject != (Object)null) || !((Object)(object)Singleton<PlayerManager>.instance != (Object)null) || Singleton<PlayerManager>.instance.localPlayer == null || !((Object)(object)Singleton<PlayerManager>.instance.localPlayer.Controller != (Object)null))
{
return;
}
if (!(bool)((ModSetting)displayAboveHealth).SavedValue)
{
Transform child = ((Component)Singleton<PlayerManager>.instance.localPlayer.Controller).gameObject.transform.GetChild(1).GetChild((!(bool)((ModSetting)swapHand).SavedValue) ? 1 : 2);
timerObject.transform.position = child.position;
timerObject.transform.Translate(((bool)((ModSetting)swapHand).SavedValue) ? rightRelativeTranslate : leftRelativeTranslate, child);
timerObject.transform.Translate(globalTranslate, (Space)0);
}
else if ((Object)(object)healthBar == (Object)null)
{
healthBar = Singleton<PlayerManager>.instance.localPlayer.Controller.GetSubsystem<PlayerHealth>().localHealthbar;
if ((Object)(object)healthBar != (Object)null)
{
timerObject.transform.parent = healthBar.transform;
timerObject.transform.localPosition = healthRelativeTranslate;
}
}
timerObject.transform.rotation = Quaternion.LookRotation(timerObject.transform.position - ((Component)Camera.main).transform.position);
}
}