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 ShoutAtHawks v1.0.0
plugins/ShoutAtHawks.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 BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Unity.Collections; using Unity.Netcode; using UnityEngine; using UnityEngine.AI; [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("ShoutAtHawks")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("ShoutAtHawks")] [assembly: AssemblyTitle("ShoutAtHawks")] [assembly: AssemblyVersion("1.0.0.0")] [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; } } } namespace ShoutAtHawks { internal sealed class HawkFear : MonoBehaviour { private const float FleeStepDistance = 25f; private const float ReportCooldownSeconds = 1f; private const int HawkCawNoiseId = 1105; private static readonly float[] FleeAngles = new float[9] { 0f, 30f, -30f, 60f, -60f, 90f, -90f, 135f, -135f }; private const BindingFlags Private = BindingFlags.Instance | BindingFlags.NonPublic; private static readonly FieldInfo MiscAnimationTimer = typeof(BaboonBirdAI).GetField("miscAnimationTimer", BindingFlags.Instance | BindingFlags.NonPublic); private static readonly FieldInfo CurrentMiscAnimation = typeof(BaboonBirdAI).GetField("currentMiscAnimation", BindingFlags.Instance | BindingFlags.NonPublic); private static readonly FieldInfo EyesClosed = typeof(BaboonBirdAI).GetField("eyesClosed", BindingFlags.Instance | BindingFlags.NonPublic); private static readonly FieldInfo RestingAtCamp = typeof(BaboonBirdAI).GetField("restingAtCamp", BindingFlags.Instance | BindingFlags.NonPublic); private static readonly FieldInfo DoingKillAnimation = typeof(BaboonBirdAI).GetField("doingKillAnimation", BindingFlags.Instance | BindingFlags.NonPublic); private static readonly MethodInfo StopFocusingThreat = typeof(BaboonBirdAI).GetMethod("StopFocusingThreat", BindingFlags.Instance | BindingFlags.NonPublic); private static readonly MethodInfo SetAggressiveMode = typeof(BaboonBirdAI).GetMethod("SetAggressiveMode", BindingFlags.Instance | BindingFlags.NonPublic); private BaboonBirdAI hawk; private NavMeshPath path; private float scaredUntil; private float braveUntil; private float nextReportAt; private float fleeSpeed; private Vector3 noisePosition; private Vector3 fleePoint; private bool hasFleePoint; public BaboonBirdAI Hawk => hawk; public bool IsScared => Time.time < scaredUntil; public bool CanBeScared { get { if (!IsScared && Time.time >= braveUntil && !((EnemyAI)hawk).isEnemyDead && !((EnemyAI)hawk).inSpecialAnimation && ((EnemyAI)hawk).stunNormalizedTimer <= 0f) { return !(bool)DoingKillAnimation.GetValue(hawk); } return false; } } public static HawkFear For(BaboonBirdAI hawk) { HawkFear hawkFear = ((Component)hawk).GetComponent<HawkFear>(); if ((Object)(object)hawkFear == (Object)null) { hawkFear = ((Component)hawk).gameObject.AddComponent<HawkFear>(); hawkFear.hawk = hawk; } return hawkFear; } public bool TryStartReport() { if (Time.time < nextReportAt) { return false; } nextReportAt = Time.time + 1f; return true; } public void Scare(Vector3 position, float seconds, float speed, float braveSeconds) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) noisePosition = position; fleeSpeed = speed; hasFleePoint = false; scaredUntil = Time.time + seconds; braveUntil = scaredUntil + braveSeconds; MiscAnimationTimer.SetValue(hawk, 0f); CurrentMiscAnimation.SetValue(hawk, -1); EyesClosed.SetValue(hawk, false); RestingAtCamp.SetValue(hawk, false); if ((Object)(object)((EnemyAI)hawk).creatureAnimator != (Object)null) { ((EnemyAI)hawk).creatureAnimator.SetBool("sit", false); ((EnemyAI)hawk).creatureAnimator.SetBool("sleep", false); } if ((Object)(object)((EnemyAI)hawk).creatureVoice != (Object)null && hawk.cawScreamSFX != null && hawk.cawScreamSFX.Length != 0) { RoundManager.PlayRandomClip(((EnemyAI)hawk).creatureVoice, hawk.cawScreamSFX, true, 1f, 1105, 1000); } if (((NetworkBehaviour)hawk).IsOwner) { DropEverythingAndRun(); } } private void DropEverythingAndRun() { if (((EnemyAI)hawk).currentBehaviourStateIndex == 2) { StopFocusingThreat.Invoke(hawk, null); } else { SetAggressiveMode.Invoke(hawk, new object[1] { 0 }); } ((EnemyAI)hawk).movingTowardsTargetPlayer = false; ((EnemyAI)hawk).targetPlayer = null; if (hawk.scoutingSearchRoutine != null && hawk.scoutingSearchRoutine.inProgress) { ((EnemyAI)hawk).StopSearch(hawk.scoutingSearchRoutine, false); } Flee(); } public void Flee() { //IL_0052: 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_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) NavMeshAgent agent = ((EnemyAI)hawk).agent; if ((Object)(object)agent != (Object)null && ((Behaviour)agent).enabled && agent.isOnNavMesh) { if (!hasFleePoint || Vector3.Distance(((Component)hawk).transform.position, fleePoint) < 2f) { fleePoint = ChooseFleePoint(agent); hasFleePoint = true; } agent.speed = fleeSpeed; agent.SetDestination(fleePoint); } ((EnemyAI)hawk).SyncPositionToClients(); } private Vector3 ChooseFleePoint(NavMeshAgent agent) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: 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: 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_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Expected O, but got Unknown //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0096: 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_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) Vector3 position = ((Component)hawk).transform.position; Vector3 val = position - noisePosition; val.y = 0f; val = ((((Vector3)(ref val)).sqrMagnitude > 0.01f) ? ((Vector3)(ref val)).normalized : (-((Component)hawk).transform.forward)); if (path == null) { path = new NavMeshPath(); } float[] fleeAngles = FleeAngles; NavMeshHit val2 = default(NavMeshHit); foreach (float num in fleeAngles) { if (NavMesh.SamplePosition(position + Quaternion.Euler(0f, num, 0f) * val * 25f, ref val2, 6f, agent.areaMask) && agent.CalculatePath(((NavMeshHit)(ref val2)).position, path) && (int)path.status == 0) { return ((NavMeshHit)(ref val2)).position; } } return position; } } [HarmonyPatch] internal static class HawkPatches { [HarmonyPatch(typeof(StartOfRound), "Start")] [HarmonyPostfix] private static void RegisterMessages() { ScareNetwork.Register(); } [HarmonyPatch(typeof(BaboonBirdAI), "DetectNoise")] [HarmonyPrefix] private static bool OnNoise(BaboonBirdAI __instance, Vector3 noisePosition, float noiseLoudness, int noiseID) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0022: 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) if (((EnemyAI)__instance).isEnemyDead) { return true; } HawkFear hawkFear = HawkFear.For(__instance); if (hawkFear.IsScared) { return false; } float distance = Vector3.Distance(noisePosition, ((Component)__instance).transform.position); if (ScareRules.ShouldScare(noiseID, noiseLoudness, distance, Plugin.Settings)) { ScareNetwork.Report(hawkFear, noisePosition); } return true; } [HarmonyPatch(typeof(BaboonBirdAI), "DoAIInterval")] [HarmonyPrefix] private static bool OnThink(BaboonBirdAI __instance) { HawkFear component = ((Component)__instance).GetComponent<HawkFear>(); if ((Object)(object)component == (Object)null || !component.IsScared || ((EnemyAI)__instance).isEnemyDead || ((EnemyAI)__instance).stunNormalizedTimer > 0f) { return true; } component.Flee(); return false; } [HarmonyPatch(typeof(BaboonBirdAI), "OnCollideWithPlayer")] [HarmonyPrefix] private static bool OnTouchPlayer(BaboonBirdAI __instance) { HawkFear component = ((Component)__instance).GetComponent<HawkFear>(); if (!((Object)(object)component == (Object)null)) { return !component.IsScared; } return true; } } [BepInPlugin("shoutathawks", "Shout At Hawks", "1.0.0")] public class Plugin : BaseUnityPlugin { public const string Guid = "shoutathawks"; public const string ModName = "Shout At Hawks"; public const string Version = "1.0.0"; internal static ManualLogSource Log; internal static ConfigEntry<bool> ScareOnVoice; internal static ConfigEntry<float> VoiceRange; internal static ConfigEntry<bool> ScareOnLoudSounds; internal static ConfigEntry<float> SoundRange; internal static ConfigEntry<float> MinSoundLoudness; internal static ConfigEntry<float> FleeSeconds; internal static ConfigEntry<float> FleeSpeed; internal static ConfigEntry<float> BraveSeconds; internal static ScareSettings Settings => new ScareSettings(ScareOnVoice.Value, VoiceRange.Value, ScareOnLoudSounds.Value, SoundRange.Value, MinSoundLoudness.Value); private void Awake() { //IL_0128: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; ScareOnVoice = ((BaseUnityPlugin)this).Config.Bind<bool>("Voice", "ScareOnVoice", true, "Hawks run from players' voices."); VoiceRange = ((BaseUnityPlugin)this).Config.Bind<float>("Voice", "VoiceRange", 9f, "How far a full shout reaches. Normal talking reaches two thirds of this."); ScareOnLoudSounds = ((BaseUnityPlugin)this).Config.Bind<bool>("Sounds", "ScareOnLoudSounds", true, "Hawks run from loud sounds like air horns, boomboxes, turrets and shovel hits."); SoundRange = ((BaseUnityPlugin)this).Config.Bind<float>("Sounds", "SoundRange", 12f, "How far the loudest sounds reach. Quieter sounds reach less far."); MinSoundLoudness = ((BaseUnityPlugin)this).Config.Bind<float>("Sounds", "MinSoundLoudness", 0.8f, "How loud a sound must be to count, from 0 to 1. Shovel hits are 0.8 and hawk bites are 0.7."); FleeSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Fleeing (host decides)", "FleeSeconds", 4f, "How long a scared hawk runs away."); FleeSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Fleeing (host decides)", "FleeSpeed", 14f, "How fast a scared hawk runs. Hawks normally scout at 10."); BraveSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Fleeing (host decides)", "BraveSeconds", 10f, "How long after fleeing a hawk ignores noise and can attack again."); new Harmony("shoutathawks").PatchAll(typeof(HawkPatches)); Log.LogInfo((object)"Shout At Hawks 1.0.0 loaded"); } } internal static class ScareNetwork { [CompilerGenerated] private static class <>O { public static HandleNamedMessageDelegate <0>__OnReportReceived; public static HandleNamedMessageDelegate <1>__OnScareReceived; } private const string ReportMessage = "ShoutAtHawks_Report"; private const string ScareMessage = "ShoutAtHawks_Scare"; public static void Register() { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Expected O, but got Unknown NetworkManager singleton = NetworkManager.Singleton; CustomMessagingManager val = (((Object)(object)singleton != (Object)null) ? singleton.CustomMessagingManager : null); if (val == null) { Plugin.Log.LogError((object)"Could not register network messages, hawks will not get scared this session"); return; } val.UnregisterNamedMessageHandler("ShoutAtHawks_Report"); val.UnregisterNamedMessageHandler("ShoutAtHawks_Scare"); object obj = <>O.<0>__OnReportReceived; if (obj == null) { HandleNamedMessageDelegate val2 = OnReportReceived; <>O.<0>__OnReportReceived = val2; obj = (object)val2; } val.RegisterNamedMessageHandler("ShoutAtHawks_Report", (HandleNamedMessageDelegate)obj); object obj2 = <>O.<1>__OnScareReceived; if (obj2 == null) { HandleNamedMessageDelegate val3 = OnScareReceived; <>O.<1>__OnScareReceived = val3; obj2 = (object)val3; } val.RegisterNamedMessageHandler("ShoutAtHawks_Scare", (HandleNamedMessageDelegate)obj2); } public unsafe static void Report(HawkFear fear, Vector3 noisePosition) { //IL_002e: 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: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || !((NetworkBehaviour)fear.Hawk).IsSpawned || !fear.TryStartReport()) { return; } if (singleton.IsServer) { TryScare(fear, noisePosition); return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(20, (Allocator)2, -1); try { ulong networkObjectId = ((NetworkBehaviour)fear.Hawk).NetworkObjectId; ((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref networkObjectId, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref noisePosition); singleton.CustomMessagingManager.SendNamedMessage("ShoutAtHawks_Report", 0uL, val, (NetworkDelivery)3); } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } } private static void OnReportReceived(ulong sender, FastBufferReader reader) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) if (NetworkManager.Singleton.IsServer) { ulong id = default(ulong); ((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref id, default(ForPrimitives)); Vector3 noisePosition = default(Vector3); ((FastBufferReader)(ref reader)).ReadValueSafe(ref noisePosition); if (TryFindHawk(id, out var hawk)) { TryScare(HawkFear.For(hawk), noisePosition); } } } private unsafe static void TryScare(HawkFear fear, Vector3 noisePosition) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_004e: 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_0097: 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_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: 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) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) if (!fear.CanBeScared) { return; } float value = Plugin.FleeSeconds.Value; float value2 = Plugin.FleeSpeed.Value; float value3 = Plugin.BraveSeconds.Value; fear.Scare(noisePosition, value, value2, value3); Plugin.Log.LogInfo((object)$"Hawk {((NetworkBehaviour)fear.Hawk).NetworkObjectId} scared by a noise {Vector3.Distance(noisePosition, ((Component)fear.Hawk).transform.position):0.0} units away"); NetworkManager singleton = NetworkManager.Singleton; FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(28, (Allocator)2, -1); try { ulong networkObjectId = ((NetworkBehaviour)fear.Hawk).NetworkObjectId; ((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref networkObjectId, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref noisePosition); ((FastBufferWriter)(ref val)).WriteValueSafe<float>(ref value, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe<float>(ref value2, default(ForPrimitives)); foreach (ulong connectedClientsId in singleton.ConnectedClientsIds) { if (connectedClientsId != 0L) { singleton.CustomMessagingManager.SendNamedMessage("ShoutAtHawks_Scare", connectedClientsId, val, (NetworkDelivery)3); } } } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } } private static void OnScareReceived(ulong sender, FastBufferReader reader) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0039: 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_0057: Unknown result type (might be due to invalid IL or missing references) if (sender == 0L) { ulong id = default(ulong); ((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref id, default(ForPrimitives)); Vector3 position = default(Vector3); ((FastBufferReader)(ref reader)).ReadValueSafe(ref position); float seconds = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe<float>(ref seconds, default(ForPrimitives)); float speed = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe<float>(ref speed, default(ForPrimitives)); if (TryFindHawk(id, out var hawk)) { HawkFear.For(hawk).Scare(position, seconds, speed, 0f); } } } private static bool TryFindHawk(ulong id, out BaboonBirdAI hawk) { hawk = null; if (NetworkManager.Singleton.SpawnManager.SpawnedObjects.TryGetValue(id, out var value)) { return ((Component)value).TryGetComponent<BaboonBirdAI>(ref hawk); } return false; } } public readonly struct ScareSettings { public readonly bool VoiceEnabled; public readonly float VoiceRange; public readonly bool SoundsEnabled; public readonly float SoundRange; public readonly float MinSoundLoudness; public ScareSettings(bool voiceEnabled, float voiceRange, bool soundsEnabled, float soundRange, float minSoundLoudness) { VoiceEnabled = voiceEnabled; VoiceRange = voiceRange; SoundsEnabled = soundsEnabled; SoundRange = soundRange; MinSoundLoudness = minSoundLoudness; } } public static class ScareRules { public const int VoiceNoiseId = 75; private const float LoudestVoice = 0.9f; private static readonly HashSet<int> IgnoredNoiseIds = new HashSet<int> { 6, 7, 546, 941, 1105, 24751 }; public static bool ShouldScare(int noiseId, float loudness, float distance, ScareSettings settings) { if (noiseId == 75) { if (settings.VoiceEnabled) { return distance <= settings.VoiceRange * (loudness / 0.9f); } return false; } if (!settings.SoundsEnabled || IgnoredNoiseIds.Contains(noiseId) || loudness < settings.MinSoundLoudness) { return false; } return distance <= settings.SoundRange * loudness; } } }