More borg tweaks (#19143)
* borg tweaks but i'm gonna go code fun stuff first * werkin' on it * a ton of tweaks * fuck everyone and then myself
This commit is contained in:
@@ -10,17 +10,27 @@ namespace Content.Shared.Access.Components
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
[Access(typeof(SharedAccessSystem))]
|
||||
public sealed class AccessComponent : Component
|
||||
[AutoGenerateComponentState]
|
||||
public sealed partial class AccessComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// True if the access provider is enabled and can grant access.
|
||||
/// </summary>
|
||||
[DataField("enabled"), ViewVariables(VVAccess.ReadWrite)]
|
||||
[AutoNetworkedField]
|
||||
public bool Enabled = true;
|
||||
|
||||
[DataField("tags", customTypeSerializer: typeof(PrototypeIdHashSetSerializer<AccessLevelPrototype>))]
|
||||
[Access(typeof(SharedAccessSystem), Other = AccessPermissions.ReadExecute)] // FIXME Friends
|
||||
[AutoNetworkedField(true)]
|
||||
public HashSet<string> Tags = new();
|
||||
|
||||
/// <summary>
|
||||
/// Access Groups. These are added to the tags during map init. After map init this will have no effect.
|
||||
/// </summary>
|
||||
[DataField("groups", readOnly: true, customTypeSerializer: typeof(PrototypeIdHashSetSerializer<AccessGroupPrototype>))]
|
||||
public readonly HashSet<string> Groups = new();
|
||||
[AutoNetworkedField(true)]
|
||||
public HashSet<string> Groups = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -8,9 +8,9 @@ using Content.Shared.PDA;
|
||||
using Content.Shared.StationRecords;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.GameStates;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using Robust.Shared.Collections;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared.Access.Systems;
|
||||
@@ -69,6 +69,8 @@ public sealed class AccessReaderSystem : EntitySystem
|
||||
/// required entity.
|
||||
/// </summary>
|
||||
/// <param name="target">The entity to search for a container</param>
|
||||
/// <param name="accessReader"></param>
|
||||
/// <param name="result"></param>
|
||||
private bool FindAccessReadersInContainer(EntityUid target, AccessReaderComponent accessReader, out List<AccessReaderComponent> result)
|
||||
{
|
||||
result = new();
|
||||
@@ -171,6 +173,11 @@ public sealed class AccessReaderSystem : EntitySystem
|
||||
{
|
||||
FindAccessItemsInventory(uid, out var items);
|
||||
|
||||
foreach (var item in new ValueList<EntityUid>(items))
|
||||
{
|
||||
items.UnionWith(FindPotentialAccessItems(item));
|
||||
}
|
||||
|
||||
var ev = new GetAdditionalAccessEvent
|
||||
{
|
||||
Entities = items
|
||||
@@ -204,6 +211,7 @@ public sealed class AccessReaderSystem : EntitySystem
|
||||
/// Finds the access tags on the given entity
|
||||
/// </summary>
|
||||
/// <param name="uid">The entity that is being searched.</param>
|
||||
/// <param name="recordKeys"></param>
|
||||
/// <param name="items">All of the items to search for access. If none are passed in, <see cref="FindPotentialAccessItems"/> will be used.</param>
|
||||
public bool FindStationRecordKeys(EntityUid uid, out ICollection<StationRecordKey> recordKeys, HashSet<EntityUid>? items = null)
|
||||
{
|
||||
@@ -277,17 +285,6 @@ public sealed class AccessReaderSystem : EntitySystem
|
||||
private bool FindAccessTagsItem(EntityUid uid, out HashSet<string> tags)
|
||||
{
|
||||
tags = new();
|
||||
if (TryComp(uid, out AccessComponent? access))
|
||||
{
|
||||
tags.UnionWith(access.Tags);
|
||||
}
|
||||
|
||||
if (TryComp(uid, out PdaComponent? pda) &&
|
||||
pda.ContainedId is { Valid: true } id)
|
||||
{
|
||||
tags.UnionWith(EntityManager.GetComponent<AccessComponent>(id).Tags);
|
||||
}
|
||||
|
||||
var ev = new GetAccessTagsEvent(tags, _prototype);
|
||||
RaiseLocalEvent(uid, ref ev);
|
||||
|
||||
|
||||
@@ -15,28 +15,7 @@ namespace Content.Shared.Access.Systems
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<AccessComponent, MapInitEvent>(OnAccessInit);
|
||||
SubscribeLocalEvent<AccessComponent, ComponentGetState>(OnAccessGetState);
|
||||
SubscribeLocalEvent<AccessComponent, ComponentHandleState>(OnAccessHandleState);
|
||||
}
|
||||
|
||||
private void OnAccessHandleState(EntityUid uid, AccessComponent component, ref ComponentHandleState args)
|
||||
{
|
||||
if (args.Current is not AccessComponentState state) return;
|
||||
|
||||
// Don't do = because prediction and refs
|
||||
component.Tags.Clear();
|
||||
component.Groups.Clear();
|
||||
component.Tags.UnionWith(state.Tags);
|
||||
component.Groups.UnionWith(state.Groups);
|
||||
}
|
||||
|
||||
private void OnAccessGetState(EntityUid uid, AccessComponent component, ref ComponentGetState args)
|
||||
{
|
||||
args.State = new AccessComponentState()
|
||||
{
|
||||
Tags = component.Tags,
|
||||
Groups = component.Groups,
|
||||
};
|
||||
SubscribeLocalEvent<AccessComponent, GetAccessTagsEvent>(OnGetAccessTags);
|
||||
}
|
||||
|
||||
private void OnAccessInit(EntityUid uid, AccessComponent component, MapInitEvent args)
|
||||
@@ -52,6 +31,22 @@ namespace Content.Shared.Access.Systems
|
||||
}
|
||||
}
|
||||
|
||||
private void OnGetAccessTags(EntityUid uid, AccessComponent component, ref GetAccessTagsEvent args)
|
||||
{
|
||||
if (!component.Enabled)
|
||||
return;
|
||||
|
||||
args.Tags.UnionWith(component.Tags);
|
||||
}
|
||||
|
||||
public void SetAccessEnabled(EntityUid uid, bool val, AccessComponent? component = null)
|
||||
{
|
||||
if (!Resolve(uid, ref component, false))
|
||||
return;
|
||||
component.Enabled = val;
|
||||
Dirty(uid, component);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Replaces the set of access tags we have with the provided set.
|
||||
/// </summary>
|
||||
@@ -122,12 +117,5 @@ namespace Content.Shared.Access.Systems
|
||||
TryAddGroups(uid, prototype.ExtendedAccessGroups, access);
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
private sealed class AccessComponentState : ComponentState
|
||||
{
|
||||
public HashSet<string> Tags = new();
|
||||
public HashSet<string> Groups = new();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,10 @@ using Content.Shared.Movement.Events;
|
||||
|
||||
namespace Content.Shared.Interaction;
|
||||
|
||||
/// <summary>
|
||||
/// Handles <see cref="BlockMovementComponent"/>, which prevents various
|
||||
/// kinds of movement and interactions when attached to an entity.
|
||||
/// </summary>
|
||||
public partial class SharedInteractionSystem
|
||||
{
|
||||
public void InitializeBlocking()
|
||||
|
||||
@@ -3,6 +3,9 @@ using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototy
|
||||
|
||||
namespace Content.Shared.NameIdentifier;
|
||||
|
||||
/// <summary>
|
||||
/// Generates a unique numeric identifier for entities, with specifics controlled by a <see cref="NameIdentifierGroupPrototype"/>.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
|
||||
public sealed partial class NameIdentifierComponent : Component
|
||||
{
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace Content.Shared.PAI
|
||||
/// The last person who activated this PAI.
|
||||
/// Used for assigning the name.
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
[DataField("lastUSer"), ViewVariables(VVAccess.ReadWrite)]
|
||||
public EntityUid? LastUser;
|
||||
|
||||
[DataField("midiAction", required: true, serverOnly: true)] // server only, as it uses a server-BUI event !type
|
||||
|
||||
@@ -18,8 +18,9 @@ namespace Content.Shared.PDA
|
||||
|
||||
SubscribeLocalEvent<PdaComponent, EntInsertedIntoContainerMessage>(OnItemInserted);
|
||||
SubscribeLocalEvent<PdaComponent, EntRemovedFromContainerMessage>(OnItemRemoved);
|
||||
}
|
||||
|
||||
SubscribeLocalEvent<PdaComponent, GetAdditionalAccessEvent>(OnGetAdditionalAccess);
|
||||
}
|
||||
protected virtual void OnComponentInit(EntityUid uid, PdaComponent pda, ComponentInit args)
|
||||
{
|
||||
if (pda.IdCard != null)
|
||||
@@ -53,6 +54,12 @@ namespace Content.Shared.PDA
|
||||
UpdatePdaAppearance(uid, pda);
|
||||
}
|
||||
|
||||
private void OnGetAdditionalAccess(EntityUid uid, PdaComponent component, ref GetAdditionalAccessEvent args)
|
||||
{
|
||||
if (component.ContainedId is { } id)
|
||||
args.Entities.Add(id);
|
||||
}
|
||||
|
||||
private void UpdatePdaAppearance(EntityUid uid, PdaComponent pda)
|
||||
{
|
||||
Appearance.SetData(uid, PdaVisuals.IdCardInserted, pda.ContainedId != null);
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
using Content.Shared.Roles;
|
||||
using Content.Shared.Whitelist;
|
||||
using Content.Shared.Whitelist;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
|
||||
|
||||
namespace Content.Shared.Silicons.Borgs.Components;
|
||||
|
||||
@@ -17,12 +13,6 @@ namespace Content.Shared.Silicons.Borgs.Components;
|
||||
[RegisterComponent, NetworkedComponent, Access(typeof(SharedBorgSystem)), AutoGenerateComponentState]
|
||||
public sealed partial class BorgChassisComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// Whether or not the borg currently has a player occupying it
|
||||
/// </summary>
|
||||
[DataField("hasPlayer")]
|
||||
public bool HasPlayer;
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not the borg is activated, meaning it has access to modules and a heightened movement speed
|
||||
/// </summary>
|
||||
@@ -43,15 +33,9 @@ public sealed partial class BorgChassisComponent : Component
|
||||
public string BrainContainerId = "borg_brain";
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public ContainerSlot BrainContainer = default!;
|
||||
public ContainerSlot BrainContainer = new();
|
||||
|
||||
public EntityUid? BrainEntity => BrainContainer.ContainedEntity;
|
||||
|
||||
/// <summary>
|
||||
/// A brain entity that fills the <see cref="BrainContainer"/> on roundstart
|
||||
/// </summary>
|
||||
[DataField("startingBrain", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
public string? StartingBrain;
|
||||
#endregion
|
||||
|
||||
#region Modules
|
||||
@@ -77,33 +61,14 @@ public sealed partial class BorgChassisComponent : Component
|
||||
public Container ModuleContainer = default!;
|
||||
|
||||
public int ModuleCount => ModuleContainer.ContainedEntities.Count;
|
||||
|
||||
/// <summary>
|
||||
/// A list of modules that fill the borg on round start.
|
||||
/// </summary>
|
||||
[DataField("startingModules", customTypeSerializer: typeof(PrototypeIdListSerializer<EntityPrototype>))]
|
||||
public List<string> StartingModules = new();
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// The job that corresponds to borgs
|
||||
/// </summary>
|
||||
[DataField("borgJobId", customTypeSerializer: typeof(PrototypeIdSerializer<JobPrototype>))]
|
||||
public string BorgJobId = "Borg";
|
||||
|
||||
/// <summary>
|
||||
/// The currently selected module
|
||||
/// </summary>
|
||||
[DataField("selectedModule")]
|
||||
public EntityUid? SelectedModule;
|
||||
|
||||
/// <summary>
|
||||
/// The access this cyborg has when a player is inhabiting it.
|
||||
/// </summary>
|
||||
[DataField("access"), ViewVariables(VVAccess.ReadWrite)]
|
||||
[AutoNetworkedField]
|
||||
public string AccessGroup = "AllAccess";
|
||||
|
||||
#region Visuals
|
||||
[DataField("hasMindState")]
|
||||
public string HasMindState = string.Empty;
|
||||
|
||||
@@ -24,12 +24,21 @@ public sealed class MMIComponent : Component
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public ItemSlot BrainSlot = default!;
|
||||
|
||||
/// <summary>
|
||||
/// The sprite state when the brain inserted has a mind.
|
||||
/// </summary>
|
||||
[DataField("hasMindState")]
|
||||
public string HasMindState = "mmi_alive";
|
||||
|
||||
/// <summary>
|
||||
/// The sprite state when the brain inserted doesn't have a mind.
|
||||
/// </summary>
|
||||
[DataField("noMindState")]
|
||||
public string NoMindState = "mmi_dead";
|
||||
|
||||
/// <summary>
|
||||
/// The sprite state when there is no brain inserted.
|
||||
/// </summary>
|
||||
[DataField("noBrainState")]
|
||||
public string NoBrainState = "mmi_off";
|
||||
}
|
||||
|
||||
@@ -7,11 +7,12 @@ namespace Content.Shared.Silicons.Borgs.Components;
|
||||
/// Mostly for receiving events.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent, Access(typeof(SharedBorgSystem))]
|
||||
public sealed class MMILinkedComponent : Component
|
||||
[AutoGenerateComponentState]
|
||||
public sealed partial class MMILinkedComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// The MMI this entity is linked to.
|
||||
/// </summary>
|
||||
[DataField("linkedMMI")]
|
||||
[DataField("linkedMMI"), AutoNetworkedField]
|
||||
public EntityUid? LinkedMMI;
|
||||
}
|
||||
|
||||
@@ -30,7 +30,6 @@ public abstract partial class SharedBorgSystem : EntitySystem
|
||||
SubscribeLocalEvent<BorgChassisComponent, EntInsertedIntoContainerMessage>(OnInserted);
|
||||
SubscribeLocalEvent<BorgChassisComponent, EntRemovedFromContainerMessage>(OnRemoved);
|
||||
SubscribeLocalEvent<BorgChassisComponent, RefreshMovementSpeedModifiersEvent>(OnRefreshMovementSpeedModifiers);
|
||||
SubscribeLocalEvent<BorgChassisComponent, GetAccessTagsEvent>(OnGetAccessTags);
|
||||
|
||||
InitializeRelay();
|
||||
}
|
||||
@@ -69,7 +68,8 @@ public abstract partial class SharedBorgSystem : EntitySystem
|
||||
|
||||
private void OnStartup(EntityUid uid, BorgChassisComponent component, ComponentStartup args)
|
||||
{
|
||||
var containerManager = EnsureComp<ContainerManagerComponent>(uid);
|
||||
if (!TryComp<ContainerManagerComponent>(uid, out var containerManager))
|
||||
return;
|
||||
|
||||
component.BrainContainer = Container.EnsureContainer<ContainerSlot>(uid, component.BrainContainerId, containerManager);
|
||||
component.ModuleContainer = Container.EnsureContainer<Container>(uid, component.ModuleContainerId, containerManager);
|
||||
@@ -96,12 +96,4 @@ public abstract partial class SharedBorgSystem : EntitySystem
|
||||
var sprintDif = movement.BaseWalkSpeed / movement.BaseSprintSpeed;
|
||||
args.ModifySpeed(1f, sprintDif);
|
||||
}
|
||||
|
||||
private void OnGetAccessTags(EntityUid uid, BorgChassisComponent component, ref GetAccessTagsEvent args)
|
||||
{
|
||||
if (!component.HasPlayer)
|
||||
return;
|
||||
args.AddGroup(component.AccessGroup);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,14 +1,31 @@
|
||||
namespace Content.Shared.Silicons.Laws.Components;
|
||||
using Content.Shared.Roles;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
|
||||
namespace Content.Shared.Silicons.Laws.Components;
|
||||
|
||||
/// <summary>
|
||||
/// This is used for an entity that grants a special "obey" law when emagge.d
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
[RegisterComponent, NetworkedComponent, Access(typeof(SharedSiliconLawSystem))]
|
||||
public sealed class EmagSiliconLawComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// The name of the person who emagged this law provider.
|
||||
/// </summary>
|
||||
[DataField("ownerName")]
|
||||
[DataField("ownerName"), ViewVariables(VVAccess.ReadWrite)]
|
||||
public string? OwnerName;
|
||||
|
||||
/// <summary>
|
||||
/// Does the panel need to be open to EMAG this law provider.
|
||||
/// </summary>
|
||||
[DataField("requireOpenPanel"), ViewVariables(VVAccess.ReadWrite)]
|
||||
public bool RequireOpenPanel = true;
|
||||
|
||||
/// <summary>
|
||||
/// A role given to entities with this component when they are emagged.
|
||||
/// Mostly just for admin purposes.
|
||||
/// </summary>
|
||||
[DataField("antagonistRole", customTypeSerializer: typeof(PrototypeIdSerializer<AntagPrototype>))]
|
||||
public string? AntagonistRole = "SubvertedSilicon";
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace Content.Shared.Silicons.Laws.Components;
|
||||
/// <summary>
|
||||
/// This is used for entities which are bound to silicon laws and can view them.
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
[RegisterComponent, Access(typeof(SharedSiliconLawSystem))]
|
||||
public sealed class SiliconLawBoundComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
@@ -30,6 +30,14 @@ public sealed class SiliconLawBoundComponent : Component
|
||||
public EntityUid? LastLawProvider;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event raised to get the laws that a law-bound entity has.
|
||||
///
|
||||
/// Is first raised on the entity itself, then on the
|
||||
/// entity's station, then on the entity's grid,
|
||||
/// before being broadcast.
|
||||
/// </summary>
|
||||
/// <param name="Entity"></param>
|
||||
[ByRefEvent]
|
||||
public record struct GetSiliconLawsEvent(EntityUid Entity)
|
||||
{
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Content.Shared.Silicons.Laws.Components;
|
||||
/// <summary>
|
||||
/// This is used for an entity which grants laws to a <see cref="SiliconLawBoundComponent"/>
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
[RegisterComponent, Access(typeof(SharedSiliconLawSystem))]
|
||||
public sealed class SiliconLawProviderComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using Content.Shared.Emag.Systems;
|
||||
using Content.Shared.Popups;
|
||||
using Content.Shared.Silicons.Laws.Components;
|
||||
using Content.Shared.Wires;
|
||||
|
||||
namespace Content.Shared.Silicons.Laws;
|
||||
|
||||
@@ -8,6 +10,8 @@ namespace Content.Shared.Silicons.Laws;
|
||||
/// </summary>
|
||||
public abstract class SharedSiliconLawSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly SharedPopupSystem _popup = default!;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -16,6 +20,14 @@ public abstract class SharedSiliconLawSystem : EntitySystem
|
||||
|
||||
protected virtual void OnGotEmagged(EntityUid uid, EmagSiliconLawComponent component, ref GotEmaggedEvent args)
|
||||
{
|
||||
if (component.RequireOpenPanel &&
|
||||
TryComp<WiresPanelComponent>(uid, out var panel) &&
|
||||
!panel.Open)
|
||||
{
|
||||
_popup.PopupClient(Loc.GetString("law-emag-require-panel"), uid, args.UserUid);
|
||||
return;
|
||||
}
|
||||
|
||||
component.OwnerName = Name(args.UserUid);
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
@@ -346,7 +346,7 @@ namespace Content.Shared.Stacks
|
||||
|
||||
private void OnStackGetState(EntityUid uid, StackComponent component, ref ComponentGetState args)
|
||||
{
|
||||
args.State = new StackComponentState(component.Count, GetMaxCount(component));
|
||||
args.State = new StackComponentState(component.Count, component.MaxCountOverride, component.Lingering);
|
||||
}
|
||||
|
||||
private void OnStackHandleState(EntityUid uid, StackComponent component, ref ComponentHandleState args)
|
||||
@@ -355,6 +355,7 @@ namespace Content.Shared.Stacks
|
||||
return;
|
||||
|
||||
component.MaxCountOverride = cast.MaxCount;
|
||||
component.Lingering = cast.Lingering;
|
||||
// This will change the count and call events.
|
||||
SetCount(uid, cast.Count, component);
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace Content.Shared.Stacks
|
||||
[DataField("lingering"), ViewVariables(VVAccess.ReadWrite)]
|
||||
public bool Lingering;
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField("throwIndividually"), ViewVariables(VVAccess.ReadWrite)]
|
||||
public bool ThrowIndividually { get; set; } = false;
|
||||
|
||||
[ViewVariables]
|
||||
@@ -84,12 +84,15 @@ namespace Content.Shared.Stacks
|
||||
public sealed class StackComponentState : ComponentState
|
||||
{
|
||||
public int Count { get; }
|
||||
public int MaxCount { get; }
|
||||
public int? MaxCount { get; }
|
||||
|
||||
public StackComponentState(int count, int maxCount)
|
||||
public bool Lingering;
|
||||
|
||||
public StackComponentState(int count, int? maxCount, bool lingering)
|
||||
{
|
||||
Count = count;
|
||||
MaxCount = maxCount;
|
||||
Lingering = lingering;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user