using Content.Shared.Chat; using Content.Shared.Speech; using Robust.Shared.Audio; using Robust.Shared.GameStates; using Robust.Shared.Serialization; namespace Content.Shared.Telephone; [RegisterComponent, NetworkedComponent, AutoGenerateComponentState] [Access(typeof(SharedTelephoneSystem))] public sealed partial class TelephoneComponent : Component { /// /// Sets how long the telephone will ring before it automatically hangs up /// [DataField] public float RingingTimeout = 30; /// /// Sets how long the telephone can remain idle in-call before it automatically hangs up /// [DataField] public float IdlingTimeout = 60; /// /// Sets how long the telephone will stay in the hanging up state before return to idle /// [DataField] public float HangingUpTimeout = 2; /// /// Tone played while the phone is ringing /// [DataField] public SoundSpecifier? RingTone = null; /// /// Sets the number of seconds before the next ring tone is played /// [DataField] public float RingInterval = 2f; /// /// The time at which the next tone will be played /// [DataField] public TimeSpan NextRingToneTime; /// /// The volume at which relayed messages are played /// [DataField] public TelephoneVolume SpeakerVolume = TelephoneVolume.Whisper; /// /// The maximum range at which the telephone initiate a call with another /// [DataField] public TelephoneRange TransmissionRange = TelephoneRange.Grid; /// /// This telephone will ignore devices that share the same grid as it /// /// /// This bool will be ignored if the is /// set to /// [DataField] public bool IgnoreTelephonesOnSameGrid = false; /// /// The telephone can only connect with other telephones which have a /// present in this list /// [DataField] public List CompatibleRanges = new List() { TelephoneRange.Grid }; /// /// The range at which the telephone picks up voices /// [DataField] public float ListeningRange = 2; /// /// Specifies whether this telephone require power to fucntion /// [DataField] public bool RequiresPower = true; /// /// This telephone should not appear on public telephone directories /// [DataField] public bool UnlistedNumber = false; /// /// Speech is relayed through this entity instead of the telephone /// [ViewVariables(VVAccess.ReadOnly)] public Entity? Speaker = null; /// /// Telephone number for this device /// /// /// For future use - a system for generating and handling telephone numbers has not been implemented yet /// [ViewVariables] public int TelephoneNumber = -1; /// /// Linked telephone /// [ViewVariables] public HashSet> LinkedTelephones = new(); /// /// Defines the current state the telephone is in /// [ViewVariables, AutoNetworkedField] public TelephoneState CurrentState = TelephoneState.Idle; /// /// The game tick the current state started /// [ViewVariables] public TimeSpan StateStartTime; /// /// Sets whether the telphone can pick up nearby speech /// [ViewVariables] public bool Muted = false; /// /// The presumed name and/or job of the last person to call this telephone /// and the name of the device that they used to do so /// [ViewVariables, AutoNetworkedField] public (string?, string?, string?) LastCallerId; } #region: Telephone events /// /// Raised when one telephone is attempting to call another /// [ByRefEvent] public record struct TelephoneCallAttemptEvent(Entity Source, Entity Receiver, EntityUid? User) { public bool Cancelled = false; } /// /// Raised when a telephone's state changes /// [ByRefEvent] public record struct TelephoneStateChangeEvent(TelephoneState OldState, TelephoneState NewState); /// /// Raised when communication between one telephone and another begins /// [ByRefEvent] public record struct TelephoneCallCommencedEvent(Entity Receiver); /// /// Raised when a telephone hangs up /// [ByRefEvent] public record struct TelephoneCallEndedEvent(); /// /// Raised when a chat message is sent by a telephone to another /// [ByRefEvent] public readonly record struct TelephoneMessageSentEvent(string Message, MsgChatMessage ChatMsg, EntityUid MessageSource); /// /// Raised when a chat message is received by a telephone from another /// [ByRefEvent] public readonly record struct TelephoneMessageReceivedEvent(string Message, MsgChatMessage ChatMsg, EntityUid MessageSource, Entity TelephoneSource); #endregion /// /// Options for tailoring telephone calls /// [Serializable, NetSerializable] public struct TelephoneCallOptions { public bool IgnoreRange; // The source can always reach its target public bool ForceConnect; // The source immediately starts a call with the receiver, potentially interrupting a call that is already in progress public bool ForceJoin; // The source smoothly joins a call in progress, or starts a normal call with the receiver if there is none public bool MuteSource; // Chatter from the source is not transmitted - could be used for eavesdropping when combined with 'ForceJoin' public bool MuteReceiver; // Chatter from the receiver is not transmitted - useful for broadcasting messages to multiple receivers } [Serializable, NetSerializable] public enum TelephoneVisuals : byte { Key } [Serializable, NetSerializable] public enum TelephoneState : byte { Idle, Calling, Ringing, InCall, EndingCall } [Serializable, NetSerializable] public enum TelephoneVolume : byte { Whisper, Speak } [Serializable, NetSerializable] public enum TelephoneRange : byte { Grid, // Can only reach telephones that are on the same grid Map, // Can reach any telephone that is on the same map Unlimited, // Can reach any telephone, across any distance }