Fix and improve bluespace lockers (#13139)
* add invulnerable plastitanium wall prototype * fix command ClearBluespaceLockerLinks.cs * fix and improve BluespaceLockerSystem.cs * fix normal plastitanium wall suffix * fix capitalization * fix capability to create one way lockers
This commit is contained in:
@@ -27,7 +27,7 @@ public sealed class ClearBluespaceLockerLinks : IConsoleCommand
|
|||||||
|
|
||||||
var entityManager = IoCManager.Resolve<IEntityManager>();
|
var entityManager = IoCManager.Resolve<IEntityManager>();
|
||||||
|
|
||||||
if (entityManager.TryGetComponent<EntityStorageComponent>(entityUid, out var originComponent))
|
if (entityManager.TryGetComponent<BluespaceLockerComponent>(entityUid, out var originComponent))
|
||||||
entityManager.RemoveComponent(entityUid, originComponent);
|
entityManager.RemoveComponent(entityUid, originComponent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,10 +53,16 @@ public sealed class LinkBluespaceLocker : IConsoleCommand
|
|||||||
|
|
||||||
entityManager.EnsureComponent<BluespaceLockerComponent>(originUid, out var originBluespaceComponent);
|
entityManager.EnsureComponent<BluespaceLockerComponent>(originUid, out var originBluespaceComponent);
|
||||||
originBluespaceComponent.BluespaceLinks.Add(targetComponent);
|
originBluespaceComponent.BluespaceLinks.Add(targetComponent);
|
||||||
|
entityManager.EnsureComponent<BluespaceLockerComponent>(targetUid, out var targetBluespaceComponent);
|
||||||
if (bidirectional)
|
if (bidirectional)
|
||||||
{
|
{
|
||||||
entityManager.EnsureComponent<BluespaceLockerComponent>(targetUid, out var targetBluespaceComponent);
|
|
||||||
targetBluespaceComponent.BluespaceLinks.Add(originComponent);
|
targetBluespaceComponent.BluespaceLinks.Add(originComponent);
|
||||||
}
|
}
|
||||||
|
else if (targetBluespaceComponent.BluespaceLinks.Count == 0)
|
||||||
|
{
|
||||||
|
targetBluespaceComponent.AllowSentient = false;
|
||||||
|
targetBluespaceComponent.TransportEntities = false;
|
||||||
|
targetBluespaceComponent.TransportGas = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,4 +27,35 @@ public sealed class BluespaceLockerComponent : Component
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("bluespaceLinks"), ViewVariables(VVAccess.ReadOnly)]
|
[DataField("bluespaceLinks"), ViewVariables(VVAccess.ReadOnly)]
|
||||||
public HashSet<EntityStorageComponent> BluespaceLinks = new();
|
public HashSet<EntityStorageComponent> BluespaceLinks = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Each time the system attempts to get a link, it will link additional lockers to ensure the minimum amount
|
||||||
|
/// are linked.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("minBluespaceLinks"), ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public uint MinBluespaceLinks;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines if links automatically added are restricted to the same map
|
||||||
|
/// </summary>
|
||||||
|
[DataField("pickLinksFromSameMap"), ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public bool PickLinksFromSameMap;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines if links automatically added must have ResistLockerComponent
|
||||||
|
/// </summary>
|
||||||
|
[DataField("pickLinksFromResistLockers"), ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public bool PickLinksFromResistLockers = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines if links automatically added are restricted to being on a station
|
||||||
|
/// </summary>
|
||||||
|
[DataField("pickLinksFromStationGrids"), ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public bool PickLinksFromStationGrids = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines if links automatically added are bidirectional
|
||||||
|
/// </summary>
|
||||||
|
[DataField("autoLinksBidirectional"), ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public bool AutoLinksBidirectional;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,19 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Server.Lock;
|
using Content.Server.Lock;
|
||||||
using Content.Server.Mind.Components;
|
using Content.Server.Mind.Components;
|
||||||
|
using Content.Server.Resist;
|
||||||
|
using Content.Server.Station.Components;
|
||||||
using Content.Server.Storage.Components;
|
using Content.Server.Storage.Components;
|
||||||
using Content.Server.Tools.Systems;
|
using Content.Server.Tools.Systems;
|
||||||
using Microsoft.Extensions.DependencyModel;
|
using Content.Shared.Coordinates;
|
||||||
|
using Robust.Shared.Random;
|
||||||
|
|
||||||
namespace Content.Server.Storage.EntitySystems;
|
namespace Content.Server.Storage.EntitySystems;
|
||||||
|
|
||||||
public sealed class BluespaceLockerSystem : EntitySystem
|
public sealed class BluespaceLockerSystem : EntitySystem
|
||||||
{
|
{
|
||||||
|
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||||
|
[Dependency] private readonly IRobustRandom _robustRandom = default!;
|
||||||
[Dependency] private readonly EntityStorageSystem _entityStorage = default!;
|
[Dependency] private readonly EntityStorageSystem _entityStorage = default!;
|
||||||
[Dependency] private readonly WeldableSystem _weldableSystem = default!;
|
[Dependency] private readonly WeldableSystem _weldableSystem = default!;
|
||||||
[Dependency] private readonly LockSystem _lockSystem = default!;
|
[Dependency] private readonly LockSystem _lockSystem = default!;
|
||||||
@@ -17,23 +22,27 @@ public sealed class BluespaceLockerSystem : EntitySystem
|
|||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
|
|
||||||
|
SubscribeLocalEvent<BluespaceLockerComponent, ComponentStartup>(OnStartup);
|
||||||
SubscribeLocalEvent<BluespaceLockerComponent, StorageBeforeOpenEvent>(PreOpen);
|
SubscribeLocalEvent<BluespaceLockerComponent, StorageBeforeOpenEvent>(PreOpen);
|
||||||
SubscribeLocalEvent<BluespaceLockerComponent, StorageAfterCloseEvent>(PostClose);
|
SubscribeLocalEvent<BluespaceLockerComponent, StorageAfterCloseEvent>(PostClose);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnStartup(EntityUid uid, BluespaceLockerComponent component, ComponentStartup args)
|
||||||
|
{
|
||||||
|
GetTargetStorage(component);
|
||||||
|
}
|
||||||
|
|
||||||
private void PreOpen(EntityUid uid, BluespaceLockerComponent component, StorageBeforeOpenEvent args)
|
private void PreOpen(EntityUid uid, BluespaceLockerComponent component, StorageBeforeOpenEvent args)
|
||||||
{
|
{
|
||||||
EntityStorageComponent? entityStorageComponent = null;
|
EntityStorageComponent? entityStorageComponent = null;
|
||||||
|
|
||||||
if (component.BluespaceLinks is not { Count: > 0 })
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!Resolve(uid, ref entityStorageComponent))
|
if (!Resolve(uid, ref entityStorageComponent))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Select target
|
// Select target
|
||||||
var targetContainerStorageComponent = component.BluespaceLinks.ToArray()[new Random().Next(0, component.BluespaceLinks.Count)];
|
var targetContainerStorageComponent = GetTargetStorage(component);
|
||||||
|
if (targetContainerStorageComponent == null)
|
||||||
|
return;
|
||||||
BluespaceLockerComponent? targetContainerBluespaceComponent = null;
|
BluespaceLockerComponent? targetContainerBluespaceComponent = null;
|
||||||
|
|
||||||
// Close target if it is open
|
// Close target if it is open
|
||||||
@@ -41,8 +50,7 @@ public sealed class BluespaceLockerSystem : EntitySystem
|
|||||||
_entityStorage.CloseStorage(targetContainerStorageComponent.Owner, targetContainerStorageComponent);
|
_entityStorage.CloseStorage(targetContainerStorageComponent.Owner, targetContainerStorageComponent);
|
||||||
|
|
||||||
// Apply bluespace effects if target is not a bluespace locker, otherwise let it handle it
|
// Apply bluespace effects if target is not a bluespace locker, otherwise let it handle it
|
||||||
if (!Resolve(targetContainerStorageComponent.Owner, ref targetContainerBluespaceComponent, false) ||
|
if (!Resolve(targetContainerStorageComponent.Owner, ref targetContainerBluespaceComponent, false))
|
||||||
targetContainerBluespaceComponent.BluespaceLinks is not { Count: > 0 })
|
|
||||||
{
|
{
|
||||||
// Move contained items
|
// Move contained items
|
||||||
if (component.TransportEntities)
|
if (component.TransportEntities)
|
||||||
@@ -62,18 +70,84 @@ public sealed class BluespaceLockerSystem : EntitySystem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool ValidLink(BluespaceLockerComponent component, EntityStorageComponent link)
|
||||||
|
{
|
||||||
|
return link.Owner.Valid && link.LifeStage != ComponentLifeStage.Deleted;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool ValidAutolink(BluespaceLockerComponent component, EntityStorageComponent link)
|
||||||
|
{
|
||||||
|
if (!ValidLink(component, link))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (component.PickLinksFromSameMap &&
|
||||||
|
link.Owner.ToCoordinates().GetMapId(_entityManager) == component.Owner.ToCoordinates().GetMapId(_entityManager))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (component.PickLinksFromStationGrids &&
|
||||||
|
!_entityManager.HasComponent<StationMemberComponent>(link.Owner.ToCoordinates().GetGridUid(_entityManager)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (component.PickLinksFromResistLockers &&
|
||||||
|
!_entityManager.HasComponent<ResistLockerComponent>(link.Owner))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private EntityStorageComponent? GetTargetStorage(BluespaceLockerComponent component)
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
// Ensure MinBluespaceLinks
|
||||||
|
if (component.BluespaceLinks.Count < component.MinBluespaceLinks)
|
||||||
|
{
|
||||||
|
// Get an shuffle the list of all EntityStorages
|
||||||
|
var storages = _entityManager.EntityQuery<EntityStorageComponent>().ToArray();
|
||||||
|
_robustRandom.Shuffle(storages);
|
||||||
|
|
||||||
|
// Add valid candidates till MinBluespaceLinks is met
|
||||||
|
foreach (var storage in storages)
|
||||||
|
{
|
||||||
|
if (!ValidAutolink(component, storage))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
component.BluespaceLinks.Add(storage);
|
||||||
|
if (component.AutoLinksBidirectional)
|
||||||
|
{
|
||||||
|
_entityManager.EnsureComponent<BluespaceLockerComponent>(storage.Owner, out var targetBluespaceComponent);
|
||||||
|
targetBluespaceComponent.BluespaceLinks.Add(_entityManager.GetComponent<EntityStorageComponent>(component.Owner));
|
||||||
|
}
|
||||||
|
if (component.BluespaceLinks.Count >= component.MinBluespaceLinks)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there are no possible link targets and no links, return null
|
||||||
|
if (component.BluespaceLinks.Count == 0)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// Attempt to select, validate, and return a link
|
||||||
|
var links = component.BluespaceLinks.ToArray();
|
||||||
|
var link = links[_robustRandom.Next(0, component.BluespaceLinks.Count)];
|
||||||
|
if (ValidLink(component, link))
|
||||||
|
return link;
|
||||||
|
component.BluespaceLinks.Remove(link);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void PostClose(EntityUid uid, BluespaceLockerComponent component, StorageAfterCloseEvent args)
|
private void PostClose(EntityUid uid, BluespaceLockerComponent component, StorageAfterCloseEvent args)
|
||||||
{
|
{
|
||||||
EntityStorageComponent? entityStorageComponent = null;
|
EntityStorageComponent? entityStorageComponent = null;
|
||||||
|
|
||||||
if (component.BluespaceLinks is not { Count: > 0 })
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!Resolve(uid, ref entityStorageComponent))
|
if (!Resolve(uid, ref entityStorageComponent))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Select target
|
// Select target
|
||||||
var targetContainerStorageComponent = component.BluespaceLinks.ToArray()[new Random().Next(0, component.BluespaceLinks.Count)];
|
var targetContainerStorageComponent = GetTargetStorage(component);
|
||||||
|
if (targetContainerStorageComponent == null)
|
||||||
|
return;
|
||||||
|
|
||||||
// Move contained items
|
// Move contained items
|
||||||
if (component.TransportEntities)
|
if (component.TransportEntities)
|
||||||
|
|||||||
@@ -388,17 +388,31 @@
|
|||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: BaseWall
|
parent: BaseWall
|
||||||
|
id: WallPlastitaniumIndestructible
|
||||||
|
name: plastitanium wall
|
||||||
|
suffix: indestructible
|
||||||
|
components:
|
||||||
|
- type: Tag
|
||||||
|
tags:
|
||||||
|
- Wall
|
||||||
|
- type: Sprite
|
||||||
|
sprite: Structures/Walls/plastitanium.rsi
|
||||||
|
- type: Icon
|
||||||
|
sprite: Structures/Walls/plastitanium.rsi
|
||||||
|
- type: IconSmooth
|
||||||
|
key: walls
|
||||||
|
base: plastitanium
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
parent: WallPlastitaniumIndestructible
|
||||||
id: WallPlastitanium
|
id: WallPlastitanium
|
||||||
name: plastitanium wall
|
name: plastitanium wall
|
||||||
|
suffix: ""
|
||||||
components:
|
components:
|
||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- Wall
|
- Wall
|
||||||
- RCDDeconstructWhitelist
|
- RCDDeconstructWhitelist
|
||||||
- type: Sprite
|
|
||||||
sprite: Structures/Walls/plastitanium.rsi
|
|
||||||
- type: Icon
|
|
||||||
sprite: Structures/Walls/plastitanium.rsi
|
|
||||||
- type: Destructible
|
- type: Destructible
|
||||||
thresholds:
|
thresholds:
|
||||||
- trigger:
|
- trigger:
|
||||||
@@ -412,9 +426,6 @@
|
|||||||
max: 1
|
max: 1
|
||||||
- !type:DoActsBehavior
|
- !type:DoActsBehavior
|
||||||
acts: [ "Destruction" ]
|
acts: [ "Destruction" ]
|
||||||
- type: IconSmooth
|
|
||||||
key: walls
|
|
||||||
base: plastitanium
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: BaseWall
|
parent: BaseWall
|
||||||
|
|||||||
Reference in New Issue
Block a user