Holopads (#32711)
* Initial resources commit * Initial code commit * Added additional resources * Continuing to build holopad and telephone systems * Added hologram shader * Added hologram system and entity * Holo calls now have a hologram of the user appear on them * Initial implementation of holopads transmitting nearby chatter * Added support for linking across multiple telephones/holopads/entities * Fixed a bunch of bugs * Tried simplifying holopad entity dependence, added support for mid-call user switching * Replaced PVS expansion with manually networked sprite states * Adjusted volume of ring tone * Added machine board * Minor features and tweaks * Resolving merge conflict * Recommit audio attributions * Telephone chat adjustments * Added support for AI interactions with holopads * Building the holopad UI * Holopad UI finished * Further UI tweaks * Station AI can hear local chatter when being projected from a holopad * Minor bug fixes * Added wire panels to holopads * Basic broadcasting * Start of emergency broadcasting code * Fixing issues with broadcasting * More work on emergency broadcasting * Updated holopad visuals * Added cooldown text to emergency broadcast and control lock out screen * Code clean up * Fixed issue with timing * Broadcasting now requires command access * Fixed some bugs * Added multiple holopad prototypes with different ranges * The AI no longer requires power to interact with holopads * Fixed some additional issues * Addressing more issues * Added emote support for holograms * Changed the broadcast lockout durations to their proper values * Added AI vision wire to holopads * Bug fixes * AI vision and interaction wires can be added to the same wire panel * Fixed error * More bug fixes * Fixed test fail * Embellished the emergency call lock out window * Holopads play borg sounds when speaking * Borg and AI names are listed as the caller ID on the holopad * Borg chassis can now be seen on holopad holograms * Holopad returns to a machine frame when badly damaged * Clarified some text * Fix merge conflict * Fixed merge conflict * Fixing merge conflict * Fixing merge conflict * Fixing merge conflict * Offset menu on open * AI can alt click on holopads to activate the projector * Bug fixes for intellicard interactions * Fixed speech issue with intellicards * The UI automatically opens for the AI when it alt-clicks on the holopad * Simplified shader math * Telephones will auto hang up 60 seconds after the last person on a call stops speaking * Added better support for AI requests when multiple AI cores are on the station * The call controls pop up for the AI when they accept a summons from a holopad * Compatibility mode fix for the hologram shader * Further shader fixes for compatibility mode * File clean up * More cleaning up * Removed access requirements from quantum holopads so they can used by nukies * The title of the holopad window now reflects the name of the device * Linked telephones will lose their connection if both move out of range of each other
This commit is contained in:
@@ -20,12 +20,15 @@ using Content.Shared.Verbs;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Map.Components;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Timing;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace Content.Shared.Silicons.StationAi;
|
||||
|
||||
@@ -68,6 +71,8 @@ public abstract partial class SharedStationAiSystem : EntitySystem
|
||||
[ValidatePrototypeId<EntityPrototype>]
|
||||
private static readonly EntProtoId DefaultAi = "StationAiBrain";
|
||||
|
||||
private const float MaxVisionMultiplier = 5f;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
@@ -344,16 +349,47 @@ public abstract partial class SharedStationAiSystem : EntitySystem
|
||||
AttachEye(ent);
|
||||
}
|
||||
|
||||
private bool SetupEye(Entity<StationAiCoreComponent> ent)
|
||||
public void SwitchRemoteEntityMode(Entity<StationAiCoreComponent> ent, bool isRemote)
|
||||
{
|
||||
if (isRemote == ent.Comp.Remote)
|
||||
return;
|
||||
|
||||
ent.Comp.Remote = isRemote;
|
||||
|
||||
EntityCoordinates? coords = ent.Comp.RemoteEntity != null ? Transform(ent.Comp.RemoteEntity.Value).Coordinates : null;
|
||||
|
||||
// Attach new eye
|
||||
ClearEye(ent);
|
||||
|
||||
if (SetupEye(ent, coords))
|
||||
AttachEye(ent);
|
||||
|
||||
// Adjust user FoV
|
||||
var user = GetInsertedAI(ent);
|
||||
|
||||
if (TryComp<EyeComponent>(user, out var eye))
|
||||
_eye.SetDrawFov(user.Value, !isRemote);
|
||||
}
|
||||
|
||||
private bool SetupEye(Entity<StationAiCoreComponent> ent, EntityCoordinates? coords = null)
|
||||
{
|
||||
if (_net.IsClient)
|
||||
return false;
|
||||
|
||||
if (ent.Comp.RemoteEntity != null)
|
||||
return false;
|
||||
|
||||
if (ent.Comp.RemoteEntityProto != null)
|
||||
var proto = ent.Comp.RemoteEntityProto;
|
||||
|
||||
if (coords == null)
|
||||
coords = Transform(ent.Owner).Coordinates;
|
||||
|
||||
if (!ent.Comp.Remote)
|
||||
proto = ent.Comp.PhysicalEntityProto;
|
||||
|
||||
if (proto != null)
|
||||
{
|
||||
ent.Comp.RemoteEntity = SpawnAtPosition(ent.Comp.RemoteEntityProto, Transform(ent.Owner).Coordinates);
|
||||
ent.Comp.RemoteEntity = SpawnAtPosition(proto, coords.Value);
|
||||
Dirty(ent);
|
||||
}
|
||||
|
||||
@@ -364,6 +400,7 @@ public abstract partial class SharedStationAiSystem : EntitySystem
|
||||
{
|
||||
if (_net.IsClient)
|
||||
return;
|
||||
|
||||
QueueDel(ent.Comp.RemoteEntity);
|
||||
ent.Comp.RemoteEntity = null;
|
||||
Dirty(ent);
|
||||
@@ -392,6 +429,17 @@ public abstract partial class SharedStationAiSystem : EntitySystem
|
||||
_mover.SetRelay(user, ent.Comp.RemoteEntity.Value);
|
||||
}
|
||||
|
||||
private EntityUid? GetInsertedAI(Entity<StationAiCoreComponent> ent)
|
||||
{
|
||||
if (!_containers.TryGetContainer(ent.Owner, StationAiHolderComponent.Container, out var container) ||
|
||||
container.ContainedEntities.Count != 1)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return container.ContainedEntities[0];
|
||||
}
|
||||
|
||||
private void OnAiInsert(Entity<StationAiCoreComponent> ent, ref EntInsertedIntoContainerMessage args)
|
||||
{
|
||||
if (args.Container.ID != StationAiCoreComponent.Container)
|
||||
@@ -400,6 +448,7 @@ public abstract partial class SharedStationAiSystem : EntitySystem
|
||||
if (_timing.ApplyingState)
|
||||
return;
|
||||
|
||||
ent.Comp.Remote = true;
|
||||
SetupEye(ent);
|
||||
|
||||
// Just so text and the likes works properly
|
||||
@@ -413,6 +462,8 @@ public abstract partial class SharedStationAiSystem : EntitySystem
|
||||
if (_timing.ApplyingState)
|
||||
return;
|
||||
|
||||
ent.Comp.Remote = true;
|
||||
|
||||
// Reset name to whatever
|
||||
_metadata.SetEntityName(ent.Owner, Prototype(ent.Owner)?.Name ?? string.Empty);
|
||||
|
||||
@@ -424,6 +475,7 @@ public abstract partial class SharedStationAiSystem : EntitySystem
|
||||
_eye.SetDrawFov(args.Entity, true, eyeComp);
|
||||
_eye.SetTarget(args.Entity, null, eyeComp);
|
||||
}
|
||||
|
||||
ClearEye(ent);
|
||||
}
|
||||
|
||||
@@ -478,6 +530,36 @@ public abstract partial class SharedStationAiSystem : EntitySystem
|
||||
|
||||
return _blocker.CanComplexInteract(entity.Owner);
|
||||
}
|
||||
|
||||
public bool TryGetStationAiCore(Entity<StationAiHeldComponent?> ent, [NotNullWhen(true)] out Entity<StationAiCoreComponent>? parentEnt)
|
||||
{
|
||||
parentEnt = null;
|
||||
var parent = Transform(ent).ParentUid;
|
||||
|
||||
if (!parent.IsValid())
|
||||
return false;
|
||||
|
||||
if (!TryComp<StationAiCoreComponent>(parent, out var stationAiCore))
|
||||
return false;
|
||||
|
||||
parentEnt = new Entity<StationAiCoreComponent>(parent, stationAiCore);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool TryGetInsertedAI(Entity<StationAiCoreComponent> ent, [NotNullWhen(true)] out Entity<StationAiHeldComponent>? insertedAi)
|
||||
{
|
||||
insertedAi = null;
|
||||
var insertedEnt = GetInsertedAI(ent);
|
||||
|
||||
if (TryComp<StationAiHeldComponent>(insertedEnt, out var stationAiHeld))
|
||||
{
|
||||
insertedAi = (insertedEnt.Value, stationAiHeld);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed partial class JumpToCoreEvent : InstantActionEvent
|
||||
|
||||
@@ -15,6 +15,7 @@ public sealed partial class StationAiCoreComponent : Component
|
||||
|
||||
/// <summary>
|
||||
/// Can it move its camera around and interact remotely with things.
|
||||
/// When false, the AI is being projected into a local area, such as a holopad
|
||||
/// </summary>
|
||||
[DataField, AutoNetworkedField]
|
||||
public bool Remote = true;
|
||||
@@ -25,8 +26,17 @@ public sealed partial class StationAiCoreComponent : Component
|
||||
[DataField, AutoNetworkedField]
|
||||
public EntityUid? RemoteEntity;
|
||||
|
||||
/// <summary>
|
||||
/// Prototype that represents the 'eye' of the AI
|
||||
/// </summary>
|
||||
[DataField(readOnly: true)]
|
||||
public EntProtoId? RemoteEntityProto = "StationAiHolo";
|
||||
|
||||
/// <summary>
|
||||
/// Prototype that represents the physical avatar of the AI
|
||||
/// </summary>
|
||||
[DataField(readOnly: true)]
|
||||
public EntProtoId? PhysicalEntityProto = "StationAiHoloLocal";
|
||||
|
||||
public const string Container = "station_ai_mind_slot";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user