mirror of
https://github.com/space-syndicate/space-station-14.git
synced 2026-10-09 10:21:18 +03:00
Merge remote-tracking branch 'upstream/master' into upstream-sync
This commit is contained in:
commit
13d74575f3
260 changed files with 6147 additions and 3330 deletions
|
|
@ -1,8 +1,4 @@
|
|||
using System;
|
||||
using Content.Shared.Administration;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
|
|
@ -21,19 +17,20 @@ public sealed class GamePrototypeLoadManager : IGamePrototypeLoadManager
|
|||
|
||||
private void LoadGamePrototype(GamePrototypeLoadMessage message)
|
||||
{
|
||||
_prototypeManager.LoadString(message.PrototypeData, true);
|
||||
var changed = new Dictionary<Type, HashSet<string>>();
|
||||
_prototypeManager.LoadString(message.PrototypeData, true, changed);
|
||||
_prototypeManager.ResolveResults();
|
||||
_prototypeManager.ReloadPrototypes(changed);
|
||||
_localizationManager.ReloadLocalizations();
|
||||
GamePrototypeLoaded?.Invoke();
|
||||
Logger.InfoS("adminbus", "Loaded adminbus prototype data.");
|
||||
}
|
||||
|
||||
public void SendGamePrototype(string prototype)
|
||||
{
|
||||
var msg = _netManager.CreateNetMessage<GamePrototypeLoadMessage>();
|
||||
msg.PrototypeData = prototype;
|
||||
var msg = new GamePrototypeLoadMessage
|
||||
{
|
||||
PrototypeData = prototype
|
||||
};
|
||||
_netManager.ClientSendMessage(msg);
|
||||
}
|
||||
|
||||
public event Action? GamePrototypeLoaded;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +0,0 @@
|
|||
using Content.Shared.Buckle.Components;
|
||||
|
||||
namespace Content.Client.Buckle;
|
||||
|
||||
[RegisterComponent]
|
||||
[ComponentReference(typeof(SharedBuckleComponent))]
|
||||
[Access(typeof(BuckleSystem))]
|
||||
public sealed class BuckleComponent : SharedBuckleComponent
|
||||
{
|
||||
public int? OriginalDrawDepth { get; set; }
|
||||
}
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
using Content.Client.Buckle.Strap;
|
||||
using Content.Client.Rotation;
|
||||
using Content.Shared.ActionBlocker;
|
||||
using Content.Shared.Buckle;
|
||||
|
|
@ -12,15 +11,14 @@ namespace Content.Client.Buckle
|
|||
internal sealed class BuckleSystem : SharedBuckleSystem
|
||||
{
|
||||
[Dependency] private readonly ActionBlockerSystem _actionBlocker = default!;
|
||||
[Dependency] private readonly AppearanceSystem AppearanceSystem = default!;
|
||||
[Dependency] private readonly RotationVisualizerSystem RotationVisualizerSystem = default!;
|
||||
[Dependency] private readonly AppearanceSystem _appearanceSystem = default!;
|
||||
[Dependency] private readonly RotationVisualizerSystem _rotationVisualizerSystem = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<BuckleComponent, ComponentHandleState>(OnBuckleHandleState);
|
||||
SubscribeLocalEvent<StrapComponent, ComponentHandleState>(OnStrapHandleState);
|
||||
SubscribeLocalEvent<BuckleComponent, AppearanceChangeEvent>(OnAppearanceChange);
|
||||
}
|
||||
|
||||
|
|
@ -65,22 +63,10 @@ namespace Content.Client.Buckle
|
|||
}
|
||||
}
|
||||
|
||||
private void OnStrapHandleState(EntityUid uid, StrapComponent component, ref ComponentHandleState args)
|
||||
{
|
||||
if (args.Current is not StrapComponentState state)
|
||||
return;
|
||||
|
||||
component.Position = state.Position;
|
||||
component.BuckleOffsetUnclamped = state.BuckleOffsetClamped;
|
||||
component.BuckledEntities.Clear();
|
||||
component.BuckledEntities.UnionWith(state.BuckledEntities);
|
||||
component.MaxBuckleDistance = state.MaxBuckleDistance;
|
||||
}
|
||||
|
||||
private void OnAppearanceChange(EntityUid uid, BuckleComponent component, ref AppearanceChangeEvent args)
|
||||
{
|
||||
if (!AppearanceSystem.TryGetData<int>(uid, StrapVisuals.RotationAngle, out var angle, args.Component) ||
|
||||
!AppearanceSystem.TryGetData<bool>(uid, BuckleVisuals.Buckled, out var buckled, args.Component) ||
|
||||
if (!_appearanceSystem.TryGetData<int>(uid, StrapVisuals.RotationAngle, out var angle, args.Component) ||
|
||||
!_appearanceSystem.TryGetData<bool>(uid, BuckleVisuals.Buckled, out var buckled, args.Component) ||
|
||||
!buckled ||
|
||||
args.Sprite == null)
|
||||
{
|
||||
|
|
@ -88,7 +74,7 @@ namespace Content.Client.Buckle
|
|||
}
|
||||
|
||||
// Animate strapping yourself to something at a given angle
|
||||
RotationVisualizerSystem.AnimateSpriteRotation(args.Sprite, Angle.FromDegrees(angle), 0.125f);
|
||||
_rotationVisualizerSystem.AnimateSpriteRotation(args.Sprite, Angle.FromDegrees(angle), 0.125f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +0,0 @@
|
|||
using Content.Shared.Buckle.Components;
|
||||
|
||||
namespace Content.Client.Buckle.Strap;
|
||||
|
||||
[RegisterComponent]
|
||||
[ComponentReference(typeof(SharedStrapComponent))]
|
||||
[Access(typeof(BuckleSystem))]
|
||||
public sealed class StrapComponent : SharedStrapComponent
|
||||
{
|
||||
}
|
||||
|
|
@ -6,10 +6,3 @@ public sealed class CartridgeLoaderSystem : SharedCartridgeLoaderSystem
|
|||
{
|
||||
//Empty client system for component replication
|
||||
}
|
||||
|
||||
[RegisterComponent]
|
||||
[ComponentReference(typeof(SharedCartridgeLoaderComponent))]
|
||||
public sealed class CartridgeLoaderComponent : SharedCartridgeLoaderComponent
|
||||
{
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
using System.Text.RegularExpressions;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Shared.GameObjects;
|
||||
using static Content.Shared.Configurable.SharedConfigurationComponent;
|
||||
using static Content.Shared.Configurable.ConfigurationComponent;
|
||||
|
||||
namespace Content.Client.Configurable.UI
|
||||
{
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ using Robust.Client.UserInterface.Controls;
|
|||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Maths;
|
||||
using static Content.Shared.Configurable.SharedConfigurationComponent;
|
||||
using static Content.Shared.Configurable.ConfigurationComponent;
|
||||
using static Robust.Client.UserInterface.Controls.BaseButton;
|
||||
using static Robust.Client.UserInterface.Controls.BoxContainer;
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ public sealed partial class DecalPlacerWindow : DefaultWindow
|
|||
|
||||
private PaletteColorPicker? _picker;
|
||||
|
||||
private Dictionary<string, Texture>? _decals;
|
||||
private SortedDictionary<string, Texture>? _decals;
|
||||
private string? _selected;
|
||||
private Color _color = Color.White;
|
||||
private bool _useColor;
|
||||
|
|
@ -170,7 +170,7 @@ public sealed partial class DecalPlacerWindow : DefaultWindow
|
|||
|
||||
public void Populate(IEnumerable<DecalPrototype> prototypes)
|
||||
{
|
||||
_decals = new Dictionary<string, Texture>();
|
||||
_decals = new SortedDictionary<string, Texture>();
|
||||
foreach (var decalPrototype in prototypes)
|
||||
{
|
||||
if (decalPrototype.ShowMenu)
|
||||
|
|
|
|||
|
|
@ -1,13 +0,0 @@
|
|||
using Content.Shared.Ensnaring.Components;
|
||||
|
||||
namespace Content.Client.Ensnaring.Components;
|
||||
[RegisterComponent]
|
||||
[ComponentReference(typeof(SharedEnsnareableComponent))]
|
||||
public sealed class EnsnareableComponent : SharedEnsnareableComponent
|
||||
{
|
||||
[DataField("sprite")]
|
||||
public string? Sprite;
|
||||
|
||||
[DataField("state")]
|
||||
public string? State;
|
||||
}
|
||||
|
|
@ -1,9 +1,3 @@
|
|||
using Content.Shared.Ensnaring.Components;
|
||||
|
||||
namespace Content.Client.Ensnaring.Components;
|
||||
[RegisterComponent]
|
||||
[ComponentReference(typeof(SharedEnsnaringComponent))]
|
||||
public sealed class EnsnaringComponent : SharedEnsnaringComponent
|
||||
{
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
using Content.Client.Ensnaring.Components;
|
||||
using Content.Shared.Ensnaring;
|
||||
using Content.Shared.Ensnaring.Components;
|
||||
using Robust.Client.GameObjects;
|
||||
|
||||
namespace Content.Client.Ensnaring.Visualizers;
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
using Content.Shared.Flash;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.Player;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Client.Flash
|
||||
|
|
|
|||
|
|
@ -1,12 +0,0 @@
|
|||
using Content.Shared.Flash;
|
||||
using Robust.Shared.Analyzers;
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
namespace Content.Client.Flash
|
||||
{
|
||||
[ComponentReference(typeof(SharedFlashableComponent))]
|
||||
[RegisterComponent, Access(typeof(FlashSystem))]
|
||||
public sealed class FlashableComponent : SharedFlashableComponent
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
using Content.Shared.Humanoid;
|
||||
using Content.Shared.Humanoid.Markings;
|
||||
using Content.Shared.Humanoid.Prototypes;
|
||||
|
||||
namespace Content.Client.Humanoid;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed class HumanoidComponent : SharedHumanoidComponent
|
||||
{
|
||||
[ViewVariables] public List<Marking> CurrentMarkings = new();
|
||||
|
||||
public Dictionary<HumanoidVisualLayers, HumanoidSpeciesSpriteLayer> BaseLayers = new();
|
||||
|
||||
public string LastSpecies = default!;
|
||||
}
|
||||
|
|
@ -108,23 +108,23 @@ public sealed class HumanoidVisualizerSystem : VisualizerSystem<HumanoidComponen
|
|||
SpriteComponent sprite)
|
||||
{
|
||||
// skip this entire thing if both sets are empty
|
||||
if (humanoid.CurrentMarkings.Count == 0 && newMarkings.Count == 0)
|
||||
if (humanoid.CurrentClientMarkings.Count == 0 && newMarkings.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var dirtyMarkings = new List<int>();
|
||||
var dirtyRangeStart = humanoid.CurrentMarkings.Count == 0 ? 0 : -1;
|
||||
var dirtyRangeStart = humanoid.CurrentClientMarkings.Count == 0 ? 0 : -1;
|
||||
|
||||
// edge cases:
|
||||
// humanoid.CurrentMarkings < newMarkings.Count
|
||||
// humanoid.CurrentClientMarkings < newMarkings.Count
|
||||
// - check if count matches this condition before diffing
|
||||
// - if count is unequal, set dirty range to start from humanoid.CurrentMarkings.Count
|
||||
// humanoid.CurrentMarkings > newMarkings.Count, no dirty markings
|
||||
// - if count is unequal, set dirty range to start from humanoid.CurrentClientMarkings.Count
|
||||
// humanoid.CurrentClientMarkings > newMarkings.Count, no dirty markings
|
||||
// - break count upon meeting this condition
|
||||
// - clear markings from newMarkings.Count to humanoid.CurrentMarkings.Count - newMarkings.Count
|
||||
// - clear markings from newMarkings.Count to humanoid.CurrentClientMarkings.Count - newMarkings.Count
|
||||
|
||||
for (var i = 0; i < humanoid.CurrentMarkings.Count; i++)
|
||||
for (var i = 0; i < humanoid.CurrentClientMarkings.Count; i++)
|
||||
{
|
||||
// if we've reached the end of the new set of markings,
|
||||
// then that means it's time to finish
|
||||
|
|
@ -135,7 +135,7 @@ public sealed class HumanoidVisualizerSystem : VisualizerSystem<HumanoidComponen
|
|||
|
||||
// if the marking is different here, set the range start to i and break, we need
|
||||
// to rebuild all markings starting from i
|
||||
if (humanoid.CurrentMarkings[i].MarkingId != newMarkings[i].MarkingId)
|
||||
if (humanoid.CurrentClientMarkings[i].MarkingId != newMarkings[i].MarkingId)
|
||||
{
|
||||
dirtyRangeStart = i;
|
||||
break;
|
||||
|
|
@ -146,7 +146,7 @@ public sealed class HumanoidVisualizerSystem : VisualizerSystem<HumanoidComponen
|
|||
// however: if the hidden layers are set to dirty, then we need to
|
||||
// instead just add every single marking, since we don't know ahead of time
|
||||
// where these markings go
|
||||
if (humanoid.CurrentMarkings[i] != newMarkings[i] || layersDirty)
|
||||
if (humanoid.CurrentClientMarkings[i] != newMarkings[i] || layersDirty)
|
||||
{
|
||||
dirtyMarkings.Add(i);
|
||||
}
|
||||
|
|
@ -162,49 +162,49 @@ public sealed class HumanoidVisualizerSystem : VisualizerSystem<HumanoidComponen
|
|||
ApplyMarking(uid, dirtyMarking, newMarkings[i].MarkingColors, newMarkings[i].Visible, humanoid, sprite);
|
||||
}
|
||||
|
||||
if (humanoid.CurrentMarkings.Count < newMarkings.Count && dirtyRangeStart < 0)
|
||||
if (humanoid.CurrentClientMarkings.Count < newMarkings.Count && dirtyRangeStart < 0)
|
||||
{
|
||||
dirtyRangeStart = humanoid.CurrentMarkings.Count;
|
||||
dirtyRangeStart = humanoid.CurrentClientMarkings.Count;
|
||||
}
|
||||
|
||||
if (dirtyRangeStart >= 0)
|
||||
{
|
||||
var range = newMarkings.GetRange(dirtyRangeStart, newMarkings.Count - dirtyRangeStart);
|
||||
|
||||
if (humanoid.CurrentMarkings.Count > 0)
|
||||
if (humanoid.CurrentClientMarkings.Count > 0)
|
||||
{
|
||||
var oldRange = humanoid.CurrentMarkings.GetRange(dirtyRangeStart, humanoid.CurrentMarkings.Count - dirtyRangeStart);
|
||||
var oldRange = humanoid.CurrentClientMarkings.GetRange(dirtyRangeStart, humanoid.CurrentClientMarkings.Count - dirtyRangeStart);
|
||||
ClearMarkings(uid, oldRange, humanoid, sprite);
|
||||
}
|
||||
|
||||
ApplyMarkings(uid, range, humanoid, sprite);
|
||||
}
|
||||
else if (humanoid.CurrentMarkings.Count != newMarkings.Count)
|
||||
else if (humanoid.CurrentClientMarkings.Count != newMarkings.Count)
|
||||
{
|
||||
if (newMarkings.Count == 0)
|
||||
{
|
||||
ClearAllMarkings(uid, humanoid, sprite);
|
||||
}
|
||||
else if (humanoid.CurrentMarkings.Count > newMarkings.Count)
|
||||
else if (humanoid.CurrentClientMarkings.Count > newMarkings.Count)
|
||||
{
|
||||
var rangeStart = newMarkings.Count;
|
||||
var rangeCount = humanoid.CurrentMarkings.Count - newMarkings.Count;
|
||||
var range = humanoid.CurrentMarkings.GetRange(rangeStart, rangeCount);
|
||||
var rangeCount = humanoid.CurrentClientMarkings.Count - newMarkings.Count;
|
||||
var range = humanoid.CurrentClientMarkings.GetRange(rangeStart, rangeCount);
|
||||
|
||||
ClearMarkings(uid, range, humanoid, sprite);
|
||||
}
|
||||
}
|
||||
|
||||
if (dirtyMarkings.Count > 0 || dirtyRangeStart >= 0 || humanoid.CurrentMarkings.Count != newMarkings.Count)
|
||||
if (dirtyMarkings.Count > 0 || dirtyRangeStart >= 0 || humanoid.CurrentClientMarkings.Count != newMarkings.Count)
|
||||
{
|
||||
humanoid.CurrentMarkings = newMarkings;
|
||||
humanoid.CurrentClientMarkings = newMarkings;
|
||||
}
|
||||
}
|
||||
|
||||
private void ClearAllMarkings(EntityUid uid, HumanoidComponent humanoid,
|
||||
SpriteComponent spriteComp)
|
||||
{
|
||||
ClearMarkings(uid, humanoid.CurrentMarkings, humanoid, spriteComp);
|
||||
ClearMarkings(uid, humanoid.CurrentClientMarkings, humanoid, spriteComp);
|
||||
}
|
||||
|
||||
private void ClearMarkings(EntityUid uid, List<Marking> markings, HumanoidComponent humanoid,
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ namespace Content.Client.Inventory
|
|||
}
|
||||
|
||||
// snare-removal button. This is just the old button before the change to item slots. It is pretty out of place.
|
||||
if (_entMan.TryGetComponent(Owner.Owner, out SharedEnsnareableComponent? snare) && snare.IsEnsnared)
|
||||
if (_entMan.TryGetComponent(Owner.Owner, out EnsnareableComponent? snare) && snare.IsEnsnared)
|
||||
{
|
||||
var button = new Button()
|
||||
{
|
||||
|
|
|
|||
7
Content.Client/Medical/Cryogenics/CryoPodComponent.cs
Normal file
7
Content.Client/Medical/Cryogenics/CryoPodComponent.cs
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
using Content.Shared.DragDrop;
|
||||
using Content.Shared.Medical.Cryogenics;
|
||||
|
||||
namespace Content.Client.Medical.Cryogenics;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed class CryoPodComponent : SharedCryoPodComponent { }
|
||||
83
Content.Client/Medical/Cryogenics/CryoPodSystem.cs
Normal file
83
Content.Client/Medical/Cryogenics/CryoPodSystem.cs
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
using Content.Shared.Destructible;
|
||||
using Content.Shared.Emag.Systems;
|
||||
using Content.Shared.Medical.Cryogenics;
|
||||
using Content.Shared.Verbs;
|
||||
using Robust.Client.GameObjects;
|
||||
using DrawDepth = Content.Shared.DrawDepth.DrawDepth;
|
||||
|
||||
namespace Content.Client.Medical.Cryogenics;
|
||||
|
||||
public sealed class CryoPodSystem: SharedCryoPodSystem
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<CryoPodComponent, ComponentInit>(OnComponentInit);
|
||||
SubscribeLocalEvent<CryoPodComponent, GetVerbsEvent<AlternativeVerb>>(AddAlternativeVerbs);
|
||||
SubscribeLocalEvent<CryoPodComponent, GotEmaggedEvent>(OnEmagged);
|
||||
SubscribeLocalEvent<CryoPodComponent, DoInsertCryoPodEvent>(DoInsertCryoPod);
|
||||
SubscribeLocalEvent<CryoPodComponent, DoInsertCancelledCryoPodEvent>(DoInsertCancelCryoPod);
|
||||
SubscribeLocalEvent<CryoPodComponent, CryoPodPryFinished>(OnCryoPodPryFinished);
|
||||
SubscribeLocalEvent<CryoPodComponent, CryoPodPryInterrupted>(OnCryoPodPryInterrupted);
|
||||
|
||||
SubscribeLocalEvent<CryoPodComponent, AppearanceChangeEvent>(OnAppearanceChange);
|
||||
SubscribeLocalEvent<InsideCryoPodComponent, ComponentStartup>(OnCryoPodInsertion);
|
||||
SubscribeLocalEvent<InsideCryoPodComponent, ComponentRemove>(OnCryoPodRemoval);
|
||||
}
|
||||
|
||||
private void OnCryoPodInsertion(EntityUid uid, InsideCryoPodComponent component, ComponentStartup args)
|
||||
{
|
||||
if (!TryComp<SpriteComponent>(uid, out var spriteComponent))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
component.PreviousOffset = spriteComponent.Offset;
|
||||
spriteComponent.Offset = new Vector2(0, 1);
|
||||
}
|
||||
|
||||
private void OnCryoPodRemoval(EntityUid uid, InsideCryoPodComponent component, ComponentRemove args)
|
||||
{
|
||||
if (!TryComp<SpriteComponent>(uid, out var spriteComponent))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
spriteComponent.Offset = component.PreviousOffset;
|
||||
}
|
||||
|
||||
private void OnAppearanceChange(EntityUid uid, SharedCryoPodComponent component, ref AppearanceChangeEvent args)
|
||||
{
|
||||
if (args.Sprite == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!args.Component.TryGetData(SharedCryoPodComponent.CryoPodVisuals.ContainsEntity, out bool isOpen)
|
||||
|| !args.Component.TryGetData(SharedCryoPodComponent.CryoPodVisuals.IsOn, out bool isOn))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (isOpen)
|
||||
{
|
||||
args.Sprite.LayerSetState(CryoPodVisualLayers.Base, "pod-open");
|
||||
args.Sprite.LayerSetVisible(CryoPodVisualLayers.Cover, false);
|
||||
args.Sprite.DrawDepth = (int) DrawDepth.Objects;
|
||||
}
|
||||
else
|
||||
{
|
||||
args.Sprite.DrawDepth = (int) DrawDepth.Mobs;
|
||||
args.Sprite.LayerSetState(CryoPodVisualLayers.Base, isOn ? "pod-on" : "pod-off");
|
||||
args.Sprite.LayerSetState(CryoPodVisualLayers.Cover, isOn ? "cover-on" : "cover-off");
|
||||
args.Sprite.LayerSetVisible(CryoPodVisualLayers.Cover, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum CryoPodVisualLayers : byte
|
||||
{
|
||||
Base,
|
||||
Cover,
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
using Content.Client.Movement.Systems;
|
||||
using Content.Shared.Climbing;
|
||||
|
||||
namespace Content.Client.Movement.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
[Access(typeof(ClimbSystem))]
|
||||
[ComponentReference(typeof(SharedClimbableComponent))]
|
||||
public sealed class ClimbableComponent : SharedClimbableComponent { }
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
using Content.Client.Movement.Systems;
|
||||
using Content.Shared.Climbing;
|
||||
|
||||
namespace Content.Client.Movement.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
[Access(typeof(ClimbSystem))]
|
||||
[ComponentReference(typeof(SharedClimbingComponent))]
|
||||
public sealed class ClimbingComponent : SharedClimbingComponent { }
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
using Content.Client.Interactable;
|
||||
using Content.Client.Movement.Components;
|
||||
using Content.Shared.Climbing;
|
||||
using Content.Shared.DragDrop;
|
||||
using Robust.Shared.GameStates;
|
||||
|
|
@ -18,14 +17,14 @@ public sealed class ClimbSystem : SharedClimbSystem
|
|||
|
||||
private static void OnClimbingState(EntityUid uid, ClimbingComponent component, ref ComponentHandleState args)
|
||||
{
|
||||
if (args.Current is not SharedClimbingComponent.ClimbModeComponentState climbModeState)
|
||||
if (args.Current is not ClimbingComponent.ClimbModeComponentState climbModeState)
|
||||
return;
|
||||
|
||||
component.IsClimbing = climbModeState.Climbing;
|
||||
component.OwnerIsTransitioning = climbModeState.IsTransitioning;
|
||||
}
|
||||
|
||||
protected override void OnCanDragDropOn(EntityUid uid, SharedClimbableComponent component, CanDragDropOnEvent args)
|
||||
protected override void OnCanDragDropOn(EntityUid uid, ClimbableComponent component, CanDragDropOnEvent args)
|
||||
{
|
||||
base.OnCanDragDropOn(uid, component, args);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
using Content.Shared.CCVar;
|
||||
using Content.Shared.Popups;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.ResourceManagement;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Shared;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Enums;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
|
|
@ -11,7 +15,9 @@ namespace Content.Client.Popups;
|
|||
/// </summary>
|
||||
public sealed class PopupOverlay : Overlay
|
||||
{
|
||||
private readonly IConfigurationManager _configManager;
|
||||
private readonly IEntityManager _entManager;
|
||||
private readonly IUserInterfaceManager _uiManager;
|
||||
private readonly PopupSystem _popup;
|
||||
|
||||
private readonly ShaderInstance _shader;
|
||||
|
|
@ -21,9 +27,17 @@ public sealed class PopupOverlay : Overlay
|
|||
|
||||
public override OverlaySpace Space => OverlaySpace.ScreenSpace;
|
||||
|
||||
public PopupOverlay(IEntityManager entManager, IPrototypeManager protoManager, IResourceCache cache, PopupSystem popup)
|
||||
public PopupOverlay(
|
||||
IConfigurationManager configManager,
|
||||
IEntityManager entManager,
|
||||
IPrototypeManager protoManager,
|
||||
IResourceCache cache,
|
||||
IUserInterfaceManager uiManager,
|
||||
PopupSystem popup)
|
||||
{
|
||||
_configManager = configManager;
|
||||
_entManager = entManager;
|
||||
_uiManager = uiManager;
|
||||
_popup = popup;
|
||||
|
||||
_shader = protoManager.Index<ShaderPrototype>("unshaded").Instance();
|
||||
|
|
@ -39,14 +53,18 @@ public sealed class PopupOverlay : Overlay
|
|||
|
||||
args.DrawingHandle.SetTransform(Matrix3.Identity);
|
||||
args.DrawingHandle.UseShader(_shader);
|
||||
var scale = _configManager.GetCVar(CVars.DisplayUIScale);
|
||||
|
||||
DrawWorld(args.ScreenHandle, args);
|
||||
DrawScreen(args.ScreenHandle, args);
|
||||
if (scale == 0f)
|
||||
scale = _uiManager.DefaultUIScale;
|
||||
|
||||
DrawWorld(args.ScreenHandle, args, scale);
|
||||
DrawScreen(args.ScreenHandle, args, scale);
|
||||
|
||||
args.DrawingHandle.UseShader(null);
|
||||
}
|
||||
|
||||
private void DrawWorld(DrawingHandleScreen worldHandle, OverlayDrawArgs args)
|
||||
private void DrawWorld(DrawingHandleScreen worldHandle, OverlayDrawArgs args, float scale)
|
||||
{
|
||||
if (_popup.WorldLabels.Count == 0)
|
||||
return;
|
||||
|
|
@ -64,11 +82,11 @@ public sealed class PopupOverlay : Overlay
|
|||
continue;
|
||||
|
||||
var pos = matrix.Transform(mapPos.Position);
|
||||
DrawPopup(popup, worldHandle, pos);
|
||||
DrawPopup(popup, worldHandle, pos, scale);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawScreen(DrawingHandleScreen screenHandle, OverlayDrawArgs args)
|
||||
private void DrawScreen(DrawingHandleScreen screenHandle, OverlayDrawArgs args, float scale)
|
||||
{
|
||||
foreach (var popup in _popup.CursorLabels)
|
||||
{
|
||||
|
|
@ -76,18 +94,17 @@ public sealed class PopupOverlay : Overlay
|
|||
if (popup.InitialPos.Window != args.ViewportControl?.Window?.Id)
|
||||
continue;
|
||||
|
||||
DrawPopup(popup, screenHandle, popup.InitialPos.Position);
|
||||
DrawPopup(popup, screenHandle, popup.InitialPos.Position, scale);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawPopup(PopupSystem.PopupLabel popup, DrawingHandleScreen handle, Vector2 position)
|
||||
private void DrawPopup(PopupSystem.PopupLabel popup, DrawingHandleScreen handle, Vector2 position, float scale)
|
||||
{
|
||||
const float alphaMinimum = 0.5f;
|
||||
|
||||
var alpha = MathF.Min(1f, 1f - (popup.TotalTime - alphaMinimum) / (PopupSystem.PopupLifetime - alphaMinimum));
|
||||
var updatedPosition = position - new Vector2(0f, 20f * (popup.TotalTime * popup.TotalTime + popup.TotalTime));
|
||||
var font = _smallFont;
|
||||
var dimensions = Vector2.Zero;
|
||||
var color = Color.White.WithAlpha(alpha);
|
||||
|
||||
switch (popup.Type)
|
||||
|
|
@ -113,7 +130,7 @@ public sealed class PopupOverlay : Overlay
|
|||
break;
|
||||
}
|
||||
|
||||
dimensions = handle.GetDimensions(font, popup.Text, 1f);
|
||||
handle.DrawString(font, updatedPosition - dimensions / 2f, popup.Text, color.WithAlpha(alpha));
|
||||
var dimensions = handle.GetDimensions(font, popup.Text, scale);
|
||||
handle.DrawString(font, updatedPosition - dimensions / 2f, popup.Text, scale, color.WithAlpha(alpha));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ using Robust.Client.Graphics;
|
|||
using Robust.Client.Input;
|
||||
using Robust.Client.Player;
|
||||
using Robust.Client.ResourceManagement;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Players;
|
||||
|
|
@ -14,11 +16,13 @@ namespace Content.Client.Popups
|
|||
{
|
||||
public sealed class PopupSystem : SharedPopupSystem
|
||||
{
|
||||
[Dependency] private readonly IConfigurationManager _configManager = default!;
|
||||
[Dependency] private readonly IInputManager _inputManager = default!;
|
||||
[Dependency] private readonly IOverlayManager _overlay = default!;
|
||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
||||
[Dependency] private readonly IResourceCache _resource = default!;
|
||||
[Dependency] private readonly IUserInterfaceManager _uiManager = default!;
|
||||
|
||||
public IReadOnlyList<WorldPopupLabel> WorldLabels => _aliveWorldLabels;
|
||||
public IReadOnlyList<CursorPopupLabel> CursorLabels => _aliveCursorLabels;
|
||||
|
|
@ -35,7 +39,7 @@ namespace Content.Client.Popups
|
|||
SubscribeNetworkEvent<PopupEntityEvent>(OnPopupEntityEvent);
|
||||
SubscribeNetworkEvent<RoundRestartCleanupEvent>(OnRoundRestart);
|
||||
_overlay
|
||||
.AddOverlay(new PopupOverlay(EntityManager, _prototype, _resource, this));
|
||||
.AddOverlay(new PopupOverlay(_configManager, EntityManager, _prototype, _resource, _uiManager, this));
|
||||
}
|
||||
|
||||
public override void Shutdown()
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
using Content.Shared.Projectiles;
|
||||
|
||||
namespace Content.Client.Projectiles
|
||||
{
|
||||
[RegisterComponent]
|
||||
[ComponentReference(typeof(SharedProjectileComponent))]
|
||||
public sealed class ProjectileComponent : SharedProjectileComponent {}
|
||||
}
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
using Content.Shared.Singularity.Components;
|
||||
|
||||
namespace Content.Client.Singularity.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
[ComponentReference(typeof(SharedContainmentFieldComponent))]
|
||||
public sealed class ContainmentFieldComponent : SharedContainmentFieldComponent { }
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
using Content.Shared.Singularity.Components;
|
||||
|
||||
namespace Content.Client.Singularity.Components;
|
||||
[RegisterComponent]
|
||||
[ComponentReference(typeof(SharedContainmentFieldGeneratorComponent))]
|
||||
public sealed class ContainmentFieldGeneratorComponent : SharedContainmentFieldGeneratorComponent { }
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
using Content.Shared.Singularity.Components;
|
||||
using Content.Client.Singularity.EntitySystems;
|
||||
|
||||
namespace Content.Client.Singularity.Components;
|
||||
|
||||
/// <summary>
|
||||
/// The client-side version of <see cref="SharedSingularityComponent"/>.
|
||||
/// Primarily managed by <see cref="SingularitySystem"/>.
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
[ComponentReference(typeof(SharedSingularityComponent))]
|
||||
public sealed class SingularityComponent : SharedSingularityComponent
|
||||
{}
|
||||
|
|
@ -14,7 +14,7 @@ public sealed class SingularitySystem : SharedSingularitySystem
|
|||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<SharedSingularityComponent, ComponentHandleState>(HandleSingularityState);
|
||||
SubscribeLocalEvent<SingularityComponent, ComponentHandleState>(HandleSingularityState);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -23,7 +23,7 @@ public sealed class SingularitySystem : SharedSingularitySystem
|
|||
/// <param name="uid">The uid of the singularity to sync.</param>
|
||||
/// <param name="comp">The state of the singularity to sync.</param>
|
||||
/// <param name="args">The event arguments including the state to sync the singularity with.</param>
|
||||
private void HandleSingularityState(EntityUid uid, SharedSingularityComponent comp, ref ComponentHandleState args)
|
||||
private void HandleSingularityState(EntityUid uid, SingularityComponent comp, ref ComponentHandleState args)
|
||||
{
|
||||
if (args.Current is not SingularityComponentState state)
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -1,18 +0,0 @@
|
|||
using Content.Client.Items.Components;
|
||||
using Content.Client.Message;
|
||||
using Content.Client.Stylesheets;
|
||||
using Content.Shared.Stacks;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Client.Stack
|
||||
{
|
||||
[RegisterComponent, Access(typeof(StackSystem), typeof(StackStatusControl))]
|
||||
[ComponentReference(typeof(SharedStackComponent))]
|
||||
public sealed class StackComponent : SharedStackComponent
|
||||
{
|
||||
[ViewVariables]
|
||||
public bool UiUpdateNeeded { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
using Content.Client.Message;
|
||||
using Content.Client.Stylesheets;
|
||||
using Content.Shared.Stacks;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Shared.Timing;
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ namespace Content.Client.Stack
|
|||
args.Controls.Add(new StackStatusControl(component));
|
||||
}
|
||||
|
||||
public override void SetCount(EntityUid uid, int amount, SharedStackComponent? component = null)
|
||||
public override void SetCount(EntityUid uid, int amount, StackComponent? component = null)
|
||||
{
|
||||
if (!Resolve(uid, ref component))
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -7,17 +7,6 @@ using Robust.Shared.Timing;
|
|||
|
||||
namespace Content.Client.Tools.Components
|
||||
{
|
||||
[RegisterComponent]
|
||||
[ComponentReference(typeof(SharedMultipleToolComponent))]
|
||||
public sealed class MultipleToolComponent : SharedMultipleToolComponent
|
||||
{
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public bool UiUpdateNeeded;
|
||||
|
||||
[DataField("statusShowBehavior")]
|
||||
public bool StatusShowBehavior = true;
|
||||
}
|
||||
|
||||
public sealed class MultipleToolStatusControl : Control
|
||||
{
|
||||
private readonly MultipleToolComponent _parent;
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ namespace Content.Client.Tools
|
|||
}
|
||||
|
||||
public override void SetMultipleTool(EntityUid uid,
|
||||
SharedMultipleToolComponent? multiple = null,
|
||||
MultipleToolComponent? multiple = null,
|
||||
ToolComponent? tool = null,
|
||||
bool playSound = false,
|
||||
EntityUid? user = null)
|
||||
|
|
@ -29,7 +29,7 @@ namespace Content.Client.Tools
|
|||
return;
|
||||
|
||||
base.SetMultipleTool(uid, multiple, tool, playSound, user);
|
||||
((MultipleToolComponent)multiple).UiUpdateNeeded = true;
|
||||
multiple.UiUpdateNeeded = true;
|
||||
|
||||
// TODO replace this with appearance + visualizer
|
||||
// in order to convert this to a specifier, the manner in which the sprite is specified in yaml needs to be updated.
|
||||
|
|
|
|||
|
|
@ -1,60 +0,0 @@
|
|||
using Content.Shared.VendingMachines;
|
||||
|
||||
namespace Content.Client.VendingMachines;
|
||||
|
||||
[RegisterComponent]
|
||||
[ComponentReference(typeof(SharedVendingMachineComponent))]
|
||||
[Access(typeof(VendingMachineSystem))]
|
||||
public sealed class VendingMachineComponent : SharedVendingMachineComponent
|
||||
{
|
||||
/// <summary>
|
||||
/// RSI state for when the vending machine is unpowered.
|
||||
/// Will be displayed on the layer <see cref="VendingMachineVisualLayers.Base"/>
|
||||
/// </summary>
|
||||
[DataField("offState")]
|
||||
public string? OffState;
|
||||
|
||||
/// <summary>
|
||||
/// RSI state for the screen of the vending machine
|
||||
/// Will be displayed on the layer <see cref="VendingMachineVisualLayers.Screen"/>
|
||||
/// </summary>
|
||||
[DataField("screenState")]
|
||||
public string? ScreenState;
|
||||
|
||||
/// <summary>
|
||||
/// RSI state for the vending machine's normal state. Usually a looping animation.
|
||||
/// Will be displayed on the layer <see cref="VendingMachineVisualLayers.BaseUnshaded"/>
|
||||
/// </summary>
|
||||
[DataField("normalState")]
|
||||
public string? NormalState;
|
||||
|
||||
/// <summary>
|
||||
/// RSI state for the vending machine's eject animation.
|
||||
/// Will be displayed on the layer <see cref="VendingMachineVisualLayers.BaseUnshaded"/>
|
||||
/// </summary>
|
||||
[DataField("ejectState")]
|
||||
public string? EjectState;
|
||||
|
||||
/// <summary>
|
||||
/// RSI state for the vending machine's deny animation. Will either be played once as sprite flick
|
||||
/// or looped depending on how <see cref="LoopDenyAnimation"/> is set.
|
||||
/// Will be displayed on the layer <see cref="VendingMachineVisualLayers.BaseUnshaded"/>
|
||||
/// </summary>
|
||||
[DataField("denyState")]
|
||||
public string? DenyState;
|
||||
|
||||
/// <summary>
|
||||
/// RSI state for when the vending machine is unpowered.
|
||||
/// Will be displayed on the layer <see cref="VendingMachineVisualLayers.Base"/>
|
||||
/// </summary>
|
||||
[DataField("brokenState")]
|
||||
public string? BrokenState;
|
||||
|
||||
/// <summary>
|
||||
/// If set to <c>true</c> (default) will loop the animation of the <see cref="DenyState"/> for the duration
|
||||
/// of <see cref="SharedVendingMachineComponent.DenyDelay"/>. If set to <c>false</c> will play a sprite
|
||||
/// flick animation for the state and then linger on the final frame until the end of the delay.
|
||||
/// </summary>
|
||||
[DataField("loopDeny")]
|
||||
public bool LoopDenyAnimation = true;
|
||||
}
|
||||
|
|
@ -137,19 +137,3 @@ public sealed class VendingMachineSystem : SharedVendingMachineSystem
|
|||
sprite.LayerSetVisible(actualLayer, false);
|
||||
}
|
||||
}
|
||||
|
||||
public enum VendingMachineVisualLayers : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Off / Broken. The other layers will overlay this if the machine is on.
|
||||
/// </summary>
|
||||
Base,
|
||||
/// <summary>
|
||||
/// Normal / Deny / Eject
|
||||
/// </summary>
|
||||
BaseUnshaded,
|
||||
/// <summary>
|
||||
/// Screens that are persistent (where the machine is not off or broken)
|
||||
/// </summary>
|
||||
Screen
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
using Content.Client.Projectiles;
|
||||
using Content.Shared.Projectiles;
|
||||
using Content.Shared.Weapons.Ranged.Components;
|
||||
using Content.Shared.Weapons.Ranged.Systems;
|
||||
using Robust.Client.Player;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Physics.Dynamics;
|
||||
using Robust.Shared.Physics.Events;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Random;
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ public sealed class TetherGunSystem : SharedTetherGunSystem
|
|||
[Dependency] private readonly IEyeManager _eyeManager = default!;
|
||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||
[Dependency] private readonly IInputManager _inputManager = default!;
|
||||
[Dependency] private readonly EntityLookupSystem _lookup = default!;
|
||||
[Dependency] private readonly InputSystem _inputSystem = default!;
|
||||
|
||||
public bool Enabled { get; set; }
|
||||
|
|
@ -85,15 +84,10 @@ public sealed class TetherGunSystem : SharedTetherGunSystem
|
|||
|
||||
if (gameState is GameplayState game)
|
||||
{
|
||||
EntityUid? uid;
|
||||
var uid = game.GetEntityUnderPosition(mousePos);
|
||||
|
||||
foreach (var ent in _lookup.GetEntitiesIntersecting(mousePos, LookupFlags.Approximate | LookupFlags.Static))
|
||||
{
|
||||
uid = game.GetEntityUnderPosition(mousePos);
|
||||
|
||||
if (uid != null)
|
||||
StartDragging(uid.Value, mousePos);
|
||||
}
|
||||
if (uid != null)
|
||||
StartDragging(uid.Value, mousePos);
|
||||
}
|
||||
|
||||
if (_dragging == null)
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
using System.Threading.Tasks;
|
||||
using Content.Server.Body.Systems;
|
||||
using Content.Server.Buckle.Components;
|
||||
using Content.Server.Buckle.Systems;
|
||||
using Content.Server.Hands.Components;
|
||||
using Content.Shared.ActionBlocker;
|
||||
using Content.Shared.Body.Components;
|
||||
using Content.Shared.Body.Part;
|
||||
using Content.Shared.Buckle.Components;
|
||||
using Content.Shared.Hands.EntitySystems;
|
||||
using Content.Shared.Standing;
|
||||
using NUnit.Framework;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server.Climbing.Components;
|
||||
using Content.Shared.Climbing;
|
||||
using NUnit.Framework;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
|
|
|
|||
|
|
@ -54,7 +54,6 @@ public sealed class PrototypeSaveTest
|
|||
"SignalSwitch",
|
||||
"SignalButton",
|
||||
"ApcNetSwitch",
|
||||
"TetherEntity",
|
||||
"SignalButtonExt1",
|
||||
"SignalButtonExt2",
|
||||
"SignalButtonExt3",
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ public sealed class ClearBluespaceLockerLinks : IConsoleCommand
|
|||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,10 +53,16 @@ public sealed class LinkBluespaceLocker : IConsoleCommand
|
|||
|
||||
entityManager.EnsureComponent<BluespaceLockerComponent>(originUid, out var originBluespaceComponent);
|
||||
originBluespaceComponent.BluespaceLinks.Add(targetComponent);
|
||||
entityManager.EnsureComponent<BluespaceLockerComponent>(targetUid, out var targetBluespaceComponent);
|
||||
if (bidirectional)
|
||||
{
|
||||
entityManager.EnsureComponent<BluespaceLockerComponent>(targetUid, out var targetBluespaceComponent);
|
||||
targetBluespaceComponent.BluespaceLinks.Add(originComponent);
|
||||
}
|
||||
else if (targetBluespaceComponent.BluespaceLinks.Count == 0)
|
||||
{
|
||||
targetBluespaceComponent.AllowSentient = false;
|
||||
targetBluespaceComponent.TransportEntities = false;
|
||||
targetBluespaceComponent.TransportGas = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ public sealed class GamePrototypeLoadManager : IGamePrototypeLoadManager
|
|||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
[Dependency] private readonly ILocalizationManager _localizationManager = default!;
|
||||
|
||||
private readonly List<string> LoadedPrototypes = new();
|
||||
private readonly List<string> _loadedPrototypes = new();
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
|
|
@ -30,8 +30,6 @@ public sealed class GamePrototypeLoadManager : IGamePrototypeLoadManager
|
|||
|
||||
}
|
||||
|
||||
public event Action? GamePrototypeLoaded;
|
||||
|
||||
private void ClientLoadsPrototype(GamePrototypeLoadMessage message)
|
||||
{
|
||||
var player = _playerManager.GetSessionByChannel(message.MsgChannel);
|
||||
|
|
@ -48,23 +46,28 @@ public sealed class GamePrototypeLoadManager : IGamePrototypeLoadManager
|
|||
|
||||
private void LoadPrototypeData(string prototypeData)
|
||||
{
|
||||
LoadedPrototypes.Add(prototypeData);
|
||||
var msg = new GamePrototypeLoadMessage();
|
||||
msg.PrototypeData = prototypeData;
|
||||
_loadedPrototypes.Add(prototypeData);
|
||||
var msg = new GamePrototypeLoadMessage
|
||||
{
|
||||
PrototypeData = prototypeData
|
||||
};
|
||||
_netManager.ServerSendToAll(msg); // everyone load it up!
|
||||
_prototypeManager.LoadString(prototypeData, true); // server needs it too.
|
||||
var changed = new Dictionary<Type, HashSet<string>>();
|
||||
_prototypeManager.LoadString(prototypeData, true, changed); // server needs it too.
|
||||
_prototypeManager.ResolveResults();
|
||||
_prototypeManager.ReloadPrototypes(changed);
|
||||
_localizationManager.ReloadLocalizations();
|
||||
GamePrototypeLoaded?.Invoke();
|
||||
}
|
||||
|
||||
private void NetManagerOnConnected(object? sender, NetChannelArgs e)
|
||||
{
|
||||
// Just dump all the prototypes on connect, before them missing could be an issue.
|
||||
foreach (var prototype in LoadedPrototypes)
|
||||
foreach (var prototype in _loadedPrototypes)
|
||||
{
|
||||
var msg = new GamePrototypeLoadMessage();
|
||||
msg.PrototypeData = prototype;
|
||||
var msg = new GamePrototypeLoadMessage
|
||||
{
|
||||
PrototypeData = prototype
|
||||
};
|
||||
e.Channel.SendMessage(msg);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ using Content.Shared.Damage;
|
|||
using Content.Shared.Database;
|
||||
using Content.Shared.Inventory;
|
||||
using Content.Shared.PDA;
|
||||
using Content.Shared.Stacks;
|
||||
using Content.Shared.Verbs;
|
||||
using Content.Shared.Weapons.Ranged.Components;
|
||||
using Robust.Server.GameObjects;
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ using Content.Server.Prayer;
|
|||
using Content.Server.Xenoarchaeology.XenoArtifacts;
|
||||
using Content.Server.Xenoarchaeology.XenoArtifacts.Triggers.Components;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.Configurable;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.GameTicking;
|
||||
using Content.Shared.Interaction.Helpers;
|
||||
|
|
@ -27,7 +28,7 @@ using Robust.Shared.Console;
|
|||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Timing;
|
||||
using static Content.Shared.Configurable.SharedConfigurationComponent;
|
||||
using static Content.Shared.Configurable.ConfigurationComponent;
|
||||
|
||||
namespace Content.Server.Administration.Systems
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ using Content.Server.Chat;
|
|||
using Content.Server.Chat.Systems;
|
||||
using Content.Server.Power.Components;
|
||||
using Content.Server.VendingMachines;
|
||||
using Content.Shared.VendingMachines;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
using Robust.Shared.Timing;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
using Content.Server.Ensnaring;
|
||||
using Content.Server.Ensnaring.Components;
|
||||
using Content.Shared.Alert;
|
||||
using Content.Shared.Ensnaring.Components;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace Content.Server.Alert.Click;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ using Content.Server.Actions;
|
|||
using Content.Server.Bed.Components;
|
||||
using Content.Server.Bed.Sleep;
|
||||
using Content.Server.Body.Systems;
|
||||
using Content.Server.Buckle.Components;
|
||||
using Content.Server.MobState;
|
||||
using Content.Server.Power.Components;
|
||||
using Content.Server.Power.EntitySystems;
|
||||
|
|
|
|||
|
|
@ -1,38 +0,0 @@
|
|||
using Content.Server.Buckle.Systems;
|
||||
using Content.Shared.Buckle.Components;
|
||||
|
||||
namespace Content.Server.Buckle.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Component that handles sitting entities into <see cref="StrapComponent"/>s.
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
[ComponentReference(typeof(SharedBuckleComponent))]
|
||||
[Access(typeof(BuckleSystem))]
|
||||
public sealed class BuckleComponent : SharedBuckleComponent
|
||||
{
|
||||
/// <summary>
|
||||
/// The amount of time that must pass for this entity to
|
||||
/// be able to unbuckle after recently buckling.
|
||||
/// </summary>
|
||||
[DataField("delay")]
|
||||
public TimeSpan UnbuckleDelay = TimeSpan.FromSeconds(0.25f);
|
||||
|
||||
/// <summary>
|
||||
/// The time that this entity buckled at.
|
||||
/// </summary>
|
||||
[ViewVariables] public TimeSpan BuckleTime;
|
||||
|
||||
/// <summary>
|
||||
/// The strap that this component is buckled to.
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
public StrapComponent? BuckledTo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The amount of space that this entity occupies in a
|
||||
/// <see cref="StrapComponent"/>.
|
||||
/// </summary>
|
||||
[DataField("size")]
|
||||
public int Size = 100;
|
||||
}
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
using Content.Server.Buckle.Systems;
|
||||
using Content.Shared.Alert;
|
||||
using Content.Shared.Buckle.Components;
|
||||
using Robust.Shared.Audio;
|
||||
|
||||
namespace Content.Server.Buckle.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
[ComponentReference(typeof(SharedStrapComponent))]
|
||||
[Access(typeof(BuckleSystem))]
|
||||
public sealed class StrapComponent : SharedStrapComponent
|
||||
{
|
||||
/// <summary>
|
||||
/// The angle in degrees to rotate the player by when they get strapped
|
||||
/// </summary>
|
||||
[DataField("rotation")]
|
||||
public int Rotation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The size of the strap which is compared against when buckling entities
|
||||
/// </summary>
|
||||
[DataField("size")]
|
||||
public int Size { get; set; } = 100;
|
||||
|
||||
/// <summary>
|
||||
/// If disabled, nothing can be buckled on this object, and it will unbuckle anything that's already buckled
|
||||
/// </summary>
|
||||
public bool Enabled { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// You can specify the offset the entity will have after unbuckling.
|
||||
/// </summary>
|
||||
[DataField("unbuckleOffset", required: false)]
|
||||
public Vector2 UnbuckleOffset = Vector2.Zero;
|
||||
/// <summary>
|
||||
/// The sound to be played when a mob is buckled
|
||||
/// </summary>
|
||||
[DataField("buckleSound")]
|
||||
public SoundSpecifier BuckleSound { get; } = new SoundPathSpecifier("/Audio/Effects/buckle.ogg");
|
||||
|
||||
/// <summary>
|
||||
/// The sound to be played when a mob is unbuckled
|
||||
/// </summary>
|
||||
[DataField("unbuckleSound")]
|
||||
public SoundSpecifier UnbuckleSound { get; } = new SoundPathSpecifier("/Audio/Effects/unbuckle.ogg");
|
||||
|
||||
/// <summary>
|
||||
/// ID of the alert to show when buckled
|
||||
/// </summary>
|
||||
[DataField("buckledAlertType")]
|
||||
public AlertType BuckledAlertType { get; } = AlertType.Buckled;
|
||||
|
||||
/// <summary>
|
||||
/// The sum of the sizes of all the buckled entities in this strap
|
||||
/// </summary>
|
||||
public int OccupiedSize { get; set; }
|
||||
}
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using Content.Server.Buckle.Components;
|
||||
using Content.Server.Storage.Components;
|
||||
using Content.Shared.Alert;
|
||||
using Content.Shared.Bed.Sleep;
|
||||
|
|
@ -14,7 +13,6 @@ using Content.Shared.Stunnable;
|
|||
using Content.Shared.Vehicle.Components;
|
||||
using Content.Shared.Verbs;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Player;
|
||||
|
||||
namespace Content.Server.Buckle.Systems;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
using System.Linq;
|
||||
using Content.Server.Buckle.Components;
|
||||
using Content.Server.Construction.Completions;
|
||||
using Content.Shared.Buckle.Components;
|
||||
using Content.Shared.Destructible;
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ using Content.Shared.Body.Components;
|
|||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.Materials;
|
||||
using Content.Shared.MobState.Components;
|
||||
using Content.Shared.Stacks;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.Map;
|
||||
|
|
|
|||
|
|
@ -1,18 +0,0 @@
|
|||
using Content.Shared.CartridgeLoader;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations;
|
||||
|
||||
namespace Content.Server.CartridgeLoader;
|
||||
|
||||
[RegisterComponent]
|
||||
[ComponentReference(typeof(SharedCartridgeLoaderComponent))]
|
||||
public sealed class CartridgeLoaderComponent : SharedCartridgeLoaderComponent
|
||||
{
|
||||
/// <summary>
|
||||
/// The maximum amount of programs that can be installed on the cartridge loader entity
|
||||
/// </summary>
|
||||
[DataField("diskSpace")]
|
||||
public int DiskSpace = 5;
|
||||
|
||||
[DataField("uiKey", readOnly: true, required: true, customTypeSerializer: typeof(EnumSerializer))]
|
||||
public Enum UiKey = default!;
|
||||
}
|
||||
|
|
@ -241,13 +241,13 @@ public sealed class CartridgeLoaderSystem : SharedCartridgeLoaderSystem
|
|||
loader.BackgroundPrograms.Remove(cartridgeUid);
|
||||
}
|
||||
|
||||
protected override void OnItemInserted(EntityUid uid, SharedCartridgeLoaderComponent loader, EntInsertedIntoContainerMessage args)
|
||||
protected override void OnItemInserted(EntityUid uid, Shared.CartridgeLoader.CartridgeLoaderComponent loader, EntInsertedIntoContainerMessage args)
|
||||
{
|
||||
RaiseLocalEvent(args.Entity, new CartridgeAddedEvent(uid));
|
||||
base.OnItemInserted(uid, loader, args);
|
||||
}
|
||||
|
||||
protected override void OnItemRemoved(EntityUid uid, SharedCartridgeLoaderComponent loader, EntRemovedFromContainerMessage args)
|
||||
protected override void OnItemRemoved(EntityUid uid, Shared.CartridgeLoader.CartridgeLoaderComponent loader, EntRemovedFromContainerMessage args)
|
||||
{
|
||||
var deactivate = loader.BackgroundPrograms.Remove(args.Entity);
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
namespace Content.Server.Chemistry.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed class ActiveSolutionHeaterComponent : Component
|
||||
{
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
namespace Content.Server.Chemistry.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed class SolutionHeaterComponent : Component
|
||||
{
|
||||
public readonly string BeakerSlotId = "beakerSlot";
|
||||
|
||||
[DataField("heatPerSecond")]
|
||||
public float HeatPerSecond = 120;
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public float HeatMultiplier = 1;
|
||||
|
||||
[DataField("machinePartHeatPerSecond")]
|
||||
public string MachinePartHeatPerSecond = "Laser";
|
||||
|
||||
[DataField("partRatingHeatMultiplier")]
|
||||
public float PartRatingHeatMultiplier = 1.5f;
|
||||
}
|
||||
|
|
@ -16,7 +16,7 @@ namespace Content.Server.Chemistry.EntitySystems
|
|||
|
||||
var coordinates = Transform(owner).Coordinates;
|
||||
|
||||
_adminLogger.Add(LogType.ChemicalReaction, reaction.Impact,
|
||||
AdminLogger.Add(LogType.ChemicalReaction, reaction.Impact,
|
||||
$"Chemical reaction {reaction.ID:reaction} occurred with strength {unitReactions:strength} on entity {ToPrettyString(owner):metabolizer} at {coordinates}");
|
||||
|
||||
SoundSystem.Play(reaction.Sound.GetSound(), Filter.Pvs(owner, entityManager:EntityManager), owner);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,65 @@
|
|||
using Content.Server.Chemistry.Components;
|
||||
using Content.Server.Chemistry.Components.SolutionManager;
|
||||
using Content.Server.Construction;
|
||||
using Content.Server.Power.Components;
|
||||
using Content.Shared.Containers.ItemSlots;
|
||||
|
||||
namespace Content.Server.Chemistry.EntitySystems;
|
||||
|
||||
public sealed class SolutionHeaterSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly ItemSlotsSystem _itemSlots = default!;
|
||||
[Dependency] private readonly SolutionContainerSystem _solution = default!;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Initialize()
|
||||
{
|
||||
SubscribeLocalEvent<SolutionHeaterComponent, PowerChangedEvent>(OnPowerChanged);
|
||||
SubscribeLocalEvent<SolutionHeaterComponent, RefreshPartsEvent>(OnRefreshParts);
|
||||
SubscribeLocalEvent<SolutionHeaterComponent, UpgradeExamineEvent>(OnUpgradeExamine);
|
||||
}
|
||||
|
||||
private void OnPowerChanged(EntityUid uid, SolutionHeaterComponent component, ref PowerChangedEvent args)
|
||||
{
|
||||
if (args.Powered)
|
||||
{
|
||||
EnsureComp<ActiveSolutionHeaterComponent>(uid);
|
||||
}
|
||||
else
|
||||
{
|
||||
RemComp<ActiveSolutionHeaterComponent>(uid);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnRefreshParts(EntityUid uid, SolutionHeaterComponent component, RefreshPartsEvent args)
|
||||
{
|
||||
var heatRating = args.PartRatings[component.MachinePartHeatPerSecond] - 1;
|
||||
|
||||
component.HeatMultiplier = MathF.Pow(component.PartRatingHeatMultiplier, heatRating);
|
||||
}
|
||||
|
||||
private void OnUpgradeExamine(EntityUid uid, SolutionHeaterComponent component, UpgradeExamineEvent args)
|
||||
{
|
||||
args.AddPercentageUpgrade("solution-heater-upgrade-heat", component.HeatMultiplier);
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
base.Update(frameTime);
|
||||
|
||||
foreach (var (_, heater) in EntityQuery<ActiveSolutionHeaterComponent, SolutionHeaterComponent>())
|
||||
{
|
||||
if (_itemSlots.GetItemOrNull(heater.Owner, heater.BeakerSlotId) is not { } item)
|
||||
continue;
|
||||
|
||||
if (!TryComp<SolutionContainerManagerComponent>(item, out var solution))
|
||||
continue;
|
||||
|
||||
var energy = heater.HeatPerSecond * heater.HeatMultiplier * frameTime;
|
||||
foreach (var s in solution.Solutions.Values)
|
||||
{
|
||||
_solution.AddThermalEnergy(solution.Owner, s, energy);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -66,7 +66,7 @@ public sealed class ClimbSystem : SharedClimbSystem
|
|||
SubscribeLocalEvent<GlassTableComponent, ClimbedOnEvent>(OnGlassClimbed);
|
||||
}
|
||||
|
||||
protected override void OnCanDragDropOn(EntityUid uid, SharedClimbableComponent component, CanDragDropOnEvent args)
|
||||
protected override void OnCanDragDropOn(EntityUid uid, ClimbableComponent component, CanDragDropOnEvent args)
|
||||
{
|
||||
base.OnCanDragDropOn(uid, component, args);
|
||||
|
||||
|
|
@ -166,6 +166,7 @@ public sealed class ClimbSystem : SharedClimbSystem
|
|||
return;
|
||||
|
||||
climbing.IsClimbing = true;
|
||||
Dirty(climbing);
|
||||
|
||||
MoveEntityToward(uid, climbable, physics, climbing);
|
||||
// we may potentially need additional logic since we're forcing a player onto a climbable
|
||||
|
|
@ -265,6 +266,7 @@ public sealed class ClimbSystem : SharedClimbSystem
|
|||
|
||||
climbing.IsClimbing = false;
|
||||
climbing.OwnerIsTransitioning = false;
|
||||
Dirty(climbing);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -275,7 +277,7 @@ public sealed class ClimbSystem : SharedClimbSystem
|
|||
/// <param name="target">The object that is being vaulted</param>
|
||||
/// <param name="reason">The reason why it cant be dropped</param>
|
||||
/// <returns></returns>
|
||||
private bool CanVault(SharedClimbableComponent component, EntityUid user, EntityUid target, out string reason)
|
||||
private bool CanVault(ClimbableComponent component, EntityUid user, EntityUid target, out string reason)
|
||||
{
|
||||
if (!_actionBlockerSystem.CanInteract(user, target))
|
||||
{
|
||||
|
|
@ -311,7 +313,7 @@ public sealed class ClimbSystem : SharedClimbSystem
|
|||
/// <param name="target">The object that is being vaulted onto</param>
|
||||
/// <param name="reason">The reason why it cant be dropped</param>
|
||||
/// <returns></returns>
|
||||
private bool CanVault(SharedClimbableComponent component, EntityUid user, EntityUid dragged, EntityUid target,
|
||||
private bool CanVault(ClimbableComponent component, EntityUid user, EntityUid dragged, EntityUid target,
|
||||
out string reason)
|
||||
{
|
||||
if (!_actionBlockerSystem.CanInteract(user, dragged) || !_actionBlockerSystem.CanInteract(user, target))
|
||||
|
|
@ -353,7 +355,7 @@ public sealed class ClimbSystem : SharedClimbSystem
|
|||
|
||||
private static void OnClimbingGetState(EntityUid uid, ClimbingComponent component, ref ComponentGetState args)
|
||||
{
|
||||
args.State = new SharedClimbingComponent.ClimbModeComponentState(component.IsClimbing, component.OwnerIsTransitioning);
|
||||
args.State = new ClimbingComponent.ClimbModeComponentState(component.IsClimbing, component.OwnerIsTransitioning);
|
||||
}
|
||||
|
||||
private void OnGlassClimbed(EntityUid uid, GlassTableComponent component, ClimbedOnEvent args)
|
||||
|
|
@ -401,7 +403,7 @@ public sealed class ClimbSystem : SharedClimbSystem
|
|||
_actionBlockerSystem.UpdateCanMove(uid);
|
||||
|
||||
// Transition back to KinematicController after BufferTime
|
||||
climbing.Owner.SpawnTimer((int) (SharedClimbingComponent.BufferTime * 1000), () =>
|
||||
climbing.Owner.SpawnTimer((int) (ClimbingComponent.BufferTime * 1000), () =>
|
||||
{
|
||||
if (climbing.Deleted) return;
|
||||
physics.BodyType = BodyType.KinematicController;
|
||||
|
|
|
|||
|
|
@ -1,49 +0,0 @@
|
|||
using Content.Shared.CCVar;
|
||||
using Content.Shared.Climbing;
|
||||
using Content.Shared.Damage;
|
||||
using Robust.Shared.Audio;
|
||||
|
||||
namespace Content.Server.Climbing.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
[ComponentReference(typeof(SharedClimbableComponent))]
|
||||
public sealed class ClimbableComponent : SharedClimbableComponent
|
||||
{
|
||||
/// <summary>
|
||||
/// The time it takes to climb onto the entity.
|
||||
/// </summary>
|
||||
[DataField("delay")]
|
||||
public float ClimbDelay = 0.8f;
|
||||
|
||||
/// <summary>
|
||||
/// If set, people can bonk on this if <see cref="CCVars.GameTableBonk"/> is set or if they are clumsy.
|
||||
/// </summary>
|
||||
[DataField("bonk")] public bool Bonk = false;
|
||||
|
||||
/// <summary>
|
||||
/// Chance of bonk triggering if the user is clumsy.
|
||||
/// </summary>
|
||||
[DataField("bonkClumsyChance")]
|
||||
public float BonkClumsyChance = 0.75f;
|
||||
|
||||
/// <summary>
|
||||
/// Sound to play when bonking.
|
||||
/// </summary>
|
||||
/// <seealso cref="Bonk"/>
|
||||
[DataField("bonkSound")]
|
||||
public SoundSpecifier? BonkSound;
|
||||
|
||||
/// <summary>
|
||||
/// How long to stun players on bonk, in seconds.
|
||||
/// </summary>
|
||||
/// <seealso cref="Bonk"/>
|
||||
[DataField("bonkTime")]
|
||||
public float BonkTime = 2;
|
||||
|
||||
/// <summary>
|
||||
/// How much damage to apply on bonk.
|
||||
/// </summary>
|
||||
/// <seealso cref="Bonk"/>
|
||||
[DataField("bonkDamage")]
|
||||
public DamageSpecifier? BonkDamage;
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
using Content.Shared.Climbing;
|
||||
|
||||
namespace Content.Server.Climbing.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
[ComponentReference(typeof(SharedClimbingComponent))]
|
||||
[Access(typeof(ClimbSystem))]
|
||||
public sealed class ClimbingComponent : SharedClimbingComponent
|
||||
{
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public override bool IsClimbing
|
||||
{
|
||||
get => base.IsClimbing;
|
||||
set
|
||||
{
|
||||
if (base.IsClimbing == value) return;
|
||||
base.IsClimbing = value;
|
||||
Dirty();
|
||||
}
|
||||
}
|
||||
|
||||
public override bool OwnerIsTransitioning
|
||||
{
|
||||
get => base.OwnerIsTransitioning;
|
||||
set
|
||||
{
|
||||
if (value == base.OwnerIsTransitioning) return;
|
||||
base.OwnerIsTransitioning = value;
|
||||
Dirty();
|
||||
}
|
||||
}
|
||||
|
||||
[ViewVariables]
|
||||
public Dictionary<string, int> DisabledFixtureMasks { get; } = new();
|
||||
}
|
||||
|
|
@ -22,6 +22,7 @@ using Content.Server.Construction.Components;
|
|||
using Content.Server.Materials;
|
||||
using Content.Server.Stack;
|
||||
using Content.Server.Jobs;
|
||||
using Content.Shared.Humanoid;
|
||||
using Content.Shared.Humanoid.Prototypes;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Server.Containers;
|
||||
|
|
|
|||
|
|
@ -1,16 +0,0 @@
|
|||
using Content.Shared.Configurable;
|
||||
using Content.Shared.Tools;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
|
||||
namespace Content.Server.Configurable;
|
||||
|
||||
[RegisterComponent]
|
||||
[ComponentReference(typeof(SharedConfigurationComponent))]
|
||||
public sealed class ConfigurationComponent : SharedConfigurationComponent
|
||||
{
|
||||
[DataField("config")]
|
||||
public readonly Dictionary<string, string> Config = new();
|
||||
|
||||
[DataField("qualityNeeded", customTypeSerializer: typeof(PrototypeIdSerializer<ToolQualityPrototype>))]
|
||||
public string QualityNeeded = "Pulsing";
|
||||
}
|
||||
|
|
@ -1,8 +1,9 @@
|
|||
using Content.Shared.Configurable;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Tools.Components;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Containers;
|
||||
using static Content.Shared.Configurable.SharedConfigurationComponent;
|
||||
using static Content.Shared.Configurable.ConfigurationComponent;
|
||||
|
||||
namespace Content.Server.Configurable;
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ using Content.Server.Stack;
|
|||
using Content.Shared.Construction;
|
||||
using Content.Shared.Hands.EntitySystems;
|
||||
using Content.Shared.Prototypes;
|
||||
using Content.Shared.Stacks;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
using Content.Server.Stack;
|
||||
using Content.Shared.Construction;
|
||||
using Content.Shared.Prototypes;
|
||||
using Content.Shared.Stacks;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ using Content.Server.Stack;
|
|||
using Content.Shared.Construction;
|
||||
using Content.Shared.Examine;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Stacks;
|
||||
using Content.Shared.Tag;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Containers;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ using Content.Server.Construction.Components;
|
|||
using Content.Server.Tools;
|
||||
using Content.Server.Stack;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Stacks;
|
||||
using Content.Shared.Tools.Components;
|
||||
|
||||
namespace Content.Server.Construction
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using Content.Server.VendingMachines;
|
||||
using Content.Shared.VendingMachines;
|
||||
|
||||
namespace Content.Server.Destructible.Thresholds.Behaviors
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
using Content.Server.Stack;
|
||||
using Content.Shared.Prototypes;
|
||||
using Content.Shared.Stacks;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Dictionary;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
using Content.Server.Bed.Components;
|
||||
using Content.Server.Buckle.Components;
|
||||
using Content.Shared.Bed.Sleep;
|
||||
using Content.Shared.Buckle.Components;
|
||||
using Content.Shared.Disease;
|
||||
|
||||
namespace Content.Server.Disease.Cures
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ using System.Threading;
|
|||
using Content.Server.Chat.Systems;
|
||||
using Content.Server.GameTicking;
|
||||
using Content.Server.GameTicking.Rules;
|
||||
using Content.Server.Humanoid;
|
||||
using Content.Server.NPC;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Dragon;
|
||||
|
|
@ -22,6 +21,7 @@ using Robust.Shared.GameStates;
|
|||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Random;
|
||||
using Content.Server.NPC.Systems;
|
||||
using Content.Shared.Humanoid;
|
||||
|
||||
namespace Content.Server.Dragon
|
||||
{
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ namespace Content.Server.Engineering.EntitySystems
|
|||
if (component.Deleted || Deleted(component.Owner))
|
||||
return;
|
||||
|
||||
if (EntityManager.TryGetComponent<SharedStackComponent?>(component.Owner, out var stackComp)
|
||||
if (EntityManager.TryGetComponent<StackComponent?>(component.Owner, out var stackComp)
|
||||
&& component.RemoveOnInteract && !_stackSystem.Use(uid, 1, stackComp))
|
||||
{
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -1,13 +0,0 @@
|
|||
using Content.Shared.Ensnaring.Components;
|
||||
using Robust.Shared.Containers;
|
||||
|
||||
namespace Content.Server.Ensnaring.Components;
|
||||
[RegisterComponent]
|
||||
[ComponentReference(typeof(SharedEnsnareableComponent))]
|
||||
public sealed class EnsnareableComponent : SharedEnsnareableComponent
|
||||
{
|
||||
/// <summary>
|
||||
/// The container where the <see cref="EnsnaringComponent"/> entity will be stored
|
||||
/// </summary>
|
||||
public Container Container = default!;
|
||||
}
|
||||
|
|
@ -1,43 +1,5 @@
|
|||
using System.Threading;
|
||||
using Content.Shared.Ensnaring.Components;
|
||||
|
||||
namespace Content.Server.Ensnaring.Components;
|
||||
[RegisterComponent]
|
||||
[ComponentReference(typeof(SharedEnsnaringComponent))]
|
||||
public sealed class EnsnaringComponent : SharedEnsnaringComponent
|
||||
{
|
||||
/// <summary>
|
||||
/// Should movement cancel breaking out?
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField("canMoveBreakout")]
|
||||
public bool CanMoveBreakout;
|
||||
|
||||
public CancellationTokenSource? CancelToken;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used for the do after event to free the entity that owns the <see cref="EnsnareableComponent"/>
|
||||
/// </summary>
|
||||
public sealed class FreeEnsnareDoAfterComplete : EntityEventArgs
|
||||
{
|
||||
public readonly EntityUid EnsnaringEntity;
|
||||
|
||||
public FreeEnsnareDoAfterComplete(EntityUid ensnaringEntity)
|
||||
{
|
||||
EnsnaringEntity = ensnaringEntity;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used for the do after event when it fails to free the entity that owns the <see cref="EnsnareableComponent"/>
|
||||
/// </summary>
|
||||
public sealed class FreeEnsnareDoAfterCancel : EntityEventArgs
|
||||
{
|
||||
public readonly EntityUid EnsnaringEntity;
|
||||
|
||||
public FreeEnsnareDoAfterCancel(EntityUid ensnaringEntity)
|
||||
{
|
||||
EnsnaringEntity = ensnaringEntity;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,10 @@
|
|||
using System.Threading;
|
||||
using Content.Server.DoAfter;
|
||||
using Content.Server.Ensnaring.Components;
|
||||
using Content.Shared.Alert;
|
||||
using Content.Shared.Ensnaring.Components;
|
||||
using Content.Shared.IdentityManagement;
|
||||
using Content.Shared.StepTrigger.Systems;
|
||||
using Content.Shared.Throwing;
|
||||
using Robust.Shared.Player;
|
||||
|
||||
namespace Content.Server.Ensnaring;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,9 @@
|
|||
using Content.Server.Ensnaring.Components;
|
||||
using Content.Server.Popups;
|
||||
using Content.Shared.Ensnaring;
|
||||
using Content.Shared.Ensnaring.Components;
|
||||
using Content.Shared.Popups;
|
||||
using Robust.Server.Containers;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.Player;
|
||||
|
||||
namespace Content.Server.Ensnaring;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +0,0 @@
|
|||
using Content.Shared.Flash;
|
||||
|
||||
namespace Content.Server.Flash.Components
|
||||
{
|
||||
[ComponentReference(typeof(SharedFlashableComponent))]
|
||||
[RegisterComponent, Access(typeof(FlashSystem))]
|
||||
public sealed class FlashableComponent : SharedFlashableComponent
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
using System.Linq;
|
||||
using Content.Server.Buckle.Components;
|
||||
using Content.Server.Buckle.Systems;
|
||||
using Content.Server.Storage.Components;
|
||||
using Content.Shared.Buckle.Components;
|
||||
using Content.Shared.Foldable;
|
||||
using Content.Shared.Verbs;
|
||||
using JetBrains.Annotations;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ using Content.Server.Actions;
|
|||
using Content.Server.Chat.Managers;
|
||||
using Content.Server.Disease;
|
||||
using Content.Server.Disease.Components;
|
||||
using Content.Server.Humanoid;
|
||||
using Content.Server.Mind.Components;
|
||||
using Content.Server.MobState;
|
||||
using Content.Server.Players;
|
||||
|
|
@ -14,6 +13,7 @@ using Content.Server.Traitor;
|
|||
using Content.Server.Zombies;
|
||||
using Content.Shared.Actions.ActionTypes;
|
||||
using Content.Shared.CCVar;
|
||||
using Content.Shared.Humanoid;
|
||||
using Content.Shared.MobState;
|
||||
using Content.Shared.MobState.Components;
|
||||
using Content.Shared.Preferences;
|
||||
|
|
@ -21,7 +21,6 @@ using Content.Shared.Roles;
|
|||
using Content.Shared.Zombies;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
using Robust.Shared.Utility;
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ using Content.Shared.Input;
|
|||
using Content.Shared.Inventory;
|
||||
using Content.Shared.Physics.Pull;
|
||||
using Content.Shared.Pulling.Components;
|
||||
using Content.Shared.Stacks;
|
||||
using Content.Shared.Throwing;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Server.Player;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
using Content.Server.Hands.Systems;
|
||||
using Content.Server.Administration.Logs;
|
||||
using Content.Server.Hands.Systems;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.Examine;
|
||||
using Content.Shared.Interaction.Events;
|
||||
using Content.Shared.Item;
|
||||
|
|
@ -20,6 +22,7 @@ public sealed class RandomGiftSystem : EntitySystem
|
|||
[Dependency] private readonly IComponentFactory _componentFactory = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
|
||||
|
||||
private readonly List<string> _possibleGiftsSafe = new();
|
||||
private readonly List<string> _possibleGiftsUnsafe = new();
|
||||
|
|
@ -54,6 +57,7 @@ public sealed class RandomGiftSystem : EntitySystem
|
|||
|
||||
var coords = Transform(args.User).Coordinates;
|
||||
var handsEnt = Spawn(component.SelectedEntity, coords);
|
||||
_adminLogger.Add(LogType.EntitySpawn, LogImpact.Low, $"{ToPrettyString(args.User)} used {ToPrettyString(component.Owner)} which spawned {ToPrettyString(handsEnt)}");
|
||||
EnsureComp<ItemComponent>(handsEnt); // For insane mode.
|
||||
if (component.Wrapper is not null)
|
||||
Spawn(component.Wrapper, coords);
|
||||
|
|
|
|||
|
|
@ -1,38 +0,0 @@
|
|||
using Content.Shared.Humanoid;
|
||||
using Content.Shared.Humanoid.Markings;
|
||||
using Content.Shared.Preferences;
|
||||
using Robust.Shared.Enums;
|
||||
|
||||
namespace Content.Server.Humanoid;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed class HumanoidComponent : SharedHumanoidComponent
|
||||
{
|
||||
public MarkingSet CurrentMarkings = new();
|
||||
|
||||
/// <summary>
|
||||
/// Any custom base layers this humanoid might have. See:
|
||||
/// limb transplants (potentially), robotic arms, etc.
|
||||
/// Stored on the server, this is merged in the client into
|
||||
/// all layer settings.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadOnly)]
|
||||
public Dictionary<HumanoidVisualLayers, CustomBaseLayerInfo> CustomBaseLayers = new();
|
||||
|
||||
public HashSet<HumanoidVisualLayers> PermanentlyHidden = new();
|
||||
|
||||
public HashSet<HumanoidVisualLayers> AllHiddenLayers
|
||||
{
|
||||
get
|
||||
{
|
||||
var result = new HashSet<HumanoidVisualLayers>(HiddenLayers);
|
||||
result.UnionWith(PermanentlyHidden);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// Couldn't these be somewhere else?
|
||||
[ViewVariables] public Gender Gender = default!;
|
||||
[ViewVariables] public int Age = 18;
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
using Content.Server.CharacterAppearance.Components;
|
||||
using Content.Shared.Humanoid;
|
||||
using Content.Shared.Preferences;
|
||||
|
||||
namespace Content.Server.Humanoid.Systems;
|
||||
|
|
|
|||
|
|
@ -1,13 +1,12 @@
|
|||
using Content.Server.Access.Systems;
|
||||
using Content.Server.Administration.Logs;
|
||||
using Content.Server.Humanoid;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.Hands;
|
||||
using Content.Shared.Humanoid;
|
||||
using Content.Shared.IdentityManagement;
|
||||
using Content.Shared.IdentityManagement.Components;
|
||||
using Content.Shared.Inventory;
|
||||
using Content.Shared.Inventory.Events;
|
||||
using Content.Shared.Preferences;
|
||||
using Robust.Shared.Enums;
|
||||
using Robust.Shared.GameObjects.Components.Localization;
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ using Content.Shared.Interaction;
|
|||
using Content.Shared.Kitchen;
|
||||
using Content.Shared.Popups;
|
||||
using Content.Shared.Random.Helpers;
|
||||
using Content.Shared.Stacks;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Audio;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
using System.Linq;
|
||||
using Content.Server.Humanoid;
|
||||
using Content.Server.UserInterface;
|
||||
using Content.Shared.Humanoid;
|
||||
using Content.Shared.Humanoid.Markings;
|
||||
using Content.Shared.MagicMirror;
|
||||
using Robust.Server.GameObjects;
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ using Content.Server.Mech.Systems;
|
|||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Mech;
|
||||
using Content.Shared.Mech.Equipment.Components;
|
||||
using Content.Shared.MobState.Components;
|
||||
using Content.Shared.Wall;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.Map;
|
||||
|
|
@ -115,17 +116,17 @@ public sealed class MechGrabberSystem : EntitySystem
|
|||
|
||||
private void OnInteract(EntityUid uid, MechGrabberComponent component, InteractNoHandEvent args)
|
||||
{
|
||||
if (args.Handled || args.Target == null)
|
||||
if (args.Handled || args.Target is not {} target)
|
||||
return;
|
||||
|
||||
var xform = Transform(args.Target.Value);
|
||||
if (xform.Anchored || HasComp<WallMountComponent>(args.Target.Value))
|
||||
var xform = Transform(target);
|
||||
if (xform.Anchored || HasComp<WallMountComponent>(target) || HasComp<MobStateComponent>(target))
|
||||
return;
|
||||
|
||||
if (component.ItemContainer.ContainedEntities.Count >= component.MaxContents)
|
||||
return;
|
||||
|
||||
if (!TryComp<MechComponent>(args.User, out var mech))
|
||||
if (!TryComp<MechComponent>(args.User, out var mech) || mech.PilotSlot.ContainedEntity == target)
|
||||
return;
|
||||
|
||||
if (mech.Energy + component.GrabEnergyDelta < 0)
|
||||
|
|
@ -134,17 +135,17 @@ public sealed class MechGrabberSystem : EntitySystem
|
|||
if (component.Token != null)
|
||||
return;
|
||||
|
||||
if (!_interaction.InRangeUnobstructed(args.User, args.Target.Value))
|
||||
if (!_interaction.InRangeUnobstructed(args.User, target))
|
||||
return;
|
||||
|
||||
args.Handled = true;
|
||||
component.Token = new();
|
||||
component.AudioStream = _audio.PlayPvs(component.GrabSound, uid);
|
||||
_doAfter.DoAfter(new DoAfterEventArgs(args.User, component.GrabDelay, component.Token.Token, args.Target, uid)
|
||||
_doAfter.DoAfter(new DoAfterEventArgs(args.User, component.GrabDelay, component.Token.Token, target, uid)
|
||||
{
|
||||
BreakOnTargetMove = true,
|
||||
BreakOnUserMove = true,
|
||||
UsedFinishedEvent = new MechGrabberGrabFinishedEvent(args.Target.Value),
|
||||
UsedFinishedEvent = new MechGrabberGrabFinishedEvent(target),
|
||||
UsedCancelledEvent = new MechGrabberGrabCancelledEvent()
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ using Content.Server.Atmos.EntitySystems;
|
|||
using Content.Server.DoAfter;
|
||||
using Content.Server.Mech.Components;
|
||||
using Content.Server.Power.Components;
|
||||
using Content.Server.Tools;
|
||||
using Content.Server.Wires;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.FixedPoint;
|
||||
|
|
@ -52,6 +53,7 @@ public sealed class MechSystem : SharedMechSystem
|
|||
SubscribeLocalEvent<MechComponent, DamageChangedEvent>(OnDamageChanged);
|
||||
SubscribeLocalEvent<MechComponent, MechEquipmentRemoveMessage>(OnRemoveEquipmentMessage);
|
||||
|
||||
SubscribeLocalEvent<MechPilotComponent, ToolUserAttemptUseEvent>(OnToolUseAttempt);
|
||||
SubscribeLocalEvent<MechPilotComponent, InhaleLocationEvent>(OnInhale);
|
||||
SubscribeLocalEvent<MechPilotComponent, ExhaleLocationEvent>(OnExhale);
|
||||
SubscribeLocalEvent<MechPilotComponent, AtmosExposedGetAirEvent>(OnExpose);
|
||||
|
|
@ -137,6 +139,12 @@ public sealed class MechSystem : SharedMechSystem
|
|||
ToggleMechUi(uid, component);
|
||||
}
|
||||
|
||||
private void OnToolUseAttempt(EntityUid uid, MechPilotComponent component, ref ToolUserAttemptUseEvent args)
|
||||
{
|
||||
if (args.Target == component.Mech)
|
||||
args.Cancelled = true;
|
||||
}
|
||||
|
||||
private void OnAlternativeVerb(EntityUid uid, MechComponent component, GetVerbsEvent<AlternativeVerb> args)
|
||||
{
|
||||
if (!args.CanAccess || !args.CanInteract || component.Broken)
|
||||
|
|
|
|||
|
|
@ -17,12 +17,11 @@ using Content.Server.Body.Components;
|
|||
using Content.Server.Climbing;
|
||||
using Content.Server.Construction;
|
||||
using Content.Server.DoAfter;
|
||||
using Content.Server.Humanoid;
|
||||
using Content.Server.Mind.Components;
|
||||
using Content.Server.Stack;
|
||||
using Content.Shared.Humanoid;
|
||||
using Content.Shared.Interaction.Events;
|
||||
using Content.Shared.Popups;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Random;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Server.Player;
|
||||
|
|
|
|||
16
Content.Server/Medical/Components/CryoPodComponent.cs
Normal file
16
Content.Server/Medical/Components/CryoPodComponent.cs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
using Content.Server.Atmos;
|
||||
using Content.Shared.Atmos;
|
||||
using Content.Shared.Medical.Cryogenics;
|
||||
|
||||
namespace Content.Server.Medical.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed class CryoPodComponent: SharedCryoPodComponent
|
||||
{
|
||||
/// <summary>
|
||||
/// Local air buffer that will be mixed with the pipenet, if one exists, per tick.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField("gasMixture")]
|
||||
public GasMixture Air { get; set; } = new(Atmospherics.OneAtmosphere);
|
||||
}
|
||||
59
Content.Server/Medical/CryoPodEjectLockWireAction.cs
Normal file
59
Content.Server/Medical/CryoPodEjectLockWireAction.cs
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
using Content.Server.Medical.Components;
|
||||
using Content.Server.Wires;
|
||||
using Content.Shared.Medical.Cryogenics;
|
||||
using Content.Shared.Wires;
|
||||
|
||||
namespace Content.Server.Medical;
|
||||
|
||||
/// <summary>
|
||||
/// Causes a failure in the cryo pod ejection system when cut. A crowbar will be needed to pry open the pod.
|
||||
/// </summary>
|
||||
[DataDefinition]
|
||||
public sealed class CryoPodEjectLockWireAction: BaseWireAction
|
||||
{
|
||||
[DataField("color")]
|
||||
private Color _statusColor = Color.Red;
|
||||
|
||||
[DataField("name")]
|
||||
private string _text = "LOCK";
|
||||
|
||||
public override object? StatusKey { get; } = CryoPodWireActionKey.Key;
|
||||
public override bool Cut(EntityUid user, Wire wire)
|
||||
{
|
||||
if (EntityManager.TryGetComponent<CryoPodComponent>(wire.Owner, out var cryoPodComponent) && !cryoPodComponent.PermaLocked)
|
||||
{
|
||||
cryoPodComponent.Locked = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool Mend(EntityUid user, Wire wire)
|
||||
{
|
||||
if (EntityManager.TryGetComponent<CryoPodComponent>(wire.Owner, out var cryoPodComponent) && !cryoPodComponent.PermaLocked)
|
||||
{
|
||||
cryoPodComponent.Locked = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool Pulse(EntityUid user, Wire wire)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public override StatusLightData? GetStatusLightData(Wire wire)
|
||||
{
|
||||
StatusLightState lightState = StatusLightState.Off;
|
||||
if (EntityManager.TryGetComponent<CryoPodComponent>(wire.Owner, out var cryoPodComponent) && cryoPodComponent.Locked)
|
||||
{
|
||||
lightState = StatusLightState.On; //TODO figure out why this doesn't get updated when the pod is emagged
|
||||
}
|
||||
|
||||
return new StatusLightData(
|
||||
_statusColor,
|
||||
lightState,
|
||||
_text);
|
||||
}
|
||||
}
|
||||
267
Content.Server/Medical/CryoPodSystem.cs
Normal file
267
Content.Server/Medical/CryoPodSystem.cs
Normal file
|
|
@ -0,0 +1,267 @@
|
|||
using System.Threading;
|
||||
using Content.Server.Atmos;
|
||||
using Content.Server.Atmos.EntitySystems;
|
||||
using Content.Server.Atmos.Piping.Components;
|
||||
using Content.Server.Atmos.Piping.Unary.EntitySystems;
|
||||
using Content.Server.Body.Components;
|
||||
using Content.Server.Body.Systems;
|
||||
using Content.Server.Chemistry.Components.SolutionManager;
|
||||
using Content.Server.Chemistry.EntitySystems;
|
||||
using Content.Server.Climbing;
|
||||
using Content.Server.DoAfter;
|
||||
using Content.Server.Medical.Components;
|
||||
using Content.Server.NodeContainer;
|
||||
using Content.Server.NodeContainer.NodeGroups;
|
||||
using Content.Server.NodeContainer.Nodes;
|
||||
using Content.Server.Power.Components;
|
||||
using Content.Server.Tools;
|
||||
using Content.Server.UserInterface;
|
||||
using Content.Shared.Chemistry;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.Containers.ItemSlots;
|
||||
using Content.Shared.Destructible;
|
||||
using Content.Shared.DragDrop;
|
||||
using Content.Shared.Emag.Systems;
|
||||
using Content.Shared.Examine;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Medical.Cryogenics;
|
||||
using Content.Shared.MedicalScanner;
|
||||
using Content.Shared.Tools.Components;
|
||||
using Content.Shared.Verbs;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Server.Medical;
|
||||
|
||||
public sealed partial class CryoPodSystem: SharedCryoPodSystem
|
||||
{
|
||||
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
|
||||
[Dependency] private readonly GasCanisterSystem _gasCanisterSystem = default!;
|
||||
[Dependency] private readonly ClimbSystem _climbSystem = default!;
|
||||
[Dependency] private readonly ItemSlotsSystem _itemSlotsSystem = default!;
|
||||
[Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!;
|
||||
[Dependency] private readonly BloodstreamSystem _bloodstreamSystem = default!;
|
||||
[Dependency] private readonly UserInterfaceSystem _userInterfaceSystem = default!;
|
||||
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
|
||||
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
|
||||
[Dependency] private readonly ToolSystem _toolSystem = default!;
|
||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||
[Dependency] private readonly MetaDataSystem _metaDataSystem = default!;
|
||||
[Dependency] private readonly ReactiveSystem _reactiveSystem = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<CryoPodComponent, ComponentInit>(OnComponentInit);
|
||||
SubscribeLocalEvent<CryoPodComponent, GetVerbsEvent<AlternativeVerb>>(AddAlternativeVerbs);
|
||||
SubscribeLocalEvent<CryoPodComponent, GotEmaggedEvent>(OnEmagged);
|
||||
SubscribeLocalEvent<CryoPodComponent, DoInsertCryoPodEvent>(DoInsertCryoPod);
|
||||
SubscribeLocalEvent<CryoPodComponent, DoInsertCancelledCryoPodEvent>(DoInsertCancelCryoPod);
|
||||
SubscribeLocalEvent<CryoPodComponent, CryoPodPryFinished>(OnCryoPodPryFinished);
|
||||
SubscribeLocalEvent<CryoPodComponent, CryoPodPryInterrupted>(OnCryoPodPryInterrupted);
|
||||
|
||||
SubscribeLocalEvent<CryoPodComponent, AtmosDeviceUpdateEvent>(OnCryoPodUpdateAtmosphere);
|
||||
SubscribeLocalEvent<CryoPodComponent, DragDropEvent>(HandleDragDropOn);
|
||||
SubscribeLocalEvent<CryoPodComponent, InteractUsingEvent>(OnInteractUsing);
|
||||
SubscribeLocalEvent<CryoPodComponent, ExaminedEvent>(OnExamined);
|
||||
SubscribeLocalEvent<CryoPodComponent, PowerChangedEvent>(OnPowerChanged);
|
||||
SubscribeLocalEvent<CryoPodComponent, GasAnalyzerScanEvent>(OnGasAnalyzed);
|
||||
SubscribeLocalEvent<CryoPodComponent, ActivatableUIOpenAttemptEvent>(OnActivateUIAttempt);
|
||||
SubscribeLocalEvent<CryoPodComponent, AfterActivatableUIOpenEvent>(OnActivateUI);
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
base.Update(frameTime);
|
||||
|
||||
var curTime = _gameTiming.CurTime;
|
||||
var bloodStreamQuery = GetEntityQuery<BloodstreamComponent>();
|
||||
var metaDataQuery = GetEntityQuery<MetaDataComponent>();
|
||||
var itemSlotsQuery = GetEntityQuery<ItemSlotsComponent>();
|
||||
var fitsInDispenserQuery = GetEntityQuery<FitsInDispenserComponent>();
|
||||
var solutionContainerManagerQuery = GetEntityQuery<SolutionContainerManagerComponent>();
|
||||
foreach (var (_, cryoPod) in EntityQuery<ActiveCryoPodComponent, CryoPodComponent>())
|
||||
{
|
||||
metaDataQuery.TryGetComponent(cryoPod.Owner, out var metaDataComponent);
|
||||
if (curTime < cryoPod.NextInjectionTime + _metaDataSystem.GetPauseTime(cryoPod.Owner, metaDataComponent))
|
||||
continue;
|
||||
cryoPod.NextInjectionTime = curTime + TimeSpan.FromSeconds(cryoPod.BeakerTransferTime);
|
||||
|
||||
if (
|
||||
!itemSlotsQuery.TryGetComponent(cryoPod.Owner, out var itemSlotsComponent)
|
||||
|| !fitsInDispenserQuery.TryGetComponent(cryoPod.Owner, out var fitsInDispenserComponent)
|
||||
|| !solutionContainerManagerQuery.TryGetComponent(cryoPod.Owner, out var solutionContainerManagerComponent))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var container = _itemSlotsSystem.GetItemOrNull(cryoPod.Owner, cryoPod.SolutionContainerName, itemSlotsComponent);
|
||||
var patient = cryoPod.BodyContainer.ContainedEntity;
|
||||
if (container != null
|
||||
&& container.Value.Valid
|
||||
&& patient != null
|
||||
&& _solutionContainerSystem.TryGetFitsInDispenser(container.Value, out var containerSolution, dispenserFits: fitsInDispenserComponent, solutionManager: solutionContainerManagerComponent))
|
||||
{
|
||||
if (!bloodStreamQuery.TryGetComponent(patient, out var bloodstream))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var solutionToInject = _solutionContainerSystem.SplitSolution(container.Value, containerSolution, cryoPod.BeakerTransferAmount);
|
||||
_bloodstreamSystem.TryAddToChemicals(patient.Value, solutionToInject, bloodstream);
|
||||
_reactiveSystem.DoEntityReaction(patient.Value, solutionToInject, ReactionMethod.Injection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void EjectBody(EntityUid uid, SharedCryoPodComponent? cryoPodComponent)
|
||||
{
|
||||
if (!Resolve(uid, ref cryoPodComponent))
|
||||
return;
|
||||
if (cryoPodComponent.BodyContainer.ContainedEntity is not {Valid: true} contained)
|
||||
return;
|
||||
base.EjectBody(uid, cryoPodComponent);
|
||||
_climbSystem.ForciblySetClimbing(contained, uid);
|
||||
}
|
||||
|
||||
#region Interaction
|
||||
|
||||
private void HandleDragDropOn(EntityUid uid, CryoPodComponent cryoPodComponent, DragDropEvent args)
|
||||
{
|
||||
if (cryoPodComponent.BodyContainer.ContainedEntity != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (cryoPodComponent.DragDropCancelToken != null)
|
||||
{
|
||||
cryoPodComponent.DragDropCancelToken.Cancel();
|
||||
cryoPodComponent.DragDropCancelToken = null;
|
||||
return;
|
||||
}
|
||||
|
||||
cryoPodComponent.DragDropCancelToken = new CancellationTokenSource();
|
||||
var doAfterArgs = new DoAfterEventArgs(args.User, cryoPodComponent.EntryDelay, cryoPodComponent.DragDropCancelToken.Token, uid, args.Dragged)
|
||||
{
|
||||
BreakOnDamage = true,
|
||||
BreakOnStun = true,
|
||||
BreakOnTargetMove = true,
|
||||
BreakOnUserMove = true,
|
||||
NeedHand = false,
|
||||
TargetFinishedEvent = new DoInsertCryoPodEvent(args.Dragged),
|
||||
TargetCancelledEvent = new DoInsertCancelledCryoPodEvent()
|
||||
};
|
||||
_doAfterSystem.DoAfter(doAfterArgs);
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
private void OnActivateUIAttempt(EntityUid uid, CryoPodComponent cryoPodComponent, ActivatableUIOpenAttemptEvent args)
|
||||
{
|
||||
if (args.Cancelled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var containedEntity = cryoPodComponent.BodyContainer.ContainedEntity;
|
||||
if (containedEntity == null || containedEntity == args.User || !HasComp<ActiveCryoPodComponent>(uid))
|
||||
{
|
||||
args.Cancel();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnActivateUI(EntityUid uid, CryoPodComponent cryoPodComponent, AfterActivatableUIOpenEvent args)
|
||||
{
|
||||
_userInterfaceSystem.TrySendUiMessage(
|
||||
uid,
|
||||
SharedHealthAnalyzerComponent.HealthAnalyzerUiKey.Key,
|
||||
new SharedHealthAnalyzerComponent.HealthAnalyzerScannedUserMessage(cryoPodComponent.BodyContainer.ContainedEntity));
|
||||
}
|
||||
|
||||
private void OnInteractUsing(EntityUid uid, CryoPodComponent cryoPodComponent, InteractUsingEvent args)
|
||||
{
|
||||
if (args.Handled || !cryoPodComponent.Locked || cryoPodComponent.BodyContainer.ContainedEntity == null)
|
||||
return;
|
||||
|
||||
if (TryComp(args.Used, out ToolComponent? tool)
|
||||
&& tool.Qualities.Contains("Prying")) // Why aren't those enums?
|
||||
{
|
||||
if (cryoPodComponent.IsPrying)
|
||||
return;
|
||||
cryoPodComponent.IsPrying = true;
|
||||
|
||||
_toolSystem.UseTool(args.Used, args.User, uid, 0f,
|
||||
cryoPodComponent.PryDelay, "Prying",
|
||||
new CryoPodPryFinished(), new CryoPodPryInterrupted(), uid);
|
||||
|
||||
args.Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnExamined(EntityUid uid, CryoPodComponent component, ExaminedEvent args)
|
||||
{
|
||||
var container = _itemSlotsSystem.GetItemOrNull(component.Owner, component.SolutionContainerName);
|
||||
if (args.IsInDetailsRange && container != null && _solutionContainerSystem.TryGetFitsInDispenser(container.Value, out var containerSolution))
|
||||
{
|
||||
args.PushMarkup(Loc.GetString("cryo-pod-examine", ("beaker", Name(container.Value))));
|
||||
if (containerSolution.CurrentVolume == 0)
|
||||
{
|
||||
args.PushMarkup(Loc.GetString("cryo-pod-empty-beaker"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPowerChanged(EntityUid uid, CryoPodComponent component, ref PowerChangedEvent args)
|
||||
{
|
||||
// Needed to avoid adding/removing components on a deleted entity
|
||||
if (Terminating(uid))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.Powered)
|
||||
{
|
||||
EnsureComp<ActiveCryoPodComponent>(uid);
|
||||
}
|
||||
else
|
||||
{
|
||||
RemComp<ActiveCryoPodComponent>(uid);
|
||||
_uiSystem.TryCloseAll(uid, SharedHealthAnalyzerComponent.HealthAnalyzerUiKey.Key);
|
||||
}
|
||||
UpdateAppearance(uid, component);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Atmos handler
|
||||
|
||||
private void OnCryoPodUpdateAtmosphere(EntityUid uid, CryoPodComponent cryoPod, AtmosDeviceUpdateEvent args)
|
||||
{
|
||||
if (!TryComp(uid, out NodeContainerComponent? nodeContainer))
|
||||
return;
|
||||
|
||||
if (!nodeContainer.TryGetNode(cryoPod.PortName, out PortablePipeNode? portNode))
|
||||
return;
|
||||
_atmosphereSystem.React(cryoPod.Air, portNode);
|
||||
|
||||
if (portNode.NodeGroup is PipeNet {NodeCount: > 1} net)
|
||||
{
|
||||
_gasCanisterSystem.MixContainerWithPipeNet(cryoPod.Air, net.Air);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnGasAnalyzed(EntityUid uid, CryoPodComponent component, GasAnalyzerScanEvent args)
|
||||
{
|
||||
var gasMixDict = new Dictionary<string, GasMixture?> { { Name(uid), component.Air } };
|
||||
// If it's connected to a port, include the port side
|
||||
if (TryComp(uid, out NodeContainerComponent? nodeContainer))
|
||||
{
|
||||
if(nodeContainer.TryGetNode(component.PortName, out PipeNode? port))
|
||||
gasMixDict.Add(component.PortName, port.Air);
|
||||
}
|
||||
args.GasMixtures = gasMixDict;
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
|
@ -123,7 +123,7 @@ public sealed class HealingSystem : EntitySystem
|
|||
return false;
|
||||
}
|
||||
|
||||
if (TryComp<SharedStackComponent>(component.Owner, out var stack) && stack.Count < 1)
|
||||
if (TryComp<StackComponent>(component.Owner, out var stack) && stack.Count < 1)
|
||||
return false;
|
||||
|
||||
component.CancelToken = new CancellationTokenSource();
|
||||
|
|
|
|||
47
Content.Server/Medical/InsideCryoPodSystem.cs
Normal file
47
Content.Server/Medical/InsideCryoPodSystem.cs
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
using Content.Server.Atmos.EntitySystems;
|
||||
using Content.Server.Medical.Components;
|
||||
using Content.Shared.Medical.Cryogenics;
|
||||
|
||||
namespace Content.Server.Medical
|
||||
{
|
||||
public sealed partial class CryoPodSystem
|
||||
{
|
||||
public override void InitializeInsideCryoPod()
|
||||
{
|
||||
base.InitializeInsideCryoPod();
|
||||
// Atmos overrides
|
||||
SubscribeLocalEvent<InsideCryoPodComponent, InhaleLocationEvent>(OnInhaleLocation);
|
||||
SubscribeLocalEvent<InsideCryoPodComponent, ExhaleLocationEvent>(OnExhaleLocation);
|
||||
SubscribeLocalEvent<InsideCryoPodComponent, AtmosExposedGetAirEvent>(OnGetAir);
|
||||
}
|
||||
|
||||
#region Atmos handlers
|
||||
|
||||
private void OnGetAir(EntityUid uid, InsideCryoPodComponent component, ref AtmosExposedGetAirEvent args)
|
||||
{
|
||||
if (TryComp<CryoPodComponent>(Transform(uid).ParentUid, out var cryoPodComponent))
|
||||
{
|
||||
args.Gas = cryoPodComponent.Air;
|
||||
args.Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnInhaleLocation(EntityUid uid, InsideCryoPodComponent component, InhaleLocationEvent args)
|
||||
{
|
||||
if (TryComp<CryoPodComponent>(Transform(uid).ParentUid, out var cryoPodComponent))
|
||||
{
|
||||
args.Gas = cryoPodComponent.Air;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnExhaleLocation(EntityUid uid, InsideCryoPodComponent component, ExhaleLocationEvent args)
|
||||
{
|
||||
if (TryComp<CryoPodComponent>(Transform(uid).ParentUid, out var cryoPodComponent))
|
||||
{
|
||||
args.Gas = cryoPodComponent.Air;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
@ -36,20 +36,6 @@ public sealed class NPCSteeringComponent : Component
|
|||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// How many times per second we're allowed to update our steering frequency.
|
||||
/// </summary>
|
||||
public const byte SteerFrequency = 10;
|
||||
|
||||
/// <summary>
|
||||
/// Last time the NPC steered.
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
public TimeSpan LastTimeSteer;
|
||||
|
||||
[ViewVariables]
|
||||
public Vector2 LastSteer;
|
||||
|
||||
/// <summary>
|
||||
/// Have we currently requested a path.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -61,6 +61,20 @@ public sealed class HTNSystem : EntitySystem
|
|||
|
||||
private void OnLoad()
|
||||
{
|
||||
// Clear all NPCs in case they're hanging onto stale tasks
|
||||
foreach (var comp in EntityQuery<HTNComponent>(true))
|
||||
{
|
||||
comp.PlanningToken?.Cancel();
|
||||
comp.PlanningToken = null;
|
||||
|
||||
if (comp.Plan != null)
|
||||
{
|
||||
var currentOperator = comp.Plan.CurrentOperator;
|
||||
currentOperator.Shutdown(comp.Blackboard, HTNOperatorStatus.Failed);
|
||||
comp.Plan = null;
|
||||
}
|
||||
}
|
||||
|
||||
// Add dependencies for all operators.
|
||||
// We put code on operators as I couldn't think of a clean way to put it on systems.
|
||||
foreach (var compound in _prototypeManager.EnumeratePrototypes<HTNCompoundTask>())
|
||||
|
|
|
|||
|
|
@ -394,7 +394,8 @@ public sealed partial class NPCSteeringSystem
|
|||
(layer & otherBody.CollisionMask) == 0x0 ||
|
||||
!factionQuery.TryGetComponent(ent, out var otherFaction) ||
|
||||
!_faction.IsFriendly(uid, ent, ourFaction, otherFaction) ||
|
||||
Vector2.Dot(otherBody.LinearVelocity, ourVelocity) < 0f)
|
||||
// Use <= 0 so we ignore stationary friends in case.
|
||||
Vector2.Dot(otherBody.LinearVelocity, ourVelocity) <= 0f)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
|
@ -415,7 +416,7 @@ public sealed partial class NPCSteeringSystem
|
|||
obstacleDirection = offsetRot.RotateVec(obstacleDirection);
|
||||
var norm = obstacleDirection.Normalized;
|
||||
var weight = obstableDistance <= agentRadius ? 1f : (detectionRadius - obstableDistance) / detectionRadius;
|
||||
weight *= 1.5f;
|
||||
weight *= 1f;
|
||||
|
||||
for (var i = 0; i < InterestDirections; i++)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -41,7 +41,6 @@ namespace Content.Server.NPC.Systems
|
|||
|
||||
[Dependency] private readonly IAdminManager _admin = default!;
|
||||
[Dependency] private readonly IConfigurationManager _configManager = default!;
|
||||
[Dependency] private readonly IDependencyCollection _dependencies = default!;
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||
[Dependency] private readonly IParallelManager _parallel = default!;
|
||||
|
|
@ -79,8 +78,8 @@ namespace Content.Server.NPC.Systems
|
|||
}
|
||||
|
||||
UpdatesBefore.Add(typeof(SharedPhysicsSystem));
|
||||
_configManager.OnValueChanged(CCVars.NPCEnabled, SetNPCEnabled);
|
||||
_configManager.OnValueChanged(CCVars.NPCPathfinding, SetNPCPathfinding);
|
||||
_configManager.OnValueChanged(CCVars.NPCEnabled, SetNPCEnabled, true);
|
||||
_configManager.OnValueChanged(CCVars.NPCPathfinding, SetNPCPathfinding, true);
|
||||
|
||||
SubscribeLocalEvent<NPCSteeringComponent, ComponentShutdown>(OnSteeringShutdown);
|
||||
SubscribeNetworkEvent<RequestNPCSteeringDebugEvent>(OnDebugRequest);
|
||||
|
|
@ -90,9 +89,11 @@ namespace Content.Server.NPC.Systems
|
|||
{
|
||||
if (!obj)
|
||||
{
|
||||
foreach (var (_, mover) in EntityQuery<NPCSteeringComponent, InputMoverComponent>())
|
||||
foreach (var (comp, mover) in EntityQuery<NPCSteeringComponent, InputMoverComponent>())
|
||||
{
|
||||
mover.CurTickSprintMovement = Vector2.Zero;
|
||||
comp.PathfindToken?.Cancel();
|
||||
comp.PathfindToken = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -117,6 +118,7 @@ namespace Content.Server.NPC.Systems
|
|||
{
|
||||
base.Shutdown();
|
||||
_configManager.UnsubValueChanged(CCVars.NPCEnabled, SetNPCEnabled);
|
||||
_configManager.UnsubValueChanged(CCVars.NPCPathfinding, SetNPCPathfinding);
|
||||
}
|
||||
|
||||
private void OnDebugRequest(RequestNPCSteeringDebugEvent msg, EntitySessionEventArgs args)
|
||||
|
|
@ -204,12 +206,18 @@ namespace Content.Server.NPC.Systems
|
|||
|
||||
var npcs = EntityQuery<NPCSteeringComponent, ActiveNPCComponent, InputMoverComponent, TransformComponent>()
|
||||
.ToArray();
|
||||
|
||||
foreach (var (steering, _, mover, xform) in npcs)
|
||||
var options = new ParallelOptions
|
||||
{
|
||||
MaxDegreeOfParallelism = _parallel.ParallelProcessCount,
|
||||
};
|
||||
|
||||
Parallel.For(0, npcs.Length, options, i =>
|
||||
{
|
||||
var (steering, _, mover, xform) = npcs[i];
|
||||
|
||||
Steer(steering, mover, xform, modifierQuery, bodyQuery, xformQuery, frameTime);
|
||||
steering.LastSteer = mover.CurTickSprintMovement;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
if (_subscribedSessions.Count > 0)
|
||||
{
|
||||
|
|
@ -278,8 +286,7 @@ namespace Content.Server.NPC.Systems
|
|||
return;
|
||||
}
|
||||
|
||||
// TODO: Pause time
|
||||
// Need it on the paused event which needs an engine PR.
|
||||
/* If you wish to not steer every tick A) Add pause support B) fix overshoots to prevent dancing
|
||||
var nextSteer = steering.LastTimeSteer + TimeSpan.FromSeconds(1f / NPCSteeringComponent.SteerFrequency);
|
||||
|
||||
if (nextSteer > _timing.CurTime)
|
||||
|
|
@ -287,8 +294,8 @@ namespace Content.Server.NPC.Systems
|
|||
SetDirection(mover, steering, steering.LastSteer, false);
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
steering.LastTimeSteer = _timing.CurTime;
|
||||
var uid = mover.Owner;
|
||||
var interest = steering.Interest;
|
||||
var danger = steering.Danger;
|
||||
|
|
@ -300,7 +307,6 @@ namespace Content.Server.NPC.Systems
|
|||
var offsetRot = -_mover.GetParentGridAngle(mover);
|
||||
modifierQuery.TryGetComponent(uid, out var modifier);
|
||||
var moveSpeed = GetSprintSpeed(steering.Owner, modifier);
|
||||
var tickMove = moveSpeed * frameTime;
|
||||
var body = bodyQuery.GetComponent(uid);
|
||||
var dangerPoints = steering.DangerPoints;
|
||||
dangerPoints.Clear();
|
||||
|
|
@ -322,7 +328,7 @@ namespace Content.Server.NPC.Systems
|
|||
DebugTools.Assert(!float.IsNaN(interest[0]));
|
||||
|
||||
// Avoid static objects like walls
|
||||
CollisionAvoidance(uid, offsetRot, worldPos, agentRadius, tickMove, layer, mask, xform, danger, dangerPoints, bodyQuery, xformQuery);
|
||||
CollisionAvoidance(uid, offsetRot, worldPos, agentRadius, moveSpeed, layer, mask, xform, danger, dangerPoints, bodyQuery, xformQuery);
|
||||
DebugTools.Assert(!float.IsNaN(danger[0]));
|
||||
|
||||
Separation(uid, offsetRot, worldPos, agentRadius, layer, mask, body, xform, danger, bodyQuery, xformQuery);
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue