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 Pigeon.Movement; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("Sparroh")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("OuroBlitzRework")] [assembly: AssemblyTitle("OuroBlitzRework")] [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.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } internal static class BlitzPatches { [HarmonyPatch(typeof(OuroObjective), "SetupOnMissionStart")] private static class SetupOnMissionStart_Patch { private static bool Prefix(ref bool ___setupOnStart) { if (!IsBlitzMission) { return true; } if (___setupOnStart) { return false; } ___setupOnStart = true; OuroObjective.ContrabandsCollected = 0; BlitzSession.Begin(); return false; } } [HarmonyPatch(typeof(OuroObjective), "SaveMissionData")] private static class SaveMissionData_Patch { private static bool Prefix() { return !IsBlitzMission; } } [HarmonyPatch(typeof(OuroObjective), "OnMissionEnded")] private static class OnMissionEnded_Patch { private struct StatsSnapshot { public bool valid; public float lastOuroTime; public int lastOuroRooms; public int lastOuroKills; public float lastOuroDamage; public int lastOuroDeaths; public int lastOuroBosses; public int lastOuroLevels; public int lastOuroUpgrades; } private static void Prefix(ref StatsSnapshot __state) { __state = default(StatsSnapshot); if (IsBlitzMission && PlayerData.Instance != null) { ref OuroData ouroData = ref PlayerData.Instance.ouroData; __state = new StatsSnapshot { valid = true, lastOuroTime = ouroData.lastOuroTime, lastOuroRooms = ouroData.lastOuroRooms, lastOuroKills = ouroData.lastOuroKills, lastOuroDamage = ouroData.lastOuroDamage, lastOuroDeaths = ouroData.lastOuroDeaths, lastOuroBosses = ouroData.lastOuroBosses, lastOuroLevels = ouroData.lastOuroLevels, lastOuroUpgrades = ouroData.lastOuroUpgrades }; } } private static void Postfix(StatsSnapshot __state) { if (__state.valid && PlayerData.Instance != null) { ref OuroData ouroData = ref PlayerData.Instance.ouroData; ouroData.lastOuroTime = __state.lastOuroTime; ouroData.lastOuroRooms = __state.lastOuroRooms; ouroData.lastOuroKills = __state.lastOuroKills; ouroData.lastOuroDamage = __state.lastOuroDamage; ouroData.lastOuroDeaths = __state.lastOuroDeaths; ouroData.lastOuroBosses = __state.lastOuroBosses; ouroData.lastOuroLevels = __state.lastOuroLevels; ouroData.lastOuroUpgrades = __state.lastOuroUpgrades; } } } [HarmonyPatch(typeof(OuroObjective), "Activate")] private static class Activate_Patch { private struct ActivateSnapshot { public bool valid; public int missionType; public bool failedRun; public ulong lastOuroLobby; } private static void Prefix(ref ActivateSnapshot __state) { __state = default(ActivateSnapshot); if (IsBlitzMission && PlayerData.Instance != null) { __state = new ActivateSnapshot { valid = true, missionType = PlayerData.Instance.ouroData.missionType, failedRun = PlayerData.Instance.ouroData.failedRun, lastOuroLobby = PlayerData.Instance.lastOuroLobby }; } } private static void Postfix(ActivateSnapshot __state) { if (__state.valid && PlayerData.Instance != null) { PlayerData.Instance.ouroData.missionType = __state.missionType; PlayerData.Instance.ouroData.failedRun = __state.failedRun; PlayerData.Instance.lastOuroLobby = __state.lastOuroLobby; } } } [HarmonyPatch(typeof(OuroObjective), "OnFinalBossKilled_ClientRpc")] private static class OnFinalBossKilled_Patch { private static void Prefix(ref bool __state) { __state = IsBlitzMission && PlayerData.Instance != null; } private static void Postfix(bool __state) { if (__state && PlayerData.Instance != null) { PlayerData.Instance.ouroData.failedRun = false; } } } [HarmonyPatch(typeof(OuroObjective), "Setup")] private static class Setup_Patch { private struct SetupSnapshot { public bool valid; public string scene; public bool failedRun; } private static void Prefix(ref SetupSnapshot __state) { __state = default(SetupSnapshot); if (IsBlitzMission && PlayerData.Instance != null) { __state = new SetupSnapshot { valid = true, scene = PlayerData.Instance.ouroData.scene, failedRun = PlayerData.Instance.ouroData.failedRun }; } } private static void Postfix(SetupSnapshot __state) { if (__state.valid && PlayerData.Instance != null) { PlayerData.Instance.ouroData.scene = __state.scene; PlayerData.Instance.ouroData.failedRun = __state.failedRun; } } } [HarmonyPatch(typeof(PlayerData), "AddResource", new Type[] { typeof(PlayerResource), typeof(int), typeof(bool) })] private static class AddResource_Patch { private static bool Prefix(PlayerResource resource, int amount) { if (!IsBlitzRun || (Object)(object)resource == (Object)null || amount <= 0) { return true; } string iD = resource.ID; if (iD != "ourosample") { return iD != "ouroscrap"; } return false; } } [HarmonyPatch(typeof(OuroMission), "HasOnMissionCompleteScreensClosedCallback")] private static class HasCleanseCallback_Patch { private static bool Prefix(OuroMission __instance, ref bool __result) { if ((Object)(object)__instance != (Object)null && !__instance.AllowContinuing) { __result = false; return false; } return true; } } [HarmonyPatch(typeof(OuroMission), "OnMissionCompleteScreensClosed")] private static class OnMissionCompleteScreensClosed_Patch { private static bool Prefix(OuroMission __instance) { if (!((Object)(object)__instance == (Object)null)) { return __instance.AllowContinuing; } return true; } } [HarmonyPatch(typeof(PlayerData), "CollectInstance", new Type[] { typeof(UpgradeInstance), typeof(UnlockFlags) })] private static class CollectInstance_Patch { private static void Postfix(UpgradeInstance instance) { if (IsBlitzRun && instance != null && instance.RemoveAfterMission) { BlitzSession.TagTemp(instance); } } } [HarmonyPatch(typeof(UpgradeInstance), "Equip")] private static class UpgradeInstanceEquip_Patch { private static bool Prefix(UpgradeInstance __instance) { if (!IsBlitzRun || __instance == null || !__instance.RemoveAfterMission) { return true; } return BlitzSession.IsBlitzMarked(__instance); } } [HarmonyPatch(typeof(GearData), "EquipUpgrade")] private static class GearDataEquipUpgrade_Patch { private static bool Prefix(UpgradeInstance upgrade) { if (!IsBlitzRun || upgrade == null || !upgrade.RemoveAfterMission) { return true; } return BlitzSession.IsBlitzMarked(upgrade); } } [HarmonyPatch(typeof(OuroObjective), "GetWeightedRarity")] private static class GetWeightedRarity_Patch { private static void Postfix(ref Rarity __result) { if (IsBlitzRun && (int)__result == 5) { __result = (Rarity)3; } } } [HarmonyPatch(typeof(OuroObjective), "SpawnUpgrades_Client")] private static class SpawnUpgradesClient_Patch { private static void Prefix(ref bool finalBoss, ref float ___contrabandChance) { if (IsBlitzRun) { finalBoss = false; ___contrabandChance = -1f; } } } [HarmonyPatch(typeof(OuroChoiceWindow), "AddUpgrade")] private static class ChoiceAddUpgrade_Patch { private static bool Prefix(UpgradeInstance upgrade) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Invalid comparison between Unknown and I4 if (!IsBlitzRun || (Object)(object)((upgrade != null) ? upgrade.Upgrade : null) == (Object)null) { return true; } if ((int)upgrade.Upgrade.Rarity == 5) { try { upgrade.Destroy(); } catch { } return false; } BlitzSession.TagTemp(upgrade); return true; } } [HarmonyPatch(typeof(OuroObjective), "GiveUpgrade")] private static class GiveUpgrade_Patch { private static void Prefix(ref bool canCleanse) { if (IsBlitzRun) { canCleanse = false; } } } [HarmonyPatch(typeof(OuroObjective), "SpawnGearCollectable")] private static class SpawnGearCollectable_Patch { private static void Prefix(ref bool canCleanseUpgrades) { if (IsBlitzRun) { canCleanseUpgrades = false; } } } [HarmonyPatch(typeof(MissionManager), "OnMissionCompleted_ClientRpc")] private static class OnMissionCompleted_Patch { private static void Prefix() { if (IsBlitzRun || IsBlitzMission) { BlitzSession.End(grantRewards: true); } } } [HarmonyPatch(typeof(MissionManager), "OnFailMission_Client")] private static class OnFailMission_Patch { private static void Prefix() { if (IsBlitzRun || IsBlitzMission) { BlitzSession.End(grantRewards: false); } } } [HarmonyPatch(typeof(GameManager), "OnSceneLoadStart_ClientRpc")] private static class OnSceneLoadStart_Patch { private static void Prefix() { if (BlitzSession.IsActive) { BlitzSession.End(grantRewards: false); } } } [HarmonyPatch(typeof(OuroMission), "HasAdditionalData")] private static class HasAdditionalData_Patch { private static void Postfix(OuroMission __instance, int index, ref bool __result) { if ((Object)(object)__instance != (Object)null && !__instance.AllowContinuing && index == 0) { __result = false; } } } private static bool IsBlitzMission => BlitzSession.IsBlitzMission(); private static bool IsBlitzRun => BlitzSession.IsActive; } internal static class BlitzRewards { private const int RewardCount = 2; public static void TryGrantCompletionRewards(ManualLogSource log) { if (PlayerData.Instance == null) { return; } List list = new List(16); BlitzSession.CollectEquippedTaggedTemps(list); if (list.Count == 0) { if (log != null) { log.LogInfo((object)"Blitz complete: no equipped session upgrades to convert."); } return; } for (int num = list.Count - 1; num > 0; num--) { int index = Random.Range(0, num + 1); UpgradeInstance value = list[num]; list[num] = list[index]; list[index] = value; } int num2 = Mathf.Min(2, list.Count); int num3 = 0; for (int i = 0; i < num2; i++) { if (TryCreatePermanentCopy(list[i], log)) { num3++; } } if (log != null) { log.LogInfo((object)$"Blitz complete: granted {num3} permanent upgrade(s) from session."); } } private static bool TryCreatePermanentCopy(UpgradeInstance source, ManualLogSource log) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Invalid comparison between Unknown and I4 //IL_009d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)((source != null) ? source.Upgrade : null) == (Object)null || source.Gear == null) { return false; } if ((int)source.Upgrade.Rarity == 5) { return false; } IUpgradable gear = source.Gear; Upgrade upgrade = source.Upgrade; UpgradeInstance val = PlayerData.CollectInstance(gear, upgrade, (UnlockFlags)0); if (val == null) { if (log != null) { log.LogWarning((object)("Failed to collect permanent copy of " + upgrade.APIName + ".")); } return false; } val.RemoveAfterMission = false; val.RemoveOnQuit = false; val.CanCleanse = true; val.CanScrap = true; val.HasBeenSeen = true; if (!val.IsUnlocked) { val.Unlock(true); } ApplyRandomSameGearSameRarityPattern(val, gear, upgrade.Rarity, log); return true; } private static void ApplyRandomSameGearSameRarityPattern(UpgradeInstance target, IUpgradable gear, Rarity rarity, ManualLogSource log) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) if (target == null) { return; } object obj; if (gear == null) { obj = null; } else { GearInfo info = gear.Info; obj = ((info != null) ? info.Upgrades : null); } if (obj == null) { return; } List list = new List(gear.Info.Upgrades.Count); for (int i = 0; i < gear.Info.Upgrades.Count; i++) { Upgrade val = gear.Info.Upgrades[i]; if (val != null && !val.IsSkin() && val.Rarity == rarity) { HexMap pattern = val.GetPattern((UpgradeInstance)null, false); if (pattern != null && pattern.GetCellCount() > 0) { list.Add(val); } } } if (list.Count == 0) { if (log != null) { string[] obj2 = new string[5] { "No same-gear/same-rarity patterns for ", null, null, null, null }; Upgrade upgrade = target.Upgrade; obj2[1] = ((upgrade != null) ? upgrade.APIName : null); obj2[2] = " on "; GearInfo info2 = gear.Info; obj2[3] = ((info2 != null) ? info2.APIName : null); obj2[4] = "."; log.LogWarning((object)string.Concat(obj2)); } } else { Upgrade val2 = list[Random.Range(0, list.Count)]; if (list.Count > 1 && val2 == target.Upgrade) { int num = list.IndexOf(val2); val2 = list[(num + Random.Range(1, list.Count)) % list.Count]; } target.OverridePattern(val2); target.UpdatePatternSize(); } } } internal static class BlitzSession { private static readonly HashSet TaggedTempIds = new HashSet(); private static bool sessionActive; private static ManualLogSource log; public static bool IsActive { get { if (sessionActive) { return IsBlitzMission(); } return false; } } public static bool SuppressTagging { get; private set; } public static void Initialize(ManualLogSource logger) { log = logger; } public static bool IsBlitzMission() { try { Mission mission = ((MissionData)(ref MissionManager.CurrentMission)).Mission; OuroMission val = (OuroMission)(object)((mission is OuroMission) ? mission : null); if (val != null) { return !val.AllowContinuing; } } catch { } return false; } public static void Begin() { sessionActive = true; TaggedTempIds.Clear(); PurgeOrphanBlitzTemps(); UnequipForeignMissionTemps(); ManualLogSource obj = log; if (obj != null) { obj.LogInfo((object)"Blitz session started (Ouro continue/cleanse state will not be touched)."); } } public static bool IsBlitzMarked(UpgradeInstance instance) { if (instance == null || !instance.RemoveAfterMission) { return false; } if (!instance.RemoveOnQuit) { return TaggedTempIds.Contains(instance.InstanceID); } return true; } public static void UnequipForeignMissionTemps() { if (PlayerData.Instance == null) { return; } int num = 0; foreach (KeyValuePair> upgradeDatum in GetUpgradeData()) { List value = upgradeDatum.Value; if (value == null) { continue; } for (int i = 0; i < value.Count; i++) { List instances = value[i].Instances; if (instances == null) { continue; } for (int j = 0; j < instances.Count; j++) { UpgradeInstance val = instances[j]; if (val == null || !val.RemoveAfterMission || IsBlitzMarked(val)) { continue; } try { val.UnequipFromAll(); num++; } catch (Exception ex) { ManualLogSource obj = log; if (obj != null) { obj.LogWarning((object)$"Failed unequipping foreign mission temp {val.InstanceID}: {ex.Message}"); } } } } } if (num <= 0) { return; } try { if ((Object)(object)Player.LocalPlayer != (Object)null) { GearUtil.ReapplyUpgrades(); } } catch (Exception ex2) { ManualLogSource obj2 = log; if (obj2 != null) { obj2.LogWarning((object)("Reapply after foreign temp unequip failed: " + ex2.Message)); } } ManualLogSource obj3 = log; if (obj3 != null) { obj3.LogInfo((object)$"Unequipped {num} non-Blitz mission temp(s) for cleanse isolation."); } } public static void End(bool grantRewards) { if (!sessionActive && TaggedTempIds.Count == 0) { return; } try { if (grantRewards) { SuppressTagging = true; try { BlitzRewards.TryGrantCompletionRewards(log); } finally { SuppressTagging = false; } } } catch (Exception arg) { SuppressTagging = false; ManualLogSource obj = log; if (obj != null) { obj.LogError((object)$"Blitz reward grant failed: {arg}"); } } try { PurgeTaggedTemps(); } catch (Exception arg2) { ManualLogSource obj2 = log; if (obj2 != null) { obj2.LogError((object)$"Blitz temp purge failed: {arg2}"); } } TaggedTempIds.Clear(); sessionActive = false; ManualLogSource obj3 = log; if (obj3 != null) { obj3.LogInfo((object)(grantRewards ? "Blitz session ended (success)." : "Blitz session ended (no rewards).")); } } public static void TagTemp(UpgradeInstance instance) { if (!SuppressTagging && instance != null && instance.RemoveAfterMission) { instance.CanCleanse = false; instance.RemoveOnQuit = true; TaggedTempIds.Add(instance.InstanceID); } } public static bool IsTagged(UpgradeInstance instance) { if (instance != null) { return TaggedTempIds.Contains(instance.InstanceID); } return false; } public static void CollectEquippedTaggedTemps(List results) { results.Clear(); if (!((Object)(object)Player.LocalPlayer == (Object)null)) { IGear obj = Player.LocalPlayer.Gear[0]; TryAddEquippedFromGear((obj != null) ? ((IUpgradable)obj).Prefab : null, results); IGear obj2 = Player.LocalPlayer.Gear[1]; TryAddEquippedFromGear((obj2 != null) ? ((IUpgradable)obj2).Prefab : null, results); IGear obj3 = Player.LocalPlayer.Gear[3]; TryAddEquippedFromGear((obj3 != null) ? ((IUpgradable)obj3).Prefab : null, results); TryAddEquippedFromGear((IUpgradable)(object)Player.LocalPlayer.Character, results); TryAddEquippedFromGear((IUpgradable)(object)Global.Instance, results); } } private static void TryAddEquippedFromGear(IUpgradable gear, List results) { //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_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Invalid comparison between Unknown and I4 if (gear == null) { return; } GearData gearData = PlayerData.GetGearData(gear); if (gearData == null) { return; } int equippedUpgradeCount = gearData.EquippedUpgradeCount; for (int i = 0; i < equippedUpgradeCount; i++) { UpgradeEquipData equippedUpgrade = gearData.GetEquippedUpgrade(i); UpgradeInstance upgrade = ((UpgradeEquipData)(ref equippedUpgrade)).GetUpgrade(); if (upgrade != null && !upgrade.IsDestroyed() && upgrade.RemoveAfterMission && !((Object)(object)upgrade.Upgrade == (Object)null) && (int)upgrade.Upgrade.Rarity != 5 && (IsTagged(upgrade) || upgrade.RemoveOnQuit) && !results.Contains(upgrade)) { results.Add(upgrade); } } } private static void PurgeTaggedTemps() { if (PlayerData.Instance == null) { return; } List list = new List(); foreach (KeyValuePair> upgradeDatum in GetUpgradeData()) { List value = upgradeDatum.Value; if (value == null) { continue; } for (int i = 0; i < value.Count; i++) { List instances = value[i].Instances; if (instances == null) { continue; } for (int j = 0; j < instances.Count; j++) { UpgradeInstance val = instances[j]; if (val != null && (TaggedTempIds.Contains(val.InstanceID) || (val.RemoveAfterMission && val.RemoveOnQuit))) { list.Add(val); } } } } for (int k = 0; k < list.Count; k++) { try { list[k].UnequipFromAll(); list[k].Destroy(); } catch (Exception ex) { ManualLogSource obj = log; if (obj != null) { UpgradeInstance obj2 = list[k]; obj.LogWarning((object)$"Failed destroying Blitz temp {((obj2 != null) ? new int?(obj2.InstanceID) : ((int?)null))}: {ex.Message}"); } } } } private static void PurgeOrphanBlitzTemps() { if (PlayerData.Instance == null) { return; } List list = new List(); foreach (KeyValuePair> upgradeDatum in GetUpgradeData()) { List value = upgradeDatum.Value; if (value == null) { continue; } for (int i = 0; i < value.Count; i++) { List instances = value[i].Instances; if (instances == null) { continue; } for (int j = 0; j < instances.Count; j++) { UpgradeInstance val = instances[j]; if (val != null && val.RemoveAfterMission && val.RemoveOnQuit) { list.Add(val); } } } } for (int k = 0; k < list.Count; k++) { try { list[k].UnequipFromAll(); list[k].Destroy(); } catch { } } } private static Dictionary> GetUpgradeData() { Dictionary> dictionary = new Dictionary>(); foreach (KeyValuePair item in PlayerData.Instance.collectedGear) { GearData value = item.Value; IUpgradable val = ((value != null) ? value.Gear : null); if (val != null) { List allUpgrades = PlayerData.GetAllUpgrades(val, false); if (allUpgrades != null && allUpgrades.Count != 0) { List list = new List(allUpgrades.Count); list.AddRange(allUpgrades); dictionary[item.Key] = list; } } } List allUpgrades2 = PlayerData.GetAllUpgrades((IUpgradable)(object)Global.Instance, false); if (allUpgrades2 != null && allUpgrades2.Count > 0) { List list2 = new List(allUpgrades2.Count); list2.AddRange(allUpgrades2); dictionary[Global.Instance.Info.ID] = list2; } return dictionary; } } [BepInPlugin("sparroh.ouroblitzrework", "OuroBlitzRework", "1.0.0")] [MycoMod(/*Could not decode attribute arguments.*/)] public class SparrohPlugin : BaseUnityPlugin { public const string PluginGUID = "sparroh.ouroblitzrework"; public const string PluginName = "OuroBlitzRework"; public const string PluginVersion = "1.0.0"; internal static ManualLogSource Log; private Harmony harmony; private void Awake() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; BlitzSession.Initialize(Log); harmony = new Harmony("sparroh.ouroblitzrework"); try { harmony.PatchAll(typeof(BlitzPatches).Assembly); Log.LogInfo((object)"OuroBlitzRework v1.0.0 loaded successfully."); } catch (Exception arg) { Log.LogError((object)$"Error applying patches: {arg}"); } } private void OnDestroy() { Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } } } namespace OuroBlitzRework { public static class MyPluginInfo { public const string PLUGIN_GUID = "OuroBlitzRework"; public const string PLUGIN_NAME = "OuroBlitzRework"; public const string PLUGIN_VERSION = "1.0.0"; } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }