scram implant (#23122)
* implement * fix charges * add listing * fixes * fix locale, probably all done * fix * fix of fix * move query init * cleanup * unbrokey rt
This commit is contained in:
26
Content.Server/Implants/Components/ScramImplantComponent.cs
Normal file
26
Content.Server/Implants/Components/ScramImplantComponent.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using Content.Server.Implants;
|
||||
using Robust.Shared.Audio;
|
||||
|
||||
namespace Content.Server.Implants.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Randomly teleports entity when triggered.
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public sealed partial class ScramImplantComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// Up to how far to teleport the user
|
||||
/// </summary>
|
||||
[DataField, ViewVariables(VVAccess.ReadWrite)]
|
||||
public float TeleportRadius = 100f;
|
||||
|
||||
/// <summary>
|
||||
/// How many times to check for a valid tile to teleport to
|
||||
/// </summary>
|
||||
[DataField, ViewVariables(VVAccess.ReadOnly)]
|
||||
public int TeleportAttempts = 20;
|
||||
|
||||
[DataField, ViewVariables(VVAccess.ReadWrite)]
|
||||
public SoundSpecifier TeleportSound = new SoundPathSpecifier("/Audio/Effects/teleport_arrival.ogg");
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using Content.Server.Cuffs;
|
||||
using Content.Server.Forensics;
|
||||
using Content.Server.Humanoid;
|
||||
using Content.Server.Implants.Components;
|
||||
using Content.Server.Store.Components;
|
||||
using Content.Server.Store.Systems;
|
||||
using Content.Shared.Cuffs.Components;
|
||||
@@ -8,8 +9,16 @@ using Content.Shared.Humanoid;
|
||||
using Content.Shared.Implants;
|
||||
using Content.Shared.Implants.Components;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Physics;
|
||||
using Content.Shared.Popups;
|
||||
using Content.Shared.Preferences;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.Physics.Components;
|
||||
using Robust.Shared.Random;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Content.Server.Implants;
|
||||
|
||||
@@ -17,18 +26,27 @@ public sealed class SubdermalImplantSystem : SharedSubdermalImplantSystem
|
||||
{
|
||||
[Dependency] private readonly CuffableSystem _cuffable = default!;
|
||||
[Dependency] private readonly HumanoidAppearanceSystem _humanoidAppearance = default!;
|
||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
[Dependency] private readonly MetaDataSystem _metaData = default!;
|
||||
[Dependency] private readonly StoreSystem _store = default!;
|
||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||
[Dependency] private readonly SharedPopupSystem _popup = default!;
|
||||
[Dependency] private readonly SharedTransformSystem _xform = default!;
|
||||
[Dependency] private readonly ForensicsSystem _forensicsSystem = default!;
|
||||
|
||||
private EntityQuery<PhysicsComponent> _physicsQuery;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
_physicsQuery = GetEntityQuery<PhysicsComponent>();
|
||||
|
||||
SubscribeLocalEvent<SubdermalImplantComponent, UseFreedomImplantEvent>(OnFreedomImplant);
|
||||
SubscribeLocalEvent<StoreComponent, ImplantRelayEvent<AfterInteractUsingEvent>>(OnStoreRelay);
|
||||
SubscribeLocalEvent<SubdermalImplantComponent, ActivateImplantEvent>(OnActivateImplantEvent);
|
||||
SubscribeLocalEvent<SubdermalImplantComponent, UseScramImplantEvent>(OnScramImplant);
|
||||
SubscribeLocalEvent<SubdermalImplantComponent, UseDnaScramblerImplantEvent>(OnDnaScramblerImplant);
|
||||
|
||||
}
|
||||
@@ -72,6 +90,52 @@ public sealed class SubdermalImplantSystem : SharedSubdermalImplantSystem
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
private void OnScramImplant(EntityUid uid, SubdermalImplantComponent component, UseScramImplantEvent args)
|
||||
{
|
||||
if (component.ImplantedEntity is not { } ent)
|
||||
return;
|
||||
|
||||
if (!TryComp<ScramImplantComponent>(uid, out var implant))
|
||||
return;
|
||||
|
||||
var xform = Transform(ent);
|
||||
var entityCoords = xform.Coordinates.ToMap(EntityManager);
|
||||
|
||||
// try to find a valid position to teleport to, teleport to whatever works if we can't
|
||||
var targetCoords = new MapCoordinates();
|
||||
for (var i = 0; i < implant.TeleportAttempts; i++)
|
||||
{
|
||||
var distance = implant.TeleportRadius * MathF.Sqrt(_random.NextFloat()); // to get an uniform distribution
|
||||
targetCoords = entityCoords.Offset(_random.NextAngle().ToVec() * distance);
|
||||
|
||||
// prefer teleporting to grids
|
||||
if (!_mapManager.TryFindGridAt(targetCoords, out var gridUid, out var grid))
|
||||
continue;
|
||||
|
||||
// the implant user probably does not want to be in your walls
|
||||
var valid = true;
|
||||
foreach (var entity in grid.GetAnchoredEntities(targetCoords))
|
||||
{
|
||||
if (!_physicsQuery.TryGetComponent(entity, out var body))
|
||||
continue;
|
||||
|
||||
if (body.BodyType != BodyType.Static ||
|
||||
!body.Hard ||
|
||||
(body.CollisionLayer & (int) CollisionGroup.Impassable) == 0)
|
||||
continue;
|
||||
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
if (valid)
|
||||
break;
|
||||
}
|
||||
_xform.SetWorldPosition(ent, targetCoords.Position);
|
||||
_audio.PlayPvs(implant.TeleportSound, ent);
|
||||
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
private void OnDnaScramblerImplant(EntityUid uid, SubdermalImplantComponent component, UseDnaScramblerImplantEvent args)
|
||||
{
|
||||
if (component.ImplantedEntity is not { } ent)
|
||||
|
||||
Reference in New Issue
Block a user