using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using Microsoft.CodeAnalysis;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyCompany("VoiceRangeMod")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("My first plugin")]
[assembly: AssemblyTitle("VoiceRangeMod")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[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.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace VoiceRangeMod
{
[BepInPlugin("com.Kingo.voicerange", "VoiceRangeMod", "1.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class VoiceRangePlugin : BaseUnityPlugin
{
public const string GUID = "com.Kingo.voicerange";
public const string NAME = "VoiceRangeMod";
public const string VERSION = "1.0.0";
internal static ManualLogSource Log;
private ConfigEntry<KeyboardShortcut> cfgWalkieKey;
private ConfigEntry<bool> cfgHoldToTalk;
private ConfigEntry<string> cfgRangeMode;
private volatile bool walkieActive = false;
private float lastApplyRangeWhen = 0f;
private readonly Dictionary<string, float> RangeMultipliers = new Dictionary<string, float>(StringComparer.OrdinalIgnoreCase)
{
{ "Normal", 1f },
{ "Far", 1.5f },
{ "VeryFar", 2f }
};
private const string DissonanceCommsTypeName = "Dissonance.DissonanceComms";
private readonly List<Behaviour> cachedBroadcastTriggers = new List<Behaviour>();
private readonly List<Behaviour> cachedReceiptTriggers = new List<Behaviour>();
private Behaviour cachedDissonanceComms = null;
private const float FallbackBaseRange = 15f;
private void Awake()
{
//IL_0025: 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)
Log = ((BaseUnityPlugin)this).Logger;
cfgWalkieKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Controls", "WalkieKey", new KeyboardShortcut((KeyCode)114, (KeyCode[])(object)new KeyCode[0]), "Key to activate Walkie-Talkie (global broadcast). Default: R");
cfgHoldToTalk = ((BaseUnityPlugin)this).Config.Bind<bool>("Controls", "HoldToTalk", true, "If true: hold the key to speak globally. If false: press once to toggle global mode.");
cfgRangeMode = ((BaseUnityPlugin)this).Config.Bind<string>("General", "RangeMode", "Normal", "Server preference for proximity voice: Normal, Far, VeryFar");
if (!RangeMultipliers.ContainsKey(cfgRangeMode.Value))
{
Log.LogWarning((object)("[VoiceRangeMod] Invalid RangeMode '" + cfgRangeMode.Value + "' in config. Resetting to 'Normal'."));
cfgRangeMode.Value = "Normal";
}
Log.LogInfo((object)string.Format("[{0}] v{1} loaded. WalkieKey={2}, HoldToTalk={3}, RangeMode={4}", "VoiceRangeMod", "1.0.0", cfgWalkieKey.Value, cfgHoldToTalk.Value, cfgRangeMode.Value));
if (Chainloader.PluginInfos.ContainsKey("com.Kingo.voicefix"))
{
Log.LogInfo((object)"[VoiceRangeMod] VoiceFix (com.Kingo.voicefix) detected — integration enabled.");
}
else
{
Log.LogInfo((object)"[VoiceRangeMod] VoiceFix not found. Running independent.");
}
DiscoverVoiceComponents();
((MonoBehaviour)this).InvokeRepeating("DiscoverVoiceComponents", 5f, 10f);
}
private void OnDestroy()
{
try
{
((MonoBehaviour)this).CancelInvoke("DiscoverVoiceComponents");
}
catch
{
}
}
private void Update()
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: 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_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
KeyboardShortcut value = cfgWalkieKey.Value;
bool flag = ((KeyboardShortcut)(ref value)).IsDown();
value = cfgWalkieKey.Value;
bool flag2 = ((KeyboardShortcut)(ref value)).IsUp();
value = cfgWalkieKey.Value;
bool flag3 = ((KeyboardShortcut)(ref value)).IsPressed();
if (cfgHoldToTalk.Value)
{
if (flag3 && !walkieActive)
{
walkieActive = true;
EnableWalkieGlobal();
}
else if (!flag3 && walkieActive)
{
walkieActive = false;
DisableWalkieGlobal();
}
}
else if (flag)
{
walkieActive = !walkieActive;
if (walkieActive)
{
EnableWalkieGlobal();
}
else
{
DisableWalkieGlobal();
}
}
float realtimeSinceStartup = Time.realtimeSinceStartup;
if (!walkieActive && realtimeSinceStartup - lastApplyRangeWhen > 1f)
{
ApplyProximityRangeMultiplier();
lastApplyRangeWhen = realtimeSinceStartup;
}
if (walkieActive && realtimeSinceStartup - lastApplyRangeWhen > 0.5f)
{
ApplyWalkieGlobalToBroadcasts();
lastApplyRangeWhen = realtimeSinceStartup;
}
}
private void DiscoverVoiceComponents()
{
cachedBroadcastTriggers.Clear();
cachedReceiptTriggers.Clear();
cachedDissonanceComms = null;
try
{
Behaviour[] array = Object.FindObjectsOfType<Behaviour>();
Behaviour[] array2 = array;
foreach (Behaviour val in array2)
{
if (!((Object)(object)val == (Object)null))
{
Type type = ((object)val).GetType();
string text = type.FullName ?? type.Name;
string text2 = text.ToLowerInvariant();
if (text2.Contains("voicebroadcast") || text2.Contains("broadcasttrigger"))
{
cachedBroadcastTriggers.Add(val);
}
if (text2.Contains("voicereceipt") || text2.Contains("receipttrigger"))
{
cachedReceiptTriggers.Add(val);
}
if (text.Equals("Dissonance.DissonanceComms", StringComparison.Ordinal) || text2.Contains("dissonancecomms"))
{
cachedDissonanceComms = val;
}
}
}
Log.LogDebug((object)string.Format("[{0}] Discovery complete. Broadcasts={1}, Receipts={2}, DissonanceComms={3}", "VoiceRangeMod", cachedBroadcastTriggers.Count, cachedReceiptTriggers.Count, (Object)(object)cachedDissonanceComms != (Object)null));
}
catch (Exception ex)
{
Log.LogWarning((object)("[VoiceRangeMod] DiscoverVoiceComponents error: " + ex.Message));
}
}
private void EnableWalkieGlobal()
{
Log.LogInfo((object)"[VoiceRangeMod] Walkie-Talkie ACTIVATED (global).");
ApplyWalkieGlobalToBroadcasts();
}
private void DisableWalkieGlobal()
{
Log.LogInfo((object)"[VoiceRangeMod] Walkie-Talkie DEACTIVATED (back to proximity).");
ApplyProximityRangeMultiplier();
}
private void ApplyWalkieGlobalToBroadcasts()
{
Behaviour[] array = cachedBroadcastTriggers.ToArray();
foreach (Behaviour val in array)
{
if ((Object)(object)val == (Object)null)
{
continue;
}
Type type = ((object)val).GetType();
PropertyInfo property = type.GetProperty("ChannelType", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if ((object)property != null)
{
try
{
Type propertyType = property.PropertyType;
string[] names = Enum.GetNames(propertyType);
string text = names.FirstOrDefault((string n) => n.Equals("Global", StringComparison.OrdinalIgnoreCase));
if (text != null)
{
object value = Enum.Parse(propertyType, text);
property.SetValue(val, value, null);
continue;
}
}
catch (Exception ex)
{
Log.LogDebug((object)("[VoiceRangeMod] ChannelType set attempt failed on " + type.FullName + ": " + ex.Message));
}
}
if (!TrySetRangeFieldOrProperty(val, 1.7014117E+38f))
{
try
{
val.enabled = false;
val.enabled = true;
}
catch
{
}
}
}
Behaviour[] array2 = cachedReceiptTriggers.ToArray();
foreach (Behaviour val2 in array2)
{
if (!((Object)(object)val2 == (Object)null))
{
TrySetRangeFieldOrProperty(val2, 1.7014117E+38f);
}
}
}
private void ApplyProximityRangeMultiplier()
{
float value = 1f;
if (!RangeMultipliers.TryGetValue(cfgRangeMode.Value, out value))
{
value = 1f;
}
float valueOrDefault = ReadBaseRangeFromAnyTrigger().GetValueOrDefault(15f);
float num = valueOrDefault * value;
Behaviour[] array = cachedBroadcastTriggers.ToArray();
foreach (Behaviour val in array)
{
if ((Object)(object)val == (Object)null || TrySetRangeFieldOrProperty(val, num))
{
continue;
}
Type type = ((object)val).GetType();
PropertyInfo property = type.GetProperty("ChannelType", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if ((object)property == null)
{
continue;
}
try
{
Type propertyType = property.PropertyType;
string[] names = Enum.GetNames(propertyType);
string text = names.FirstOrDefault((string n) => n.Equals("Proximity", StringComparison.OrdinalIgnoreCase) || n.Equals("Nearby", StringComparison.OrdinalIgnoreCase));
if (text != null)
{
object value2 = Enum.Parse(propertyType, text);
property.SetValue(val, value2, null);
}
}
catch
{
}
}
Behaviour[] array2 = cachedReceiptTriggers.ToArray();
foreach (Behaviour val2 in array2)
{
if (!((Object)(object)val2 == (Object)null))
{
TrySetRangeFieldOrProperty(val2, num);
}
}
Log.LogInfo((object)string.Format("[{0}] Applied RangeMode={1} multiplier={2} targetRange={3:F1}", "VoiceRangeMod", cfgRangeMode.Value, value, num));
}
private bool TrySetRangeFieldOrProperty(Behaviour comp, float value)
{
if ((Object)(object)comp == (Object)null)
{
return false;
}
Type type = ((object)comp).GetType();
string[] array = new string[8] { "Range", "range", "Radius", "radius", "Distance", "distance", "MaxDistance", "maxDistance" };
try
{
string[] array2 = array;
foreach (string text in array2)
{
PropertyInfo property = type.GetProperty(text, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if ((object)property != null)
{
if ((object)property.PropertyType == typeof(float))
{
try
{
property.SetValue(comp, value, null);
return true;
}
catch (Exception ex)
{
Log.LogDebug((object)("[VoiceRangeMod] prop.SetValue(" + text + ") failed on " + type.FullName + ": " + ex.Message));
}
}
else if ((object)property.PropertyType == typeof(double))
{
try
{
property.SetValue(comp, (double)value, null);
return true;
}
catch (Exception ex2)
{
Log.LogDebug((object)("[VoiceRangeMod] prop.SetValue(" + text + ") failed on " + type.FullName + ": " + ex2.Message));
}
}
}
FieldInfo field = type.GetField(text, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if ((object)field == null)
{
continue;
}
if ((object)field.FieldType == typeof(float))
{
try
{
field.SetValue(comp, value);
return true;
}
catch (Exception ex3)
{
Log.LogDebug((object)("[VoiceRangeMod] fld.SetValue(" + text + ") failed on " + type.FullName + ": " + ex3.Message));
}
}
else if ((object)field.FieldType == typeof(double))
{
try
{
field.SetValue(comp, (double)value);
return true;
}
catch (Exception ex4)
{
Log.LogDebug((object)("[VoiceRangeMod] fld.SetValue(" + text + ") failed on " + type.FullName + ": " + ex4.Message));
}
}
}
}
catch (Exception ex5)
{
Log.LogDebug((object)("[VoiceRangeMod] TrySetRangeFieldOrProperty outer error: " + ex5.Message));
}
return false;
}
private float? ReadBaseRangeFromAnyTrigger()
{
foreach (Behaviour item in cachedBroadcastTriggers.Concat(cachedReceiptTriggers))
{
if ((Object)(object)item == (Object)null)
{
continue;
}
Type type = ((object)item).GetType();
string[] array = new string[8] { "Range", "range", "Radius", "radius", "Distance", "distance", "MaxDistance", "maxDistance" };
try
{
string[] array2 = array;
foreach (string name in array2)
{
PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if ((object)property != null)
{
try
{
object value = property.GetValue(item, null);
if (value is float value2)
{
return value2;
}
if (value is double)
{
double num = (double)value;
if (true)
{
return (float)num;
}
}
}
catch
{
}
}
FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if ((object)field == null)
{
continue;
}
try
{
object value3 = field.GetValue(item);
if (value3 is float value4)
{
return value4;
}
if (value3 is double)
{
double num2 = (double)value3;
if (true)
{
return (float)num2;
}
}
}
catch
{
}
}
}
catch
{
}
}
return null;
}
}
public static class MyPluginInfo
{
public const string PLUGIN_GUID = "VoiceRangeMod";
public const string PLUGIN_NAME = "My first plugin";
public const string PLUGIN_VERSION = "1.0.0";
}
}