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 RaiseToUpgrade v0.1.0
BepInEx\plugins\RaiseToUpgrade\RaiseToUpgrade.dll
Decompiled a day 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 UnityEngine; [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("artrointel")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Hold up a shop upgrade and look skyward for two seconds to claim a free personal +1 each shop.")] [assembly: AssemblyFileVersion("0.1.0.0")] [assembly: AssemblyInformationalVersion("0.1.0+4d5a3c5223e0f5bf2d8471f0d16f72805a00cdb8")] [assembly: AssemblyProduct("RaiseToUpgrade")] [assembly: AssemblyTitle("RaiseToUpgrade")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.1.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 RaiseToUpgrade { [HarmonyPatch(typeof(ItemUpgrade), "Start")] internal static class ItemUpgradePatch { private static readonly IReadOnlyDictionary<string, string> UpgradeNames = new Dictionary<string, string> { ["ItemUpgradeDeathHeadBattery"] = "DeathHeadBattery", ["ItemUpgradeMapPlayerCount"] = "MapPlayerCount", ["ItemUpgradePlayerCrouchRest"] = "CrouchRest", ["ItemUpgradePlayerEnergy"] = "Stamina", ["ItemUpgradePlayerExtraJump"] = "ExtraJump", ["ItemUpgradePlayerGrabRange"] = "Range", ["ItemUpgradePlayerGrabStrength"] = "Strength", ["ItemUpgradePlayerGrabThrow"] = "Throw", ["ItemUpgradePlayerHealth"] = "Health", ["ItemUpgradePlayerSprintSpeed"] = "Speed", ["ItemUpgradePlayerTumbleClimb"] = "TumbleClimb", ["ItemUpgradePlayerTumbleLaunch"] = "Launch", ["ItemUpgradePlayerTumbleWings"] = "TumbleWings" }; [HarmonyPostfix] private static void Postfix(ItemUpgrade __instance) { if ((Object)(object)((Component)__instance).GetComponent<UpgradeEffectCarrier>() != (Object)null || (Object)(object)((Component)__instance).GetComponent<UpgradeHoldTracker>() != (Object)null) { return; } PhysGrabObject component = ((Component)__instance).GetComponent<PhysGrabObject>(); if ((Object)(object)component == (Object)null) { return; } MonoBehaviour[] components = ((Component)__instance).GetComponents<MonoBehaviour>(); foreach (MonoBehaviour val in components) { if ((Object)(object)val != (Object)null && UpgradeNames.TryGetValue(((object)val).GetType().Name, out string value)) { UpgradeHoldTracker upgradeHoldTracker = ((Component)__instance).gameObject.AddComponent<UpgradeHoldTracker>(); upgradeHoldTracker.Initialize(__instance, component, value); break; } } } } [BepInPlugin("artrointel.RaiseToUpgrade", "RaiseToUpgrade", "0.1.0")] public sealed class Plugin : BaseUnityPlugin { public const string PluginGuid = "artrointel.RaiseToUpgrade"; public const string PluginName = "RaiseToUpgrade"; public const string PluginVersion = "0.1.0"; private Harmony? _harmony; internal static ManualLogSource ModLogger { get; private set; } private void Awake() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown ModLogger = ((BaseUnityPlugin)this).Logger; _harmony = new Harmony("artrointel.RaiseToUpgrade"); _harmony.PatchAll(); ModLogger.LogInfo((object)"RaiseToUpgrade v0.1.0 loaded."); } private void Update() { ShopUpgradeService.TickShopState(); } private void OnDestroy() { Harmony? harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } } internal static class ShopUpgradeService { private sealed class PreparedUpgrade { internal int SourceInstanceId { get; } internal string UpgradeName { get; } internal GameObject Carrier { get; } internal PreparedUpgrade(int sourceInstanceId, string upgradeName, GameObject carrier) { SourceInstanceId = sourceInstanceId; UpgradeName = upgradeName; Carrier = carrier; } } private const string SetPositionRpcName = "SetPositionRPC"; private const string ToggleItemRpcName = "ToggleItemRPC"; private static readonly Vector3 CarrierStagingOffset = new Vector3(4096f, 4096f, 4096f); private static readonly HashSet<string> ClaimedPlayers = new HashSet<string>(StringComparer.Ordinal); private static readonly Dictionary<string, PreparedUpgrade> PreparedByPlayer = new Dictionary<string, PreparedUpgrade>(StringComparer.Ordinal); private static bool _wasInShop; internal static bool IsHostInShop { get { if ((Object)(object)RunManager.instance != (Object)null && (Object)(object)GameManager.instance != (Object)null && SemiFunc.RunIsShop()) { return SemiFunc.IsMasterClientOrSingleplayer(); } return false; } } internal static void TickShopState() { if ((Object)(object)RunManager.instance == (Object)null) { ClearPreparedUpgrades(); _wasInShop = false; return; } bool flag = SemiFunc.RunIsShop(); if (flag && !_wasInShop) { ClearPreparedUpgrades(); ClaimedPlayers.Clear(); Plugin.ModLogger.LogInfo((object)"Entered the shop. Every player may claim one held upgrade."); } else if (!flag && _wasInShop) { ClearPreparedUpgrades(); } _wasInShop = flag; } internal static bool HasClaimed(string steamId) { return ClaimedPlayers.Contains(steamId); } internal static bool EnsurePrepared(ItemUpgrade sourceUpgrade, PlayerAvatar playerAvatar, string upgradeName) { if (!IsHostInShop) { return false; } string text = SemiFunc.PlayerGetSteamID(playerAvatar); if (string.IsNullOrWhiteSpace(text) || HasClaimed(text)) { return false; } int instanceID = ((Object)sourceUpgrade).GetInstanceID(); if (PreparedByPlayer.TryGetValue(text, out PreparedUpgrade value)) { if (value.SourceInstanceId == instanceID && value.UpgradeName == upgradeName && (Object)(object)value.Carrier != (Object)null) { return true; } PreparedByPlayer.Remove(text); DestroyCarrier(value.Carrier); } GameObject carrier; try { carrier = CreateCarrier(sourceUpgrade, upgradeName); } catch (Exception arg) { Plugin.ModLogger.LogError((object)$"Could not prepare {upgradeName} feedback for {text}: {arg}"); return false; } PreparedByPlayer[text] = new PreparedUpgrade(instanceID, upgradeName, carrier); return false; } internal static void CancelPreparation(string steamId, ItemUpgrade sourceUpgrade) { if (!string.IsNullOrWhiteSpace(steamId) && PreparedByPlayer.TryGetValue(steamId, out PreparedUpgrade value) && value.SourceInstanceId == ((Object)sourceUpgrade).GetInstanceID()) { PreparedByPlayer.Remove(steamId); DestroyCarrier(value.Carrier); } } internal static void CancelPreparationsForSource(ItemUpgrade sourceUpgrade) { int instanceID = ((Object)sourceUpgrade).GetInstanceID(); List<string> list = new List<string>(); foreach (KeyValuePair<string, PreparedUpgrade> item in PreparedByPlayer) { if (item.Value.SourceInstanceId == instanceID) { list.Add(item.Key); } } foreach (string item2 in list) { PreparedUpgrade preparedUpgrade = PreparedByPlayer[item2]; PreparedByPlayer.Remove(item2); DestroyCarrier(preparedUpgrade.Carrier); } } internal static bool TryClaim(ItemUpgrade sourceUpgrade, PlayerAvatar playerAvatar, string upgradeName) { if (!IsHostInShop) { return false; } string text = SemiFunc.PlayerGetSteamID(playerAvatar); if (string.IsNullOrWhiteSpace(text) || HasClaimed(text)) { return false; } if (!PreparedByPlayer.TryGetValue(text, out PreparedUpgrade value) || value.SourceInstanceId != ((Object)sourceUpgrade).GetInstanceID() || value.UpgradeName != upgradeName || (Object)(object)value.Carrier == (Object)null) { return false; } ClaimedPlayers.Add(text); PreparedByPlayer.Remove(text); try { TriggerVanillaUpgrade(value.Carrier, sourceUpgrade, playerAvatar); Plugin.ModLogger.LogInfo((object)("Played vanilla " + upgradeName + " +1 use for " + SemiFunc.PlayerGetName(playerAvatar) + " (" + text + ").")); return true; } catch (Exception arg) { ClaimedPlayers.Remove(text); DestroyCarrier(value.Carrier); Plugin.ModLogger.LogError((object)$"Failed to grant {upgradeName} +1 to player {text}: {arg}"); return false; } } private static GameObject CreateCarrier(ItemUpgrade sourceUpgrade, string upgradeName) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: 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_002d: 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) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0040: 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_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) Item item = sourceUpgrade.itemAttributes.item; Vector3 val = ((Component)sourceUpgrade).transform.position + CarrierStagingOffset; Quaternion rotation = ((Component)sourceUpgrade).transform.rotation; GameObject val2 = ((!SemiFunc.IsMultiplayer()) ? Object.Instantiate<GameObject>(((PrefabRef<GameObject>)(object)item.prefab).Prefab, val, rotation) : PhotonNetwork.InstantiateRoomObject(((PrefabRef<GameObject>)(object)item.prefab).ResourcePath, val, rotation, (byte)0, (object[])null)); if ((Object)(object)val2 == (Object)null) { throw new InvalidOperationException("Could not prepare the vanilla effect carrier for " + upgradeName + "."); } val2.AddComponent<UpgradeEffectCarrier>(); Rigidbody component = val2.GetComponent<Rigidbody>(); if ((Object)(object)component != (Object)null) { component.velocity = Vector3.zero; component.angularVelocity = Vector3.zero; component.detectCollisions = false; component.isKinematic = true; } Collider[] componentsInChildren = val2.GetComponentsInChildren<Collider>(); foreach (Collider val3 in componentsInChildren) { val3.enabled = false; } return val2; } private static void TriggerVanillaUpgrade(GameObject carrier, ItemUpgrade sourceUpgrade, PlayerAvatar playerAvatar) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: 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) ItemToggle component = carrier.GetComponent<ItemToggle>(); PhysGrabObject component2 = carrier.GetComponent<PhysGrabObject>(); if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null) { throw new MissingComponentException("The prepared vanilla effect carrier is missing required components."); } string name = ((Object)sourceUpgrade.itemAttributes.item).name; int value; bool hadPurchasedEntry = StatsManager.instance.itemsPurchased.TryGetValue(name, out value); try { Vector3 position = ((Component)sourceUpgrade).transform.position; Quaternion rotation = ((Component)sourceUpgrade).transform.rotation; int viewID = playerAvatar.photonView.ViewID; if (SemiFunc.IsMultiplayer()) { PhotonView component3 = carrier.GetComponent<PhotonView>(); if ((Object)(object)component3 == (Object)null || component3.ViewID == 0) { throw new MissingComponentException("The prepared effect carrier has no networked PhotonView."); } component3.RPC("SetPositionRPC", (RpcTarget)0, new object[2] { position, rotation }); component3.RPC("ToggleItemRPC", (RpcTarget)0, new object[2] { true, viewID }); } else { component2.SetPositionLogic(position, rotation); component.ToggleItemLogic(true, viewID); } } finally { RestorePurchasedItemCount(name, hadPurchasedEntry, value); } } private static void RestorePurchasedItemCount(string itemName, bool hadPurchasedEntry, int originalCount) { if (hadPurchasedEntry) { StatsManager.instance.itemsPurchased[itemName] = originalCount; } else { StatsManager.instance.itemsPurchased.Remove(itemName); } } private static void ClearPreparedUpgrades() { if (PreparedByPlayer.Count == 0) { return; } foreach (PreparedUpgrade value in PreparedByPlayer.Values) { DestroyCarrier(value.Carrier); } PreparedByPlayer.Clear(); } private static void DestroyCarrier(GameObject? carrier) { if ((Object)(object)carrier == (Object)null) { return; } try { if (SemiFunc.IsMultiplayer()) { PhotonNetwork.Destroy(carrier); } else { Object.Destroy((Object)(object)carrier); } } catch (Exception arg) { Plugin.ModLogger.LogWarning((object)$"Could not clean up a prepared upgrade effect carrier: {arg}"); } } } internal sealed class UpgradeEffectCarrier : MonoBehaviour { } [HarmonyPatch(typeof(ShopManager), "ShoppingListItemAdd")] internal static class UpgradeEffectCarrierShopPatch { [HarmonyPrefix] private static bool Prefix(ItemAttributes item) { if (!((Object)(object)item == (Object)null)) { return (Object)(object)((Component)item).GetComponent<UpgradeEffectCarrier>() == (Object)null; } return true; } } internal sealed class UpgradeHoldTracker : MonoBehaviour { internal const float RequiredHoldSeconds = 2f; internal const float MinimumLookUpDot = 0.8660254f; private readonly Dictionary<string, float> _holdSeconds = new Dictionary<string, float>(); private readonly HashSet<string> _currentlyGrabbing = new HashSet<string>(); private readonly HashSet<string> _previouslyGrabbing = new HashSet<string>(); private readonly List<string> _stalePlayers = new List<string>(); private readonly List<PhysGrabber> _pendingReleases = new List<PhysGrabber>(); private PhysGrabObject _physGrabObject; private ItemUpgrade _itemUpgrade; private string _upgradeName = string.Empty; internal void Initialize(ItemUpgrade itemUpgrade, PhysGrabObject physGrabObject, string upgradeName) { _itemUpgrade = itemUpgrade; _physGrabObject = physGrabObject; _upgradeName = upgradeName; } private void Update() { if ((Object)(object)_physGrabObject == (Object)null || !ShopUpgradeService.IsHostInShop) { CancelTrackedPreparations(); _holdSeconds.Clear(); return; } _currentlyGrabbing.Clear(); _pendingReleases.Clear(); foreach (PhysGrabber item in _physGrabObject.playerGrabbing) { if ((Object)(object)item == (Object)null || (Object)(object)item.playerAvatar == (Object)null) { continue; } PlayerAvatar playerAvatar = item.playerAvatar; string text = SemiFunc.PlayerGetSteamID(playerAvatar); if (string.IsNullOrWhiteSpace(text) || ShopUpgradeService.HasClaimed(text) || !_currentlyGrabbing.Add(text)) { continue; } if (!ShopUpgradeService.EnsurePrepared(_itemUpgrade, playerAvatar, _upgradeName)) { _holdSeconds.Remove(text); continue; } if (!IsLookingUp(playerAvatar)) { _holdSeconds.Remove(text); continue; } _holdSeconds.TryGetValue(text, out var value); value += Time.unscaledDeltaTime; _holdSeconds[text] = value; if (value >= 2f && ShopUpgradeService.TryClaim(_itemUpgrade, playerAvatar, _upgradeName)) { _holdSeconds.Remove(text); _pendingReleases.Add(item); } } RemoveInterruptedHolds(); ReleaseSuccessfulPlayers(); } private static bool IsLookingUp(PlayerAvatar playerAvatar) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) PlayerLocalCamera localCamera = playerAvatar.localCamera; if ((Object)(object)localCamera == (Object)null) { return false; } return Vector3.Dot(((Component)localCamera).transform.forward, Vector3.up) >= 0.8660254f; } private void RemoveInterruptedHolds() { _stalePlayers.Clear(); foreach (string key in _holdSeconds.Keys) { if (!_currentlyGrabbing.Contains(key)) { _stalePlayers.Add(key); } } foreach (string stalePlayer in _stalePlayers) { _holdSeconds.Remove(stalePlayer); } _stalePlayers.Clear(); foreach (string item in _previouslyGrabbing) { if (!_currentlyGrabbing.Contains(item)) { _stalePlayers.Add(item); } } foreach (string stalePlayer2 in _stalePlayers) { ShopUpgradeService.CancelPreparation(stalePlayer2, _itemUpgrade); } _previouslyGrabbing.Clear(); _previouslyGrabbing.UnionWith(_currentlyGrabbing); } private void ReleaseSuccessfulPlayers() { int num = (((Object)(object)_physGrabObject.photonView != (Object)null) ? _physGrabObject.photonView.ViewID : (-1)); foreach (PhysGrabber pendingRelease in _pendingReleases) { if (!((Object)(object)pendingRelease == (Object)null)) { try { pendingRelease.OverrideGrabRelease(num, 0.25f); } catch (Exception arg) { Plugin.ModLogger.LogWarning((object)$"Upgrade was granted, but the held item could not be released: {arg}"); } } } _pendingReleases.Clear(); } private void OnDestroy() { CancelTrackedPreparations(); if ((Object)(object)_itemUpgrade != (Object)null) { ShopUpgradeService.CancelPreparationsForSource(_itemUpgrade); } } private void CancelTrackedPreparations() { if ((Object)(object)_itemUpgrade == (Object)null) { return; } foreach (string item in _previouslyGrabbing) { ShopUpgradeService.CancelPreparation(item, _itemUpgrade); } foreach (string item2 in _currentlyGrabbing) { ShopUpgradeService.CancelPreparation(item2, _itemUpgrade); } _previouslyGrabbing.Clear(); _currentlyGrabbing.Clear(); } } }