add ai detector from ss13 (#3192)

* add CollidingVisuals system

* add AiDetectable to ai eye

* add AI detector item

* add AI detector to uplink, clean up observation kit too

* switch to component...

---------

Co-authored-by: deltanedas <@deltanedas:kde.org>
This commit is contained in:
deltanedas 2025-03-13 08:39:19 +00:00 committed by GitHub
parent 7b80e4645f
commit 79d34a02bb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 207 additions and 15 deletions

View File

@ -0,0 +1,42 @@
using Content.Shared.Whitelist;
using Robust.Shared.Serialization;
namespace Content.Shared._DV.Physics;
/// <summary>
/// Changes an appearance data string depending on active collisions with fixtures.
/// </summary>
[RegisterComponent, Access(typeof(CollidingVisualsSystem))]
public sealed partial class CollidingVisualsComponent : Component
{
/// <summary>
/// A whitelist entities must match to be counted for collisions.
/// </summary>
[DataField]
public EntityWhitelist? Whitelist;
/// <summary>
/// The string to use for appearance data when no fixtures are being collided with.
/// </summary>
[DataField]
public string Default = "none";
/// <summary>
/// The list of fixtures to check for collisions, first one colliding is used so is most important.
/// </summary>
[DataField(required: true)]
public List<string> Fixtures = new();
/// <summary>
/// Actively colliding fixtures.
/// </summary>
[DataField]
public HashSet<string> Active = new();
}
[Serializable, NetSerializable]
public enum CollidingVisuals : byte
{
Layer,
Fixture
}

View File

@ -0,0 +1,64 @@
using Content.Shared.Whitelist;
using Robust.Shared.Physics.Events;
namespace Content.Shared._DV.Physics;
public sealed class CollidingVisualsSystem : EntitySystem
{
[Dependency] private readonly EntityWhitelistSystem _whitelist = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<CollidingVisualsComponent, StartCollideEvent>(OnStartCollide);
SubscribeLocalEvent<CollidingVisualsComponent, EndCollideEvent>(OnEndCollide);
}
private void OnStartCollide(Entity<CollidingVisualsComponent> ent, ref StartCollideEvent args)
{
if (_whitelist.IsWhitelistFail(ent.Comp.Whitelist, args.OtherEntity))
return;
// update active fixtures and state
var state = ent.Comp.Default;
foreach (var id in ent.Comp.Fixtures)
{
if (args.OurFixtureId == id)
{
ent.Comp.Active.Add(id);
state = id;
break;
}
}
SetState(ent, state);
}
private void OnEndCollide(Entity<CollidingVisualsComponent> ent, ref EndCollideEvent args)
{
if (_whitelist.IsWhitelistFail(ent.Comp.Whitelist, args.OtherEntity))
return;
ent.Comp.Active.Remove(args.OurFixtureId);
// find the first state that is still active
var state = ent.Comp.Default;
foreach (var id in ent.Comp.Fixtures)
{
if (ent.Comp.Active.Contains(id))
{
state = id;
break;
}
}
SetState(ent, state);
}
public void SetState(EntityUid uid, string state)
{
_appearance.SetData(uid, CollidingVisuals.Fixture, state);
}
}

View File

@ -0,0 +1,9 @@
using Robust.Shared.GameStates;
namespace Content.Shared._DV.Whitelist;
/// <summary>
/// Component added to AI eye entity that lets it get detected by the syndicate ai detector.
/// </summary>
[RegisterComponent, NetworkedComponent]
public sealed partial class AiDetectableComponent : Component;

View File

@ -0,0 +1,4 @@
uplink-observation-kit-desc-deltav = Includes a syndicate crew monitor, high-capacity power cell and security hud disguised as sunglasses.
uplink-ai-detector-name = AI Detector
uplink-ai-detector-desc = This multitool has a custom display that changes color depending on how close the AI's camera is to you. Use it to stay clear of snooping eyes!

View File

@ -210,7 +210,7 @@ uplink-micro-bomb-implanter-desc = Explode on death or manual activation with th
# Bundles
uplink-observation-kit-name = Observation Kit
uplink-observation-kit-desc = Includes syndicate crew monitor, high power cell and security hud disguised as sunglasses.
uplink-observation-kit-desc = Includes surveillance camera monitor board and security hud disguised as sunglasses.
uplink-emp-kit-name = Electrical Disruptor Kit
uplink-emp-kit-desc = The ultimate reversal on energy-based weaponry: Disables disablers, stuns stunbatons, discharges laser guns! Contains 3 EMP grenades and an EMP implanter. Note: Does not disrupt actual firearms.

View File

@ -478,6 +478,7 @@
- state: ai_camera
shader: unshaded
map: ["base"]
- type: AiDetectable # DeltaV - AI detector
# The holographic representation of the AI that is projected from a holopad.
- type: entity

View File

@ -0,0 +1,29 @@
- type: listing
id: Observationkit
name: uplink-observation-kit-name
description: uplink-observation-kit-desc-deltav
icon:
sprite: Objects/Storage/boxicons.rsi
state: tracks
productEntity: Observationskit
discountCategory: usualDiscounts
discountDownTo:
Telecrystal: 3
cost:
Telecrystal: 6
categories:
- UplinkDeception
- type: listing
id: MultitoolAiDetector
name: uplink-ai-detector-name
description: uplink-ai-detector-desc
icon:
sprite: Objects/Tools/multitool.rsi
state: icon
productEntity: MultitoolAiDetector
cost:
Telecrystal: 1
categories:
- UplinkDeception

View File

@ -77,20 +77,6 @@
components:
- SurplusBundle
- type: listing
id: Observationkit
name: uplink-observation-kit-name
description: uplink-observation-kit-desc
icon: { sprite: /Textures/Objects/Storage/boxicons.rsi, state: tracks }
productEntity: Observationskit
discountCategory: usualDiscounts
discountDownTo:
Telecrystal: 3
cost:
Telecrystal: 6 # DeltaV - Price Goes up, but the goods are better!
categories:
- UplinkDeception
- type: listing
id: UplinkSyndicateRadioImplanter
name: uplink-syndicate-radio-implanter-name

View File

@ -0,0 +1,57 @@
- type: entity
parent: Multitool
id: MultitoolAiDetector
suffix: AI Detector
components:
- type: Sprite
layers:
- state: icon
- state: green-unlit
shader: unshaded
map: [ enum.CollidingVisuals.Layer ]
- type: Physics
canCollide: true
- type: Fixtures
fixtures:
fix1:
shape: !type:PhysShapeAabb
bounds: "-0.25,-0.25,0.25,0.25"
density: 20
mask:
- ItemMask
restitution: 0.3 # fite me
friction: 0.2
yellow:
shape: !type:PhysShapeCircle
radius: 12
density: 0
hard: false
mask:
- GhostImpassable
red:
shape: !type:PhysShapeCircle
radius: 5
density: 0
hard: false
mask:
- GhostImpassable
- type: CollisionWake # don't stop checking for AI just because this isn't moving
enabled: false
- type: Appearance
- type: GenericVisualizer
visuals:
enum.CollidingVisuals.Fixture:
enum.CollidingVisuals.Layer:
none: { state: "green-unlit" }
yellow: { state: "yellow-unlit" }
red: { state: "red-unlit" }
- type: CollidingVisuals
whitelist:
components:
- AiDetectable
fixtures:
- red
- yellow
- type: MappingCategories # don't map valid multitool by mistake
categories:
- Syndicate