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 Ship Comms v1.1.6
BepInEx/plugins/ShipComms/ShipComms.dll
Decompiled 2 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using Dissonance; using Dissonance.Audio.Playback; using GameNetcodeStuff; using HarmonyLib; using LethalConfig; using LethalConfig.ConfigItems; using LethalLib.Modules; using Microsoft.CodeAnalysis; using TMPro; using Unity.Collections; using Unity.Netcode; using UnityEngine; using UnityEngine.Events; using UnityEngine.InputSystem; using UnityEngine.UI; [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("ShipComms")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.1.6.0")] [assembly: AssemblyInformationalVersion("1.1.6")] [assembly: AssemblyProduct("ShipComms")] [assembly: AssemblyTitle("ShipComms")] [assembly: AssemblyVersion("1.1.6.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [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 ShipComms { [HarmonyPatch(typeof(LungProp), "EquipItem")] internal static class ApparatusRemovalPatch { [HarmonyPrefix] internal static void Prefix(LungProp __instance, out bool __state) { __state = __instance.isLungDocked; } [HarmonyPostfix] internal static void Postfix(LungProp __instance, bool __state) { //IL_002c: 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_003a: Unknown result type (might be due to invalid IL or missing references) StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance == (Object)null) { return; } int num; if (!((GrabbableObject)__instance).isInShipRoom) { if ((Object)(object)instance.shipInnerRoomBounds != (Object)null) { Bounds bounds = instance.shipInnerRoomBounds.bounds; num = (((Bounds)(ref bounds)).Contains(((Component)__instance).transform.position) ? 1 : 0); } else { num = 0; } } else { num = 1; } bool inShip = (byte)num != 0; CommsRuntime.ObserveApparatusPickup(__state, __instance.isLungDocked, !instance.inShipPhase, inShip); } } [HarmonyPatch(typeof(StartOfRound), "StartGame")] internal static class InterferenceNewMoonPatch { [HarmonyPrefix] internal static void Prefix(StartOfRound __instance) { if (((NetworkBehaviour)__instance).IsServer && __instance.inShipPhase) { CommsRuntime.ResetApparatusInterference(); } } } [HarmonyPatch(typeof(StartOfRound), "SetShipReadyToLand")] internal static class InterferenceOrbitPatch { [HarmonyPostfix] internal static void Postfix() { CommsRuntime.ResetApparatusInterference(); } } internal static class AuxiliaryPowerUpgrade { internal const string Name = "Auxiliary Power Unit"; internal static UnlockableItem? Item { get { if (!((Object)(object)StartOfRound.Instance == (Object)null)) { return StartOfRound.Instance.unlockablesList.unlockables.Find((UnlockableItem item) => item.unlockableName == "Auxiliary Power Unit"); } return null; } } internal static bool IsPurchased { get { UnlockableItem item = Item; if (item != null) { if (!item.hasBeenUnlockedByPlayer) { return item.alreadyUnlocked; } return true; } return false; } } internal static void ClearFurnitureState() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: 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) UnlockableItem item = Item; if (item != null) { item.inStorage = false; item.hasBeenMoved = false; item.placedPosition = Vector3.zero; item.placedRotation = Vector3.zero; } } } [HarmonyPatch(typeof(StartOfRound), "LoadUnlockables")] internal static class AuxiliaryPowerLoadPatch { [HarmonyPostfix] internal static void Postfix() { AuxiliaryPowerUpgrade.ClearFurnitureState(); } } [HarmonyPatch(typeof(GameNetworkManager), "ResetUnlockablesListValues")] internal static class AuxiliaryPowerResetPatch { [HarmonyPostfix] internal static void Postfix(bool onlyResetPrefabItems) { UnlockableItem item = AuxiliaryPowerUpgrade.Item; if (item != null && onlyResetPrefabItems) { item.hasBeenUnlockedByPlayer = false; } AuxiliaryPowerUpgrade.ClearFurnitureState(); } } internal static class ChimeWaveform { internal const int SampleRate = 48000; internal const float Duration = 1.2f; internal const int SampleCount = 57600; internal const string ResourceName = "ShipComms.Assets.IntercomStart.pcm"; internal static float[] Create() { using Stream stream = typeof(ChimeWaveform).Assembly.GetManifestResourceStream("ShipComms.Assets.IntercomStart.pcm") ?? throw new InvalidDataException("The intercom startup recording is missing."); if (stream.Length != 115200) { throw new InvalidDataException("The intercom startup recording has an unexpected length."); } using BinaryReader binaryReader = new BinaryReader(stream); float[] array = new float[57600]; for (int i = 0; i < array.Length; i++) { array[i] = (float)binaryReader.ReadInt16() / 32768f; } return array; } } internal enum UnitKind : byte { Intercom, Receiver, AuxiliaryPower } internal enum Command : byte { Snapshot, Begin, End, Power, Heartbeat } internal enum IntercomPhase : byte { Off, Starting, Live } internal static class CommsRules { internal const ulong Nobody = ulong.MaxValue; internal const float LeaseSeconds = 1.2f; internal const double StartupSeconds = 1.2; internal const float UseRange = 3.5f; internal const float ReceiverRange = 16f; internal const int NoiseId = 18473; internal static bool CanUse(bool alive, bool inShip, bool spawned, bool stored, float distance) { if (alive && inShip && spawned && !stored) { return distance <= 3.5f; } return false; } internal static bool CanTakeMic(ulong current, ulong requester) { if (current != ulong.MaxValue) { return current == requester; } return true; } internal static bool CanHearIntercom(bool listenerAlive, bool inside, bool speakerAlive, bool transmitting) { return listenerAlive && inside && speakerAlive && transmitting; } internal static bool CanHearReceiver(bool listenerAlive, bool insideFactory, bool powered, bool speakerAlive, bool usingRadio, float distance) { if (listenerAlive && !insideFactory && powered && speakerAlive && usingRadio) { return distance < 16f; } return false; } internal static float ReceiverGain(float distance) { return Math.Max(0f, Math.Min(1f, (16f - distance) / 14f)); } internal static float ReceiverVoiceGain(float distance, float receiverVolume, bool personalRadioAudible) { return Math.Max(ReceiverGain(distance) * receiverVolume, personalRadioAudible ? 1f : 0f); } internal static float ClampPickupRange(float range) { if (!float.IsNaN(range) && !float.IsInfinity(range)) { return Math.Max(1f, Math.Min(12f, range)); } return 4f; } internal static float PickupGain(bool active, bool alive, bool insideFactory, bool operatorSpeaking, float distance, float range) { if (!active || !alive || insideFactory) { return 0f; } if (operatorSpeaking) { return 1f; } range = ClampPickupRange(range); return Math.Max(0f, Math.Min(1f, (range - distance) / (range * 0.75f))); } internal static bool EmitNoise(bool powered, bool validTransmitter, bool speaking, float amplitude) { if (powered && validTransmitter && speaking) { return amplitude >= 0.005f; } return false; } internal static bool CanHearStatic(UnitKind kind, bool listenerAlive, bool insideFactory, bool active, bool receivedVoice, float receiverDistance) { if (receivedVoice) { return kind switch { UnitKind.Receiver => CanHearReceiver(listenerAlive, insideFactory, active, speakerAlive: true, usingRadio: true, receiverDistance), UnitKind.Intercom => CanHearIntercom(listenerAlive, insideFactory, speakerAlive: true, active), _ => false, }; } return false; } internal static bool HasApparatusInterference(bool apparatusRemoved, bool enabled, bool auxiliaryPowerOnline) { if (apparatusRemoved && enabled) { return !auxiliaryPowerOnline; } return false; } internal static int ClampCost(int value) { return Math.Max(0, Math.Min(100000, value)); } } internal readonly struct SignalProfile { internal readonly float LowPass; internal readonly float HighPass; internal readonly float Distortion; internal SignalProfile(UnitKind kind, float strength, bool apparatusInterference = false) { strength = (float.IsNaN(strength) ? 0f : Math.Max(0f, Math.Min(1f, strength))); LowPass = 4000f - strength * ((kind == UnitKind.Intercom) ? 700f : 1700f); HighPass = 300f + strength * ((kind == UnitKind.Intercom) ? 200f : 400f); Distortion = strength * ((kind == UnitKind.Intercom) ? 0.2f : 0.36f); if (apparatusInterference) { LowPass = Math.Min(LowPass, (kind == UnitKind.Intercom) ? 2200f : 1800f); HighPass = Math.Max(HighPass, (kind == UnitKind.Intercom) ? 600f : 700f); Distortion = Math.Max(Distortion, (kind == UnitKind.Intercom) ? 0.35f : 0.45f); } } } internal readonly struct ReceiverPlayback { internal readonly bool Spatial; internal readonly float SourceGain; internal readonly float AudibleGain; internal ReceiverPlayback(float distance, float volume, bool personalRadioAudible, bool canPositionSource) { AudibleGain = CommsRules.ReceiverVoiceGain(distance, volume, personalRadioAudible); Spatial = !personalRadioAudible && canPositionSource; SourceGain = (Spatial ? volume : AudibleGain); } } internal sealed class ApparatusState { internal bool Removed { get; private set; } internal bool ObservePickup(bool wasDocked, bool isDocked, bool duringMoon, bool inShip) { if (Removed || !wasDocked || isDocked || !duringMoon || inShip) { return false; } Removed = true; return true; } internal void Reset() { Removed = false; } } internal sealed class UnitState { internal bool Powered; internal ulong Speaker = ulong.MaxValue; internal double Expires; internal uint Sequence; internal double ReadyAt; internal bool StartupCue; internal bool Begin(ulong sender, double now, bool startCue = true) { if (!CommsRules.CanTakeMic(Speaker, sender)) { return false; } if (Speaker == ulong.MaxValue) { Sequence++; StartupCue = startCue; ReadyAt = now + (startCue ? 1.2 : 0.0); } Speaker = sender; Expires = now + 1.2000000476837158; return true; } internal bool End(ulong sender) { if (Speaker != sender) { return false; } Speaker = ulong.MaxValue; Expires = 0.0; ReadyAt = 0.0; StartupCue = false; return true; } internal bool Expire(double now, bool valid) { if (Speaker == ulong.MaxValue || (valid && now < Expires)) { return false; } return End(Speaker); } } internal sealed class StartupGate { private ulong speaker = ulong.MaxValue; private uint sequence; private double localReadyAt; internal bool Matches(UnitState state) { if (speaker == state.Speaker) { return sequence == state.Sequence; } return false; } internal bool Observe(UnitState state, double serverNow, double audioNow) { if (Matches(state)) { return false; } speaker = state.Speaker; sequence = state.Sequence; bool flag = speaker != ulong.MaxValue && state.StartupCue && serverNow < state.ReadyAt; localReadyAt = audioNow + (flag ? 1.2 : 0.0); return flag; } internal IntercomPhase Phase(UnitState state, double serverNow, double audioNow, bool cuePlaying) { if (state.Speaker == ulong.MaxValue) { return IntercomPhase.Off; } if (!Matches(state) || !(serverNow >= state.ReadyAt) || !(audioNow >= localReadyAt) || cuePlaying) { return IntercomPhase.Starting; } return IntercomPhase.Live; } internal void Reset() { speaker = ulong.MaxValue; sequence = 0u; localReadyAt = 0.0; } } public sealed class CommsRuntime : MonoBehaviour { [CompilerGenerated] private static class <>O { public static HandleNamedMessageDelegate <0>__OnRequest; } private const string RequestMessage = "sockpoop.shipcomms.request.v2"; private const string StateMessage = "sockpoop.shipcomms.state.v2"; internal static readonly List<CommsUnit> Units = new List<CommsUnit>(); private static readonly Dictionary<ulong, UnitState> states = new Dictionary<ulong, UnitState>(); internal static CommsUnit? HeldUnit; private static NetworkManager? network; private bool connected; private bool receivedState; private float nextRequest; private static float nextHeartbeat; private float nextNoise; private bool lastHostChimeEnabled = true; internal static bool StartChimeEnabled = true; private float lastHostPickupRange = 4f; internal static float PickupRange = 4f; private static readonly ApparatusState apparatus = new ApparatusState(); internal static bool ApparatusInterference; private bool lastHostInterference; internal static bool AuxiliaryPowerOnline; private bool lastHostAuxiliaryPower; private static readonly UnitState inactive = new UnitState(); internal static double ServerClock { get { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)network != (Object)null) || !network.IsListening) { return 0.0; } NetworkTime serverTime = network.ServerTime; return ((NetworkTime)(ref serverTime)).Time; } } internal static bool LocalIsBroadcasting { get { if ((Object)(object)network != (Object)null && (Object)(object)HeldUnit != (Object)null && HeldUnit.Transmitting && HeldUnit.State.Speaker == network.LocalClientId && CanUse(GameNetworkManager.Instance?.localPlayerController, HeldUnit) && (Object)(object)InputSystem.actions != (Object)null) { return InputSystem.actions.FindAction("Interact", false).IsPressed(); } return false; } } internal static UnitState StateFor(ulong id) { if (!states.TryGetValue(id, out UnitState value)) { return inactive; } return value; } internal static PlayerControllerB? Player(ulong clientId) { if ((Object)(object)StartOfRound.Instance == (Object)null) { return null; } PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts; foreach (PlayerControllerB val in allPlayerScripts) { if ((Object)(object)val != (Object)null && val.actualClientId == clientId && val.isPlayerControlled) { return val; } } return null; } internal static bool CanUse(PlayerControllerB? player, CommsUnit? unit) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player != (Object)null && (Object)(object)unit != (Object)null) { return CommsRules.CanUse(!player.isPlayerDead && player.isPlayerControlled, player.isInHangarShipRoom, unit.Available, !unit.Available, Vector3.Distance(((Component)player).transform.position, ((Component)unit).transform.position)); } return false; } private void Update() { //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Expected O, but got Unknown //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Expected O, but got Unknown NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || !singleton.IsListening || singleton.CustomMessagingManager == null) { if (connected) { Disconnect(); } return; } if (!connected || (Object)(object)network != (Object)(object)singleton) { Disconnect(); network = singleton; CustomMessagingManager customMessagingManager = network.CustomMessagingManager; object obj = <>O.<0>__OnRequest; if (obj == null) { HandleNamedMessageDelegate val = OnRequest; <>O.<0>__OnRequest = val; obj = (object)val; } customMessagingManager.RegisterNamedMessageHandler("sockpoop.shipcomms.request.v2", (HandleNamedMessageDelegate)obj); network.CustomMessagingManager.RegisterNamedMessageHandler("sockpoop.shipcomms.state.v2", new HandleNamedMessageDelegate(OnState)); connected = true; receivedState = singleton.IsServer; nextRequest = 0f; } if (!receivedState && Time.realtimeSinceStartup >= nextRequest) { Send(Command.Snapshot, 0uL); nextRequest = Time.realtimeSinceStartup + 1f; } if ((Object)(object)HeldUnit != (Object)null) { PlayerControllerB val2 = GameNetworkManager.Instance?.localPlayerController; if (!CanUse(val2, HeldUnit) || val2.inTerminalMenu || val2.isTypingChat || val2.inSpecialMenu || (Object)(object)InputSystem.actions == (Object)null || !InputSystem.actions.FindAction("Interact", false).IsPressed()) { StopLocalTalk(); } else if (Time.realtimeSinceStartup >= nextHeartbeat) { Send(Command.Heartbeat, HeldUnit.Id); nextHeartbeat = Time.realtimeSinceStartup + 0.25f; } } if (!singleton.IsServer) { return; } StartChimeEnabled = Plugin.StartChimeEnabled.Value; PickupRange = CommsRules.ClampPickupRange(Plugin.IntercomPickupRange.Value); AuxiliaryPowerOnline = AuxiliaryPowerUpgrade.IsPurchased; ApparatusInterference = CommsRules.HasApparatusInterference(apparatus.Removed, Plugin.ApparatusInterferenceEnabled.Value, AuxiliaryPowerOnline); bool flag = lastHostChimeEnabled != StartChimeEnabled || lastHostPickupRange != PickupRange || lastHostInterference != ApparatusInterference || lastHostAuxiliaryPower != AuxiliaryPowerOnline; lastHostChimeEnabled = StartChimeEnabled; lastHostPickupRange = PickupRange; lastHostInterference = ApparatusInterference; lastHostAuxiliaryPower = AuxiliaryPowerOnline; foreach (CommsUnit unit in Units) { if (!((Object)(object)unit == (Object)null) && unit.Available) { UnitState unitState = MutableState(unit.Id); if (unit.Kind == UnitKind.Intercom && unitState.Expire(ServerClock, CanUse(Player(unitState.Speaker), unit))) { flag = true; } } } foreach (KeyValuePair<ulong, UnitState> state in states) { if ((Object)(object)FindUnit(state.Key) == (Object)null && state.Value.Expire(ServerClock, valid: false)) { flag = true; } } if (flag) { Broadcast(); } if (Time.realtimeSinceStartup >= nextNoise) { VoiceRouting.EmitWorldNoise(); nextNoise = Time.realtimeSinceStartup + 0.25f; } } private void Disconnect() { if ((Object)(object)network != (Object)null && network.CustomMessagingManager != null) { network.CustomMessagingManager.UnregisterNamedMessageHandler("sockpoop.shipcomms.request.v2"); network.CustomMessagingManager.UnregisterNamedMessageHandler("sockpoop.shipcomms.state.v2"); } HeldUnit = null; states.Clear(); foreach (CommsUnit unit in Units) { if ((Object)(object)unit != (Object)null) { unit.ResetStartup(); } } connected = false; receivedState = false; network = null; StartChimeEnabled = Plugin.StartChimeEnabled.Value; PickupRange = CommsRules.ClampPickupRange(Plugin.IntercomPickupRange.Value); apparatus.Reset(); ApparatusInterference = false; AuxiliaryPowerOnline = false; VoiceRouting.Reset(); UpgradeCatalog.HostIntercomCost = CommsRules.ClampCost(Plugin.IntercomCost.Value); UpgradeCatalog.HostReceiverCost = CommsRules.ClampCost(Plugin.ReceiverCost.Value); UpgradeCatalog.HostAuxiliaryPowerCost = CommsRules.ClampCost(Plugin.AuxiliaryPowerCost.Value); } private void OnDestroy() { Disconnect(); } internal static void ObserveApparatusPickup(bool wasDocked, bool isDocked, bool duringMoon, bool inShip) { if (!((Object)(object)network == (Object)null) && network.IsServer && apparatus.ObservePickup(wasDocked, isDocked, duringMoon, inShip)) { Broadcast(); } } internal static void ResetApparatusInterference() { if (!((Object)(object)network == (Object)null) && network.IsServer) { apparatus.Reset(); Broadcast(); } } private static UnitState MutableState(ulong id) { if (!states.TryGetValue(id, out UnitState value)) { states.Add(id, value = new UnitState()); } return value; } private static CommsUnit? FindUnit(ulong id) { foreach (CommsUnit unit in Units) { if ((Object)(object)unit != (Object)null && unit.Available && unit.Id == id) { return unit; } } return null; } internal static void BeginLocalTalk(CommsUnit unit) { if ((Object)(object)HeldUnit != (Object)null && (Object)(object)HeldUnit != (Object)(object)unit) { StopLocalTalk(); } HeldUnit = unit; nextHeartbeat = Time.realtimeSinceStartup + 0.25f; Send(Command.Begin, unit.Id); } internal static void StopLocalTalk() { if ((Object)(object)HeldUnit != (Object)null) { Send(Command.End, HeldUnit.Id); } HeldUnit = null; } internal unsafe static void Send(Command command, ulong id, bool power = false) { //IL_004c: 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_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)network == (Object)null || !network.IsListening) { return; } if (network.IsServer) { Handle(network.LocalClientId, command, id, power); return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(16, (Allocator)2, -1); try { byte b = (byte)command; ((FastBufferWriter)(ref val)).WriteValueSafe<byte>(ref b, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref id, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref power, default(ForPrimitives)); network.CustomMessagingManager.SendNamedMessage("sockpoop.shipcomms.request.v2", 0uL, val, (NetworkDelivery)3); } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } } private static void OnRequest(ulong sender, FastBufferReader reader) { //IL_002b: 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_003d: 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_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)network == (Object)null) && network.IsServer && ((FastBufferReader)(ref reader)).TryBeginRead(10)) { byte b = default(byte); ((FastBufferReader)(ref reader)).ReadValueSafe<byte>(ref b, default(ForPrimitives)); ulong id = default(ulong); ((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref id, default(ForPrimitives)); bool power = default(bool); ((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref power, default(ForPrimitives)); if (b <= 4) { Handle(sender, (Command)b, id, power); } } } private static void Handle(ulong sender, Command command, ulong id, bool power) { if ((Object)(object)network == (Object)null || !network.IsServer || !network.ConnectedClients.ContainsKey(sender)) { return; } if (command == Command.Snapshot) { Broadcast(sender); return; } CommsUnit commsUnit = FindUnit(id); if ((Object)(object)commsUnit == (Object)null) { return; } UnitState unitState = MutableState(id); if (command == Command.End) { if (commsUnit.Kind == UnitKind.Intercom && unitState.End(sender)) { Broadcast(); } } else { if (!CanUse(Player(sender), commsUnit)) { return; } if (command == Command.Power && commsUnit.Kind == UnitKind.Receiver) { unitState.Powered = power; Broadcast(); } else if (commsUnit.Kind == UnitKind.Intercom && (command == Command.Begin || command == Command.Heartbeat) && (command != Command.Heartbeat || unitState.Speaker == sender)) { bool flag = unitState.Speaker != sender; if (unitState.Begin(sender, ServerClock, Plugin.StartChimeEnabled.Value) && (flag || command == Command.Begin)) { Broadcast(); } } } } private unsafe static void Broadcast(ulong? target = null) { //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0087: 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_009c: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_018d: 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_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Unknown result type (might be due to invalid IL or missing references) //IL_0208: Unknown result type (might be due to invalid IL or missing references) //IL_0217: Unknown result type (might be due to invalid IL or missing references) //IL_021d: Unknown result type (might be due to invalid IL or missing references) //IL_022c: 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) //IL_026f: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)network == (Object)null || !network.IsServer) { return; } StartChimeEnabled = Plugin.StartChimeEnabled.Value; PickupRange = CommsRules.ClampPickupRange(Plugin.IntercomPickupRange.Value); AuxiliaryPowerOnline = AuxiliaryPowerUpgrade.IsPurchased; ApparatusInterference = CommsRules.HasApparatusInterference(apparatus.Removed, Plugin.ApparatusInterferenceEnabled.Value, AuxiliaryPowerOnline); FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(2048, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref UpgradeCatalog.HostIntercomCost, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref UpgradeCatalog.HostReceiverCost, default(ForPrimitives)); List<CommsUnit> list = new List<CommsUnit>(); foreach (CommsUnit unit in Units) { if ((Object)(object)unit != (Object)null && unit.Available) { list.Add(unit); } } int num = Math.Min(list.Count, 64); ((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref num, default(ForPrimitives)); for (int i = 0; i < num; i++) { CommsUnit commsUnit = list[i]; UnitState unitState = MutableState(commsUnit.Id); ulong id = commsUnit.Id; ((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref id, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref unitState.Powered, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref unitState.Speaker, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe<uint>(ref unitState.Sequence, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe<double>(ref unitState.ReadyAt, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref unitState.StartupCue, default(ForPrimitives)); } ((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref StartChimeEnabled, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe<float>(ref PickupRange, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref ApparatusInterference, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref UpgradeCatalog.HostAuxiliaryPowerCost, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref AuxiliaryPowerOnline, default(ForPrimitives)); if (target.HasValue) { network.CustomMessagingManager.SendNamedMessage("sockpoop.shipcomms.state.v2", target.Value, val, (NetworkDelivery)3); } else { network.CustomMessagingManager.SendNamedMessageToAll("sockpoop.shipcomms.state.v2", val, (NetworkDelivery)3); } } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } } private void OnState(ulong sender, FastBufferReader reader) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0041: 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_0054: 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_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: 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) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)network == (Object)null || network.IsServer || sender != 0L || !((FastBufferReader)(ref reader)).TryBeginRead(12)) { return; } int value = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref value, default(ForPrimitives)); int value2 = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref value2, default(ForPrimitives)); int num = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref num, default(ForPrimitives)); if (num < 0 || num > 64 || !((FastBufferReader)(ref reader)).TryBeginRead(num * 30)) { return; } Dictionary<ulong, UnitState> dictionary = new Dictionary<ulong, UnitState>(); ulong key = default(ulong); bool powered = default(bool); ulong speaker = default(ulong); uint sequence = default(uint); double num2 = default(double); bool startupCue = default(bool); for (int i = 0; i < num; i++) { ((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref key, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref powered, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref speaker, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValueSafe<uint>(ref sequence, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValueSafe<double>(ref num2, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref startupCue, default(ForPrimitives)); if (double.IsNaN(num2) || double.IsInfinity(num2)) { return; } dictionary[key] = new UnitState { Powered = powered, Speaker = speaker, Sequence = sequence, ReadyAt = num2, StartupCue = startupCue }; } bool startChimeEnabled = true; if (((FastBufferReader)(ref reader)).TryBeginRead(1)) { ((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref startChimeEnabled, default(ForPrimitives)); } StartChimeEnabled = startChimeEnabled; float range = 4f; if (((FastBufferReader)(ref reader)).TryBeginRead(4)) { ((FastBufferReader)(ref reader)).ReadValueSafe<float>(ref range, default(ForPrimitives)); } PickupRange = CommsRules.ClampPickupRange(range); bool apparatusInterference = false; if (((FastBufferReader)(ref reader)).TryBeginRead(1)) { ((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref apparatusInterference, default(ForPrimitives)); } ApparatusInterference = apparatusInterference; int value3 = 300; if (((FastBufferReader)(ref reader)).TryBeginRead(4)) { ((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref value3, default(ForPrimitives)); } bool auxiliaryPowerOnline = false; if (((FastBufferReader)(ref reader)).TryBeginRead(1)) { ((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref auxiliaryPowerOnline, default(ForPrimitives)); } AuxiliaryPowerOnline = auxiliaryPowerOnline; states.Clear(); foreach (KeyValuePair<ulong, UnitState> item in dictionary) { states.Add(item.Key, item.Value); } UpgradeCatalog.HostIntercomCost = CommsRules.ClampCost(value); UpgradeCatalog.HostReceiverCost = CommsRules.ClampCost(value2); UpgradeCatalog.HostAuxiliaryPowerCost = CommsRules.ClampCost(value3); UpgradeCatalog.ApplyPrices(); receivedState = true; } } public sealed class CommsUnit : MonoBehaviour { [SerializeField] internal UnitKind Kind; [SerializeField] internal InteractTrigger Trigger; [SerializeField] internal Transform Button; [SerializeField] internal Renderer Indicator; [SerializeField] internal Material LightOn; [SerializeField] internal Material LightStarting; [SerializeField] internal Material LightOff; [SerializeField] internal AudioSource SpeakerAudio; private Vector3 buttonPosition; private AutoParentToShip parent; private PlaceableShipObject placeable; private NetworkObject netObject; private bool wasPowered; private readonly StartupGate startup = new StartupGate(); internal float AudibleUntil; internal bool AmbientAudible; internal ulong Id { get { if (!((Object)(object)netObject != (Object)null)) { return ulong.MaxValue; } return netObject.NetworkObjectId; } } internal bool Available { get { if ((Object)(object)netObject != (Object)null && netObject.IsSpawned && ((Behaviour)this).isActiveAndEnabled && (Object)(object)parent != (Object)null && !parent.disableObject && (Object)(object)StartOfRound.Instance != (Object)null) { return !StartOfRound.Instance.suckingFurnitureOutOfShip; } return false; } } internal UnitState State => CommsRuntime.StateFor(Id); internal bool ChannelActive { get { if (Available) { if (Kind != UnitKind.Receiver) { if (Kind == UnitKind.Intercom) { return Transmitting; } return false; } return State.Powered; } return false; } } internal bool Transmitting => Phase == IntercomPhase.Live; internal IntercomPhase Phase { get { if (!Available || Kind != UnitKind.Intercom) { return IntercomPhase.Off; } RefreshStartup(); return startup.Phase(State, CommsRuntime.ServerClock, AudioSettings.dspTime, SpeakerAudio.isPlaying); } } internal Vector3 MicrophonePosition => ((Component)this).transform.TransformPoint(new Vector3(-0.14f, 1.39f, 0.045f) * 1.2f); private void Start() { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: 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_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) netObject = ((Component)this).GetComponent<NetworkObject>(); parent = ((Component)this).GetComponent<AutoParentToShip>(); placeable = ((Component)this).GetComponentInChildren<PlaceableShipObject>(); buttonPosition = Button.localPosition; ((UnityEvent<PlayerControllerB>)(object)Trigger.onInteract).AddListener((UnityAction<PlayerControllerB>)Use); InteractTrigger[] array = Object.FindObjectsOfType<InteractTrigger>(); foreach (InteractTrigger val in array) { if ((Object)(object)val != (Object)(object)Trigger && (Object)(object)val.hoverIcon != (Object)null) { Trigger.hoverIcon = val.hoverIcon; break; } } GameObject val2 = new GameObject("Nameplate"); val2.transform.SetParent(((Component)this).transform, false); val2.transform.localPosition = new Vector3(0f, 0.69f, -0.232f) * 1.2f; val2.transform.localScale = Vector3.one * 1.2f; TextMeshPro val3 = val2.AddComponent<TextMeshPro>(); ((TMP_Text)val3).fontSize = 0.65f; ((TMP_Text)val3).enableAutoSizing = true; ((TMP_Text)val3).fontSizeMin = 0.3f; ((TMP_Text)val3).fontSizeMax = 0.65f; ((TMP_Text)val3).enableWordWrapping = false; ((TMP_Text)val3).overflowMode = (TextOverflowModes)3; ((TMP_Text)val3).alignment = (TextAlignmentOptions)514; ((Graphic)val3).color = new Color(0.88f, 0.89f, 0.77f); ((TMP_Text)val3).rectTransform.sizeDelta = new Vector2(0.49f, 0.09f); if ((Object)(object)HUDManager.Instance != (Object)null && HUDManager.Instance.controlTipLines.Length != 0) { ((TMP_Text)val3).font = ((TMP_Text)HUDManager.Instance.controlTipLines[0]).font; } ((TMP_Text)val3).text = ((Kind == UnitKind.Intercom) ? "SHIP INTERCOM" : "RADIO RECEIVER"); if ((Object)(object)ShipBuildModeManager.Instance != (Object)null) { placeable.placeObjectSFX = ShipBuildModeManager.Instance.beginPlacementSFX; } CommsRuntime.Units.Add(this); Plugin.Log.LogInfo((object)("Spawned " + Kind.ToString() + " upgrade (network object " + Id + ").")); } private void Use(PlayerControllerB player) { if ((Object)(object)GameNetworkManager.Instance == (Object)null || (Object)(object)player != (Object)(object)GameNetworkManager.Instance.localPlayerController || !CommsRuntime.CanUse(player, this)) { return; } if (Kind == UnitKind.Intercom) { if ((Object)(object)IngamePlayerSettings.Instance == (Object)null || !IngamePlayerSettings.Instance.settings.micEnabled) { HUDManager.Instance.DisplayTip("Microphone disabled", "Enable your microphone in the game settings to use the intercom.", false, false, "LC_Tip1"); } else { CommsRuntime.BeginLocalTalk(this); } } else { CommsRuntime.Send(Command.Power, Id, !State.Powered); } } private void Update() { //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0081: 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) if (!Available) { ResetStartup(); return; } bool flag = ((Kind == UnitKind.Receiver) ? State.Powered : (State.Speaker != ulong.MaxValue)); IntercomPhase intercomPhase = ((Kind == UnitKind.Intercom) ? Phase : IntercomPhase.Off); Indicator.sharedMaterial = ((!flag) ? LightOff : ((intercomPhase == IntercomPhase.Starting) ? LightStarting : LightOn)); Button.localPosition = buttonPosition + (flag ? (Vector3.down * 0.018000001f) : Vector3.zero); Trigger.hoverTip = ((Kind != UnitKind.Intercom) ? (flag ? "Receiver ON - switch off : [E]" : "Receiver OFF - switch on : [E]") : ((intercomPhase == IntercomPhase.Starting) ? "Wait for green (hold) : [E]" : (flag ? "Broadcasting (hold) : [E]" : "Hold to broadcast : [E]"))); if (Kind == UnitKind.Receiver) { SignalProcessing.Configure(SpeakerAudio, UnitKind.Receiver); SpeakerAudio.volume = (flag ? Plugin.ReceiverVolume.Value : 0f); if (wasPowered && !flag) { SpeakerAudio.Stop(); AudibleUntil = 0f; } wasPowered = flag; } placeable.inUse = Kind == UnitKind.Intercom && flag; } private void RefreshStartup() { UnitState state = State; if (!startup.Matches(state)) { SpeakerAudio.Stop(); AudibleUntil = 0f; AmbientAudible = false; } if (startup.Observe(state, CommsRuntime.ServerClock, AudioSettings.dspTime)) { IntercomChime.Play(this); } IntercomChime.StopOutsideFacility(this); } internal void ResetStartup() { startup.Reset(); if (Kind == UnitKind.Intercom && (Object)(object)SpeakerAudio != (Object)null) { SpeakerAudio.Stop(); } AudibleUntil = 0f; AmbientAudible = false; } private void OnDisable() { ResetStartup(); if ((Object)(object)CommsRuntime.HeldUnit == (Object)(object)this) { CommsRuntime.StopLocalTalk(); } } private void OnDestroy() { ResetStartup(); CommsRuntime.Units.Remove(this); if ((Object)(object)CommsRuntime.HeldUnit == (Object)(object)this) { CommsRuntime.StopLocalTalk(); } } } internal static class ConfigMenu { [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] internal static void Register() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected O, but got Unknown //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Expected O, but got Unknown //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Expected O, but got Unknown //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Expected O, but got Unknown //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Expected O, but got Unknown //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: 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 //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Expected O, but got Unknown //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Expected O, but got Unknown LethalConfigManager.AddConfigItem((BaseConfigItem)new IntInputFieldConfigItem(Plugin.IntercomCost, true)); LethalConfigManager.AddConfigItem((BaseConfigItem)new IntInputFieldConfigItem(Plugin.ReceiverCost, true)); LethalConfigManager.AddConfigItem((BaseConfigItem)new IntInputFieldConfigItem(Plugin.AuxiliaryPowerCost, true)); LethalConfigManager.AddConfigItem((BaseConfigItem)new FloatSliderConfigItem(Plugin.IntercomVolume, false)); LethalConfigManager.AddConfigItem((BaseConfigItem)new FloatSliderConfigItem(Plugin.ReceiverVolume, false)); LethalConfigManager.AddConfigItem((BaseConfigItem)new BoolCheckBoxConfigItem(Plugin.StartChimeEnabled, false)); LethalConfigManager.AddConfigItem((BaseConfigItem)new FloatSliderConfigItem(Plugin.StartChimeVolume, false)); LethalConfigManager.AddConfigItem((BaseConfigItem)new FloatSliderConfigItem(Plugin.IntercomPickupRange, false)); LethalConfigManager.AddConfigItem((BaseConfigItem)new FloatSliderConfigItem(Plugin.IntercomEnvironmentVolume, false)); LethalConfigManager.AddConfigItem((BaseConfigItem)new FloatSliderConfigItem(Plugin.IntercomProcessing, false)); LethalConfigManager.AddConfigItem((BaseConfigItem)new FloatSliderConfigItem(Plugin.ReceiverProcessing, false)); LethalConfigManager.AddConfigItem((BaseConfigItem)new BoolCheckBoxConfigItem(Plugin.ApparatusInterferenceEnabled, false)); LethalConfigManager.AddConfigItem((BaseConfigItem)new FloatSliderConfigItem(Plugin.NormalStaticVolume, false)); LethalConfigManager.AddConfigItem((BaseConfigItem)new FloatSliderConfigItem(Plugin.ApparatusStaticVolume, false)); } } internal static class IntercomChime { private static AudioClip? clip; private static bool LocalCanHear() { PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if ((Object)(object)val != (Object)null) { return CommsRules.CanHearIntercom(val.isPlayerControlled && !val.isPlayerDead, val.isInsideFactory, speakerAlive: true, transmitting: true); } return false; } internal static void StopOutsideFacility(CommsUnit unit) { if (unit.SpeakerAudio.isPlaying && !LocalCanHear()) { unit.SpeakerAudio.Stop(); } } internal static void Play(CommsUnit unit) { //IL_0139: Unknown result type (might be due to invalid IL or missing references) if (LocalCanHear()) { if ((Object)(object)clip == (Object)null) { float[] array = ChimeWaveform.Create(); clip = AudioClip.Create("Ship Comms transmission start", array.Length, 1, 48000, false); clip.SetData(array, 0); } unit.SpeakerAudio.spatialBlend = 0f; unit.SpeakerAudio.clip = clip; unit.SpeakerAudio.loop = false; unit.SpeakerAudio.pitch = 1f; unit.SpeakerAudio.volume = Plugin.IntercomVolume.Value * Plugin.StartChimeVolume.Value; unit.SpeakerAudio.time = 0f; unit.SpeakerAudio.Play(); } if ((Object)(object)NetworkManager.Singleton == (Object)null || !NetworkManager.Singleton.IsServer || (Object)(object)StartOfRound.Instance == (Object)null || StartOfRound.Instance.inShipPhase || (Object)(object)RoundManager.Instance == (Object)null) { return; } PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts; foreach (PlayerControllerB val in allPlayerScripts) { if ((Object)(object)val != (Object)null && val.isPlayerControlled && !val.isPlayerDead && val.isInsideFactory) { RoundManager.Instance.PlayAudibleNoise(((Component)val).transform.position, 12f, 0.5f, 0, false, 18473); } } } } internal sealed class IntercomEnvironmentRelay : MonoBehaviour { private readonly Dictionary<AudioSource, AudioSource> outputs = new Dictionary<AudioSource, AudioSource>(); private readonly Dictionary<AudioSource, float> oneShotUntil = new Dictionary<AudioSource, float>(); private CommsUnit unit; private AudioSource? oneShots; private float nextScan; private void Awake() { unit = ((Component)this).GetComponent<CommsUnit>(); } private static bool LocalCanHear() { PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if ((Object)(object)val != (Object)null && val.isPlayerControlled && !val.isPlayerDead) { return val.isInsideFactory; } return false; } private static bool IsWorldSound(AudioSource source) { if ((Object)(object)source != (Object)null && ((Behaviour)source).isActiveAndEnabled && !source.mute && source.volume > 0f && source.spatialBlend > 0.01f && (Object)(object)((Component)source).GetComponentInParent<CommsUnit>() == (Object)null && (Object)(object)((Component)source).GetComponentInParent<WalkieTalkie>() == (Object)null && (Object)(object)((Component)source).GetComponentInParent<PlayerVoiceIngameSettings>() == (Object)null) { return (Object)(object)((Component)source).GetComponentInParent<VoicePlayback>() == (Object)null; } return false; } private float Pickup(AudioSource source) { //IL_0014: 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) return CommsRules.PickupGain(unit.Transmitting, alive: true, insideFactory: false, operatorSpeaking: false, Vector3.Distance(((Component)source).transform.position, unit.MicrophonePosition), CommsRuntime.PickupRange); } private AudioSource CreateOutput(string name) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name); val.transform.SetParent(((Component)this).transform, false); AudioSource obj = val.AddComponent<AudioSource>(); obj.playOnAwake = false; obj.spatialBlend = 0f; SignalProcessing.Configure(obj, UnitKind.Intercom); return obj; } internal void RelayOneShot(AudioSource source, AudioClip clip, float volume) { if ((Object)(object)unit == (Object)null || !unit.Transmitting || !IsWorldSound(source) || (Object)(object)clip == (Object)null || volume <= 0f) { return; } float num = Pickup(source) * source.volume * volume; if (num <= 0.001f) { return; } float num2 = Time.realtimeSinceStartup + clip.length; unit.AudibleUntil = Mathf.Max(unit.AudibleUntil, num2); if ((Object)(object)source.clip == (Object)(object)clip) { oneShotUntil[source] = num2; } if (LocalCanHear()) { if ((Object)(object)oneShots == (Object)null) { oneShots = CreateOutput("Intercom world one-shots"); } oneShots.outputAudioMixerGroup = source.outputAudioMixerGroup; oneShots.volume = Plugin.IntercomVolume.Value * Plugin.IntercomEnvironmentVolume.Value; SignalProcessing.Configure(oneShots, UnitKind.Intercom); oneShots.PlayOneShot(clip, num); } } private void Update() { //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Invalid comparison between Unknown and I4 if ((Object)(object)unit == (Object)null || !unit.Transmitting) { StopPlayback(); oneShotUntil.Clear(); if ((Object)(object)unit != (Object)null) { unit.AmbientAudible = false; unit.AudibleUntil = 0f; } return; } bool flag = LocalCanHear(); if (!flag) { StopPlayback(); } if ((Object)(object)oneShots != (Object)null) { oneShots.volume = Plugin.IntercomVolume.Value * Plugin.IntercomEnvironmentVolume.Value; SignalProcessing.Configure(oneShots, UnitKind.Intercom); } if (Time.realtimeSinceStartup < nextScan) { return; } nextScan = Time.realtimeSinceStartup + 0.2f; List<AudioSource> list = new List<AudioSource>(); foreach (KeyValuePair<AudioSource, float> item in oneShotUntil) { if ((Object)(object)item.Key == (Object)null || Time.realtimeSinceStartup >= item.Value) { list.Add(item.Key); } } foreach (AudioSource item2 in list) { oneShotUntil.Remove(item2); } Dictionary<AudioSource, float> dictionary = new Dictionary<AudioSource, float>(); AudioSource[] array = Object.FindObjectsOfType<AudioSource>(); foreach (AudioSource val in array) { if (IsWorldSound(val) && val.isPlaying && !((Object)(object)val.clip == (Object)null) && (int)val.clip.loadState == 2 && !oneShotUntil.ContainsKey(val)) { float num = Pickup(val) * val.volume; if (num > 0.001f && dictionary.Count < 16) { dictionary[val] = num; } } } unit.AmbientAudible = dictionary.Count > 0; if (!flag) { return; } List<AudioSource> list2 = new List<AudioSource>(); foreach (KeyValuePair<AudioSource, AudioSource> output in outputs) { if ((Object)(object)output.Key == (Object)null || !dictionary.ContainsKey(output.Key)) { if ((Object)(object)output.Value != (Object)null) { Object.Destroy((Object)(object)((Component)output.Value).gameObject); } list2.Add(output.Key); } } foreach (AudioSource item3 in list2) { outputs.Remove(item3); } foreach (KeyValuePair<AudioSource, float> item4 in dictionary) { AudioSource key = item4.Key; if (!outputs.TryGetValue(key, out AudioSource value)) { value = CreateOutput("Intercom nearby world audio"); outputs.Add(key, value); } bool num2 = (Object)(object)value.clip != (Object)(object)key.clip || !value.isPlaying; value.clip = key.clip; value.loop = key.loop; value.pitch = key.pitch; value.outputAudioMixerGroup = key.outputAudioMixerGroup; value.volume = item4.Value * Plugin.IntercomVolume.Value * Plugin.IntercomEnvironmentVolume.Value; SignalProcessing.Configure(value, UnitKind.Intercom); float num3 = Mathf.Clamp(key.time, 0f, Mathf.Max(0f, key.clip.length - 0.001f)); if (num2) { value.time = num3; value.Play(); } else if (Mathf.Abs(value.time - num3) > 0.2f) { value.time = num3; } } } private void StopPlayback() { if ((Object)(object)oneShots != (Object)null) { oneShots.Stop(); } foreach (AudioSource value in outputs.Values) { if ((Object)(object)value != (Object)null) { Object.Destroy((Object)(object)((Component)value).gameObject); } } outputs.Clear(); } private void OnDisable() { StopPlayback(); if ((Object)(object)unit != (Object)null) { unit.AmbientAudible = false; unit.AudibleUntil = 0f; } } } internal static class InterferenceEnvelope { private const double SliceSeconds = 0.12; private const float Edge = 0.08f; internal static float Gain(bool interference, double serverTime, ulong sender) { if (!interference) { return 1f; } if (double.IsNaN(serverTime) || double.IsInfinity(serverTime) || serverTime < 0.0) { return 0.55f; } double num = serverTime / 0.12; long num2 = (long)Math.Floor(num); float num3 = (float)(num - (double)num2); float num4 = Sample(num2, sender); if (num3 < 0.08f) { float num5 = Sample(num2 - 1, sender); return num5 + (num4 - num5) * ((num3 + 0.08f) / 0.16f); } if (num3 > 0.92f) { return num4 + (Sample(num2 + 1, sender) - num4) * ((num3 - 0.92f) / 0.16f); } return num4; } private static float Sample(long slice, ulong sender) { uint num = (uint)(((int)slice * -1640531527) ^ (int)sender ^ (int)(sender >> 32)); num ^= num >> 16; num *= 2146121005; num ^= num >> 15; num *= 2221713035u; num ^= num >> 16; if ((num & 0xFF) >= 64) { return 0.48f + (float)((num >> 8) & 0xFF) / 255f * 0.12f; } return 0f; } } [BepInPlugin("sockpoop.shipcomms", "Ship Comms", "1.1.6")] [BepInDependency("evaisa.lethallib", "1.2.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class Plugin : BaseUnityPlugin { public const string Guid = "sockpoop.shipcomms"; public const string Name = "Ship Comms"; public const string Version = "1.1.6"; internal static ManualLogSource Log; internal static ConfigEntry<int> IntercomCost; internal static ConfigEntry<int> ReceiverCost; internal static ConfigEntry<int> AuxiliaryPowerCost; internal static ConfigEntry<float> IntercomVolume; internal static ConfigEntry<float> ReceiverVolume; internal static ConfigEntry<bool> StartChimeEnabled; internal static ConfigEntry<float> StartChimeVolume; internal static ConfigEntry<float> IntercomPickupRange; internal static ConfigEntry<float> IntercomEnvironmentVolume; internal static ConfigEntry<float> IntercomProcessing; internal static ConfigEntry<float> ReceiverProcessing; internal static ConfigEntry<bool> ApparatusInterferenceEnabled; internal static ConfigEntry<float> NormalStaticVolume; internal static ConfigEntry<float> ApparatusStaticVolume; private Harmony? harmony; private void Awake() { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Expected O, but got Unknown //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Expected O, but got Unknown //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Expected O, but got Unknown //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Expected O, but got Unknown //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Expected O, but got Unknown //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Expected O, but got Unknown //IL_01f8: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Expected O, but got Unknown //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Expected O, but got Unknown //IL_0272: Unknown result type (might be due to invalid IL or missing references) //IL_027c: Expected O, but got Unknown //IL_02cf: Unknown result type (might be due to invalid IL or missing references) //IL_02d9: Expected O, but got Unknown //IL_030c: Unknown result type (might be due to invalid IL or missing references) //IL_0316: Expected O, but got Unknown //IL_033c: Unknown result type (might be due to invalid IL or missing references) //IL_0346: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; IntercomCost = ((BaseUnityPlugin)this).Config.Bind<int>("Prices", "IntercomCost", 250, new ConfigDescription("Ship Intercom price in credits. Host value is used by the lobby. Restart after editing.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100000), Array.Empty<object>())); ReceiverCost = ((BaseUnityPlugin)this).Config.Bind<int>("Prices", "ReceiverCost", 150, new ConfigDescription("Radio Receiver price in credits. Host value is used by the lobby. Restart after editing.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100000), Array.Empty<object>())); AuxiliaryPowerCost = ((BaseUnityPlugin)this).Config.Bind<int>("Prices", "AuxiliaryPowerCost", 300, new ConfigDescription("Auxiliary Power Unit price in credits. Buying this passive upgrade protects both communication channels from apparatus interference; no model or placement is required. Host value is used by the lobby. Restart after editing.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100000), Array.Empty<object>())); IntercomVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Audio", "IntercomVolume", 0.9f, new ConfigDescription("Local listening volume for facility broadcasts. Does not change enemy hearing.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); ReceiverVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Audio", "ReceiverVolume", 0.9f, new ConfigDescription("Local listening volume for the receiver. Use its physical OFF button to silence it for enemies.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); StartChimeEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Sound Effects", "IntercomStartChimeEnabled", true, "Host setting: play the 1.2-second PA startup tone before opening the intercom. Yellow means wait; green means live. The tone and its enemy noise occur only inside the facility. Disabling skips the tone and wait on the next press."); StartChimeVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Sound Effects", "IntercomStartChimeVolume", 0.8f, new ConfigDescription("Local volume of the PA startup tone in the facility, multiplied by IntercomVolume. Muting it does not skip the transmission delay or change enemy hearing.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); IntercomPickupRange = ((BaseUnityPlugin)this).Config.Bind<float>("Intercom", "PickupRange", 4f, new ConfigDescription("Host setting: microphone pickup radius in metres for nearby voices and world sounds while the button is held. The button operator is always heard. Takes effect immediately.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 12f), Array.Empty<object>())); IntercomEnvironmentVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Audio", "IntercomEnvironmentVolume", 0.65f, new ConfigDescription("Local volume for world sounds picked up by the microphone, multiplied by IntercomVolume. Does not change voices or enemy hearing.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); IntercomProcessing = ((BaseUnityPlugin)this).Config.Bind<float>("Sound Effects", "IntercomProcessing", 0.7f, new ConfigDescription("Local PA filtering and mild distortion. Zero restores the original clean transmission effect; one is strongest.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); ReceiverProcessing = ((BaseUnityPlugin)this).Config.Bind<float>("Sound Effects", "ReceiverProcessing", 0.8f, new ConfigDescription("Local narrow-band radio filtering and distortion. Zero restores the original clean transmission effect; one is strongest.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); ApparatusInterferenceEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Sound Effects", "ApparatusInterferenceEnabled", true, "Host setting: removing the docked apparatus causes quieter voices, short cutouts, stronger processing, and heavy static during received speech until returning to orbit, unless auxiliary power is purchased. No idle hiss. Intercom static is heard only inside the facility."); NormalStaticVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Sound Effects", "NormalStaticVolume", 0.035f, new ConfigDescription("Local background static during received speech, multiplied by the device volume. Silent between voices; intercom static is facility-only. Does not change enemy hearing.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); ApparatusStaticVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Sound Effects", "ApparatusStaticVolume", 0.32f, new ConfigDescription("Local heavy static during received speech after apparatus removal, multiplied by the device volume. Silent between voices and for ambient sounds alone. Intercom static is facility-only. Does not change enemy hearing; use the receiver OFF button or release the intercom.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); if (Chainloader.PluginInfos.ContainsKey("ainavt.lc.lethalconfig")) { ConfigMenu.Register(); } UpgradeCatalog.Register(); harmony = new Harmony("sockpoop.shipcomms"); harmony.PatchAll(typeof(Plugin).Assembly); ((Component)this).gameObject.AddComponent<CommsRuntime>(); Log.LogInfo((object)"Ship Comms 1.1.6 loaded: Ship Intercom, Radio Receiver, and Auxiliary Power Unit. All players need this mod."); } private void OnDestroy() { Harmony? obj = harmony; if (obj != null) { obj.UnpatchSelf(); } } } [HarmonyPatch(typeof(Terminal), "Awake")] internal static class TerminalSetupPatch { [HarmonyPostfix] internal static void Postfix() { UpgradeCatalog.FinishSetup(); } } [HarmonyPatch(typeof(StartOfRound), "Update")] internal static class IntercomPushToTalkPatch { [HarmonyPostfix] internal static void Postfix(StartOfRound __instance) { if (CommsRuntime.LocalIsBroadcasting && (Object)(object)IngamePlayerSettings.Instance != (Object)null && IngamePlayerSettings.Instance.settings.micEnabled && (Object)(object)__instance.voiceChatModule != (Object)null) { __instance.voiceChatModule.IsMuted = false; } } } [HarmonyPatch(typeof(PlayerVoiceIngameSettings), "LateUpdate")] internal static class VoiceOutputPatch { [HarmonyPostfix] [HarmonyPriority(0)] internal static void Postfix(PlayerVoiceIngameSettings __instance) { VoiceRouting.Apply(__instance); } } internal sealed class RadioEnvironmentRelay : MonoBehaviour { private static readonly FieldInfo replaySources = AccessTools.Field(typeof(WalkieTalkie), "audioSourcesToReplay"); private readonly Dictionary<AudioSource, AudioSource> outputs = new Dictionary<AudioSource, AudioSource>(); private CommsUnit unit; private float nextUpdate; private void Start() { unit = ((Component)this).GetComponent<CommsUnit>(); } private void Update() { //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_0320: Unknown result type (might be due to invalid IL or missing references) //IL_0325: Unknown result type (might be due to invalid IL or missing references) //IL_0341: Unknown result type (might be due to invalid IL or missing references) //IL_0347: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)unit == (Object)null) { return; } if (!unit.Available || !unit.State.Powered) { foreach (AudioSource value3 in outputs.Values) { if ((Object)(object)value3 != (Object)null) { value3.Stop(); } } unit.AmbientAudible = false; } else { if (Time.realtimeSinceStartup < nextUpdate) { return; } nextUpdate = Time.realtimeSinceStartup + 0.1f; Dictionary<AudioSource, float> dictionary = new Dictionary<AudioSource, float>(); foreach (WalkieTalkie allWalkieTalky in WalkieTalkie.allWalkieTalkies) { if ((Object)(object)allWalkieTalky == (Object)null || !((GrabbableObject)allWalkieTalky).isBeingUsed || !allWalkieTalky.clientIsHoldingAndSpeakingIntoThis || (Object)(object)((GrabbableObject)allWalkieTalky).playerHeldBy == (Object)null || !(replaySources.GetValue(allWalkieTalky) is List<AudioSource> list)) { continue; } foreach (AudioSource item in list) { if (!((Object)(object)item == (Object)null) && item.isPlaying && !((Object)(object)item.clip == (Object)null) && !((Object)(object)((Component)item).GetComponent<PlayerVoiceIngameSettings>() != (Object)null) && !((Object)(object)((Component)item).GetComponentInParent<CommsUnit>() != (Object)null)) { float num = Vector3.Distance(((Component)item).transform.position, ((Component)allWalkieTalky).transform.position); float num2 = Mathf.Clamp01(1f - num / (VoiceRouting.RadioRange(allWalkieTalky) + 3f)) * VoiceRouting.RadioVolume(allWalkieTalky); if (num2 > 0f && dictionary.Count < 16 && (!dictionary.TryGetValue(item, out var value) || value < num2)) { dictionary[item] = num2; } } } } unit.AmbientAudible = dictionary.Count > 0; List<AudioSource> list2 = new List<AudioSource>(); foreach (KeyValuePair<AudioSource, AudioSource> output in outputs) { if ((Object)(object)output.Key == (Object)null || !dictionary.ContainsKey(output.Key)) { if ((Object)(object)output.Value != (Object)null) { Object.Destroy((Object)(object)((Component)output.Value).gameObject); } list2.Add(output.Key); } } foreach (AudioSource item2 in list2) { outputs.Remove(item2); } foreach (KeyValuePair<AudioSource, float> item3 in dictionary) { if (!outputs.TryGetValue(item3.Key, out AudioSource value2)) { GameObject val = new GameObject("Radio ambience"); val.transform.SetParent(((Component)unit.SpeakerAudio).transform, false); val.transform.localPosition = Vector3.zero; value2 = val.AddComponent<AudioSource>(); value2.playOnAwake = false; value2.spatialBlend = 1f; value2.minDistance = 2f; value2.maxDistance = 16f; value2.rolloffMode = (AudioRolloffMode)1; outputs.Add(item3.Key, value2); } SignalProcessing.Configure(value2, UnitKind.Receiver); bool num3 = (Object)(object)value2.clip != (Object)(object)item3.Key.clip || !value2.isPlaying; value2.clip = item3.Key.clip; value2.loop = item3.Key.loop; value2.pitch = item3.Key.pitch; value2.volume = item3.Value * Plugin.ReceiverVolume.Value; if (num3) { value2.time = item3.Key.time; value2.Play(); } else if (Mathf.Abs(value2.time - item3.Key.time) > 0.2f) { value2.time = item3.Key.time; } } } } } internal static class SignalProcessing { internal static SignalProfile Profile(UnitKind kind, bool allowApparatusInterference = true) { return new SignalProfile(kind, (kind == UnitKind.Intercom) ? Plugin.IntercomProcessing.Value : Plugin.ReceiverProcessing.Value, CommsRuntime.ApparatusInterference && allowApparatusInterference); } internal static void Configure(AudioSource audio, UnitKind kind) { SignalProfile signalProfile = Profile(kind); AudioLowPassFilter obj = ((Component)audio).GetComponent<AudioLowPassFilter>() ?? ((Component)audio).gameObject.AddComponent<AudioLowPassFilter>(); AudioHighPassFilter val = ((Component)audio).GetComponent<AudioHighPassFilter>() ?? ((Component)audio).gameObject.AddComponent<AudioHighPassFilter>(); AudioDistortionFilter val2 = ((Component)audio).GetComponent<AudioDistortionFilter>() ?? ((Component)audio).gameObject.AddComponent<AudioDistortionFilter>(); bool enabled = (((Behaviour)val).enabled = true); ((Behaviour)obj).enabled = enabled; obj.cutoffFrequency = signalProfile.LowPass; obj.lowpassResonanceQ = 1f; val.cutoffFrequency = signalProfile.HighPass; val2.distortionLevel = signalProfile.Distortion; ((Behaviour)val2).enabled = signalProfile.Distortion > 0f; } } internal static class StaticWaveform { internal const int SampleRate = 48000; internal static float[] Create() { float[] array = new float[96000]; uint num = 177820071u; double num2 = 0.0; double num3 = 0.0; for (int i = 0; i < array.Length; i++) { num = num * 1664525 + 1013904223; double num4 = (double)(num >> 8) / 8388607.5 - 1.0; num2 += 0.45 * (num4 - num2); num3 += 0.01 * (num2 - num3); double num5 = ((num4 > 0.995) ? 0.12 : ((num4 < -0.995) ? (-0.12) : 0.0)); double num6 = Math.Min(1.0, (double)Math.Min(i, array.Length - 1 - i) / 384.0); array[i] = (float)(Math.Max(-0.85, Math.Min(0.85, (num2 - num3) * 0.95 + num5)) * num6); } return array; } } internal sealed class TransmissionStatic : MonoBehaviour { private static AudioClip? clip; private CommsUnit unit; private AudioSource? noise; private void Awake() { unit = ((Component)this).GetComponent<CommsUnit>(); } private void Update() { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Expected O, but got Unknown //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Unknown result type (might be due to invalid IL or missing references) PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if ((Object)(object)unit == (Object)null || (Object)(object)val == (Object)null) { Silence(); return; } float receiverDistance = ((unit.Kind == UnitKind.Receiver) ? Vector3.Distance(((Component)val.gameplayCamera).transform.position, ((Component)unit.SpeakerAudio).transform.position) : 0f); if (!CommsRules.CanHearStatic(unit.Kind, val.isPlayerControlled && !val.isPlayerDead, val.isInsideFactory, unit.ChannelActive, VoiceRouting.HasAudibleVoice(unit, val), receiverDistance)) { Silence(); return; } float num = (CommsRuntime.ApparatusInterference ? Plugin.ApparatusStaticVolume.Value : Plugin.NormalStaticVolume.Value) * ((unit.Kind == UnitKind.Intercom) ? Plugin.IntercomVolume.Value : Plugin.ReceiverVolume.Value); if (num <= 0f) { Silence(); return; } if ((Object)(object)noise == (Object)null) { if ((Object)(object)clip == (Object)null) { float[] array = StaticWaveform.Create(); clip = AudioClip.Create("Ship Comms carrier static", array.Length, 1, 48000, false); clip.SetData(array, 0); } GameObject val2 = new GameObject("Communication static"); val2.transform.SetParent((unit.Kind == UnitKind.Receiver) ? ((Component)unit.SpeakerAudio).transform : ((Component)this).transform, false); val2.transform.localPosition = ((unit.Kind == UnitKind.Receiver) ? Vector3.zero : (Vector3.up * 1.32f)); noise = val2.AddComponent<AudioSource>(); noise.playOnAwake = false; noise.loop = true; noise.clip = clip; noise.volume = 0f; noise.minDistance = 2f; noise.maxDistance = 16f; noise.rolloffMode = (AudioRolloffMode)1; noise.dopplerLevel = 0f; val2.AddComponent<AudioHighPassFilter>().cutoffFrequency = 450f; val2.AddComponent<AudioLowPassFilter>().cutoffFrequency = ((unit.Kind == UnitKind.Intercom) ? 6500f : 5500f); } noise.spatialBlend = ((unit.Kind == UnitKind.Intercom) ? 0f : 1f); noise.volume = Mathf.MoveTowards(noise.volume, num, Time.deltaTime * 2f); if (!noise.isPlaying) { noise.Play(); } } private void Silence() { if ((Object)(object)noise != (Object)null) { noise.Stop(); noise.volume = 0f; } } private void OnDisable() { Silence(); } } internal static class UpgradeCatalog { internal static readonly List<UnlockableItem> Items = new List<UnlockableItem>(); internal static int HostIntercomCost; internal static int HostReceiverCost; internal static int HostAuxiliaryPowerCost; internal static void Register() { HostIntercomCost = CommsRules.ClampCost(Plugin.IntercomCost.Value); HostReceiverCost = CommsRules.ClampCost(Plugin.ReceiverCost.Value); HostAuxiliaryPowerCost = CommsRules.ClampCost(Plugin.AuxiliaryPowerCost.Value); Add(UnitKind.Intercom, "Ship Intercom", HostIntercomCost, "Hold the microphone button to broadcast your voice, nearby voices, and local sounds to everyone inside the facility. No walkie required at the receiving end. Release to stop. One-way broadcast; your microphone setting must be enabled."); Add(UnitKind.Receiver, "Radio Receiver", HostReceiverCost, "A receive-only ship radio. Press its power button to hear players transmitting on walkie-talkies. It cannot transmit. Eyeless Dogs can hear the speaker; switch OFF to silence it. Starts OFF."); Add(UnitKind.AuxiliaryPower, "Auxiliary Power Unit", HostAuxiliaryPowerCost, "An automatic ship upgrade that protects every ship intercom and radio receiver from interference caused by removing the facility apparatus. Buy once to activate it for this save. No furniture, placement, or controls are required."); } private static void Add(UnitKind kind, string name, int price, string description) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003b: 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_0049: 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_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Expected O, but got Unknown bool flag = kind != UnitKind.AuxiliaryPower; UnlockableItem val = new UnlockableItem { unlockableName = name, unlockableType = 1, prefabObject = (flag ? UnitModel.Create(kind) : null), alwaysInStock = true, IsPlaceable = flag, canBeStored = flag, spawnPrefab = flag, maxNumber = 1, alreadyUnlocked = false, hasBeenUnlockedByPlayer = false }; TerminalNode val2 = ScriptableObject.CreateInstance<TerminalNode>(); ((Object)val2).name = name.Replace(" ", "") + "Info"; val2.displayText = description + "\n\n"; val2.clearPreviousText = true; TerminalNode val3 = ScriptableObject.CreateInstance<TerminalNode>(); ((Object)val3).name = name.Replace(" ", "") + "Purchased"; val3.displayText = name + " installed in the ship. Balance: [playerCredits].\n" + (flag ? "Press B while looking at the cabinet to move it." : "Auxiliary power is online. Both communication channels are protected from apparatus interference.") + "\n\n"; val3.clearPreviousText = true; val3.maxCharactersToType = 35; Unlockables.RegisterUnlockable(val, (StoreType)1, (TerminalNode)null, val3, val2, price); Items.Add(val); } internal static void FinishSetup() { if ((Object)(object)StartOfRound.Instance == (Object)null) { return; } foreach (UnlockableItem item in Items) { int num = StartOfRound.Instance.unlockablesList.unlockables.IndexOf(item); if (num >= 0 && !((Object)(object)item.prefabObject == (Object)null)) { item.prefabObject.GetComponent<AutoParentToShip>().unlockableID = num; item.prefabObject.GetComponentInChildren<PlaceableShipObject>(true).unlockableID = num; } } ApplyPrices(); } internal static void ApplyPrices() { if ((Object)(object)StartOfRound.Instance == (Object)null) { return; } for (int i = 0; i < Items.Count; i++) { int num = i switch { 1 => HostReceiverCost, 0 => HostIntercomCost, _ => HostAuxiliaryPowerCost, }; int num2 = StartOfRound.Instance.unlockablesList.unlockables.IndexOf(Items[i]); if (num2 < 0) { continue; } foreach (RegisteredUnlockable registeredUnlockable in Unlockables.registeredUnlockables) { if (registeredUnlockable.unlockable == Items[i]) { registeredUnlockable.price = num; } } TerminalNode[] array = Resources.FindObjectsOfTypeAll<TerminalNode>(); foreach (TerminalNode val in array) { if (val.shipUnlockableID == num2) { val.itemCost = num; } } } } } internal static class UnitModel { internal const float ModelScale = 1.2f; private static Material MakeMaterial(string name, Color color, bool glow = false) { //IL_003a: 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_0047: Expected O, but got Unknown //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0073: 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_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) Shader obj = Shader.Find("HDRP/Lit") ?? Shader.Find("Standard") ?? Shader.Find("Unlit/Color"); if ((Object)(object)obj == (Object)null) { throw new InvalidOperationException("No supported shader was loaded for Ship Comms."); } Material val = new Material(obj) { name = name }; if (val.HasProperty("_BaseColor")) { val.SetColor("_BaseColor", color); } if (val.HasProperty("_Color")) { val.SetColor("_Color", color); } if (val.HasProperty("_Smoothness")) { val.SetFloat("_Smoothness", 0.25f); } if (glow) { val.EnableKeyword("_EMISSION"); if (val.HasProperty("_EmissionColor")) { val.SetColor("_EmissionColor", color * 2f); } if (val.HasProperty("_EmissiveColor")) { val.SetColor("_EmissiveColor", color * 2f); } } return val; } private static GameObject Part(Transform parent, string name, PrimitiveType primitive, Vector3 position, Vector3 scale, Material material) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0020: 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) GameObject obj = GameObject.CreatePrimitive(primitive); ((Object)obj).name = name; obj.transform.SetParent(parent, false); obj.transform.localPosition = position; obj.transform.localScale = scale; obj.GetComponent<Renderer>().sharedMaterial = material; Collider component = obj.GetComponent<Collider>(); component.enabled = false; Object.Destroy((Object)(object)component); return obj; } internal static GameObject Create(UnitKind kind) { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006f: 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) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Unknown result type (might be due to invalid IL or missing references) //IL_022d: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_0284: Unknown result type (might be due to invalid IL or missing references) //IL_0298: Unknown result type (might be due to invalid IL or missing references) //IL_02d1: Unknown result type (might be due to invalid IL or missing references) //IL_02e5: Unknown result type (might be due to invalid IL or missing references) //IL_030d: Unknown result type (might be due to invalid IL or missing references) //IL_0321: Unknown result type (might be due to invalid IL or missing references) //IL_0333: Unknown result type (might be due to invalid IL or missing references) //IL_035e: Unknown result type (might be due to invalid IL or missing references) //IL_0379: Unknown result type (might be due to invalid IL or missing references) //IL_038b: Unknown result type (might be due to invalid IL or missing references) //IL_039f: Unknown result type (might be due to invalid IL or missing references) //IL_050b: Unknown result type (might be due to invalid IL or missing references) //IL_051f: Unknown result type (might be due to invalid IL or missing references) //IL_0547: Unknown result type (might be due to invalid IL or missing references) //IL_055b: Unknown result type (might be due to invalid IL or missing references) //IL_0594: Unknown result type (might be due to invalid IL or missing references) //IL_05d1: Unknown result type (might be due to invalid IL or missing references) //IL_05db: Expected O, but got Unknown //IL_05dd: Unknown result type (might be due to invalid IL or missing references) //IL_05e7: Expected O, but got Unknown //IL_05e9: Unknown result type (might be due to invalid IL or missing references) //IL_05f3: Expected O, but got Unknown //IL_05f5: Unknown result type (might be due to invalid IL or missing references) //IL_05ff: Expected O, but got Unknown //IL_0601: Unknown result type (might be due to invalid IL or missing references) //IL_060b: Expected O, but got Unknown //IL_060d: Unknown result type (might be due to invalid IL or missing references) //IL_0617: Expected O, but got Unknown //IL_0648: Unknown result type (might be due to invalid IL or missing references) //IL_065c: Unknown result type (might be due to invalid IL or missing references) //IL_067b: Unknown result type (might be due to invalid IL or missing references) //IL_0682: Expected O, but got Unknown //IL_06ab: Unknown result type (might be due to invalid IL or missing references) //IL_06e4: Unknown result type (might be due to invalid IL or missing references) //IL_075d: Unknown result type (might be due to invalid IL or missing references) //IL_0762: Unknown result type (might be due to invalid IL or missing references) //IL_0774: Unknown result type (might be due to invalid IL or missing references) //IL_0431: Unknown result type (might be due to invalid IL or missing references) //IL_0445: Unknown result type (might be due to invalid IL or missing references) //IL_0794: Unknown result type (might be due to invalid IL or missing references) //IL_077e: Unknown result type (might be due to invalid IL or missing references) //IL_03de: Unknown result type (might be due to invalid IL or missing references) //IL_03f2: Unknown result type (might be due to invalid IL or missing references) //IL_0488: Unknown result type (might be due to invalid IL or missing references) //IL_049c: Unknown result type (might be due to invalid IL or missing references) //IL_04cf: Unknown result type (might be due to invalid IL or missing references) //IL_04e3: Unknown result type (might be due to invalid IL or missing references) //IL_0815: Unknown result type (might be due to invalid IL or missing references) //IL_081c: Expected O, but got Unknown //IL_081f: Unknown result type (might be due to invalid IL or missing references) //IL_0829: Unknown result type (might be due to invalid IL or missing references) //IL_0846: Unknown result type (might be due to invalid IL or missing references) //IL_0850: Unknown result type (might be due to invalid IL or missing references) //IL_087d: Unknown result type (might be due to invalid IL or missing references) //IL_0887: Unknown result type (might be due to invalid IL or missing references) if (kind != UnitKind.Intercom && kind != UnitKind.Receiver) { throw new ArgumentOutOfRangeException("kind", "Only communication devices have furniture models."); } GameObject val = NetworkPrefabs.CreateNetworkPrefab("ShipComms_" + kind); val.layer = 26; AutoParentToShip val2 = val.AddComponent<AutoParentToShip>(); val2.overrideOffset = true; val2.positionOffset = new Vector3((kind == UnitKind.Intercom) ? (-1.6f) : (-0.8f), 0.1f, -5.6f); val2.rotationOffset = Vector3.zero; CommsUnit commsUnit = val.AddComponent<CommsUnit>(); commsUnit.Kind = kind; Material material = MakeMaterial("Comms painted steel", new Color(0.24f, 0.32f, 0.32f)); Material material2 = MakeMaterial("Comms faceplate", new Color(0.65f, 0.66f, 0.59f)); Material material3 = MakeMaterial("Comms grille", new Color(0.035f, 0.042f, 0.045f)); Material material4 = MakeMaterial("Comms microphone stem", new Color(0.36f, 0.4f, 0.41f)); Material material5 = MakeMaterial("Comms push button", new Color(0.8f, 0.17f, 0.09f)); commsUnit.LightOn = MakeMaterial("Comms signal on", new Color(0.2f, 0.95f, 0.37f), glow: true); commsUnit.LightStarting = MakeMaterial("Comms signal starting", new Color(1f, 0.76f, 0.08f), glow: true); commsUnit.LightOff = MakeMaterial("Comms signal off", new Color(0.12f, 0.17f, 0.12f)); Part(val.transform, "Foot", (PrimitiveType)3, new Vector3(0f, 0.04f, 0f), new Vector3(0.66f, 0.08f, 0.5f), material3); GameObject val3 = Part(val.transform, "Cabinet", (PrimitiveType)3, new Vector3(0f, 0.49f, 0f), new Vector3(0.59f, 0.9f, 0.42f), material); Part(val.transform, "Control panel", (PrimitiveType)3, new Vector3(0f, 0.96f, 0f), new Vector3(0.62f, 0.07f, 0.46f), material2); for (int i = 0; i < 6; i++) { Part(val.transform, "Vent " + i, (PrimitiveType)3, new Vector3(0f, 0.22f + (float)i * 0.055f, -0.216f), new Vector3(0.39f, 0.014f, 0.012f), material3); } switch (kind) { case UnitKind.Intercom: { Part(val.transform, "Microphone base", (PrimitiveType)2, new Vector3(-0.14f, 1.015f, 0.075f), new Vector3(0.14f, 0.02f, 0.14f), material3); Part(val.transform, "Microphone stem", (PrimitiveType)2, new Vector3(-0.14f, 1.18f, 0.075f), new Vector3(0.025f, 0.15f, 0.025f), material4); Transform transform = new GameObject("Microphone head").transform; transform.SetParent(val.transform, false); transform.localPosition = new Vector3(-0.14f, 1.39f, 0.045f); transform.localRotation = Quaternion.Euler(-20f, 0f, 0f); Part(transform, "Microphone", (PrimitiveType)1, Vector3.zero, new Vector3(0.105f, 0.115f, 0.105f), material3); for (int k = 0; k < 5; k++) { Part(transform, "Microphone grille " + k, (PrimitiveType)3, new Vector3(0f, -0.05f + (float)k * 0.025f, -0.052f), new Vector3(0.09f, 0.008f, 0.012f), material4); } break; } case UnitKind.Receiver: { Part(val.transform, "Speaker cabinet", (PrimitiveType)3, new Vector3(-0.13f, 1.16f, 0.09f), new Vector3(0.28f, 0.32f, 0.18f), material3); for (int j = 0; j < 8; j++) { Part(val.transform, "Speaker grille " + j, (PrimitiveType)3, new Vector3(-0.13f, 1.035f + (float)j * 0.035f, -0.006f), new Vector3(0.25f, 0.013f, 0.015f), material4); } Part(val.transform, "Antenna", (PrimitiveType)2, new Vector3(-0.24f, 1.43f, 0.15f), new Vector3(0.012f, 0.14f, 0.012f), material4); break; } } Part(val.transform, "Button bezel", (PrimitiveType)2, new Vector3(0.17f, 1.012f, -0.085f), new Vector3(0.17f, 0.02f, 0.17f), material3); GameObject val4 = Part(val.transform, "Button", (PrimitiveType)2, new Vector3(0.17f, 1.04f, -0.085f), new Vector3(0.13f, 0.019f, 0.13f), material5); val4.layer = 9; val4.tag = "InteractTrigger"; val4.AddComponent<BoxCollider>().size = new Vector3(1.25f, 3f, 1.25f); InteractTrigger val5 = val4.AddComponent<InteractTrigger>(); val5.disableTriggerMesh = false; val5.interactCooldown = false; val5.holdInteraction = false; val5.oneHandedItemAllowed = true; val5.twoHandedItemAllowed = false; val5.onInteract = new InteractEvent(); val5.onInteractEarly = new InteractEvent(); val5.onInteractEarlyOtherClients = new InteractEvent(); val5.onStopInteract = new InteractEvent(); val5.onCancelAnimation = new InteractEvent(); val5.holdingInteractEvent = new InteractEventFloat(); commsUnit.Trigger = val5; commsUnit.Button = val4.transform; commsUnit.Indicator = Part(val.transform, "Signal light", (PrimitiveType)0, new Vector3(0.17f, 1.009f, 0.1f), new Vector3(0.045f, 0.018f, 0.045f), commsUnit.LightOff).GetComponent<Renderer>(); GameObject val6 = new GameObject("Furniture bounds"); val6.transform.SetParent(val.transform, false); val6.transform.localPosition = new Vector3(0f, 0.48f, 0f); val6.layer = 26; val6.tag = "PlaceableObject"; BoxCollider val7 = val6.AddComponent<BoxCollider>(); val7.size = new Vector3(0.66f, 0.96f, 0.5f); PlaceableShipObject obj = val6.AddComponent<PlaceableShipObject>(); obj.parentObject = val2; obj.mainMesh = val3.GetComponent<MeshFilter>(); obj.mainTransform = val.transform; obj.placeObjectCollider = (Collider)(object)val7; obj.yOffset = 0.57600003f; obj.AllowPlacementOnCounters = true; obj.AllowPlacementOnWalls = false; AudioSource obj2 = val6.AddComponent<AudioSource>(); obj2.playOnAwake = false; obj2.spatialBlend = 1f; obj2.maxDistance = 12f; GameObject val8 = new GameObject("Comms speaker"); val8.transform.SetParent(val.transform, false); val8.transform.localPosition = (Vector3)((kind == UnitKind.Receiver) ? new Vector3(-0.13f, 1.16f, -0.015f) : Vector3.up); AudioSource val9 = val8.AddComponent<AudioSource>(); val9.playOnAwake = false; val9.spatialBlend = 1f; val9.minDistance = 2f; val9.maxDistance = 16f; val9.rolloffMode = (AudioRolloffMode)1; commsUnit.SpeakerAudio = val9; val.AddComponent<TransmissionStatic>(); switch (kind) { case UnitKind.Receiver: val.AddComponent<RadioEnvironmentRelay>(); break; case UnitKind.Intercom: val.AddComponent<IntercomEnvironmentRelay>(); break; } foreach (Transform item in val.transform) { Transform val10 = item; val10.localPosition *= 1.2f; if ((Object)(object)val10 != (Object)(object)val6.transform) { val10.localScale *= 1.2f; } } val7.size *= 1.2f; return val; } } internal static class VoiceRouting { private sealed class Original { internal AudioSource Audio; internal PlayerControllerB Player; internal Vector3 NativePosition; internal float SpatialBlend; internal float MinDistance; internal float MaxDistance; internal float Spread; internal float Doppler; internal AudioRolloffMode Rolloff; internal bool SpatialChanged; internal float Pan; internal float HighCutoff; internal float LowCutoff; internal AudioDistortionFilter Distortion; internal bool OwnsDistortion; internal bool DistortionEnabled; internal float DistortionLevel; } private static readonly FieldInfo radioRange = AccessTools.Field(typeof(WalkieTalkie), "recordingRange"); private static readonly FieldInfo radioVolume = AccessTools.Field(typeof(WalkieTalkie), "maxVolume"); private static readonly Dictionary<PlayerVoiceIngameSettings, Original> overridden = new Dictionary<PlayerVoiceIngameSettings, Original>(); internal static float RadioRange(WalkieTalkie radio) { return (float)radioRange.GetValue(radio); } internal static float RadioVolume(WalkieTalkie radio) { return (float)radioVolume.GetValue(radio); } internal static bool IsRadioSender(PlayerControllerB player) { if ((Object)(object)player == (Object)null || player.isPlayerDead || !player.isPlayerControlled || !player.speakingToWalkieTalkie) { return false; } foreach (WalkieTalkie allWalkieTalky in WalkieTalkie.allWalkieTalkies) { if ((Object)(object)allWalkieTalky != (Object)null && (Object)(object)((GrabbableObject)allWalkieTalky).playerHeldBy == (Object)(object)player && ((GrabbableObject)allWalkieTalky).isBeingUsed && allWalkieTalky.clientIsHoldingAndSpeakingIntoThis) { return true; } } return false; } private static bool CanHearPersonalRadio(PlayerControllerB local) { if (local.holdingWalkieTalkie) { return true; } foreach (WalkieTalkie allWalkieTalky in WalkieTalkie.allWalkieTalkies) { if ((Object)(object)allWalkieTalky != (Object)null && ((GrabbableObject)allWalkieTalky).isBeingUsed && (Object)(object)((GrabbableObject)allWalkieTalky).playerHeldBy == (Object)(object)local) { return true; } } return false; } internal static float MicrophoneGain(PlayerControllerB player,