using System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Bootstrap; using HarmonyLib; using Microsoft.CodeAnalysis; using RoR2; 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("AerosSkillsTurretCompat")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("AerosSkillsTurretCompat")] [assembly: AssemblyTitle("AerosSkillsTurretCompat")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.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] [Microsoft.CodeAnalysis.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] [Microsoft.CodeAnalysis.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 AerosSkillsTurretCompat { [BepInPlugin("stimmchen.AerosSkillsTurretCompat", "AerosSkills Turret Compat", "1.2.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { private readonly struct SpawnRecord { public readonly float Time; public readonly Vector3 Position; public SpawnRecord(float time, Vector3 position) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) Time = time; Position = position; } } [HarmonyPatch(typeof(CharacterMaster), "AddDeployable")] private static class CharacterMasterAddDeployablePatch { private static void Postfix(CharacterMaster __instance, Deployable deployable, DeployableSlot slot) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)__instance == (Object)null) && !((Object)(object)deployable == (Object)null) && TryGetAerosBigTurretSlot(out var slot2) && slot == slot2 && !TrySuppressLikelyDuplicateSpawn(__instance, deployable)) { TryAttachSyncedComponent(__instance, deployable); TryApplyInfusionInheritance(__instance, deployable); } } } public const string PluginGuid = "stimmchen.AerosSkillsTurretCompat"; public const string PluginName = "AerosSkills Turret Compat"; public const string PluginVersion = "1.2.0"; private const string AerosGuid = "com.Dragonyck.AerosSkills"; private const string SyncedGuid = "com.WPhantom.SyncedTurrets"; private const string InfusedGuid = "Chinchi.InfusedTurrets"; private const string TurretDeathNoteGuid = "Watch_Me_Be_Meh.TurretDeathNote"; private static Plugin? _instance; private static FieldInfo? _aerosBigTurretField; private static Type? _syncedTurretsType; private static FieldInfo? _syncedCharacterMasterField; private static MethodInfo? _syncedInitMethod; private static bool _hasSynced; private static bool _hasInfused; private static bool _hasTurretDeathNote; private static MethodInfo? _tdnDeathHandlerMethod; private const float DuplicateSpawnWindowSeconds = 0.3f; private const float DuplicateSpawnDistanceMeters = 1f; private static readonly Dictionary LastAerosSpawnByOwner = new Dictionary(); private void Awake() { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Expected O, but got Unknown _instance = this; Harmony val = new Harmony("stimmchen.AerosSkillsTurretCompat"); _hasSynced = Chainloader.PluginInfos.ContainsKey("com.WPhantom.SyncedTurrets"); _hasInfused = Chainloader.PluginInfos.ContainsKey("Chinchi.InfusedTurrets"); _hasTurretDeathNote = Chainloader.PluginInfos.ContainsKey("Watch_Me_Be_Meh.TurretDeathNote"); Type type = AccessTools.TypeByName("AerosSkills.Prefabs"); _aerosBigTurretField = (((object)type != null) ? AccessTools.Field(type, "bigTurret") : null); if (_hasSynced) { _syncedTurretsType = AccessTools.TypeByName("SyncedTurrets.SyncTurrets"); _syncedCharacterMasterField = ((_syncedTurretsType != null) ? AccessTools.Field(_syncedTurretsType, "characterMaster") : null); _syncedInitMethod = ((_syncedTurretsType != null) ? AccessTools.Method(_syncedTurretsType, "Init", (Type[])null, (Type[])null) : null); } if (_hasTurretDeathNote) { Type type2 = AccessTools.TypeByName("TurretDeathNote.TurretDeathNote"); Type type3 = AccessTools.TypeByName("TurretDeathNote.TurretDeathNote+<>c"); if (type2 != null && type3 != null) { _tdnDeathHandlerMethod = AccessTools.Method(type3, "b__6_0", (Type[])null, (Type[])null); if (_tdnDeathHandlerMethod != null) { HarmonyMethod val2 = new HarmonyMethod(typeof(Plugin), "TurretDeathNoteDeathHandlerFinalizer", (Type[])null); val.Patch((MethodBase)_tdnDeathHandlerMethod, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, val2, (HarmonyMethod)null); } } else { ((BaseUnityPlugin)this).Logger.LogWarning((object)"TurretDeathNote detected but type lookup failed."); } GlobalEventManager.onCharacterDeathGlobal += OnCharacterDeathGlobalCompat; } val.PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Loaded. Aeros slot hook active. Synced_Turrets present={_hasSynced}, InfusedTurrets present={_hasInfused}, TurretDeathNote present={_hasTurretDeathNote}"); } private void OnDestroy() { if (_hasTurretDeathNote) { GlobalEventManager.onCharacterDeathGlobal -= OnCharacterDeathGlobalCompat; } } private static bool TryGetAerosBigTurretSlot(out DeployableSlot slot) { //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_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected I4, but got Unknown slot = (DeployableSlot)0; if (_aerosBigTurretField == null) { return false; } try { object value = _aerosBigTurretField.GetValue(null); if (value is DeployableSlot) { DeployableSlot val = (DeployableSlot)value; slot = (DeployableSlot)(int)val; return true; } } catch (Exception arg) { Plugin? instance = _instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogError((object)$"Failed reading AerosSkills bigTurret slot: {arg}"); } } return false; } private static void TryAttachSyncedComponent(CharacterMaster ownerMaster, Deployable deployable) { if (!_hasSynced || _syncedTurretsType == null) { return; } GameObject gameObject = ((Component)deployable).gameObject; if ((Object)(object)gameObject == (Object)null) { return; } try { if ((Object)(object)gameObject.GetComponent(_syncedTurretsType) != (Object)null) { return; } Component val = gameObject.AddComponent(_syncedTurretsType); if (!((Object)(object)val == (Object)null)) { _syncedCharacterMasterField?.SetValue(val, ownerMaster); _syncedInitMethod?.Invoke(val, null); Plugin? instance = _instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogInfo((object)("Synced_Turrets compat attached to " + ((Object)((Component)deployable).gameObject).name + " for owner " + ((Object)ownerMaster).name + ".")); } } } catch (Exception arg) { Plugin? instance2 = _instance; if (instance2 != null) { ((BaseUnityPlugin)instance2).Logger.LogError((object)$"Failed attaching Synced_Turrets component: {arg}"); } } } private static void TryApplyInfusionInheritance(CharacterMaster ownerMaster, Deployable deployable) { if (!_hasInfused) { return; } try { CharacterMaster component = ((Component)deployable).GetComponent(); Inventory val = ((component != null) ? component.inventory : null); Inventory inventory = ownerMaster.inventory; if ((Object)(object)val == (Object)null || (Object)(object)inventory == (Object)null) { return; } uint infusionBonus = inventory.infusionBonus; if (infusionBonus != 0) { val.AddInfusionBonus(infusionBonus); Plugin? instance = _instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogInfo((object)$"InfusedTurrets compat copied infusionBonus={infusionBonus} to {((Object)((Component)deployable).gameObject).name}."); } } } catch (Exception arg) { Plugin? instance2 = _instance; if (instance2 != null) { ((BaseUnityPlugin)instance2).Logger.LogError((object)$"Failed applying InfusedTurrets compatibility: {arg}"); } } } private static Exception? TurretDeathNoteDeathHandlerFinalizer(Exception __exception) { if (__exception is MissingFieldException) { Plugin? instance = _instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogWarning((object)"Suppressed TurretDeathNote MissingFieldException on this RoR2 build."); } return null; } return __exception; } private static bool TrySuppressLikelyDuplicateSpawn(CharacterMaster ownerMaster, Deployable deployable) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) int instanceID = ((Object)ownerMaster).GetInstanceID(); float unscaledTime = Time.unscaledTime; Vector3 position = ((Component)deployable).transform.position; if (LastAerosSpawnByOwner.TryGetValue(instanceID, out var value)) { bool num = unscaledTime - value.Time <= 0.3f; bool flag = Vector3.Distance(position, value.Position) <= 1f; if (num && flag) { ownerMaster.RemoveDeployable(deployable); CharacterMaster component = ((Component)deployable).GetComponent(); if ((Object)(object)component != (Object)null) { component.TrueKill(); } else { Object.Destroy((Object)(object)((Component)deployable).gameObject); } Plugin? instance = _instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogWarning((object)$"Suppressed duplicate Aeros turret spawn for owner {((Object)ownerMaster).name} at {position}."); } return true; } } LastAerosSpawnByOwner[instanceID] = new SpawnRecord(unscaledTime, position); return false; } private static void OnCharacterDeathGlobalCompat(DamageReport report) { if (!_hasTurretDeathNote || (Object)(object)report?.victimMaster == (Object)null || !IsAerosTurretVictim(report.victimMaster)) { return; } try { string attackerName = GetAttackerName(report); if (attackerName != "???") { Chat.AddMessage("Engineer's turret was killed by: " + attackerName); } else { Chat.AddMessage("damageReport.damageInfo.inflictor: " + (object)report.damageInfo.inflictor); } } catch (Exception arg) { Plugin? instance = _instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogError((object)$"Failed TurretDeathNote compatibility handler: {arg}"); } } } private static bool IsAerosTurretVictim(CharacterMaster victimMaster) { string text = (Object.op_Implicit((Object)(object)victimMaster.bodyPrefab) ? ((Object)victimMaster.bodyPrefab).name : null); if (!string.IsNullOrEmpty(text) && text.Contains("AerosBigTurretBody", StringComparison.Ordinal)) { return true; } string text2 = (Object.op_Implicit((Object)(object)((Component)victimMaster).gameObject) ? ((Object)((Component)victimMaster).gameObject).name : null); if (!string.IsNullOrEmpty(text2) && text2.Contains("AerosBigTurretMaster", StringComparison.Ordinal)) { return true; } return false; } private static string GetAttackerName(DamageReport report) { if ((Object)(object)report.attackerMaster != (Object)null) { PlayerCharacterMasterController playerCharacterMasterController = report.attackerMaster.playerCharacterMasterController; if ((Object)(object)playerCharacterMasterController != (Object)null && (Object)(object)playerCharacterMasterController.networkUser != (Object)null) { return playerCharacterMasterController.networkUser.userName; } if ((Object)(object)report.attackerBody != (Object)null) { return Util.GetBestBodyName(((Component)report.attackerBody).gameObject); } } if ((Object)(object)report.attacker != (Object)null) { return Util.GetBestBodyName(report.attacker); } return "???"; } } }