Skip to content

Commit

Permalink
Station AI (#30944)
Browse files Browse the repository at this point in the history
* Station AI overlay

* implement

* Bunch of ports

* Fix a heap of bugs and basic scouting

* helldivers

* Shuffle interactions a bit

* navmap stuff

* Revert "navmap stuff"

This reverts commit d1f89dd4be83233e22cf5dd062b2581f3c6da062.

* AI wires implemented

* Fix examines

* Optimise the overlay significantly

* Back to old static

* BUI radial working

* lots of work

* Saving work

* thanks fork

* alright

* pc

* AI upload console

* AI upload

* stuff

* Fix copy-paste shitcode

* AI actions

* navmap work

* Fixes

* first impressions

* a

* reh

* Revert "navmap work"

This reverts commit 6f63fea6e9245e189f368f97be3e32e9b210580e.

* OD

* radar

* weh

* Fix examines

* scoop mine eyes

* fixes

* reh

* Optimise

* Final round of optimisations

* Fixes

* fixes
  • Loading branch information
metalgearsloth authored and sleepyyapril committed Jan 4, 2025
1 parent 87c7979 commit d8ae58e
Show file tree
Hide file tree
Showing 142 changed files with 2,278 additions and 256 deletions.
13 changes: 5 additions & 8 deletions Content.Client/Chat/UI/EmotesMenu.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,15 @@ public sealed partial class EmotesMenu : RadialMenu
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly ISharedPlayerManager _playerManager = default!;

private readonly SpriteSystem _spriteSystem;
private readonly EntityWhitelistSystem _whitelistSystem;

public event Action<ProtoId<EmotePrototype>>? OnPlayEmote;

public EmotesMenu()
{
IoCManager.InjectDependencies(this);
RobustXamlLoader.Load(this);

_spriteSystem = _entManager.System<SpriteSystem>();
_whitelistSystem = _entManager.System<EntityWhitelistSystem>();
var spriteSystem = _entManager.System<SpriteSystem>();
var whitelistSystem = _entManager.System<EntityWhitelistSystem>();

var main = FindControl<RadialContainer>("Main");

Expand All @@ -40,8 +37,8 @@ public EmotesMenu()
var player = _playerManager.LocalSession?.AttachedEntity;
if (emote.Category == EmoteCategory.Invalid ||
emote.ChatTriggers.Count == 0 ||
!(player.HasValue && _whitelistSystem.IsWhitelistPassOrNull(emote.Whitelist, player.Value)) ||
_whitelistSystem.IsBlacklistPass(emote.Blacklist, player.Value))
!(player.HasValue && whitelistSystem.IsWhitelistPassOrNull(emote.Whitelist, player.Value)) ||
whitelistSystem.IsBlacklistPass(emote.Blacklist, player.Value))
continue;

if (!emote.Available &&
Expand All @@ -63,7 +60,7 @@ public EmotesMenu()
{
VerticalAlignment = VAlignment.Center,
HorizontalAlignment = HAlignment.Center,
Texture = _spriteSystem.Frame0(emote.Icon),
Texture = spriteSystem.Frame0(emote.Icon),
TextureScale = new Vector2(2f, 2f),
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace Content.Client.Silicons.Laws.SiliconLawEditUi;

public sealed class SiliconLawEui : BaseEui
{
public readonly EntityManager _entityManager = default!;
private readonly EntityManager _entityManager;

private SiliconLawUi _siliconLawUi;
private EntityUid _target;
Expand Down
28 changes: 28 additions & 0 deletions Content.Client/Silicons/StationAi/StationAiBoundUserInterface.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using Content.Shared.Silicons.StationAi;
using Robust.Client.UserInterface;

namespace Content.Client.Silicons.StationAi;

public sealed class StationAiBoundUserInterface : BoundUserInterface
{
private StationAiMenu? _menu;

public StationAiBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
{
}

protected override void Open()
{
base.Open();
_menu = this.CreateWindow<StationAiMenu>();
_menu.Track(Owner);

_menu.OnAiRadial += args =>
{
SendPredictedMessage(new StationAiRadialMessage()
{
Event = args,
});
};
}
}
13 changes: 13 additions & 0 deletions Content.Client/Silicons/StationAi/StationAiMenu.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<ui:RadialMenu xmlns="https://spacestation14.io"
xmlns:ui="clr-namespace:Content.Client.UserInterface.Controls"
BackButtonStyleClass="RadialMenuBackButton"
CloseButtonStyleClass="RadialMenuCloseButton"
VerticalExpand="True"
HorizontalExpand="True"
MinSize="450 450">

<!-- Main -->
<ui:RadialContainer Name="Main" VerticalExpand="True" HorizontalExpand="True" Radius="64" ReserveSpaceForHiddenChildren="False">
</ui:RadialContainer>

</ui:RadialMenu>
128 changes: 128 additions & 0 deletions Content.Client/Silicons/StationAi/StationAiMenu.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
using System.Numerics;
using Content.Client.UserInterface.Controls;
using Content.Shared.Silicons.StationAi;
using Robust.Client.AutoGenerated;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Timing;

namespace Content.Client.Silicons.StationAi;

[GenerateTypedNameReferences]
public sealed partial class StationAiMenu : RadialMenu
{
[Dependency] private readonly IClyde _clyde = default!;
[Dependency] private readonly IEntityManager _entManager = default!;
[Dependency] private readonly IEyeManager _eyeManager = default!;

public event Action<BaseStationAiAction>? OnAiRadial;

private EntityUid _tracked;

public StationAiMenu()
{
IoCManager.InjectDependencies(this);
RobustXamlLoader.Load(this);
}

public void Track(EntityUid owner)
{
_tracked = owner;

if (!_entManager.EntityExists(_tracked))
{
Close();
return;
}

BuildButtons();
UpdatePosition();
}

private void BuildButtons()
{
var ev = new GetStationAiRadialEvent();
_entManager.EventBus.RaiseLocalEvent(_tracked, ref ev);

var main = FindControl<RadialContainer>("Main");
main.DisposeAllChildren();
var sprites = _entManager.System<SpriteSystem>();

foreach (var action in ev.Actions)
{
// TODO: This radial boilerplate is quite annoying
var button = new StationAiMenuButton(action.Event)
{
StyleClasses = { "RadialMenuButton" },
SetSize = new Vector2(64f, 64f),
ToolTip = action.Tooltip != null ? Loc.GetString(action.Tooltip) : null,
};

if (action.Sprite != null)
{
var texture = sprites.Frame0(action.Sprite);
var scale = Vector2.One;

if (texture.Width <= 32)
{
scale *= 2;
}

var tex = new TextureRect
{
VerticalAlignment = VAlignment.Center,
HorizontalAlignment = HAlignment.Center,
Texture = texture,
TextureScale = scale,
};

button.AddChild(tex);
}

button.OnPressed += args =>
{
OnAiRadial?.Invoke(action.Event);
Close();
};
main.AddChild(button);
}
}

protected override void FrameUpdate(FrameEventArgs args)
{
base.FrameUpdate(args);
UpdatePosition();
}

private void UpdatePosition()
{
if (!_entManager.TryGetComponent(_tracked, out TransformComponent? xform))
{
Close();
return;
}

if (!xform.Coordinates.IsValid(_entManager))
{
Close();
return;
}

var coords = _entManager.System<SpriteSystem>().GetSpriteScreenCoordinates((_tracked, null, xform));

if (!coords.IsValid)
{
Close();
return;
}

OpenScreenAt(coords.Position, _clyde);
}
}

public sealed class StationAiMenuButton(BaseStationAiAction action) : RadialMenuTextureButton
{
public BaseStationAiAction Action = action;
}
23 changes: 16 additions & 7 deletions Content.Client/Silicons/StationAi/StationAiOverlay.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,17 @@
using Robust.Client.Player;
using Robust.Shared.Enums;
using Robust.Shared.Map.Components;
using Robust.Shared.Physics;
using Robust.Shared.Prototypes;
using Robust.Shared.Timing;

namespace Content.Client.Silicons.StationAi;

public sealed class StationAiOverlay : Overlay
{
[Dependency] private readonly IClyde _clyde = default!;
[Dependency] private readonly IEntityManager _entManager = default!;
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly IPlayerManager _player = default!;
[Dependency] private readonly IPrototypeManager _proto = default!;

Expand All @@ -22,6 +25,9 @@ public sealed class StationAiOverlay : Overlay
private IRenderTexture? _staticTexture;
private IRenderTexture? _stencilTexture;

private float _updateRate = 1f / 30f;
private float _accumulator;

public StationAiOverlay()
{
IoCManager.InjectDependencies(this);
Expand All @@ -47,19 +53,22 @@ protected override void Draw(in OverlayDrawArgs args)
_entManager.TryGetComponent(playerEnt, out TransformComponent? playerXform);
var gridUid = playerXform?.GridUid ?? EntityUid.Invalid;
_entManager.TryGetComponent(gridUid, out MapGridComponent? grid);
_entManager.TryGetComponent(gridUid, out BroadphaseComponent? broadphase);

var invMatrix = args.Viewport.GetWorldToLocalMatrix();
_accumulator -= (float) _timing.FrameTime.TotalSeconds;

if (grid != null)
if (grid != null && broadphase != null)
{
// TODO: Pass in attached entity's grid.
// TODO: Credit OD on the moved to code
// TODO: Call the moved-to code here.

_visibleTiles.Clear();
var lookups = _entManager.System<EntityLookupSystem>();
var xforms = _entManager.System<SharedTransformSystem>();
_entManager.System<StationAiVisionSystem>().GetView((gridUid, grid), worldBounds, _visibleTiles);

if (_accumulator <= 0f)
{
_accumulator = MathF.Max(0f, _accumulator + _updateRate);
_visibleTiles.Clear();
_entManager.System<StationAiVisionSystem>().GetView((gridUid, broadphase, grid), worldBounds, _visibleTiles);
}

var gridMatrix = xforms.GetWorldMatrix(gridUid);
var matty = Matrix3x2.Multiply(gridMatrix, invMatrix);
Expand Down
30 changes: 30 additions & 0 deletions Content.Client/Silicons/StationAi/StationAiSystem.Airlock.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using Content.Shared.Doors.Components;
using Content.Shared.Silicons.StationAi;
using Robust.Shared.Utility;

namespace Content.Client.Silicons.StationAi;

public sealed partial class StationAiSystem
{
private void InitializeAirlock()
{
SubscribeLocalEvent<DoorBoltComponent, GetStationAiRadialEvent>(OnDoorBoltGetRadial);
}

private void OnDoorBoltGetRadial(Entity<DoorBoltComponent> ent, ref GetStationAiRadialEvent args)
{
args.Actions.Add(new StationAiRadial()
{
Sprite = ent.Comp.BoltsDown ?
new SpriteSpecifier.Rsi(
new ResPath("/Textures/Structures/Doors/Airlocks/Standard/basic.rsi"), "open") :
new SpriteSpecifier.Rsi(
new ResPath("/Textures/Structures/Doors/Airlocks/Standard/basic.rsi"), "closed"),
Tooltip = ent.Comp.BoltsDown ? Loc.GetString("bolt-open") : Loc.GetString("bolt-close"),
Event = new StationAiBoltEvent()
{
Bolted = !ent.Comp.BoltsDown,
}
});
}
}
32 changes: 32 additions & 0 deletions Content.Client/Silicons/StationAi/StationAiSystem.Light.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using Content.Shared.Item.ItemToggle.Components;
using Content.Shared.Light.Components;
using Content.Shared.Silicons.StationAi;
using Robust.Shared.Utility;

namespace Content.Client.Silicons.StationAi;

public sealed partial class StationAiSystem
{
// Used for surveillance camera lights

private void InitializePowerToggle()
{
SubscribeLocalEvent<ItemTogglePointLightComponent, GetStationAiRadialEvent>(OnLightGetRadial);
}

private void OnLightGetRadial(Entity<ItemTogglePointLightComponent> ent, ref GetStationAiRadialEvent args)
{
if (!TryComp(ent.Owner, out ItemToggleComponent? toggle))
return;

args.Actions.Add(new StationAiRadial()
{
Tooltip = Loc.GetString("toggle-light"),
Sprite = new SpriteSpecifier.Texture(new ResPath("/Textures/Interface/VerbIcons/light.svg.192dpi.png")),
Event = new StationAiLightEvent()
{
Enabled = !toggle.Activated
}
});
}
}
6 changes: 3 additions & 3 deletions Content.Client/Silicons/StationAi/StationAiSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

namespace Content.Client.Silicons.StationAi;

public sealed partial class StationAiSystem : EntitySystem
public sealed partial class StationAiSystem : SharedStationAiSystem
{
[Dependency] private readonly IOverlayManager _overlayMgr = default!;
[Dependency] private readonly IPlayerManager _player = default!;
Expand All @@ -15,8 +15,8 @@ public sealed partial class StationAiSystem : EntitySystem
public override void Initialize()
{
base.Initialize();
// InitializeAirlock();
// InitializePowerToggle();
InitializeAirlock();
InitializePowerToggle();

SubscribeLocalEvent<StationAiOverlayComponent, LocalPlayerAttachedEvent>(OnAiAttached);
SubscribeLocalEvent<StationAiOverlayComponent, LocalPlayerDetachedEvent>(OnAiDetached);
Expand Down
5 changes: 3 additions & 2 deletions Content.Client/Verbs/VerbSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ public bool TryGetEntityMenuEntities(MapCoordinates targetPos, [NotNullWhen(true

// Get entities
List<EntityUid> entities;
var examineFlags = LookupFlags.All & ~LookupFlags.Sensors;

// Do we have to do FoV checks?
if ((visibility & MenuVisibility.NoFov) == 0)
Expand All @@ -85,15 +86,15 @@ public bool TryGetEntityMenuEntities(MapCoordinates targetPos, [NotNullWhen(true

// Then check every entity
entities = new();
foreach (var ent in _entityLookup.GetEntitiesInRange(targetPos, EntityMenuLookupSize))
foreach (var ent in _entityLookup.GetEntitiesInRange(targetPos, EntityMenuLookupSize, flags: examineFlags))
{
if (_examine.CanExamine(player.Value, targetPos, Predicate, ent, examiner))
entities.Add(ent);
}
}
else
{
entities = _entityLookup.GetEntitiesInRange(targetPos, EntityMenuLookupSize).ToList();
entities = _entityLookup.GetEntitiesInRange(targetPos, EntityMenuLookupSize, flags: examineFlags).ToList();
}

if (entities.Count == 0)
Expand Down
1 change: 1 addition & 0 deletions Content.Server/Administration/Systems/AdminVerbSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
using System.Linq;
using System.Numerics;
using Content.Server.Silicons.Laws;
using Content.Shared.Silicons.Laws;
using Content.Shared.Silicons.Laws.Components;
using Robust.Server.Player;
using Robust.Shared.Physics.Components;
Expand Down
Loading

0 comments on commit d8ae58e

Please sign in to comment.