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.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Mirror;
using TMPro;
using UnityEngine;
using UnityEngine.Localization;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("GameAssembly")]
[assembly: IgnoresAccessChecksTo("SharedAssembly")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("RandomWind")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+1b90ff945a285959a9ec2b98a235974fe797ddc3")]
[assembly: AssemblyProduct("Random Wind")]
[assembly: AssemblyTitle("RandomWind")]
[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;
}
}
}
namespace RandomWind
{
[BepInPlugin("com.sbg.randomwind", "RandomWind", "1.0.0")]
public class Plugin : BaseUnityPlugin
{
public const string PLUGIN_GUID = "com.sbg.randomwind";
public const string PLUGIN_NAME = "RandomWind";
public const string PLUGIN_VERSION = "1.0.0";
internal static ManualLogSource Log { get; private set; }
internal static RandomWindConfig Settings { get; private set; }
private void Awake()
{
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
Log = ((BaseUnityPlugin)this).Logger;
Settings = new RandomWindConfig(((BaseUnityPlugin)this).Config);
new Harmony("com.sbg.randomwind").PatchAll();
var (num, num2) = Settings.GetNormalizedRange();
Log.LogInfo((object)string.Format("{0} {1} loaded (random wind {2}-{3} km/h).", "RandomWind", "1.0.0", num, num2));
}
}
internal sealed class RandomWindConfig
{
internal const int MAX_POSSIBLE_WIND_KMH = 100;
internal const int MIN_POSSIBLE_WIND_KMH = 0;
private const int DEFAULT_MIN_WIND_KMH = 0;
private const int DEFAULT_MAX_WIND_KMH = 99;
private const float NO_BIAS = 1f;
private const float MAX_LOW_WIND_BIAS = 4f;
private const int DEFAULT_NO_WIND_CHANCE_PERCENT = 0;
private const string SECTION = "RandomWind";
private const string SECTION_DISTRIBUTION = "Distribution";
internal ConfigEntry<int> MinWindKmh { get; }
internal ConfigEntry<int> MaxWindKmh { get; }
internal ConfigEntry<float> LowWindBias { get; }
internal ConfigEntry<int> NoWindChancePercent { get; }
internal ConfigEntry<bool> UseDropdownOption { get; }
internal ConfigEntry<bool> FallbackOverrideEnabled { get; }
internal RandomWindConfig(ConfigFile config)
{
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_0031: Expected O, but got Unknown
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_0059: Expected O, but got Unknown
//IL_0088: Unknown result type (might be due to invalid IL or missing references)
//IL_0092: Expected O, but got Unknown
//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
//IL_00c0: Expected O, but got Unknown
AcceptableValueRange<int> val = new AcceptableValueRange<int>(0, 100);
MinWindKmh = config.Bind<int>("RandomWind", "MinWindKmh", 0, new ConfigDescription("Lowest wind speed (km/h) the Random option can roll.", (AcceptableValueBase)(object)val, Array.Empty<object>()));
MaxWindKmh = config.Bind<int>("RandomWind", "MaxWindKmh", 99, new ConfigDescription("Highest wind speed (km/h) the Random option can roll.", (AcceptableValueBase)(object)val, Array.Empty<object>()));
LowWindBias = config.Bind<float>("Distribution", "LowWindBias", 1f, new ConfigDescription("1 = every speed equally likely. Higher skews rolls toward the minimum: 1.5 averages about 40 km/h over 0-99 (like vanilla Medium), 2 about 33.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 4f), Array.Empty<object>()));
NoWindChancePercent = config.Bind<int>("Distribution", "NoWindChancePercent", 0, new ConfigDescription("Extra chance (0-100) that a hole rolls exactly the minimum speed, checked before anything else. With a minimum of 0 this is the chance of no wind.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
UseDropdownOption = config.Bind<bool>("RandomWind", "UseDropdownOption", true, "Add a 'Random' entry to the Wind dropdown in the match setup menu.");
FallbackOverrideEnabled = config.Bind<bool>("RandomWind", "FallbackOverrideEnabled", false, "Roll every non-Off wind setting in the min/max range instead of its tier. Use this if the dropdown option misbehaves after a game update.");
}
internal (int Min, int Max) GetNormalizedRange()
{
return WindSpeedRoller.Normalize(MinWindKmh.Value, MaxWindKmh.Value, 0, 100);
}
}
internal static class WindSpeedRoller
{
private const int PERCENT_SCALE = 100;
private const double NO_BIAS_THRESHOLD = 1.0;
internal static (int Min, int Max) Normalize(int first, int second, int floor, int ceiling)
{
int num = Math.Min(Math.Max(first, floor), ceiling);
int num2 = Math.Min(Math.Max(second, floor), ceiling);
if (num > num2)
{
return (Min: num2, Max: num);
}
return (Min: num, Max: num2);
}
internal static int Roll(int min, int max, double lowWindBias, int noWindChancePercent, Func<int, int, int> nextIntExclusiveMax, Func<double> nextUnit)
{
if (noWindChancePercent > 0 && nextIntExclusiveMax(0, 100) < noWindChancePercent)
{
return min;
}
if (lowWindBias <= 1.0)
{
return nextIntExclusiveMax(min, max + 1);
}
int num = max - min;
double num2 = Math.Pow(nextUnit(), lowWindBias);
return min + Math.Min(num, (int)(num2 * (double)(num + 1)));
}
}
public static class MyPluginInfo
{
public const string PLUGIN_GUID = "RandomWind";
public const string PLUGIN_NAME = "Random Wind";
public const string PLUGIN_VERSION = "1.0.0";
}
}
namespace RandomWind.Patches
{
internal static class RandomWindOption
{
internal const int RANDOM_WIND_VALUE = 5;
internal const string RANDOM_OPTION_LABEL = "Random";
private const int VANILLA_OPTION_COUNT = 5;
private static readonly HashSet<LocalizeDropdown> ExtendedDropdowns = new HashSet<LocalizeDropdown>();
internal static bool IsExtended(LocalizeDropdown dropdown)
{
return ExtendedDropdowns.Contains(dropdown);
}
internal static void EnsureRandomOption(DropdownOption windDropdown)
{
//IL_008b: Unknown result type (might be due to invalid IL or missing references)
//IL_0091: 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_00a0: Expected O, but got Unknown
LocalizeDropdown val = (((Object)(object)windDropdown != (Object)null) ? windDropdown.Localized : null);
if ((Object)(object)val == (Object)null)
{
Plugin.Log.LogWarning((object)"Wind dropdown has no LocalizeDropdown; cannot add the Random option. Cause: the game's menu layout changed. Resolution: enable FallbackOverrideEnabled in the config.");
}
else if (!ExtendedDropdowns.Contains(val))
{
List<LocalizedString> dropdownOptions = val.dropdownOptions;
if (dropdownOptions.Count != 5)
{
Plugin.Log.LogWarning((object)($"Wind dropdown has {dropdownOptions.Count} options, expected {5}; " + "leaving it untouched."));
return;
}
LocalizedString val2 = dropdownOptions[dropdownOptions.Count - 1];
dropdownOptions.Add(new LocalizedString(((LocalizedReference)val2).TableReference, ((LocalizedReference)val2).TableEntryReference));
ExtendedDropdowns.Add(val);
val.RefreshOptions();
}
}
}
[HarmonyPatch(typeof(MatchSetupRules), "Initialize")]
internal static class AddRandomOptionPatch
{
[HarmonyPrefix]
private static void Prefix(MatchSetupRules __instance)
{
if (Plugin.Settings.UseDropdownOption.Value)
{
RandomWindOption.EnsureRandomOption(__instance.wind);
}
}
}
[HarmonyPatch(typeof(LocalizeDropdown), "RefreshOptions")]
internal static class RelabelRandomOptionPatch
{
[HarmonyPostfix]
private static void Postfix(LocalizeDropdown __instance)
{
if (RandomWindOption.IsExtended(__instance))
{
List<OptionData> options = __instance.tmpDropdown.options;
if (options.Count > 5)
{
options[5].text = "Random";
__instance.tmpDropdown.RefreshShownValue();
}
}
}
}
[HarmonyPatch(typeof(MatchSetupRules), "GetFormattedValue")]
internal static class FormatRandomValuePatch
{
[HarmonyPostfix]
private static void Postfix(MatchSetupRules __instance, Rule rule, ref string __result)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0003: Invalid comparison between Unknown and I4
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
if ((int)rule == 20 && (int)__instance.GetValueInternal(rule) == 5)
{
__result = "Random";
}
}
}
[HarmonyPatch(typeof(WindManager), "RandomizeWind")]
internal static class WindRollPatch
{
private const int WIND_RULE_OFF_VALUE = 0;
[HarmonyPostfix]
private static void Postfix(WindManager __instance)
{
if (NetworkServer.active && __instance.initialized && ShouldRollRandomSpeed())
{
var (min, max) = Plugin.Settings.GetNormalizedRange();
__instance.NetworkcurrentWindSpeed = WindSpeedRoller.Roll(min, max, (double)Plugin.Settings.LowWindBias.Value, Plugin.Settings.NoWindChancePercent.Value, (Func<int, int, int>)Random.Range, (Func<double>)(() => Random.value));
}
}
private static bool ShouldRollRandomSpeed()
{
int num = (int)MatchSetupRules.GetValue((Rule)20);
if (num == 5)
{
return Plugin.Settings.UseDropdownOption.Value;
}
if (Plugin.Settings.FallbackOverrideEnabled.Value)
{
return num != 0;
}
return false;
}
}
}
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
internal sealed class IgnoresAccessChecksToAttribute : Attribute
{
public IgnoresAccessChecksToAttribute(string assemblyName)
{
}
}
}