using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using Crest; using HarmonyLib; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("RandomEncounters")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("raddude")] [assembly: AssemblyProduct("RandomEncounters")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("06b0b4cd-89d7-4ff2-8dc9-3eaa535b8d99")] [assembly: AssemblyFileVersion("1.4.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.4.0.0")] [module: UnverifiableCode] namespace RandomEncounters; internal class SeaLifeMod { private static List s_whaleSpawns; private static Type _finWhaleAIType; private static Type _effectControllerType; private static FastInvokeHandler _triggerRandomAnimation; private static int _activeWhales; private static Component _whale0Ai; private static AssetBundle _assetBundle; private static AudioClip[] _blowholeSounds; private static AudioClip[] _breachSplashSounds; private static AudioClip[] _breachEmergeSounds; private static AudioClip[] _tailSplashSounds; private static int _soundsToLoad; private static int _soundsLoaded; private static bool _allSoundsLoaded; private const float MAX_DISTANCE = 650f; public static void PatchMod() { //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Expected O, but got Unknown //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Expected O, but got Unknown ((MonoBehaviour)RE_Plugin.SeaLifeModPluginInstance).StopAllCoroutines(); _finWhaleAIType = AccessTools.TypeByName("FinWhaleAI"); _effectControllerType = AccessTools.TypeByName("EffectController"); MethodInfo methodInfo = AccessTools.Method(_finWhaleAIType, "TriggerRandomAnimation", (Type[])null, (Type[])null); _triggerRandomAnimation = MethodInvoker.GetHandler(methodInfo, false); string[] array = new string[3] { "FindPlayer", "CheckDistanceToPlayer", "SetRandomScale" }; string[] array2 = array; foreach (string text in array2) { MethodInfo methodInfo2 = AccessTools.Method(_finWhaleAIType, text, (Type[])null, (Type[])null); MethodInfo methodInfo3 = AccessTools.Method(typeof(SeaLifeModPatches), "DoNotRun", (Type[])null, (Type[])null); RE_Plugin.HarmonyInstance.Patch((MethodBase)methodInfo2, new HarmonyMethod(methodInfo3), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } MethodInfo methodInfo4 = AccessTools.Method(_effectControllerType, "LoadSounds", (Type[])null, (Type[])null); MethodInfo methodInfo5 = AccessTools.Method(typeof(SeaLifeModPatches), "DoNotRun", (Type[])null, (Type[])null); RE_Plugin.HarmonyInstance.Patch((MethodBase)methodInfo4, new HarmonyMethod(methodInfo5), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ((MonoBehaviour)RE_Plugin.Instance).StartCoroutine(LoadSoundsAsync()); ((MonoBehaviour)RE_Plugin.Instance).StartCoroutine(InstantiateWhales()); } private static IEnumerator InstantiateWhales() { if ((Object)(object)RE_Plugin.SeaLifeModPluginInstance == (Object)null) { yield break; } GameObject whalePrefab = RE_Plugin.SeaLifeModPluginInstance.GetPrivateField("animalPrefab"); s_whaleSpawns = new List(); yield return (object)new WaitUntil((Func)(() => (Object)(object)Refs.shiftingWorld != (Object)null && _allSoundsLoaded)); for (int i = 0; i < 5; i++) { GameObject whale = Object.Instantiate(whalePrefab, Refs.shiftingWorld); Component ai = whale.AddComponent(_finWhaleAIType); if (i == 0) { _whale0Ai = ai; } Component effectController = whale.AddComponent(_effectControllerType); effectController.SetPrivateField("blowholeSounds", _blowholeSounds); effectController.SetPrivateField("breachSplashSounds", _breachSplashSounds); effectController.SetPrivateField("breachEmergeSounds", _breachEmergeSounds); effectController.SetPrivateField("tailSplashSounds", _tailSplashSounds); whale.transform.position = Vector3.zero; whale.gameObject.SetActive(false); s_whaleSpawns.Add(whale); } } internal static void SpawnWhale(int i, Vector3 spawnPosition) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) RE_Plugin.LogDebug("Spawning FinWhale"); float num = Random.Range(0.8f, 1.4f); int num2 = Random.Range(0, 360); GameObject val = s_whaleSpawns[i]; Transform transform = val.transform; transform.position = spawnPosition; transform.rotation = Quaternion.Euler(0f, (float)num2, 0f); transform.localScale = new Vector3(num, num, num); val.SetActive(true); _activeWhales++; } internal static void TriggerEntranceAnimation() { _triggerRandomAnimation.Invoke((object)_whale0Ai, Array.Empty()); } internal static void CheckWhaleDistance() { //IL_002f: 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) if (_activeWhales == 0) { return; } foreach (GameObject s_whaleSpawn in s_whaleSpawns) { float num = Vector3.Distance(s_whaleSpawn.transform.position, ((Component)Refs.observerMirror).transform.position); if (s_whaleSpawn.activeInHierarchy && num > 650f) { RE_Plugin.LogDebug("Removing FinWhale"); s_whaleSpawn.SetActive(false); _activeWhales--; } } } private static IEnumerator LoadSoundsAsync() { _soundsToLoad = 0; _soundsLoaded = 0; _assetBundle = RE_Plugin.SeaLifeModPluginInstance.GetPrivateField("seaLifeBundle"); ((MonoBehaviour)RE_Plugin.Instance).StartCoroutine(LoadAudioClipsAsync("WhaleBlowMed", 6, delegate(AudioClip[] clips) { _blowholeSounds = clips; })); ((MonoBehaviour)RE_Plugin.Instance).StartCoroutine(LoadAudioClipsAsync("BreachSplashLarge", 5, delegate(AudioClip[] clips) { _breachSplashSounds = clips; })); ((MonoBehaviour)RE_Plugin.Instance).StartCoroutine(LoadAudioClipsAsync("BreachSplashSmall", 6, delegate(AudioClip[] clips) { _breachEmergeSounds = clips; })); ((MonoBehaviour)RE_Plugin.Instance).StartCoroutine(LoadAudioClipsAsync("TailSplash", 4, delegate(AudioClip[] clips) { _tailSplashSounds = clips; })); while (_soundsLoaded < _soundsToLoad) { yield return null; } _allSoundsLoaded = true; } private static IEnumerator LoadAudioClipsAsync(string baseName, int count, Action onComplete) { _soundsToLoad += count; AudioClip[] clips = (AudioClip[])(object)new AudioClip[count]; for (int i = 0; i < count; i++) { string clipName = $"{baseName}{i + 1:00}"; AssetBundleRequest request = _assetBundle.LoadAssetAsync("Assets/Audio/" + clipName + ".wav"); yield return request; ref AudioClip reference = ref clips[i]; Object asset = request.asset; reference = (AudioClip)(object)((asset is AudioClip) ? asset : null); _soundsLoaded++; } while (_soundsLoaded < _soundsToLoad) { yield return null; } onComplete(clips); } } public class SeaLifeModPatches { [HarmonyPrefix] public static bool DoNotRun() { return false; } } internal class EncounterGenerator : MonoBehaviour { private bool _moveSeagulls; private const float MIN_DISTANCE = 1000f; public static EncounterGenerator Instance { get; private set; } public void Awake() { if ((Object)(object)Instance != (Object)null && (Object)(object)Instance != (Object)(object)this) { Object.Destroy((Object)(object)((Component)this).gameObject); return; } Instance = this; ((MonoBehaviour)this).StartCoroutine(ScheduleEncounter()); } public void Update() { SeaLifeMod.CheckWhaleDistance(); } private List BuildEncounterTable() { List list = new List(); bool flag = Configs.controlSeaLifeMod.Value && (Object)(object)RE_Plugin.SeaLifeModPluginInstance != (Object)null; if (Configs.enableFlotsam.Value) { list.Add(new EncounterEntry { Name = "Flotsam", Weight = 15, Trigger = GenerateFlotsam }); } if (Configs.enableFlotsam.Value && flag) { list.Add(new EncounterEntry { Name = "Flotsam and Whales", Weight = 5, Trigger = delegate { GenerateFlotsam(); ((MonoBehaviour)this).StartCoroutine(GenerateWhales()); } }); } if (flag) { list.Add(new EncounterEntry { Name = "Whales", Weight = 25, Trigger = delegate { ((MonoBehaviour)this).StartCoroutine(GenerateWhales()); } }); } if (Configs.enableDenseFog.Value) { list.Add(new EncounterEntry { Name = "Dense Fog", Weight = 5, Trigger = delegate { ((MonoBehaviour)this).StartCoroutine(GenerateDenseFog()); } }); } if (Configs.enableDenseFog.Value && flag) { list.Add(new EncounterEntry { Name = "Dense Fog and Whales", Weight = 5, Trigger = delegate { ((MonoBehaviour)this).StartCoroutine(GenerateDenseFog()); ((MonoBehaviour)this).StartCoroutine(GenerateWhales()); } }); } if (Configs.enableFishingBonanza.Value) { list.Add(new EncounterEntry { Name = "Fishing Bonanza", Weight = 15, Trigger = delegate { ((MonoBehaviour)this).StartCoroutine(GenerateFishingBonanza()); } }); } if (Configs.enableIntenseStorm.Value) { list.Add(new EncounterEntry { Name = "Intense Storm", Weight = 5, Trigger = delegate { ((MonoBehaviour)this).StartCoroutine(GenerateIntenseStorm()); } }); } return list; } private IEnumerator ScheduleEncounter() { yield return (object)new WaitUntil((Func)(() => GameState.playing)); int minTime = Mathf.Abs(Configs.generateEncounterMinTime.Value); int range = Mathf.Abs(Configs.generateEncounterTimeRange.Value); int timeToNextEncounter = minTime + Random.Range(0, range); yield return (object)new WaitForSeconds((float)timeToNextEncounter); if ((Object)(object)GameState.currentBoat != (Object)null) { Generate(); } ((MonoBehaviour)this).StartCoroutine(ScheduleEncounter()); } private void Generate() { if (!GameState.playing) { return; } if (GameState.distanceToLand <= 1000f) { RE_Plugin.LogDebug($"Too close to land (distance: {GameState.distanceToLand}), skipping encounter generation."); return; } if (GameState.sleeping) { RE_Plugin.LogDebug("Player sleeping, skipping encounter generation."); return; } if (Random.value > Mathf.Abs((float)Configs.encounterRollChance.Value / 100f)) { RE_Plugin.LogInfo("No encounter this time"); return; } List list = BuildEncounterTable(); if (list.Count == 0) { RE_Plugin.LogDebug("No encounters enabled"); return; } int num = list.Sum((EncounterEntry e) => e.Weight); int num2 = Random.Range(0, num); int num3 = 0; foreach (EncounterEntry item in list) { num3 += item.Weight; if (num2 < num3) { RE_Plugin.LogDebug("Encounter: " + item.Name); item.Trigger(); break; } } } private static void GenerateFlotsam() { //IL_0006: 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_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0029: 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_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: 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) Vector3 spawnPoint = GameState.currentBoat.position + GameState.currentBoat.right * 200f + GameState.currentBoat.forward * (float)Random.Range(-30, 30); Flotsam.Spawn(spawnPoint); } private IEnumerator GenerateWhales() { Vector3 boatPosition = GameState.currentBoat.position; int spawnCount = Random.Range(2, 5); WaitForSeconds spawnDelay = new WaitForSeconds(2f); for (int i = 0; i < spawnCount; i++) { Vector3 randomOffset = new Vector3((float)Random.Range(-200, 200), -8f, (float)Random.Range(-200, 200)); yield return spawnDelay; SeaLifeMod.SpawnWhale(i, boatPosition + randomOffset); } yield return spawnDelay; SeaLifeMod.TriggerEntranceAnimation(); } private IEnumerator GenerateDenseFog() { if (DenseFog.IsRunning || WeatherStorms.instance.InvokePrivateMethod("GetNormalizedDistance") < 0.75f) { yield break; } DenseFog.Spawn(); List waveAudioSources = DenseFog.WaveAudioSources.Keys.ToList(); AudioSource windAudioSource = DenseFog.WindAudioSource.source; float windOrigVolume = DenseFog.WindAudioSource.origVolume; for (float t = 0f; t < 4f; t += Time.deltaTime) { float lerpValue = t / 4f; foreach (AudioSource audioSource in waveAudioSources) { audioSource.volume = Mathf.Lerp(DenseFog.WaveAudioSources[audioSource], 0f, lerpValue); } if ((Object)(object)windAudioSource != (Object)null) { windAudioSource.volume = Mathf.Lerp(windOrigVolume, 0.0001f, lerpValue); } yield return null; } for (int i = 0; i < 4; i++) { Vector3 spawnPoint = GameState.currentBoat.position + GameState.currentBoat.right * (200f + Random.Range(20f, 60f) * (float)i) + GameState.currentBoat.forward * (float)Random.Range(-200, 200); Flotsam.SpawnItem(spawnPoint, (Random.Range(1, 100) > 50) ? AssetLoader.SmallWreck : AssetLoader.Hull, 1f, wreckage: true); yield return (object)new WaitForSeconds(1f); } yield return (object)new WaitForSeconds((float)Configs.fogDuration.Value); DenseFog.ClearFog(); for (float t2 = 0f; t2 < 4f; t2 += Time.deltaTime) { float lerpValue2 = t2 / 4f; foreach (AudioSource audioSource2 in waveAudioSources) { audioSource2.volume = Mathf.Lerp(0f, DenseFog.WaveAudioSources[audioSource2], lerpValue2); } if ((Object)(object)windAudioSource != (Object)null) { windAudioSource.volume = Mathf.Lerp(0.0001f, windOrigVolume, lerpValue2); } yield return null; } } private IEnumerator GenerateFishingBonanza() { float stormDistance = WeatherStorms.instance.InvokePrivateMethod("GetNormalizedDistance"); if ((Object)(object)GameState.currentBoat == (Object)null || stormDistance < 0.75f) { RE_Plugin.LogDebug($"Storm too close for fishing bonanza {stormDistance} {stormDistance < 0.75f}"); yield break; } Transform? obj = ((IEnumerable)((Component)Refs.islands[3]).GetComponentsInChildren()).FirstOrDefault((Func)((Transform t) => ((Object)t).name == "seagulls")); GameObject seagullsGO = ((obj != null) ? ((Component)obj).gameObject : null); if ((Object)(object)seagullsGO == (Object)null) { RE_Plugin.LogDebug("No seagulls found"); yield break; } GameObject seagulls = Object.Instantiate(seagullsGO, Refs.shiftingWorld); if (!seagulls.activeInHierarchy) { seagulls.SetActive(true); } seagulls.GetComponent().PlayOneShot(seagulls.GetComponent().clip); ParticleSystem seagullsPS = seagulls.GetComponent(); MainModule main = seagullsPS.main; ((MainModule)(ref main)).maxParticles = 25; ((MainModule)(ref main)).startLifetime = MinMaxCurve.op_Implicit((float)Configs.fishingBonanzaDuration.Value); ((MainModule)(ref main)).startRotation = MinMaxCurve.op_Implicit(0f); ((MainModule)(ref main)).startRotation3D = false; RotationOverLifetimeModule rol = seagullsPS.rotationOverLifetime; ((RotationOverLifetimeModule)(ref rol)).enabled = false; ((RotationOverLifetimeModule)(ref rol)).x = MinMaxCurve.op_Implicit(0f); ((RotationOverLifetimeModule)(ref rol)).y = MinMaxCurve.op_Implicit(0f); ((RotationOverLifetimeModule)(ref rol)).z = MinMaxCurve.op_Implicit(0f); VelocityOverLifetimeModule vol = seagullsPS.velocityOverLifetime; ((VelocityOverLifetimeModule)(ref vol)).enabled = true; ((VelocityOverLifetimeModule)(ref vol)).orbitalX = MinMaxCurve.op_Implicit(0f); ((VelocityOverLifetimeModule)(ref vol)).orbitalY = MinMaxCurve.op_Implicit(0f); ((VelocityOverLifetimeModule)(ref vol)).orbitalZ = MinMaxCurve.op_Implicit(0f); ((VelocityOverLifetimeModule)(ref vol)).orbitalXMultiplier = 0f; ((VelocityOverLifetimeModule)(ref vol)).orbitalYMultiplier = 0f; ((VelocityOverLifetimeModule)(ref vol)).orbitalZMultiplier = 0f; RotationBySpeedModule rbs = seagullsPS.rotationBySpeed; ((RotationBySpeedModule)(ref rbs)).enabled = false; ParticleSystemRenderer seagullPSR = seagulls.GetComponent(); seagullPSR.alignment = (ParticleSystemRenderSpace)2; ShapeModule shape = seagullsPS.shape; ((ShapeModule)(ref shape)).shapeType = (ParticleSystemShapeType)18; ((ShapeModule)(ref shape)).scale = new Vector3(25f, 25f, 0.2f); EmissionModule emission = seagullsPS.emission; if (!((EmissionModule)(ref emission)).enabled) { ((EmissionModule)(ref emission)).enabled = true; } RE_Plugin.LogDebug("Starting fishing bonanza"); FishingBonanza.IsBonanzaActive = true; _moveSeagulls = true; ((MonoBehaviour)this).StartCoroutine(MoveSeagulls(seagulls.transform, GameState.currentBoat)); yield return (object)new WaitForSeconds((float)Configs.fishingBonanzaDuration.Value); RE_Plugin.LogDebug("Stopping fishing bonanza"); FishingBonanza.IsBonanzaActive = false; _moveSeagulls = false; Object.Destroy((Object)(object)seagulls); } private IEnumerator MoveSeagulls(Transform seagulls, Transform boat) { while (_moveSeagulls) { Vector3 targetPosition = boat.position + boat.up * 40f; seagulls.position = Vector3.Lerp(seagulls.position, targetPosition, 0.2f * Time.deltaTime); Vector3 newRotation = seagulls.eulerAngles; newRotation.y = Mathf.LerpAngle(seagulls.eulerAngles.y, boat.eulerAngles.y - 90f, 0.2f * Time.deltaTime); seagulls.rotation = Quaternion.Euler(newRotation); yield return null; } } private IEnumerator GenerateIntenseStorm() { WeatherStorms weatherStorms = WeatherStorms.instance; WanderingStorm storm = weatherStorms.GetCurrentStorm(); WanderingStormLightning lightning = ((Component)((Component)storm).transform.GetChild(3)).GetComponent(); Region targetRegion = RegionBlender.instance.GetPrivateField("currentTargetRegion"); float origInertiaWindScale = IntenseStorm.oceanUpdaterCrest.inertiaWindScale; float origWindSpeedMult = IntenseStorm.oceanUpdaterCrest.GetPrivateField("windSpeedMult"); float origSmallWavesMult = IntenseStorm.oceanUpdaterCrest.GetPrivateField("smallWavesMult"); float origLightningInterval = lightning.GetPrivateField("lightningInterval"); float origRainDensity = targetRegion.stormWeather.particles.rainDensity; lightning.SetPrivateField("lightningInterval", 5f); targetRegion.stormWeather.particles.rainDensity = 70f; float stormDist = Vector3.Distance(((Component)Camera.main).transform.position, ((Component)storm).transform.position); Vector3 vector = ((Component)Camera.main).transform.position - ((Component)storm).transform.position; vector.y = 0f; RE_Plugin.LogDebug(((Object)storm).name + " approaching"); while (stormDist > 1500f) { vector = ((Component)Camera.main).transform.position - ((Component)storm).transform.position; vector.y = 0f; Wind.currentBaseWind = vector * 50f; float translateSpeed = ((weatherStorms.InvokePrivateMethod("GetNormalizedDistance") < weatherStorms.GetPrivateField("rainBorder")) ? 0.005f : 0.25f); ((Component)storm).transform.Translate(vector * translateSpeed); yield return (object)new WaitForSeconds(0.3f); stormDist = Vector3.Distance(((Component)Camera.main).transform.position, ((Component)storm).transform.position); } RE_Plugin.LogDebug(((Object)storm).name + " arrived"); IntenseStorm.oceanUpdaterCrest.inertiaWindScale = 0.22f; IntenseStorm.oceanUpdaterCrest.SetPrivateField("windSpeedMult", 5f); IntenseStorm.oceanUpdaterCrest.SetPrivateField("smallWavesMult", 0.4f); for (int i = 0; i < Configs.intenseStormDuration.Value; i++) { Wind.currentBaseWind = vector * 50f; yield return (object)new WaitForSeconds(1f); } RE_Plugin.LogDebug(((Object)storm).name + " dying down"); lightning.SetPrivateField("lightningInterval", origLightningInterval); Weather.instance.currentRegion.stormWeather.particles.rainDensity = origRainDensity; IntenseStorm.oceanUpdaterCrest.inertiaWindScale = origInertiaWindScale; IntenseStorm.oceanUpdaterCrest.SetPrivateField("windSpeedMult", origWindSpeedMult); IntenseStorm.oceanUpdaterCrest.SetPrivateField("smallWavesMult", origSmallWavesMult); } } internal class DenseFog { [HarmonyPatch(typeof(OceanColorBlender))] private class OceanColorBlenderPatches { [HarmonyPrefix] [HarmonyPatch("ApplyPalette")] public static void ApplyFogDensity(ref OceanColorPalette palette) { if (IsRunning) { _originalFogDensity = ((_originalFogDensity == 0f) ? palette.fogDensity : _originalFogDensity); _currentFogDensity = ((_currentFogDensity == 0f) ? palette.fogDensity : _currentFogDensity); if (_clearFog && _currentFogDensity > _originalFogDensity) { _currentFogDensity -= 1E-05f; } if (!_clearFog && _currentFogDensity < 0.06f) { _currentFogDensity += 1E-05f; } palette.fogDensity = _currentFogDensity; if (_clearFog && _currentFogDensity <= _originalFogDensity) { IsRunning = false; _currentFogDensity = 0f; _originalFogDensity = 0f; Traverse.Create((object)GameObject.Find("wind").GetComponent()).Field("timer").SetValue((object)0); } } } } [HarmonyPatch(typeof(Wind))] private class WindPatches { [HarmonyPrefix] [HarmonyPatch("SetNewGustTarget")] public static bool NoGust(ref Vector3 ___currentGustTarget, Vector3 ___currentWindTarget) { //IL_0012: 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) if (!IsRunning) { return true; } ___currentGustTarget = ___currentWindTarget; return false; } [HarmonyPrefix] [HarmonyPatch("SetNewWindTarget")] public static bool LightWind(ref Vector3 ___currentWindTarget) { //IL_0017: 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_0026: Unknown result type (might be due to invalid IL or missing references) if (!IsRunning) { return true; } ___currentWindTarget = ((Vector3)(ref Wind.currentBaseWind)).normalized * 3f; return false; } } [HarmonyPatch(typeof(WaveSound))] private class WaveSoundPatches { [HarmonyPrefix] [HarmonyPatch("UpdateIntensity")] public static bool SetToMinVolume() { if (!IsRunning) { return true; } return false; } [HarmonyPostfix] [HarmonyPatch("Start")] public static void GetAudioSource(AudioSource ___audio) { if (!WaveAudioSources.ContainsKey(___audio)) { WaveAudioSources.Add(___audio, ___audio.volume); } } } [HarmonyPatch(typeof(WindSound))] private class WindSoundPatches { [HarmonyPrefix] [HarmonyPatch("Update")] public static bool SetToMinVolume() { if (!IsRunning) { return true; } return false; } [HarmonyPostfix] [HarmonyPatch("Start")] public static void GetAudioSource(AudioSource ___audio) { WindAudioSource = (source: ___audio, origVolume: ___audio.volume); } } private static bool _clearFog = true; private static float _currentFogDensity = 0f; private static float _originalFogDensity = 0f; private const float MAX_FOG_DENSITY = 0.06f; public static bool IsRunning { get; private set; } = false; public static Dictionary WaveAudioSources { get; private set; } = new Dictionary(); public static (AudioSource source, float origVolume) WindAudioSource { get; private set; } = (source: null, origVolume: 0f); public static void Spawn() { RE_Plugin.LogDebug("Spawning fog"); foreach (AudioSource item in WaveAudioSources.Keys.ToList()) { WaveAudioSources[item] = item.volume; } if ((Object)(object)WindAudioSource.source != (Object)null) { WindAudioSource = (source: WindAudioSource.source, origVolume: WindAudioSource.source.volume); } _clearFog = false; IsRunning = true; } public static void ClearFog() { RE_Plugin.LogDebug("Clearing fog"); _clearFog = true; } } internal class EncounterEntry { public string Name; public int Weight; public Action Trigger; } internal class FishingBonanza { [HarmonyPatch(typeof(FishingRodFish))] [HarmonyPatch("Update")] private class FishingRodFishPatches { [HarmonyPostfix] public static void IncreaseCatchChance(FishingRodFish __instance, ShipItemFishingRod ___rod, SimpleFloatingObject ___floater, ConfigurableJoint ___bobberJoint, ref float ___fishTimer) { //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) if (!IsBonanzaActive || (Object)(object)__instance.currentFish != (Object)null || ((ShipItem)___rod).health <= 0f || (!Object.op_Implicit((Object)(object)((PickupableItem)___rod).held) && !RE_Plugin.IdleFishingPluginDetected && !RE_Plugin.HooksHangMorePluginDetected) || !((FloatingObjectBase)___floater).InWater) { return; } SoftJointLimit linearLimit = ___bobberJoint.linearLimit; if (((SoftJointLimit)(ref linearLimit)).limit <= 1f || ((Component)__instance).gameObject.layer == 16) { return; } ___fishTimer -= Time.deltaTime; float num = Vector3.Distance(((Component)__instance).transform.position, ((Component)___rod).transform.position); float num2 = Mathf.InverseLerp(3f, 20f, num) * 2.5f + 0.5f; if (___fishTimer <= 0f) { ___fishTimer = 1f; float num3 = (Object.op_Implicit((Object)(object)((PickupableItem)___rod).held) ? 20f : 3f); if (Random.Range(0f, 100f) < num2 * num3) { __instance.CatchFish(); } } } } public static bool IsBonanzaActive { get; set; } } internal class Flotsam { private static readonly int[] _cargos = new int[36] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 18, 19, 24, 25, 26, 27, 201, 202, 206, 212, 213, 214, 216, 219, 220, 222, 223, 224, 227, 228 }; private static readonly int[] _consumables = new int[4] { 104, 108, 131, 132 }; private static readonly int[] _bottles = new int[5] { 55, 56, 57, 58, 59 }; private static readonly int[] _tobaccoCrates = new int[4] { 311, 313, 315, 319 }; private const int MAX_CARGO_TYPES = 4; private const int MAX_CARGOS = 3; private const int MAX_CONSUME_TYPES = 2; internal static void Spawn(Vector3 spawnPoint) { //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_0228: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < Random.Range(1, 4); i++) { int num = Random.Range(0, _cargos.Length - 1); for (int j = 0; j < Random.Range(1, 3); j++) { RE_Plugin.LogDebug($"Choice: {_cargos[num]}"); GameObject val = PrefabsDirectory.instance.directory[_cargos[num]]; float amount = (float)Math.Round((decimal)Random.Range(0f, val.GetComponent().amount)); SpawnItem(spawnPoint, val, amount); } } for (int k = 0; k < Random.Range(1, 2); k++) { int num2 = Random.Range(0, _consumables.Length - 1); RE_Plugin.LogDebug($"Choice: {_consumables[num2]}"); GameObject val2 = PrefabsDirectory.instance.directory[_consumables[num2]]; float amount2 = (float)Math.Round((decimal)Random.Range(0f, val2.GetComponent().amount)); SpawnItem(spawnPoint, val2, amount2); } for (int l = 0; l < Random.Range(5, 10); l++) { int num3 = Random.Range(0, _bottles.Length - 1); RE_Plugin.LogDebug($"Choice: {_bottles[num3]}"); GameObject prefabGO = PrefabsDirectory.instance.directory[_bottles[num3]]; float amount3 = 0f; SpawnItem(spawnPoint, prefabGO, amount3); } int num4 = Random.Range(0, _tobaccoCrates.Length - 1); RE_Plugin.LogDebug($"Choice: {_tobaccoCrates[num4]}"); GameObject val3 = PrefabsDirectory.instance.directory[_tobaccoCrates[num4]]; float amount4 = (float)Math.Round((decimal)Random.Range(0f, val3.GetComponent().amount)); SpawnItem(spawnPoint, val3, amount4); SpawnItem(spawnPoint, AssetLoader.SmallWreck, 1f, wreckage: true); } internal static void SpawnItem(Vector3 spawnPoint, GameObject prefabGO, float amount, bool wreckage = false) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) GameObject val = Object.Instantiate(prefabGO, spawnPoint, Quaternion.Euler((float)Random.Range(0, 360), (float)Random.Range(0, 360), (float)Random.Range(0, 360))); ShipItem component = val.GetComponent(); component.sold = true; component.amount = amount; component.health = amount; val.GetComponent().RegisterToSave(); Good component2 = val.GetComponent(); if ((Object)(object)component2 != (Object)null) { component2.RegisterAsMissionless(); } ShipItemCrate val2 = (ShipItemCrate)(object)((component is ShipItemCrate) ? component : null); if (val2 != null) { ((MonoBehaviour)EncounterGenerator.Instance).StartCoroutine(UnsealCrate(val2)); } if (wreckage) { ((GoPointerButton)val.GetComponent()).unclickable = true; val.transform.parent = Refs.shiftingWorld; } RE_Plugin.LogDebug("Prefab " + ((Object)prefabGO).name + " spawned"); } internal static IEnumerator UnsealCrate(ShipItemCrate crate) { yield return (object)new WaitForEndOfFrame(); yield return (object)new WaitForEndOfFrame(); CrateInventory crateInventory = ((Component)crate).GetComponent(); int num = (int)((ShipItem)crate).amount; for (int i = 0; i < num; i++) { RE_Plugin.LogDebug("Inserting item " + ((ShipItem)crate).amount); GameObject gameObject = Object.Instantiate(crate.GetContainedPrefab(), ((Component)crate).transform.position + new Vector3(0f, 100.5f, 0f), ((Component)crate).transform.rotation); ((ShipItem)crate).amount = ((ShipItem)crate).amount - 1f; gameObject.GetComponent().RegisterToSave(); if (Object.op_Implicit((Object)(object)gameObject.GetComponent())) { if (crate.smokedFood) { gameObject.GetComponent().smoked = 1f; gameObject.GetComponent().amount = 1.01f; } gameObject.GetComponent().dried = 1f; gameObject.GetComponent().UpdateMaterial(); } ((MonoBehaviour)EncounterGenerator.Instance).StartCoroutine(InsertItem(crateInventory, gameObject.GetComponent())); } ((ShipItem)crate).UpdateLookText(); ((ShipItem)crate).itemRigidbodyC.UpdateMass(); RE_Plugin.LogDebug("Unsealed crate."); } private static IEnumerator InsertItem(CrateInventory crateInventory, ShipItem item) { yield return (object)new WaitForEndOfFrame(); item.sold = true; crateInventory.InsertItem(item); } } internal class IntenseStorm { [HarmonyPatch(typeof(OceanUpdaterCrest))] private static class OceanUpdaterCrestPatches { [HarmonyPostfix] [HarmonyPatch("Awake")] public static void Awake(OceanUpdaterCrest __instance) { oceanUpdaterCrest = __instance; } } internal static OceanUpdaterCrest oceanUpdaterCrest; } [BepInPlugin("com.raddude82.randomencounters", "RandomEncounters", "1.4.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class RE_Plugin : BaseUnityPlugin { public const string PLUGIN_GUID = "com.raddude82.randomencounters"; public const string PLUGIN_NAME = "RandomEncounters"; public const string PLUGIN_VERSION = "1.4.0"; public const string SEALIFEMOD_GUID = "com.yourname.sailwind.sealifeplugin"; public const string IDLEFISHING_GUID = "ISA_IdleFishing"; public const string HOOKSHANGMORE_GUID = "com.raddude82.hookshangmore"; private static ManualLogSource _logger; internal static BaseUnityPlugin SeaLifeModPluginInstance { get; private set; } internal static bool IdleFishingPluginDetected { get; private set; } internal static bool HooksHangMorePluginDetected { get; private set; } internal static RE_Plugin Instance { get; private set; } internal static Harmony HarmonyInstance { get; private set; } public static bool IsFlotsamEnabled => Configs.enableFlotsam.Value; public static bool IsSeaLifeModEnabled => (Object)(object)SeaLifeModPluginInstance != (Object)null && Configs.controlSeaLifeMod.Value; public static bool IsIntenseStormEnabled => Configs.enableIntenseStorm.Value; public static bool IsDenseFogEnabled => Configs.enableDenseFog.Value; public static bool IsFishingBonanzaEnabled => Configs.enableFishingBonanza.Value; internal static void LogDebug(string message) { _logger.LogDebug((object)message); } internal static void LogInfo(string message) { _logger.LogInfo((object)message); } internal static void LogWarning(string message) { _logger.LogWarning((object)message); } internal static void LogError(string message) { _logger.LogError((object)message); } private void Awake() { if ((Object)(object)Instance != (Object)null && (Object)(object)Instance != (Object)(object)this) { Object.Destroy((Object)(object)((Component)this).gameObject); return; } Instance = this; _logger = ((BaseUnityPlugin)this).Logger; Configs.InitializeConfigs(); ((MonoBehaviour)this).StartCoroutine(AssetLoader.LoadAssetBundle()); HarmonyInstance = Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "com.raddude82.randomencounters"); foreach (KeyValuePair pluginInfo in Chainloader.PluginInfos) { BepInPlugin metadata = pluginInfo.Value.Metadata; if (Configs.controlSeaLifeMod.Value && metadata.GUID.Equals("com.yourname.sailwind.sealifeplugin")) { LogInfo("SealLifeMod mod found"); SeaLifeModPluginInstance = pluginInfo.Value.Instance; SeaLifeMod.PatchMod(); } if (metadata.GUID.Equals("ISA_IdleFishing")) { LogInfo("IdleFishing mod found"); IdleFishingPluginDetected = true; } if (metadata.GUID.Equals("com.raddude82.hookshangmore")) { LogInfo("HooksHangMore mod found"); HooksHangMorePluginDetected = true; } } ((Component)this).gameObject.AddComponent(); } } internal class AssetLoader { private static readonly List assetPaths = new List { Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)RE_Plugin.Instance).Info.Location), "Assets"), Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)RE_Plugin.Instance).Info.Location)) }; public static GameObject Hull { get; private set; } public static GameObject SmallWreck { get; private set; } public static string FindAssetPath(string fileName) { foreach (string assetPath in assetPaths) { string text = Path.Combine(assetPath, fileName); if (File.Exists(text)) { return text; } } return null; } internal static IEnumerator LoadAssetBundle() { RE_Plugin.LogDebug("Loading bundle"); string bundlePath = FindAssetPath("wreckage_bundle"); if (string.IsNullOrEmpty(bundlePath)) { RE_Plugin.LogError("Asset bundle path not found"); yield break; } AssetBundleCreateRequest assetBundleRequest = AssetBundle.LoadFromFileAsync(bundlePath); yield return assetBundleRequest; AssetBundle assetBundle = assetBundleRequest.assetBundle; if ((Object)(object)assetBundle == (Object)null) { RE_Plugin.LogError("Failed to load " + bundlePath); } AssetBundleRequest request = assetBundle.LoadAllAssetsAsync(); yield return request; Object? obj = ((IEnumerable)request.allAssets).FirstOrDefault((Func)((Object a) => a.name == "hull")); Hull = (GameObject)(object)((obj is GameObject) ? obj : null); Object? obj2 = ((IEnumerable)request.allAssets).FirstOrDefault((Func)((Object a) => a.name == "small_wreck")); SmallWreck = (GameObject)(object)((obj2 is GameObject) ? obj2 : null); if ((Object)(object)Hull == (Object)null || (Object)(object)SmallWreck == (Object)null) { RE_Plugin.LogError("Failed to load all assets from the bundle"); } else { RE_Plugin.LogInfo("Assets loaded"); } } } internal class Configs { internal static ConfigEntry encounterRollChance; internal static ConfigEntry generateEncounterMinTime; internal static ConfigEntry generateEncounterTimeRange; internal static ConfigEntry enableFlotsam; internal static ConfigEntry controlSeaLifeMod; internal static ConfigEntry enableDenseFog; internal static ConfigEntry fogDuration; internal static ConfigEntry enableFishingBonanza; internal static ConfigEntry fishingBonanzaDuration; internal static ConfigEntry enableIntenseStorm; internal static ConfigEntry intenseStormDuration; internal static void InitializeConfigs() { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown ConfigFile config = ((BaseUnityPlugin)RE_Plugin.Instance).Config; encounterRollChance = config.Bind("Encounter Generation Settings", "Chance an encounter occurs", 60, new ConfigDescription("Percent chance an encounter occurs.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 100), Array.Empty())); generateEncounterMinTime = config.Bind("Encounter Generation Settings", "Minimum encounter chance time", 900, "Minimum time in seconds to get a chance roll for an encounter, a random amount of time from the 'Variation in encounter chance time' setting will be added to this."); generateEncounterTimeRange = config.Bind("Encounter Generation Settings", "Variation in encounter chance time", 300, "A random number of seconds from 0 up to the value specified will be added to the 'Minimum encounter chance time' setting."); enableFlotsam = config.Bind("Encounter Types", "Enable flotsam encounters", true, (ConfigDescription)null); controlSeaLifeMod = config.Bind("Encounter Types", "Control SeaLifeMod spawns", true, "Use this mod to control SeaLifeMod spawns."); enableDenseFog = config.Bind("Encounter Types", "Enable dense fog encounters", true, (ConfigDescription)null); enableFishingBonanza = config.Bind("Encounter Types", "Enable fishing bonanza encounters", true, (ConfigDescription)null); enableIntenseStorm = config.Bind("Encounter Types", "Enable intense storm encounters", true, (ConfigDescription)null); fogDuration = config.Bind("Encounter Settings", "Fog encounter duration", 300, "In seconds, the amount of time the fog encounter lasts."); fishingBonanzaDuration = config.Bind("Encounter Settings", "Fishing bonanza duration", 300, "In seconds, the amount of time the fishing bonanza encounter lasts."); intenseStormDuration = config.Bind("Encounter Settings", "Intense storm duration", 300, "In seconds, the amount of time the intense storm encounter lasts."); } } internal static class Extensions { public static T GetPrivateField(this object obj, string field) { return (T)Traverse.Create(obj).Field(field).GetValue(); } public static void SetPrivateField(this object obj, string field, object value) { Traverse.Create(obj).Field(field).SetValue(value); } public static T InvokePrivateMethod(this object obj, string method) { return Traverse.Create(obj).Method(method, Array.Empty()).GetValue(); } public static T InvokePrivateMethod(this object obj, string method, params object[] parameters) { return Traverse.Create(obj).Method(method, parameters).GetValue(); } }