Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tweaks for the holopad #33928

Merged
merged 12 commits into from
Dec 19, 2024
31 changes: 27 additions & 4 deletions Content.Server/Holopad/HolopadSystem.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Content.Server.Chat.Systems;
using Content.Server.Popups;
using Content.Server.Power.EntitySystems;
using Content.Server.Speech.Components;
using Content.Server.Telephone;
Expand Down Expand Up @@ -31,6 +32,7 @@ public sealed class HolopadSystem : SharedHolopadSystem
[Dependency] private readonly SharedStationAiSystem _stationAiSystem = default!;
[Dependency] private readonly AccessReaderSystem _accessReaderSystem = default!;
[Dependency] private readonly ChatSystem _chatSystem = default!;
[Dependency] private readonly PopupSystem _popupSystem = default!;
[Dependency] private readonly IGameTiming _timing = default!;

private float _updateTimer = 1.0f;
Expand Down Expand Up @@ -117,7 +119,22 @@ private void OnHolopadAnswerCall(Entity<HolopadComponent> receiver, ref HolopadA
var source = GetLinkedHolopads(receiver).FirstOrNull();

if (source != null)
{
// Close any AI request windows
if (_stationAiSystem.TryGetStationAiCore(args.Actor, out var stationAiCore) && stationAiCore != null)
_userInterfaceSystem.CloseUi(receiver.Owner, HolopadUiKey.AiRequestWindow, args.Actor);

// Try to warn the AI if the source of the call is out of its range
if (TryComp<TelephoneComponent>(stationAiCore, out var stationAiTelephone) &&
TryComp<TelephoneComponent>(source, out var sourceTelephone) &&
!_telephoneSystem.IsSourceInRangeOfReceiver((stationAiCore.Value.Owner, stationAiTelephone), (source.Value.Owner, sourceTelephone)))
{
_popupSystem.PopupEntity(Loc.GetString("holopad-ai-is-unable-to-reach-holopad"), receiver, args.Actor);
return;
}

ActivateProjector(source.Value, args.Actor);
}

return;
}
Expand All @@ -134,15 +151,17 @@ private void OnHolopadEndCall(Entity<HolopadComponent> entity, ref HolopadEndCal
if (IsHolopadControlLocked(entity, args.Actor))
return;

_telephoneSystem.EndTelephoneCalls((entity, entityTelephone));
if (entityTelephone.CurrentState != TelephoneState.EndingCall && entityTelephone.CurrentState != TelephoneState.Idle)
_telephoneSystem.EndTelephoneCalls((entity, entityTelephone));

// If the user is an AI, end all calls originating from its
// associated core to ensure that any broadcasts will end
if (!TryComp<StationAiHeldComponent>(args.Actor, out var stationAiHeld) ||
!_stationAiSystem.TryGetStationAiCore((args.Actor, stationAiHeld), out var stationAiCore))
return;

if (TryComp<TelephoneComponent>(stationAiCore, out var telephone))
if (TryComp<TelephoneComponent>(stationAiCore, out var telephone) &&
telephone.CurrentState != TelephoneState.EndingCall && telephone.CurrentState != TelephoneState.Idle)
_telephoneSystem.EndTelephoneCalls((stationAiCore.Value, telephone));
}

Expand Down Expand Up @@ -414,7 +433,7 @@ private void AddToggleProjectorVerb(Entity<HolopadComponent> entity, ref GetVerb
AlternativeVerb verb = new()
{
Act = () => ActivateProjector(entity, user),
Text = Loc.GetString("activate-holopad-projector-verb"),
Text = Loc.GetString("holopad-activate-projector-verb"),
Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/vv.svg.192dpi.png")),
};

Expand Down Expand Up @@ -594,7 +613,8 @@ private void ShutDownHolopad(Entity<HolopadComponent> entity)
{
_stationAiSystem.SwitchRemoteEntityMode((entity.Owner, stationAiCore), true);

if (TryComp<TelephoneComponent>(entity, out var stationAiCoreTelphone))
if (TryComp<TelephoneComponent>(entity, out var stationAiCoreTelphone) &&
stationAiCoreTelphone.CurrentState != TelephoneState.EndingCall && stationAiCoreTelphone.CurrentState != TelephoneState.Idle)
_telephoneSystem.EndTelephoneCalls((entity, stationAiCoreTelphone));
}

Expand Down Expand Up @@ -648,6 +668,9 @@ private void ActivateProjector(Entity<HolopadComponent> entity, EntityUid user)

var source = new Entity<TelephoneComponent>(stationAiCore.Value, stationAiTelephone);

if (!_telephoneSystem.IsSourceInRangeOfReceiver(source, receiver))
return;

// Terminate any calls that the core is hosting and immediately connect to the receiver
_telephoneSystem.TerminateTelephoneCalls(source);

Expand Down
32 changes: 20 additions & 12 deletions Content.Server/Telephone/TelephoneSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,10 @@ public void EndTelephoneCall(Entity<TelephoneComponent> source, Entity<Telephone

public void EndTelephoneCalls(Entity<TelephoneComponent> entity)
{
// No need to end any calls if the telephone is already ending a call
if (entity.Comp.CurrentState == TelephoneState.EndingCall)
return;

HandleEndingTelephoneCalls(entity, TelephoneState.EndingCall);

var ev = new TelephoneCallEndedEvent();
Expand All @@ -285,14 +289,15 @@ public void EndTelephoneCalls(Entity<TelephoneComponent> entity)

public void TerminateTelephoneCalls(Entity<TelephoneComponent> entity)
{
// No need to terminate any calls if the telephone is idle
if (entity.Comp.CurrentState == TelephoneState.Idle)
return;

HandleEndingTelephoneCalls(entity, TelephoneState.Idle);
}

private void HandleEndingTelephoneCalls(Entity<TelephoneComponent> entity, TelephoneState newState)
{
if (entity.Comp.CurrentState == newState)
return;

foreach (var linkedTelephone in entity.Comp.LinkedTelephones)
{
if (!linkedTelephone.Comp.LinkedTelephones.Remove(entity))
Expand Down Expand Up @@ -431,23 +436,26 @@ public bool IsSourceAbleToReachReceiver(Entity<TelephoneComponent> source, Entit

public bool IsSourceInRangeOfReceiver(Entity<TelephoneComponent> source, Entity<TelephoneComponent> receiver)
{
// Check if the source and receiver have compatible transmision / reception bandwidths
if (!source.Comp.CompatibleRanges.Contains(receiver.Comp.TransmissionRange))
return false;

var sourceXform = Transform(source);
var receiverXform = Transform(receiver);

// Check if we should ignore a device thats on the same grid
if (source.Comp.IgnoreTelephonesOnSameGrid &&
source.Comp.TransmissionRange != TelephoneRange.Grid &&
receiverXform.GridUid == sourceXform.GridUid)
return false;

switch (source.Comp.TransmissionRange)
{
case TelephoneRange.Grid:
return sourceXform.GridUid != null &&
receiverXform.GridUid == sourceXform.GridUid &&
receiver.Comp.TransmissionRange != TelephoneRange.Long;
return sourceXform.GridUid == receiverXform.GridUid;

case TelephoneRange.Map:
return sourceXform.MapID == receiverXform.MapID &&
receiver.Comp.TransmissionRange != TelephoneRange.Long;

case TelephoneRange.Long:
return sourceXform.MapID != receiverXform.MapID &&
receiver.Comp.TransmissionRange == TelephoneRange.Long;
return sourceXform.MapID == receiverXform.MapID;

case TelephoneRange.Unlimited:
return true;
Expand Down
28 changes: 22 additions & 6 deletions Content.Shared/Telephone/TelephoneComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,28 @@ public sealed partial class TelephoneComponent : Component
public TelephoneVolume SpeakerVolume = TelephoneVolume.Whisper;

/// <summary>
/// The range at which the telephone can connect to another
/// The maximum range at which the telephone initiate a call with another
/// </summary>
[DataField]
public TelephoneRange TransmissionRange = TelephoneRange.Grid;

/// <summary>
/// This telephone will ignore devices that share the same grid as it
/// </summary>
/// <remarks>
/// This bool will be ignored if the <see cref="TransmissionRange"/> is
/// set to <see cref="TelephoneRange.Grid"/>
/// </remarks>
[DataField]
public bool IgnoreTelephonesOnSameGrid = false;

/// <summary>
/// The telephone can only connect with other telephones which have a
/// <see cref="TransmissionRange"/> present in this list
/// </summary>
[DataField]
public List<TelephoneRange> CompatibleRanges = new List<TelephoneRange>() { TelephoneRange.Grid };

/// <summary>
/// The range at which the telephone picks up voices
/// </summary>
Expand All @@ -70,7 +87,7 @@ public sealed partial class TelephoneComponent : Component
public bool RequiresPower = true;

/// <summary>
/// This telephone does not appear on public telephone directories
/// This telephone should not appear on public telephone directories
/// </summary>
[DataField]
public bool UnlistedNumber = false;
Expand Down Expand Up @@ -196,8 +213,7 @@ public enum TelephoneVolume : byte
[Serializable, NetSerializable]
public enum TelephoneRange : byte
{
Grid, // Can call grid/map range telephones that are on the same grid
Map, // Can call grid/map range telephones that are on the same map
Long, // Can only long range telephones that are on a different map
Unlimited // Can call any telephone
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
}
3 changes: 2 additions & 1 deletion Resources/Locale/en-US/holopad/holopad.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ holopad-window-flavor-right = v3.0.9
holopad-hologram-name = hologram of {THE($name)}

# Holopad actions
activate-holopad-projector-verb = Activate holopad projector
holopad-activate-projector-verb = Activate holopad projector
holopad-ai-is-unable-to-reach-holopad = You are unable to interface with the source of the call, it is too far from your core.

# Mapping prototypes
# General
Expand Down
4 changes: 4 additions & 0 deletions Resources/Prototypes/Entities/Mobs/Player/silicon.yml
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,10 @@
Empty: { state: ai_empty }
Occupied: { state: ai }
- type: Telephone
compatibleRanges:
- Grid
- Map
- Unlimited
listeningRange: 0
speakerVolume: Speak
unlistedNumber: true
Expand Down
41 changes: 30 additions & 11 deletions Resources/Prototypes/Entities/Structures/Machines/holopad.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
- type: StationAiVision
- type: Sprite
sprite: Structures/Machines/holopad.rsi
drawdepth: FloorObjects
snapCardinals: true
layers:
- state: base
Expand Down Expand Up @@ -71,9 +72,8 @@
speechSounds: Borg
speechBubbleOffset: 0.45
- type: Telephone
transmissionRange: Map
ringTone: /Audio/Machines/double_ring.ogg
listeningRange: 4
listeningRange: 2.5
speakerVolume: Speak
- type: AccessReader
access: [[ "Command" ]]
Expand Down Expand Up @@ -104,28 +104,47 @@
node: machineFrame
- !type:DoActsBehavior
acts: ["Destruction"]

- type: entity
name: long-range holopad
description: "A floor-mounted device for projecting holographic images to other devices that are far away."
description: "A floor-mounted device for projecting holographic images to similar devices that are far away."
parent: Holopad
id: HolopadLongRange
suffix: For calls between maps
components:
- type: Telephone
transmissionRange: Long

transmissionRange: Map
compatibleRanges:
- Map
- Unlimited
ignoreTelephonesOnSameGrid: true

- type: entity
name: quantum entangling holopad
description: "An experimental floor-mounted device for projecting holographic images at extreme distances."
description: "An floor-mounted device for projecting holographic images to similar devices at extreme distances."
parent: Holopad
id: HolopadUnlimitedRange
suffix: Unlimited range
components:
- type: Telephone
transmissionRange: Unlimited
- type: AccessReader
access: [[]]
compatibleRanges:
- Map
- Unlimited
ignoreTelephonesOnSameGrid: true

- type: entity
name: bluespace holopad
description: "An experimental floor-mounted device for projecting holographic images via bluespace."
parent: Holopad
id: HolopadBluespace
suffix: Unrestricted range
components:
- type: Telephone
unlistedNumber: true
transmissionRange: Unlimited
compatibleRanges:
- Grid
- Map
- Unlimited

# These are spawned by holopads
- type: entity
Expand Down
Loading