using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("ChaoticWind")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.2.0.0")]
[assembly: AssemblyInformationalVersion("1.2.0")]
[assembly: AssemblyProduct("ChaoticWind")]
[assembly: AssemblyTitle("ChaoticWind")]
[assembly: AssemblyVersion("1.2.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 ChaoticWind
{
internal sealed class ConfigurationManagerMetadata
{
public bool? ShowRangeAsPercent;
public string DispName;
public int? Order;
}
[BepInPlugin("com.pete.sailwind.windconfigurator", "Chaotic Wind", "1.2.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class ChaoticWindPlugin : BaseUnityPlugin
{
public const string PluginGuid = "com.pete.sailwind.windconfigurator";
public const string PluginName = "Chaotic Wind";
public const string PluginVersion = "1.2.0";
public const string BorderExpanderGuid = "com.nandbrew.borderexpander";
public const string ClimatePluginGuid = "com.raddude.climate";
private const float DefaultAlAnkhDirectionChaos = 0.14f;
private const float DefaultEmeraldDirectionChaos = 0.18f;
private const float DefaultFireFishDirectionChaos = 0.25f;
private const float DefaultAestrinDirectionChaos = 0.21f;
private const float DefaultChronosDirectionChaos = 0.21f;
private const float DefaultWindChangeTimer = 40f;
private const float DefaultFinalLerpSpeed = 0.5f;
private const float DefaultCombinedBonusCap = 20f;
private ConfigEntry<float> alAnkhDirectionChaos;
private ConfigEntry<float> emeraldDirectionChaos;
private ConfigEntry<float> fireFishDirectionChaos;
private ConfigEntry<float> aestrinDirectionChaos;
private ConfigEntry<float> chronosDirectionChaos;
private ConfigEntry<float> windChangeTimer;
private ConfigEntry<bool> overrideFinalLerpSpeed;
private ConfigEntry<float> finalLerpSpeed;
private ConfigEntry<bool> additionalOceanScaling;
private ConfigEntry<float> combinedBonusCap;
private Harmony harmony;
private Wind trackedWind;
private float capturedFinalLerpSpeed;
private bool hasCapturedFinalLerpSpeed;
private bool finalLerpOverrideApplied;
private float capturedTradeWindInfluence;
private float capturedMinimumMagnitude;
private bool hasCapturedTradeWindDefaults;
public static ChaoticWindPlugin Instance { get; private set; }
public ConfigEntry<bool> DisableTradeWind { get; private set; }
public bool TradeWindDisabled
{
get
{
if (DisableTradeWind != null)
{
return DisableTradeWind.Value;
}
return false;
}
}
public bool TradeWindOverrideActive
{
get
{
if (TradeWindDisabled)
{
return !ClimateCustomWindsActive();
}
return false;
}
}
private void Awake()
{
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Expected O, but got Unknown
Instance = this;
BindConfiguration();
SubscribeToConfiguration();
harmony = new Harmony("com.pete.sailwind.windconfigurator");
harmony.PatchAll(Assembly.GetExecutingAssembly());
ApplyRuntimeSettings();
((BaseUnityPlugin)this).Logger.LogInfo((object)"Chaotic Wind 1.2.0 loaded.");
}
private void OnDestroy()
{
UnsubscribeFromConfiguration();
if ((Object)(object)trackedWind != (Object)null && finalLerpOverrideApplied && hasCapturedFinalLerpSpeed)
{
trackedWind.finalLerpSpeed = capturedFinalLerpSpeed;
}
Harmony obj = harmony;
if (obj != null)
{
obj.UnpatchSelf();
}
if ((Object)(object)Instance == (Object)(object)this)
{
Instance = null;
}
}
private void BindConfiguration()
{
DisableTradeWind = ((BaseUnityPlugin)this).Config.Bind<bool>("Trade Wind", "Disable Trade Wind", true, "When enabled, Wind.GetCurrentTradeWind returns Vector3.zero.");
alAnkhDirectionChaos = BindDirectionChaos("AlAnkh", "Al'Ankh", 0.14f, 50);
emeraldDirectionChaos = BindDirectionChaos("Emerald", "Emerald", 0.18f, 40);
fireFishDirectionChaos = BindDirectionChaos("Fire Fish Lagoon", "Fire Fish Lagoon", 0.25f, 30);
aestrinDirectionChaos = BindDirectionChaos("Aestrin", "Aestrin", 0.21f, 20);
chronosDirectionChaos = BindDirectionChaos("Chronos", "Chronos", 0.21f, 10);
windChangeTimer = BindSlider("Wind Timing", "Wind Change Timer", 40f, 2f, 900f, "There is a random range for time from half the setting value to double the setting value. Setting value higher than 600sec(10min) is recommended if you go crazy on Direction Chaos setting.", 10);
overrideFinalLerpSpeed = ((BaseUnityPlugin)this).Config.Bind<bool>("Wind Smoothing", "Override Final Lerp Speed", false, "Enable the Final Lerp Speed slider override. When disabled, the original game value remains in use.");
finalLerpSpeed = BindSlider("Wind Smoothing", "Final Lerp Speed", 0.5f, 0.1f, 60f, "This value changes how fast wind speed changes. At 60 it will instantly change to the new wind speed at 60 FPS. USE AT YOUR OWN RISK.", 10);
additionalOceanScaling = ((BaseUnityPlugin)this).Config.Bind<bool>("Open Ocean Wind", "Enable Additional Ocean Scaling", false, "Continue ocean scaling beyond 4,000 units, reaching 2.3 (~1.52x Base Wind as bonus) at 72,000 units. Ignored while Climate Custom Winds is enabled.");
combinedBonusCap = BindSlider("Open Ocean Wind", "Storm + Ocean Bonus Cap", 20f, 0f, 100f, "Maximum combined storm and ocean wind bonus. Original game value is 20. Ignored while Climate Custom Winds is enabled.", 10);
}
private ConfigEntry<float> BindDirectionChaos(string key, string displayName, float defaultValue, int order)
{
return BindSlider("Direction Chaos", key, defaultValue, 0.01f, 1f, "Direction chaos for " + displayName + ".", order, displayName);
}
private ConfigEntry<float> BindSlider(string section, string key, float defaultValue, float minimum, float maximum, string description, int order, string displayName = null)
{
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: Expected O, but got Unknown
ConfigurationManagerMetadata configurationManagerMetadata = new ConfigurationManagerMetadata
{
ShowRangeAsPercent = false,
DispName = displayName,
Order = order
};
return ((BaseUnityPlugin)this).Config.Bind<float>(section, key, defaultValue, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<float>(minimum, maximum), new object[1] { configurationManagerMetadata }));
}
private void SubscribeToConfiguration()
{
alAnkhDirectionChaos.SettingChanged += OnRegionSettingChanged;
emeraldDirectionChaos.SettingChanged += OnRegionSettingChanged;
fireFishDirectionChaos.SettingChanged += OnRegionSettingChanged;
aestrinDirectionChaos.SettingChanged += OnRegionSettingChanged;
chronosDirectionChaos.SettingChanged += OnRegionSettingChanged;
DisableTradeWind.SettingChanged += OnWindSettingChanged;
windChangeTimer.SettingChanged += OnWindSettingChanged;
overrideFinalLerpSpeed.SettingChanged += OnWindSettingChanged;
finalLerpSpeed.SettingChanged += OnWindSettingChanged;
}
private void UnsubscribeFromConfiguration()
{
alAnkhDirectionChaos.SettingChanged -= OnRegionSettingChanged;
emeraldDirectionChaos.SettingChanged -= OnRegionSettingChanged;
fireFishDirectionChaos.SettingChanged -= OnRegionSettingChanged;
aestrinDirectionChaos.SettingChanged -= OnRegionSettingChanged;
chronosDirectionChaos.SettingChanged -= OnRegionSettingChanged;
DisableTradeWind.SettingChanged -= OnWindSettingChanged;
windChangeTimer.SettingChanged -= OnWindSettingChanged;
overrideFinalLerpSpeed.SettingChanged -= OnWindSettingChanged;
finalLerpSpeed.SettingChanged -= OnWindSettingChanged;
}
private void OnRegionSettingChanged(object sender, EventArgs e)
{
ApplyRuntimeSettings();
}
private void OnWindSettingChanged(object sender, EventArgs e)
{
ApplyRuntimeSettings();
}
private void ApplyRuntimeSettings()
{
ApplyRegionSettings();
TrackAndApplyWind(Wind.instance);
ApplyActiveRegionChaos();
}
public void ApplyRegionSettings()
{
Region[] array = Object.FindObjectsOfType<Region>();
foreach (Region val in array)
{
if (TryGetChaosForRegion(val, out var chaos))
{
val.windDirChaos = chaos;
}
}
}
internal void ApplyActiveRegionChaos()
{
if (!((Object)(object)Weather.instance == (Object)null) && !((Object)(object)Weather.instance.currentRegion == (Object)null))
{
Region region = GetRegionBlenderTargetRegion() ?? Weather.instance.currentRegion;
if (TryGetChaosForRegion(region, out var chaos))
{
Weather.instance.currentRegion.windDirChaos = chaos;
}
}
}
private static Region GetRegionBlenderTargetRegion()
{
if ((Object)(object)RegionBlender.instance == (Object)null)
{
return null;
}
object? obj = AccessTools.Field(typeof(RegionBlender), "currentTargetRegion")?.GetValue(RegionBlender.instance);
return (Region)((obj is Region) ? obj : null);
}
private bool TryGetChaosForRegion(Region region, out float chaos)
{
chaos = 0f;
if ((Object)(object)region == (Object)null)
{
return false;
}
switch (((Object)((Component)region).gameObject).name)
{
case "Region Al'ankh":
case "Region Equatorial":
case "Region Mid Latitude":
chaos = alAnkhDirectionChaos.Value;
return true;
case "Region Emerald (new smaller)":
chaos = emeraldDirectionChaos.Value;
return true;
case "Region Emerald Lagoon":
chaos = fireFishDirectionChaos.Value;
return true;
case "Region Medi":
chaos = aestrinDirectionChaos.Value;
return true;
case "Region Medi East":
case "Region Northern":
chaos = chronosDirectionChaos.Value;
return true;
default:
return false;
}
}
public void TrackAndApplyWind(Wind wind)
{
if (!((Object)(object)wind == (Object)null))
{
if ((Object)(object)trackedWind != (Object)(object)wind)
{
trackedWind = wind;
capturedFinalLerpSpeed = wind.finalLerpSpeed;
hasCapturedFinalLerpSpeed = true;
finalLerpOverrideApplied = false;
capturedTradeWindInfluence = wind.tradeWindInfluence;
capturedMinimumMagnitude = wind.minimumMagnitude;
hasCapturedTradeWindDefaults = true;
}
wind.changeTimer = windChangeTimer.Value;
if (overrideFinalLerpSpeed.Value)
{
wind.finalLerpSpeed = finalLerpSpeed.Value;
finalLerpOverrideApplied = true;
}
else if (finalLerpOverrideApplied && hasCapturedFinalLerpSpeed)
{
wind.finalLerpSpeed = capturedFinalLerpSpeed;
finalLerpOverrideApplied = false;
}
}
}
public void EnforceTradeWindOverride(Wind wind, ref Vector3 result)
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
if (TradeWindOverrideActive)
{
result = Vector3.zero;
if (hasCapturedTradeWindDefaults && (Object)(object)wind == (Object)(object)trackedWind)
{
wind.tradeWindInfluence = capturedTradeWindInfluence;
wind.minimumMagnitude = capturedMinimumMagnitude;
}
}
}
internal static float GetConfiguredOceanLerp(float originalMinimum, float originalMaximum, float distance)
{
ChaoticWindPlugin instance = Instance;
if ((Object)(object)instance == (Object)null || !instance.additionalOceanScaling.Value)
{
return Mathf.InverseLerp(originalMinimum, originalMaximum, distance);
}
if (!(distance <= 4000f))
{
return Mathf.Lerp(1f, 2.3f, Mathf.InverseLerp(4000f, 72000f, distance));
}
return Mathf.InverseLerp(1500f, 4000f, distance);
}
internal static float GetConfiguredBonusCap()
{
if (!((Object)(object)Instance == (Object)null))
{
return Instance.combinedBonusCap.Value;
}
return 20f;
}
internal static bool ClimateCustomWindsActive()
{
if (!GameState.playing || !Chainloader.PluginInfos.TryGetValue("com.raddude.climate", out var value) || (Object)(object)value.Instance == (Object)null)
{
return false;
}
ConfigEntry<bool> val = default(ConfigEntry<bool>);
if (value.Instance.Config.TryGetEntry<bool>("Settings", "Enable Custom Winds", ref val))
{
return val.Value;
}
return false;
}
}
[HarmonyPatch(typeof(Wind), "GetCurrentTradeWind")]
internal static class GetCurrentTradeWindPatch
{
[HarmonyPrefix]
[HarmonyPriority(600)]
[HarmonyBefore(new string[] { "com.nandbrew.borderexpander" })]
private static bool Prefix(ref Vector3 __result)
{
//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)
ChaoticWindPlugin instance = ChaoticWindPlugin.Instance;
if ((Object)(object)instance == (Object)null || !instance.TradeWindOverrideActive)
{
return true;
}
__result = Vector3.zero;
return false;
}
[HarmonyPostfix]
[HarmonyAfter(new string[] { "com.nandbrew.borderexpander" })]
private static void Postfix(Wind __instance, ref Vector3 __result)
{
ChaoticWindPlugin.Instance?.EnforceTradeWindOverride(__instance, ref __result);
}
}
[HarmonyPatch(typeof(Wind), "Awake")]
internal static class WindAwakePatch
{
[HarmonyPostfix]
private static void Postfix(Wind __instance)
{
ChaoticWindPlugin.Instance?.TrackAndApplyWind(__instance);
}
}
[HarmonyPatch(typeof(Wind), "SetNewWindTarget")]
internal static class WindSetNewTargetPatch
{
[HarmonyPrefix]
[HarmonyPriority(600)]
[HarmonyBefore(new string[] { "com.raddude.climate" })]
private static void Prefix()
{
ChaoticWindPlugin.Instance?.ApplyActiveRegionChaos();
}
[HarmonyTranspiler]
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
{
//IL_0196: Unknown result type (might be due to invalid IL or missing references)
//IL_019d: Expected O, but got Unknown
List<CodeInstruction> list = new List<CodeInstruction>(instructions);
MethodInfo objB = AccessTools.Method(typeof(Mathf), "InverseLerp", new Type[3]
{
typeof(float),
typeof(float),
typeof(float)
}, (Type[])null);
FieldInfo objB2 = AccessTools.Field(typeof(GameState), "distanceToLand");
MethodInfo operand = AccessTools.Method(typeof(ChaoticWindPlugin), "GetConfiguredOceanLerp", (Type[])null, (Type[])null);
MethodInfo methodInfo = AccessTools.Method(typeof(ChaoticWindPlugin), "GetConfiguredBonusCap", (Type[])null, (Type[])null);
int num = -1;
List<int> list2 = new List<int>();
for (int i = 0; i < list.Count; i++)
{
if (i >= 3 && object.Equals(list[i].operand, objB) && LoadsFloat(list[i - 3], 1500f) && LoadsFloat(list[i - 2], 4000f) && list[i - 1].opcode == OpCodes.Ldsfld && object.Equals(list[i - 1].operand, objB2))
{
num = i;
}
if (LoadsFloat(list[i], 20f))
{
list2.Add(i);
}
}
if (num < 0 || list2.Count != 2)
{
Debug.LogError((object)"[Chaotic Wind] Vanilla ocean wind patch pattern was not found.");
return list;
}
list[num].operand = operand;
for (int j = 0; j < list2.Count; j++)
{
int index = list2[j];
CodeInstruction val = list[index];
CodeInstruction val2 = new CodeInstruction(OpCodes.Call, (object)methodInfo);
val2.labels.AddRange(val.labels);
val2.blocks.AddRange(val.blocks);
list[index] = val2;
}
return list;
}
private static bool LoadsFloat(CodeInstruction instruction, float value)
{
if (instruction.opcode == OpCodes.Ldc_R4 && instruction.operand is float num)
{
return num == value;
}
return false;
}
}
[HarmonyPatch(typeof(RegionBlender), "Start")]
internal static class RegionBlenderStartPatch
{
[HarmonyPostfix]
[HarmonyAfter(new string[] { "com.nandbrew.borderexpander" })]
private static void Postfix()
{
ChaoticWindPlugin.Instance?.ApplyRegionSettings();
ChaoticWindPlugin.Instance?.ApplyActiveRegionChaos();
}
}
}