Tweaks for the holopad (#33928)
* Initial commit * AIs get a warning when trying to answer long distance calls * Better handling of ending telephone calls * Fixed issue with duplicated holopad window when an AI answers a summons * Changed how ranges are handled, added the bluespace holopad * Bug fixes * More bug fixes * More bug fixes * Update Resources/Prototypes/Entities/Structures/Machines/holopad.yml Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * Update Resources/Prototypes/Entities/Structures/Machines/holopad.yml Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> --------- Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
using Content.Server.Chat.Systems;
|
using Content.Server.Chat.Systems;
|
||||||
|
using Content.Server.Popups;
|
||||||
using Content.Server.Power.EntitySystems;
|
using Content.Server.Power.EntitySystems;
|
||||||
using Content.Server.Speech.Components;
|
using Content.Server.Speech.Components;
|
||||||
using Content.Server.Telephone;
|
using Content.Server.Telephone;
|
||||||
@@ -31,6 +32,7 @@ public sealed class HolopadSystem : SharedHolopadSystem
|
|||||||
[Dependency] private readonly SharedStationAiSystem _stationAiSystem = default!;
|
[Dependency] private readonly SharedStationAiSystem _stationAiSystem = default!;
|
||||||
[Dependency] private readonly AccessReaderSystem _accessReaderSystem = default!;
|
[Dependency] private readonly AccessReaderSystem _accessReaderSystem = default!;
|
||||||
[Dependency] private readonly ChatSystem _chatSystem = default!;
|
[Dependency] private readonly ChatSystem _chatSystem = default!;
|
||||||
|
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
||||||
[Dependency] private readonly IGameTiming _timing = default!;
|
[Dependency] private readonly IGameTiming _timing = default!;
|
||||||
|
|
||||||
private float _updateTimer = 1.0f;
|
private float _updateTimer = 1.0f;
|
||||||
@@ -117,7 +119,22 @@ public sealed class HolopadSystem : SharedHolopadSystem
|
|||||||
var source = GetLinkedHolopads(receiver).FirstOrNull();
|
var source = GetLinkedHolopads(receiver).FirstOrNull();
|
||||||
|
|
||||||
if (source != null)
|
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);
|
ActivateProjector(source.Value, args.Actor);
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -134,7 +151,8 @@ public sealed class HolopadSystem : SharedHolopadSystem
|
|||||||
if (IsHolopadControlLocked(entity, args.Actor))
|
if (IsHolopadControlLocked(entity, args.Actor))
|
||||||
return;
|
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
|
// If the user is an AI, end all calls originating from its
|
||||||
// associated core to ensure that any broadcasts will end
|
// associated core to ensure that any broadcasts will end
|
||||||
@@ -142,7 +160,8 @@ public sealed class HolopadSystem : SharedHolopadSystem
|
|||||||
!_stationAiSystem.TryGetStationAiCore((args.Actor, stationAiHeld), out var stationAiCore))
|
!_stationAiSystem.TryGetStationAiCore((args.Actor, stationAiHeld), out var stationAiCore))
|
||||||
return;
|
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));
|
_telephoneSystem.EndTelephoneCalls((stationAiCore.Value, telephone));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -414,7 +433,7 @@ public sealed class HolopadSystem : SharedHolopadSystem
|
|||||||
AlternativeVerb verb = new()
|
AlternativeVerb verb = new()
|
||||||
{
|
{
|
||||||
Act = () => ActivateProjector(entity, user),
|
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")),
|
Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/vv.svg.192dpi.png")),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -594,7 +613,8 @@ public sealed class HolopadSystem : SharedHolopadSystem
|
|||||||
{
|
{
|
||||||
_stationAiSystem.SwitchRemoteEntityMode((entity.Owner, stationAiCore), true);
|
_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));
|
_telephoneSystem.EndTelephoneCalls((entity, stationAiCoreTelphone));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -648,6 +668,9 @@ public sealed class HolopadSystem : SharedHolopadSystem
|
|||||||
|
|
||||||
var source = new Entity<TelephoneComponent>(stationAiCore.Value, stationAiTelephone);
|
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
|
// Terminate any calls that the core is hosting and immediately connect to the receiver
|
||||||
_telephoneSystem.TerminateTelephoneCalls(source);
|
_telephoneSystem.TerminateTelephoneCalls(source);
|
||||||
|
|
||||||
|
|||||||
@@ -277,6 +277,10 @@ public sealed class TelephoneSystem : SharedTelephoneSystem
|
|||||||
|
|
||||||
public void EndTelephoneCalls(Entity<TelephoneComponent> entity)
|
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);
|
HandleEndingTelephoneCalls(entity, TelephoneState.EndingCall);
|
||||||
|
|
||||||
var ev = new TelephoneCallEndedEvent();
|
var ev = new TelephoneCallEndedEvent();
|
||||||
@@ -285,14 +289,15 @@ public sealed class TelephoneSystem : SharedTelephoneSystem
|
|||||||
|
|
||||||
public void TerminateTelephoneCalls(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);
|
HandleEndingTelephoneCalls(entity, TelephoneState.Idle);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleEndingTelephoneCalls(Entity<TelephoneComponent> entity, TelephoneState newState)
|
private void HandleEndingTelephoneCalls(Entity<TelephoneComponent> entity, TelephoneState newState)
|
||||||
{
|
{
|
||||||
if (entity.Comp.CurrentState == newState)
|
|
||||||
return;
|
|
||||||
|
|
||||||
foreach (var linkedTelephone in entity.Comp.LinkedTelephones)
|
foreach (var linkedTelephone in entity.Comp.LinkedTelephones)
|
||||||
{
|
{
|
||||||
if (!linkedTelephone.Comp.LinkedTelephones.Remove(entity))
|
if (!linkedTelephone.Comp.LinkedTelephones.Remove(entity))
|
||||||
@@ -431,23 +436,26 @@ public sealed class TelephoneSystem : SharedTelephoneSystem
|
|||||||
|
|
||||||
public bool IsSourceInRangeOfReceiver(Entity<TelephoneComponent> source, Entity<TelephoneComponent> receiver)
|
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 sourceXform = Transform(source);
|
||||||
var receiverXform = Transform(receiver);
|
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)
|
switch (source.Comp.TransmissionRange)
|
||||||
{
|
{
|
||||||
case TelephoneRange.Grid:
|
case TelephoneRange.Grid:
|
||||||
return sourceXform.GridUid != null &&
|
return sourceXform.GridUid == receiverXform.GridUid;
|
||||||
receiverXform.GridUid == sourceXform.GridUid &&
|
|
||||||
receiver.Comp.TransmissionRange != TelephoneRange.Long;
|
|
||||||
|
|
||||||
case TelephoneRange.Map:
|
case TelephoneRange.Map:
|
||||||
return sourceXform.MapID == receiverXform.MapID &&
|
return sourceXform.MapID == receiverXform.MapID;
|
||||||
receiver.Comp.TransmissionRange != TelephoneRange.Long;
|
|
||||||
|
|
||||||
case TelephoneRange.Long:
|
|
||||||
return sourceXform.MapID != receiverXform.MapID &&
|
|
||||||
receiver.Comp.TransmissionRange == TelephoneRange.Long;
|
|
||||||
|
|
||||||
case TelephoneRange.Unlimited:
|
case TelephoneRange.Unlimited:
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -52,11 +52,28 @@ public sealed partial class TelephoneComponent : Component
|
|||||||
public TelephoneVolume SpeakerVolume = TelephoneVolume.Whisper;
|
public TelephoneVolume SpeakerVolume = TelephoneVolume.Whisper;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The range at which the telephone can connect to another
|
/// The maximum range at which the telephone initiate a call with another
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField]
|
[DataField]
|
||||||
public TelephoneRange TransmissionRange = TelephoneRange.Grid;
|
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>
|
/// <summary>
|
||||||
/// The range at which the telephone picks up voices
|
/// The range at which the telephone picks up voices
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -70,7 +87,7 @@ public sealed partial class TelephoneComponent : Component
|
|||||||
public bool RequiresPower = true;
|
public bool RequiresPower = true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This telephone does not appear on public telephone directories
|
/// This telephone should not appear on public telephone directories
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField]
|
[DataField]
|
||||||
public bool UnlistedNumber = false;
|
public bool UnlistedNumber = false;
|
||||||
@@ -196,8 +213,7 @@ public enum TelephoneVolume : byte
|
|||||||
[Serializable, NetSerializable]
|
[Serializable, NetSerializable]
|
||||||
public enum TelephoneRange : byte
|
public enum TelephoneRange : byte
|
||||||
{
|
{
|
||||||
Grid, // Can call grid/map range telephones that are on the same grid
|
Grid, // Can only reach telephones that are on the same grid
|
||||||
Map, // Can call grid/map range telephones that are on the same map
|
Map, // Can reach any telephone that is on the same map
|
||||||
Long, // Can only long range telephones that are on a different map
|
Unlimited, // Can reach any telephone, across any distance
|
||||||
Unlimited // Can call any telephone
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,8 @@ holopad-window-flavor-right = v3.0.9
|
|||||||
holopad-hologram-name = hologram of {THE($name)}
|
holopad-hologram-name = hologram of {THE($name)}
|
||||||
|
|
||||||
# Holopad actions
|
# 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
|
# Mapping prototypes
|
||||||
# General
|
# General
|
||||||
|
|||||||
@@ -369,6 +369,10 @@
|
|||||||
Empty: { state: ai_empty }
|
Empty: { state: ai_empty }
|
||||||
Occupied: { state: ai }
|
Occupied: { state: ai }
|
||||||
- type: Telephone
|
- type: Telephone
|
||||||
|
compatibleRanges:
|
||||||
|
- Grid
|
||||||
|
- Map
|
||||||
|
- Unlimited
|
||||||
listeningRange: 0
|
listeningRange: 0
|
||||||
speakerVolume: Speak
|
speakerVolume: Speak
|
||||||
unlistedNumber: true
|
unlistedNumber: true
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
- type: StationAiVision
|
- type: StationAiVision
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Structures/Machines/holopad.rsi
|
sprite: Structures/Machines/holopad.rsi
|
||||||
|
drawdepth: FloorObjects
|
||||||
snapCardinals: true
|
snapCardinals: true
|
||||||
layers:
|
layers:
|
||||||
- state: base
|
- state: base
|
||||||
@@ -71,9 +72,8 @@
|
|||||||
speechSounds: Borg
|
speechSounds: Borg
|
||||||
speechBubbleOffset: 0.45
|
speechBubbleOffset: 0.45
|
||||||
- type: Telephone
|
- type: Telephone
|
||||||
transmissionRange: Map
|
|
||||||
ringTone: /Audio/Machines/double_ring.ogg
|
ringTone: /Audio/Machines/double_ring.ogg
|
||||||
listeningRange: 4
|
listeningRange: 2.5
|
||||||
speakerVolume: Speak
|
speakerVolume: Speak
|
||||||
- type: AccessReader
|
- type: AccessReader
|
||||||
access: [[ "Command" ]]
|
access: [[ "Command" ]]
|
||||||
@@ -104,28 +104,47 @@
|
|||||||
node: machineFrame
|
node: machineFrame
|
||||||
- !type:DoActsBehavior
|
- !type:DoActsBehavior
|
||||||
acts: ["Destruction"]
|
acts: ["Destruction"]
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
name: long-range holopad
|
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
|
parent: Holopad
|
||||||
id: HolopadLongRange
|
id: HolopadLongRange
|
||||||
suffix: For calls between maps
|
|
||||||
components:
|
components:
|
||||||
- type: Telephone
|
- type: Telephone
|
||||||
transmissionRange: Long
|
transmissionRange: Map
|
||||||
|
compatibleRanges:
|
||||||
|
- Map
|
||||||
|
- Unlimited
|
||||||
|
ignoreTelephonesOnSameGrid: true
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
name: quantum entangling holopad
|
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
|
parent: Holopad
|
||||||
id: HolopadUnlimitedRange
|
id: HolopadUnlimitedRange
|
||||||
suffix: Unlimited range
|
|
||||||
components:
|
components:
|
||||||
- type: Telephone
|
- type: Telephone
|
||||||
transmissionRange: Unlimited
|
transmissionRange: Unlimited
|
||||||
- type: AccessReader
|
compatibleRanges:
|
||||||
access: [[]]
|
- 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
|
# These are spawned by holopads
|
||||||
- type: entity
|
- type: entity
|
||||||
|
|||||||
Reference in New Issue
Block a user