Merge pull request #2 from space-wizards/master
This commit is contained in:
@@ -3,8 +3,10 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using Content.Client.GameObjects.EntitySystems.DoAfter;
|
||||
using Content.Shared.GameObjects.Components;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameObjects.Systems;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.Interfaces.Network;
|
||||
using Robust.Shared.Interfaces.Timing;
|
||||
using Robust.Shared.IoC;
|
||||
@@ -38,6 +40,18 @@ namespace Content.Client.GameObjects.Components
|
||||
}
|
||||
}
|
||||
|
||||
public override void HandleMessage(ComponentMessage message, IComponent? component)
|
||||
{
|
||||
base.HandleMessage(message, component);
|
||||
switch (message)
|
||||
{
|
||||
case PlayerDetachedMsg _:
|
||||
_doAfters.Clear();
|
||||
CancelledDoAfters.Clear();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove a DoAfter without showing a cancellation graphic.
|
||||
/// </summary>
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
using Content.Client.GameObjects.Components.Items;
|
||||
using Content.Client.Interfaces.GameObjects.Components.Interaction;
|
||||
using Content.Shared.GameObjects.Components.GUI;
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
namespace Content.Client.GameObjects.Components.GUI
|
||||
{
|
||||
[RegisterComponent]
|
||||
public class StrippableComponent : SharedStrippableComponent, IClientDraggable
|
||||
{
|
||||
public bool ClientCanDropOn(CanDropEventArgs eventArgs)
|
||||
{
|
||||
return eventArgs.Target.HasComponent<HandsComponent>()
|
||||
&& eventArgs.Target != eventArgs.Dragged && eventArgs.Target == eventArgs.User;
|
||||
}
|
||||
|
||||
public bool ClientCanDrag(CanDragEventArgs eventArgs)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
using System.Collections.Generic;
|
||||
using Content.Client.UserInterface;
|
||||
using Content.Shared.GameObjects.Components.GUI;
|
||||
using Content.Shared.GameObjects.Components.Inventory;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.GameObjects.Components.UserInterface;
|
||||
using Robust.Shared.GameObjects.Components.UserInterface;
|
||||
using Robust.Shared.ViewVariables;
|
||||
using static Content.Shared.GameObjects.Components.Inventory.EquipmentSlotDefines;
|
||||
|
||||
namespace Content.Client.GameObjects.Components.HUD.Inventory
|
||||
{
|
||||
[UsedImplicitly]
|
||||
public class StrippableBoundUserInterface : BoundUserInterface
|
||||
{
|
||||
public Dictionary<Slots, string> Inventory { get; private set; }
|
||||
public Dictionary<string, string> Hands { get; private set; }
|
||||
|
||||
[ViewVariables]
|
||||
private StrippingMenu _strippingMenu;
|
||||
|
||||
public StrippableBoundUserInterface(ClientUserInterfaceComponent owner, object uiKey) : base(owner, uiKey)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void Open()
|
||||
{
|
||||
base.Open();
|
||||
|
||||
_strippingMenu = new StrippingMenu($"{Owner.Owner.Name}'s inventory");
|
||||
_strippingMenu.OpenCentered();
|
||||
UpdateMenu();
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
base.Dispose(disposing);
|
||||
if (!disposing) return;
|
||||
_strippingMenu.Dispose();
|
||||
|
||||
_strippingMenu.Close();
|
||||
}
|
||||
|
||||
private void UpdateMenu()
|
||||
{
|
||||
if (_strippingMenu == null) return;
|
||||
|
||||
_strippingMenu.ClearButtons();
|
||||
|
||||
if(Inventory != null)
|
||||
foreach (var (slot, name) in Inventory)
|
||||
{
|
||||
_strippingMenu.AddButton(EquipmentSlotDefines.SlotNames[slot], name, (ev) =>
|
||||
{
|
||||
SendMessage(new StrippingInventoryButtonPressed(slot));
|
||||
});
|
||||
}
|
||||
|
||||
if(Hands != null)
|
||||
foreach (var (hand, name) in Hands)
|
||||
{
|
||||
_strippingMenu.AddButton(hand, name, (ev) =>
|
||||
{
|
||||
SendMessage(new StrippingHandButtonPressed(hand));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
protected override void UpdateState(BoundUserInterfaceState state)
|
||||
{
|
||||
base.UpdateState(state);
|
||||
|
||||
if (!(state is StrippingBoundUserInterfaceState stripState)) return;
|
||||
|
||||
Inventory = stripState.Inventory;
|
||||
Hands = stripState.Hands;
|
||||
|
||||
UpdateMenu();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@ namespace Content.Client.GameObjects.Components.Items
|
||||
[Dependency] private readonly IGameHud _gameHud = default!;
|
||||
#pragma warning restore 649
|
||||
|
||||
/// <inheritdoc />
|
||||
private readonly List<Hand> _hands = new List<Hand>();
|
||||
|
||||
[ViewVariables] public IReadOnlyList<Hand> Hands => _hands;
|
||||
|
||||
@@ -1,25 +1,16 @@
|
||||
using Content.Client.GameObjects.Components.Mobs;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameObjects.Systems;
|
||||
|
||||
namespace Content.Client.GameObjects.EntitySystems
|
||||
{
|
||||
public sealed class CameraRecoilSystem : EntitySystem
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
EntityQuery = new TypeEntityQuery(typeof(CameraRecoilComponent));
|
||||
}
|
||||
|
||||
public override void FrameUpdate(float frameTime)
|
||||
{
|
||||
base.FrameUpdate(frameTime);
|
||||
|
||||
foreach (var entity in RelevantEntities)
|
||||
foreach (var recoil in EntityManager.ComponentManager.EntityQuery<CameraRecoilComponent>())
|
||||
{
|
||||
var recoil = entity.GetComponent<CameraRecoilComponent>();
|
||||
recoil.FrameUpdate(frameTime);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,6 +43,25 @@ namespace Content.Client.GameObjects.EntitySystems.DoAfter
|
||||
LayoutContainer.SetGrowVertical(this, LayoutContainer.GrowDirection.Begin);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the mind is detached from an entity
|
||||
/// </summary>
|
||||
/// Rather than just dispose of the Gui we'll just remove its child controls and re-use the control.
|
||||
public void Detached()
|
||||
{
|
||||
foreach (var (_, control) in _doAfterControls)
|
||||
{
|
||||
control.Dispose();
|
||||
}
|
||||
_doAfterControls.Clear();
|
||||
foreach (var (_, control) in _doAfterBars)
|
||||
{
|
||||
control.Dispose();
|
||||
}
|
||||
_doAfterBars.Clear();
|
||||
_cancelledDoAfters.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add the necessary control for a DoAfter progress bar.
|
||||
/// </summary>
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace Content.Client.GameObjects.EntitySystems.DoAfter
|
||||
{
|
||||
_player = entity;
|
||||
// Setup the GUI and pass the new data to it if applicable.
|
||||
Gui?.Dispose();
|
||||
Gui?.Detached();
|
||||
|
||||
if (entity == null)
|
||||
{
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using Content.Client.GameObjects.Components.Instruments;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameObjects.Systems;
|
||||
using Robust.Shared.Interfaces.Timing;
|
||||
using Robust.Shared.IoC;
|
||||
@@ -12,12 +11,6 @@ namespace Content.Client.GameObjects.EntitySystems
|
||||
{
|
||||
[Dependency] private readonly IGameTiming _gameTiming = default;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
EntityQuery = new TypeEntityQuery(typeof(InstrumentComponent));
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
base.Update(frameTime);
|
||||
@@ -27,9 +20,9 @@ namespace Content.Client.GameObjects.EntitySystems
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var entity in RelevantEntities)
|
||||
foreach (var instrumentComponent in EntityManager.ComponentManager.EntityQuery<InstrumentComponent>())
|
||||
{
|
||||
entity.GetComponent<InstrumentComponent>().Update(frameTime);
|
||||
instrumentComponent.Update(frameTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Content.Client.GameObjects.Components.Markers;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameObjects.Systems;
|
||||
|
||||
namespace Content.Client.GameObjects.EntitySystems
|
||||
@@ -8,13 +7,6 @@ namespace Content.Client.GameObjects.EntitySystems
|
||||
{
|
||||
private bool _markersVisible;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
EntityQuery = new TypeEntityQuery<MarkerComponent>();
|
||||
}
|
||||
|
||||
public bool MarkersVisible
|
||||
{
|
||||
get => _markersVisible;
|
||||
@@ -27,9 +19,9 @@ namespace Content.Client.GameObjects.EntitySystems
|
||||
|
||||
private void UpdateMarkers()
|
||||
{
|
||||
foreach (var entity in RelevantEntities)
|
||||
foreach (var markerComponent in EntityManager.ComponentManager.EntityQuery<MarkerComponent>())
|
||||
{
|
||||
entity.GetComponent<MarkerComponent>().UpdateVisibility();
|
||||
markerComponent.UpdateVisibility();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using Content.Client.GameObjects.Components.Mobs;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameObjects.Systems;
|
||||
|
||||
namespace Content.Client.GameObjects.EntitySystems
|
||||
@@ -8,20 +7,13 @@ namespace Content.Client.GameObjects.EntitySystems
|
||||
[UsedImplicitly]
|
||||
public sealed class MeleeLungeSystem : EntitySystem
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
EntityQuery = new TypeEntityQuery<MeleeLungeComponent>();
|
||||
}
|
||||
|
||||
public override void FrameUpdate(float frameTime)
|
||||
{
|
||||
base.FrameUpdate(frameTime);
|
||||
|
||||
foreach (var entity in RelevantEntities)
|
||||
foreach (var meleeLungeComponent in EntityManager.ComponentManager.EntityQuery<MeleeLungeComponent>())
|
||||
{
|
||||
entity.GetComponent<MeleeLungeComponent>().Update(frameTime);
|
||||
meleeLungeComponent.Update(frameTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,16 +24,15 @@ namespace Content.Client.GameObjects.EntitySystems
|
||||
public override void Initialize()
|
||||
{
|
||||
SubscribeNetworkEvent<PlayMeleeWeaponAnimationMessage>(PlayWeaponArc);
|
||||
EntityQuery = new TypeEntityQuery(typeof(MeleeWeaponArcAnimationComponent));
|
||||
}
|
||||
|
||||
public override void FrameUpdate(float frameTime)
|
||||
{
|
||||
base.FrameUpdate(frameTime);
|
||||
|
||||
foreach (var entity in RelevantEntities)
|
||||
foreach (var arcAnimationComponent in EntityManager.ComponentManager.EntityQuery<MeleeWeaponArcAnimationComponent>())
|
||||
{
|
||||
entity.GetComponent<MeleeWeaponArcAnimationComponent>().Update(frameTime);
|
||||
arcAnimationComponent.Update(frameTime);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,11 +30,10 @@ namespace Content.Client.GameObjects.EntitySystems
|
||||
return;
|
||||
}
|
||||
|
||||
var physics = playerEnt.GetComponent<IPhysicsComponent>();
|
||||
playerEnt.TryGetComponent(out ICollidableComponent? collidable);
|
||||
physics.Predict = true;
|
||||
var collidable = playerEnt.GetComponent<ICollidableComponent>();
|
||||
collidable.Predict = true;
|
||||
|
||||
UpdateKinematics(playerEnt.Transform, mover, physics, collidable);
|
||||
UpdateKinematics(playerEnt.Transform, mover, collidable);
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Content.Client.GameObjects.Components.Mobs;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameObjects.Systems;
|
||||
using Robust.Shared.Interfaces.Timing;
|
||||
using Robust.Shared.IoC;
|
||||
@@ -12,11 +11,6 @@ namespace Content.Client.GameObjects.EntitySystems
|
||||
[Dependency] private IGameTiming _gameTiming;
|
||||
#pragma warning restore 649
|
||||
|
||||
public StatusEffectsSystem()
|
||||
{
|
||||
EntityQuery = new TypeEntityQuery(typeof(ClientStatusEffectsComponent));
|
||||
}
|
||||
|
||||
public override void FrameUpdate(float frameTime)
|
||||
{
|
||||
base.FrameUpdate(frameTime);
|
||||
@@ -24,9 +18,9 @@ namespace Content.Client.GameObjects.EntitySystems
|
||||
if (!_gameTiming.IsFirstTimePredicted)
|
||||
return;
|
||||
|
||||
foreach (var entity in RelevantEntities)
|
||||
foreach (var clientStatusEffectsComponent in EntityManager.ComponentManager.EntityQuery<ClientStatusEffectsComponent>())
|
||||
{
|
||||
entity.GetComponent<ClientStatusEffectsComponent>().FrameUpdate(frameTime);
|
||||
clientStatusEffectsComponent.FrameUpdate(frameTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,6 +210,9 @@ namespace Content.Client.GameObjects.EntitySystems
|
||||
if (verb.RequireInteractionRange && !VerbUtility.InVerbUseRange(user, entity))
|
||||
continue;
|
||||
|
||||
if (verb.BlockedByContainers && !user.IsInSameOrNoContainer(entity))
|
||||
continue;
|
||||
|
||||
var verbData = verb.GetData(user, component);
|
||||
|
||||
if (verbData.IsInvisible)
|
||||
@@ -232,6 +235,9 @@ namespace Content.Client.GameObjects.EntitySystems
|
||||
if (globalVerb.RequireInteractionRange && !VerbUtility.InVerbUseRange(user, entity))
|
||||
continue;
|
||||
|
||||
if (globalVerb.BlockedByContainers && !user.IsInSameOrNoContainer(entity))
|
||||
continue;
|
||||
|
||||
var verbData = globalVerb.GetData(user, entity);
|
||||
|
||||
if (verbData.IsInvisible)
|
||||
|
||||
@@ -11,6 +11,8 @@ namespace Content.Client.GlobalVerbs
|
||||
{
|
||||
public override bool RequireInteractionRange => false;
|
||||
|
||||
public override bool BlockedByContainers => false;
|
||||
|
||||
public override void GetData(IEntity user, IEntity target, VerbData data)
|
||||
{
|
||||
data.Visibility = VerbVisibility.Visible;
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace Content.Client.GlobalVerbs
|
||||
class ViewVariablesVerb : GlobalVerb
|
||||
{
|
||||
public override bool RequireInteractionRange => false;
|
||||
public override bool BlockedByContainers => false;
|
||||
|
||||
public override void GetData(IEntity user, IEntity target, VerbData data)
|
||||
{
|
||||
|
||||
@@ -8,6 +8,7 @@ using Robust.Client.Graphics;
|
||||
using Robust.Client.Interfaces.ResourceManagement;
|
||||
using Robust.Shared.Interfaces.Configuration;
|
||||
using Robust.Shared.Interfaces.Log;
|
||||
using Robust.Shared.Interfaces.Resources;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Utility;
|
||||
@@ -59,16 +60,11 @@ namespace Content.Client.Parallax
|
||||
|
||||
if (!debugParallax && _resourceCache.UserData.Exists(ParallaxConfigOld))
|
||||
{
|
||||
bool match;
|
||||
using (var data = _resourceCache.UserData.Open(ParallaxConfigOld, FileMode.Open))
|
||||
using (var reader = new StreamReader(data, EncodingHelpers.UTF8))
|
||||
{
|
||||
match = reader.ReadToEnd() == contents;
|
||||
}
|
||||
var match = _resourceCache.UserData.ReadAllText(ParallaxConfigOld) == contents;
|
||||
|
||||
if (match)
|
||||
{
|
||||
using (var stream = _resourceCache.UserData.Open(ParallaxPath, FileMode.Open))
|
||||
using (var stream = _resourceCache.UserData.OpenRead(ParallaxPath))
|
||||
{
|
||||
ParallaxTexture = Texture.LoadFromPNGStream(stream, "Parallax");
|
||||
}
|
||||
@@ -95,7 +91,7 @@ namespace Content.Client.Parallax
|
||||
ParallaxTexture = Texture.LoadFromImage(image, "Parallax");
|
||||
|
||||
// Store it and CRC so further game starts don't need to regenerate it.
|
||||
using (var stream = _resourceCache.UserData.Open(ParallaxPath, FileMode.Create))
|
||||
using (var stream = _resourceCache.UserData.Create(ParallaxPath))
|
||||
{
|
||||
image.SaveAsPng(stream);
|
||||
}
|
||||
@@ -105,8 +101,7 @@ namespace Content.Client.Parallax
|
||||
var i = 0;
|
||||
foreach (var debugImage in debugImages)
|
||||
{
|
||||
using (var stream = _resourceCache.UserData.Open(new ResourcePath($"/parallax_debug_{i}.png"),
|
||||
FileMode.Create))
|
||||
using (var stream = _resourceCache.UserData.Create(new ResourcePath($"/parallax_debug_{i}.png")))
|
||||
{
|
||||
debugImage.SaveAsPng(stream);
|
||||
}
|
||||
@@ -117,7 +112,7 @@ namespace Content.Client.Parallax
|
||||
|
||||
image.Dispose();
|
||||
|
||||
using (var stream = _resourceCache.UserData.Open(ParallaxConfigOld, FileMode.Create))
|
||||
using (var stream = _resourceCache.UserData.Create(ParallaxConfigOld))
|
||||
using (var writer = new StreamWriter(stream, EncodingHelpers.UTF8))
|
||||
{
|
||||
writer.Write(contents);
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace Content.Client
|
||||
}
|
||||
|
||||
await using var file =
|
||||
_resourceManager.UserData.Open(BaseScreenshotPath / $"{filename}.png", FileMode.CreateNew);
|
||||
_resourceManager.UserData.Open(BaseScreenshotPath / $"{filename}.png", FileMode.CreateNew, FileAccess.Read, FileShare.None);
|
||||
|
||||
await Task.Run(() =>
|
||||
{
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Content.Client.Sandbox;
|
||||
using Robust.Client.Console;
|
||||
using Robust.Client.Console;
|
||||
using Robust.Client.Interfaces.Placement;
|
||||
using Robust.Client.Interfaces.ResourceManagement;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
@@ -15,16 +14,12 @@ namespace Content.Client.UserInterface
|
||||
internal sealed class EscapeMenu : SS14Window
|
||||
{
|
||||
private readonly IClientConsole _console;
|
||||
private readonly ITileDefinitionManager __tileDefinitionManager;
|
||||
private readonly ITileDefinitionManager _tileDefinitionManager;
|
||||
private readonly IPlacementManager _placementManager;
|
||||
private readonly IPrototypeManager _prototypeManager;
|
||||
private readonly IResourceCache _resourceCache;
|
||||
private readonly IConfigurationManager _configSystem;
|
||||
private readonly ILocalizationManager _localizationManager;
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly ISandboxManager _sandboxManager;
|
||||
[Dependency] private readonly IClientConGroupController _conGroupController;
|
||||
#pragma warning restore 649
|
||||
|
||||
private BaseButton DisconnectButton;
|
||||
private BaseButton QuitButton;
|
||||
@@ -41,7 +36,7 @@ namespace Content.Client.UserInterface
|
||||
_configSystem = configSystem;
|
||||
_localizationManager = localizationManager;
|
||||
_console = console;
|
||||
__tileDefinitionManager = tileDefinitionManager;
|
||||
_tileDefinitionManager = tileDefinitionManager;
|
||||
_placementManager = placementManager;
|
||||
_prototypeManager = prototypeManager;
|
||||
_resourceCache = resourceCache;
|
||||
|
||||
64
Content.Client/UserInterface/StrippingMenu.cs
Normal file
64
Content.Client/UserInterface/StrippingMenu.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
using System;
|
||||
using Content.Client.UserInterface.Stylesheets;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Maths;
|
||||
|
||||
namespace Content.Client.UserInterface
|
||||
{
|
||||
public class StrippingMenu : SS14Window
|
||||
{
|
||||
protected override Vector2? CustomSize => new Vector2(400, 600);
|
||||
|
||||
private readonly VBoxContainer _vboxContainer;
|
||||
|
||||
public StrippingMenu(string title)
|
||||
{
|
||||
Title = title;
|
||||
|
||||
_vboxContainer = new VBoxContainer()
|
||||
{
|
||||
SizeFlagsVertical = SizeFlags.FillExpand,
|
||||
SeparationOverride = 5,
|
||||
};
|
||||
|
||||
Contents.AddChild(_vboxContainer);
|
||||
}
|
||||
|
||||
public void ClearButtons()
|
||||
{
|
||||
_vboxContainer.DisposeAllChildren();
|
||||
}
|
||||
|
||||
public void AddButton(string title, string name, Action<BaseButton.ButtonEventArgs> onPressed)
|
||||
{
|
||||
var button = new Button()
|
||||
{
|
||||
Text = name,
|
||||
StyleClasses = { StyleBase.ButtonOpenRight }
|
||||
};
|
||||
|
||||
button.OnPressed += onPressed;
|
||||
|
||||
_vboxContainer.AddChild(new HBoxContainer()
|
||||
{
|
||||
SizeFlagsHorizontal = SizeFlags.FillExpand,
|
||||
SeparationOverride = 5,
|
||||
Children =
|
||||
{
|
||||
new Label()
|
||||
{
|
||||
Text = $"{title}:"
|
||||
},
|
||||
new Control()
|
||||
{
|
||||
SizeFlagsHorizontal = SizeFlags.FillExpand
|
||||
},
|
||||
button,
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,10 +4,12 @@ using Content.Server.GameObjects.Components.Markers;
|
||||
using Robust.Server.Interfaces.Console;
|
||||
using Robust.Server.Interfaces.Player;
|
||||
using Robust.Shared.Enums;
|
||||
using Robust.Shared.GameObjects.Components;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.Interfaces.Map;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Maths;
|
||||
|
||||
namespace Content.Server.Administration
|
||||
{
|
||||
@@ -107,6 +109,10 @@ namespace Content.Server.Administration
|
||||
if (found.GridID != GridId.Invalid)
|
||||
{
|
||||
player.AttachedEntity.Transform.GridPosition = found;
|
||||
if (player.AttachedEntity.TryGetComponent(out ICollidableComponent collidable))
|
||||
{
|
||||
collidable.Stop();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -49,19 +49,23 @@ namespace Content.Server.Atmos
|
||||
{
|
||||
|
||||
|
||||
if (maxForce > ThrowForce && throwTarget != GridCoordinates.InvalidGrid)
|
||||
if (maxForce > ThrowForce)
|
||||
{
|
||||
var moveForce = MathF.Min(maxForce * FloatMath.Clamp(moveProb, 0, 100) / 100f, 50f);
|
||||
var pos = throwTarget.Position - transform.GridPosition.Position;
|
||||
LinearVelocity = pos * moveForce;
|
||||
}
|
||||
else
|
||||
{
|
||||
var moveForce = MathF.Min(maxForce * FloatMath.Clamp(moveProb, 0, 100) / 100f, 25f);
|
||||
LinearVelocity = direction.ToVec() * moveForce;
|
||||
}
|
||||
if (throwTarget != GridCoordinates.InvalidGrid)
|
||||
{
|
||||
var moveForce = maxForce * FloatMath.Clamp(moveProb, 0, 100) / 150f;
|
||||
var pos = ((throwTarget.Position - transform.GridPosition.Position).Normalized + direction.ToVec()).Normalized;
|
||||
LinearVelocity = pos * moveForce;
|
||||
}
|
||||
|
||||
pressureComponent.LastHighPressureMovementAirCycle = cycle;
|
||||
else
|
||||
{
|
||||
var moveForce = MathF.Min(maxForce * FloatMath.Clamp(moveProb, 0, 100) / 2500f, 20f);
|
||||
LinearVelocity = direction.ToVec() * moveForce;
|
||||
}
|
||||
|
||||
pressureComponent.LastHighPressureMovementAirCycle = cycle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,7 +76,7 @@ namespace Content.Server.Atmos
|
||||
if (ControlledComponent != null && !_physicsManager.IsWeightless(ControlledComponent.Owner.Transform.GridPosition))
|
||||
{
|
||||
LinearVelocity *= 0.85f;
|
||||
if (LinearVelocity.Length < 1f)
|
||||
if (MathF.Abs(LinearVelocity.Length) < 1f)
|
||||
Stop();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,11 @@ namespace Content.Server.Atmos
|
||||
/// <param name="indices"></param>
|
||||
void Invalidate(MapIndices indices);
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to fix a sudden vacuum by creating gas.
|
||||
/// </summary>
|
||||
void FixVacuum(MapIndices indices);
|
||||
|
||||
/// <summary>
|
||||
/// Adds an active tile so it becomes processed every update until it becomes inactive.
|
||||
/// Also makes the tile excited.
|
||||
|
||||
@@ -17,6 +17,7 @@ using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.Interfaces.Map;
|
||||
using Robust.Shared.Interfaces.Random;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Random;
|
||||
@@ -78,7 +79,6 @@ namespace Content.Server.Atmos
|
||||
[ViewVariables]
|
||||
public Hotspot Hotspot;
|
||||
|
||||
[ViewVariables]
|
||||
private Direction _pressureDirection;
|
||||
|
||||
[ViewVariables]
|
||||
@@ -106,6 +106,7 @@ namespace Content.Server.Atmos
|
||||
GridIndex = gridIndex;
|
||||
GridIndices = gridIndices;
|
||||
Air = mixture;
|
||||
ResetTileAtmosInfo();
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
@@ -181,6 +182,8 @@ namespace Content.Server.Atmos
|
||||
|| ContainerHelpers.IsInContainer(entity))
|
||||
continue;
|
||||
|
||||
physics.WakeBody();
|
||||
|
||||
var pressureMovements = physics.EnsureController<HighPressureMovementController>();
|
||||
if (pressure.LastHighPressureMovementAirCycle < _gridAtmosphereComponent.UpdateCounter)
|
||||
{
|
||||
@@ -221,7 +224,8 @@ namespace Content.Server.Atmos
|
||||
{
|
||||
if (Air == null || (_tileAtmosInfo.LastCycle >= cycleNum)) return; // Already done.
|
||||
|
||||
_tileAtmosInfo = new TileAtmosInfo();
|
||||
ResetTileAtmosInfo();
|
||||
|
||||
|
||||
var startingMoles = Air.TotalMoles;
|
||||
var runAtmos = false;
|
||||
@@ -264,7 +268,7 @@ namespace Content.Server.Atmos
|
||||
{
|
||||
if (adj?.Air == null) continue;
|
||||
if(adj._tileAtmosInfo.LastQueueCycle == queueCycle) continue;
|
||||
adj._tileAtmosInfo = new TileAtmosInfo();
|
||||
adj.ResetTileAtmosInfo();
|
||||
|
||||
adj._tileAtmosInfo.LastQueueCycle = queueCycle;
|
||||
if(tileCount < Atmospherics.ZumosHardTileLimit)
|
||||
@@ -328,7 +332,7 @@ namespace Content.Server.Atmos
|
||||
var tile = tiles[i];
|
||||
tile._tileAtmosInfo.FastDone = true;
|
||||
if (!(tile._tileAtmosInfo.MoleDelta > 0)) continue;
|
||||
Direction eligibleAdjBits = 0;
|
||||
var eligibleDirections = new List<Direction>();
|
||||
var amtEligibleAdj = 0;
|
||||
foreach (var direction in Cardinal)
|
||||
{
|
||||
@@ -338,16 +342,17 @@ namespace Content.Server.Atmos
|
||||
if (tile2._tileAtmosInfo.FastDone || tile2._tileAtmosInfo.LastQueueCycle != queueCycle)
|
||||
continue;
|
||||
|
||||
eligibleAdjBits |= direction;
|
||||
eligibleDirections.Add(direction);
|
||||
amtEligibleAdj++;
|
||||
}
|
||||
|
||||
if (amtEligibleAdj <= 0)
|
||||
continue; // Oof we've painted ourselves into a corner. Bad luck. Next part will handle this.
|
||||
|
||||
var molesToMove = tile._tileAtmosInfo.MoleDelta / amtEligibleAdj;
|
||||
foreach (var direction in Cardinal)
|
||||
{
|
||||
if ((eligibleAdjBits & direction) == 0 ||
|
||||
if (eligibleDirections.Contains(direction) ||
|
||||
!tile._adjacentTiles.TryGetValue(direction, out var tile2)) continue;
|
||||
tile.AdjustEqMovement(direction, molesToMove);
|
||||
tile._tileAtmosInfo.MoleDelta -= molesToMove;
|
||||
@@ -394,13 +399,10 @@ namespace Content.Server.Atmos
|
||||
foreach (var direction in Cardinal)
|
||||
{
|
||||
if (!tile._adjacentTiles.TryGetValue(direction, out var tile2)) continue;
|
||||
if (giver._tileAtmosInfo.MoleDelta <= 0)
|
||||
break; // We're done here now. Let's not do more work than needed.
|
||||
|
||||
if (tile2?._tileAtmosInfo == null || tile2._tileAtmosInfo.LastQueueCycle != queueCycle)
|
||||
continue;
|
||||
|
||||
if (giver._tileAtmosInfo.MoleDelta <= 0) break; // We're done here now. Let's not do more work than needed.
|
||||
if (tile2._tileAtmosInfo.LastQueueCycle != queueCycle) continue;
|
||||
if (tile2._tileAtmosInfo.LastSlowQueueCycle == queueCycleSlow) continue;
|
||||
|
||||
queue[queueLength++] = tile2;
|
||||
tile2._tileAtmosInfo.LastSlowQueueCycle = queueCycleSlow;
|
||||
tile2._tileAtmosInfo.CurrentTransferDirection = direction.GetOpposite();
|
||||
@@ -458,7 +460,7 @@ namespace Content.Server.Atmos
|
||||
var queueLength = 0;
|
||||
queue[queueLength++] = taker;
|
||||
taker._tileAtmosInfo.LastSlowQueueCycle = queueCycleSlow;
|
||||
for (int i = 0; i < queueLength; i++)
|
||||
for (var i = 0; i < queueLength; i++)
|
||||
{
|
||||
if (taker._tileAtmosInfo.MoleDelta >= 0)
|
||||
break; // We're done here now. Let's not do more work than needed.
|
||||
@@ -469,11 +471,8 @@ namespace Content.Server.Atmos
|
||||
if (!tile._adjacentTiles.ContainsKey(direction)) continue;
|
||||
var tile2 = tile._adjacentTiles[direction];
|
||||
|
||||
if (taker._tileAtmosInfo.MoleDelta >= 0)
|
||||
break; // We're done here now. Let's not do more work than needed.
|
||||
|
||||
if (tile2?._tileAtmosInfo == null || tile2._tileAtmosInfo.LastQueueCycle != queueCycle)
|
||||
continue;
|
||||
if (taker._tileAtmosInfo.MoleDelta >= 0) break; // We're done here now. Let's not do more work than needed.
|
||||
if (tile2._tileAtmosInfo.LastQueueCycle != queueCycle) continue;
|
||||
if (tile2._tileAtmosInfo.LastSlowQueueCycle == queueCycleSlow) continue;
|
||||
queue[queueLength++] = tile2;
|
||||
tile2._tileAtmosInfo.LastSlowQueueCycle = queueCycleSlow;
|
||||
@@ -504,16 +503,16 @@ namespace Content.Server.Atmos
|
||||
for (var i = queueLength - 1; i >= 0; i--)
|
||||
{
|
||||
var tile = queue[i];
|
||||
if (tile._tileAtmosInfo.CurrentTransferAmount == 0 ||
|
||||
tile._tileAtmosInfo.CurrentTransferDirection == Direction.Invalid) continue;
|
||||
tile.AdjustEqMovement(tile._tileAtmosInfo.CurrentTransferDirection,
|
||||
tile._tileAtmosInfo.CurrentTransferAmount);
|
||||
if (tile._tileAtmosInfo.CurrentTransferAmount == 0 || tile._tileAtmosInfo.CurrentTransferDirection == Direction.Invalid)
|
||||
continue;
|
||||
|
||||
if (tile._adjacentTiles.TryGetValue(tile._tileAtmosInfo.CurrentTransferDirection,
|
||||
out var adjacent))
|
||||
adjacent._tileAtmosInfo.CurrentTransferAmount +=
|
||||
tile._tileAtmosInfo.CurrentTransferAmount;
|
||||
tile._tileAtmosInfo.CurrentTransferAmount = 0;
|
||||
tile.AdjustEqMovement(tile._tileAtmosInfo.CurrentTransferDirection, tile._tileAtmosInfo.CurrentTransferAmount);
|
||||
|
||||
if (tile._adjacentTiles.TryGetValue(tile._tileAtmosInfo.CurrentTransferDirection, out var adjacent))
|
||||
{
|
||||
adjacent._tileAtmosInfo.CurrentTransferAmount += tile._tileAtmosInfo.CurrentTransferAmount;
|
||||
tile._tileAtmosInfo.CurrentTransferAmount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -552,38 +551,34 @@ namespace Content.Server.Atmos
|
||||
foreach (var direction in Cardinal)
|
||||
{
|
||||
var amount = _tileAtmosInfo[direction];
|
||||
transferDirections[direction] = amount;
|
||||
if (amount == 0) continue;
|
||||
transferDirections[direction] = amount;
|
||||
_tileAtmosInfo[direction] = 0;
|
||||
hasTransferDirs = true;
|
||||
}
|
||||
|
||||
if (!hasTransferDirs) return;
|
||||
|
||||
foreach (var direction in Cardinal)
|
||||
foreach (var (direction, amount) in transferDirections)
|
||||
{
|
||||
var amount = transferDirections[direction];
|
||||
if (!_adjacentTiles.TryGetValue(direction, out var tile) || tile.Air == null) continue;
|
||||
if (amount > 0)
|
||||
{
|
||||
// Prevent infinite recursion.
|
||||
tile._tileAtmosInfo[direction.GetOpposite()] = 0;
|
||||
|
||||
if (Air.TotalMoles < amount)
|
||||
FinalizeEqNeighbors();
|
||||
FinalizeEqNeighbors(transferDirections.Keys);
|
||||
|
||||
tile.Air.Merge(Air.Remove(amount));
|
||||
UpdateVisuals();
|
||||
tile.UpdateVisuals();
|
||||
ConsiderPressureDifference(tile, amount);
|
||||
ConsiderPressureDifference(direction, amount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private void FinalizeEqNeighbors()
|
||||
private void FinalizeEqNeighbors(IEnumerable<Direction> directions)
|
||||
{
|
||||
foreach (var direction in Cardinal)
|
||||
foreach (var direction in directions)
|
||||
{
|
||||
var amount = _tileAtmosInfo[direction];
|
||||
if(amount < 0 && _adjacentTiles.TryGetValue(direction, out var adjacent))
|
||||
@@ -592,13 +587,13 @@ namespace Content.Server.Atmos
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private void ConsiderPressureDifference(TileAtmosphere tile, float difference)
|
||||
private void ConsiderPressureDifference(Direction direction, float difference)
|
||||
{
|
||||
_gridAtmosphereComponent.AddHighPressureDelta(this);
|
||||
if (difference > PressureDifference)
|
||||
{
|
||||
PressureDifference = difference;
|
||||
_pressureDirection = ((Vector2i) (GridIndices - tile.GridIndices)).GetCardinalDir();
|
||||
_pressureDirection = difference < 0 ? direction.GetOpposite() : direction;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -606,8 +601,14 @@ namespace Content.Server.Atmos
|
||||
private void AdjustEqMovement(Direction direction, float molesToMove)
|
||||
{
|
||||
_tileAtmosInfo[direction] += molesToMove;
|
||||
if(direction != (Direction)(-1) && _adjacentTiles.TryGetValue(direction, out var adj))
|
||||
_adjacentTiles[direction]._tileAtmosInfo[direction.GetOpposite()] -= molesToMove;
|
||||
if(direction != Direction.Invalid && _adjacentTiles.TryGetValue(direction, out var adj))
|
||||
adj._tileAtmosInfo[direction.GetOpposite()] -= molesToMove;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private void ResetTileAtmosInfo()
|
||||
{
|
||||
_tileAtmosInfo = new TileAtmosInfo {CurrentTransferDirection = Direction.Invalid};
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
@@ -625,7 +626,7 @@ namespace Content.Server.Atmos
|
||||
|
||||
_currentCycle = fireCount;
|
||||
var adjacentTileLength = 0;
|
||||
foreach (var (_, enemyTile) in _adjacentTiles)
|
||||
foreach (var (direction, enemyTile) in _adjacentTiles)
|
||||
{
|
||||
// If the tile is null or has no air, we don't do anything
|
||||
if(enemyTile?.Air == null) continue;
|
||||
@@ -675,11 +676,11 @@ namespace Content.Server.Atmos
|
||||
// Space wind!
|
||||
if (difference > 0)
|
||||
{
|
||||
ConsiderPressureDifference(enemyTile, difference);
|
||||
ConsiderPressureDifference(direction, difference);
|
||||
}
|
||||
else
|
||||
{
|
||||
enemyTile.ConsiderPressureDifference(this, -difference);
|
||||
enemyTile.ConsiderPressureDifference(direction.GetOpposite(), -difference);
|
||||
}
|
||||
|
||||
LastShareCheck();
|
||||
@@ -929,11 +930,10 @@ namespace Content.Server.Atmos
|
||||
var tiles = new List<TileAtmosphere>();
|
||||
var spaceTiles = new List<TileAtmosphere>();
|
||||
tiles.Add(this);
|
||||
_tileAtmosInfo = new TileAtmosInfo
|
||||
{
|
||||
LastQueueCycle = queueCycle,
|
||||
CurrentTransferDirection = Direction.Invalid
|
||||
};
|
||||
|
||||
ResetTileAtmosInfo();
|
||||
_tileAtmosInfo.LastQueueCycle = queueCycle;
|
||||
|
||||
var tileCount = 1;
|
||||
for (var i = 0; i < tileCount; i++)
|
||||
{
|
||||
@@ -947,16 +947,17 @@ namespace Content.Server.Atmos
|
||||
}
|
||||
else
|
||||
{
|
||||
if (i > Atmospherics.ZumosHardTileLimit) continue;
|
||||
if (i > Atmospherics.ZumosTileLimit) continue;
|
||||
foreach (var direction in Cardinal)
|
||||
{
|
||||
if (!_adjacentTiles.TryGetValue(direction, out var tile2)) continue;
|
||||
if (!tile._adjacentTiles.TryGetValue(direction, out var tile2)) continue;
|
||||
if (tile2?.Air == null) continue;
|
||||
if (tile2._tileAtmosInfo.LastQueueCycle == queueCycle) continue;
|
||||
tile.ConsiderFirelocks(tile2);
|
||||
if (tile._adjacentTiles[direction]?.Air != null)
|
||||
{
|
||||
tile2._tileAtmosInfo = new TileAtmosInfo {LastQueueCycle = queueCycle};
|
||||
tile2.ResetTileAtmosInfo();
|
||||
tile2._tileAtmosInfo.LastQueueCycle = queueCycle;
|
||||
tiles.Add(tile2);
|
||||
tileCount++;
|
||||
}
|
||||
@@ -979,7 +980,7 @@ namespace Content.Server.Atmos
|
||||
var tile = progressionOrder[i];
|
||||
foreach (var direction in Cardinal)
|
||||
{
|
||||
if (!_adjacentTiles.TryGetValue(direction, out var tile2)) continue;
|
||||
if (!tile._adjacentTiles.TryGetValue(direction, out var tile2)) continue;
|
||||
if (tile2?._tileAtmosInfo.LastQueueCycle != queueCycle) continue;
|
||||
if (tile2._tileAtmosInfo.LastSlowQueueCycle == queueCycleSlow) continue;
|
||||
if(tile2.Air.Immutable) continue;
|
||||
@@ -992,14 +993,12 @@ namespace Content.Server.Atmos
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < progressionCount; i++)
|
||||
for (var i = progressionCount - 1; i >= 0; i--)
|
||||
{
|
||||
var tile = progressionOrder[i];
|
||||
if (tile._tileAtmosInfo.CurrentTransferDirection == Direction.Invalid) continue;
|
||||
var hpdLength = _gridAtmosphereComponent.HighPressureDeltaCount;
|
||||
var inHdp = _gridAtmosphereComponent.HasHighPressureDelta(tile);
|
||||
if(!inHdp)
|
||||
_gridAtmosphereComponent.AddHighPressureDelta(tile);
|
||||
_gridAtmosphereComponent.AddHighPressureDelta(tile);
|
||||
_gridAtmosphereComponent.AddActiveTile(tile);
|
||||
if (!tile._adjacentTiles.TryGetValue(tile._tileAtmosInfo.CurrentTransferDirection, out var tile2) || tile2.Air == null) continue;
|
||||
var sum = tile2.Air.TotalMoles;
|
||||
totalGasesRemoved += sum;
|
||||
@@ -1007,11 +1006,13 @@ namespace Content.Server.Atmos
|
||||
tile2._tileAtmosInfo.CurrentTransferAmount += tile._tileAtmosInfo.CurrentTransferAmount;
|
||||
tile.PressureDifference = tile._tileAtmosInfo.CurrentTransferAmount;
|
||||
tile._pressureDirection = tile._tileAtmosInfo.CurrentTransferDirection;
|
||||
|
||||
if (tile2._tileAtmosInfo.CurrentTransferDirection == Direction.Invalid)
|
||||
{
|
||||
tile2.PressureDifference = tile2._tileAtmosInfo.CurrentTransferAmount;
|
||||
tile2._pressureDirection = tile._tileAtmosInfo.CurrentTransferDirection;
|
||||
}
|
||||
|
||||
tile.Air.Clear();
|
||||
tile.UpdateVisuals();
|
||||
tile.HandleDecompressionFloorRip(sum);
|
||||
@@ -1020,7 +1021,8 @@ namespace Content.Server.Atmos
|
||||
|
||||
private void HandleDecompressionFloorRip(float sum)
|
||||
{
|
||||
if (sum > 20 && _robustRandom.Prob(FloatMath.Clamp(sum / 100, 0.005f, 0.5f)))
|
||||
var chance = FloatMath.Clamp(sum / 500, 0.005f, 0.5f);
|
||||
if (sum > 20 && _robustRandom.Prob(chance))
|
||||
_gridAtmosphereComponent.PryTile(GridIndices);
|
||||
}
|
||||
|
||||
@@ -1061,14 +1063,19 @@ namespace Content.Server.Atmos
|
||||
{
|
||||
foreach (var direction in Cardinal)
|
||||
{
|
||||
if(!_gridAtmosphereComponent.IsAirBlocked(GridIndices.Offset(direction)))
|
||||
_adjacentTiles[direction] = _gridAtmosphereComponent.GetTile(GridIndices.Offset(direction));
|
||||
if (!_gridAtmosphereComponent.IsAirBlocked(GridIndices.Offset(direction)))
|
||||
{
|
||||
var adjacent = _gridAtmosphereComponent.GetTile(GridIndices.Offset(direction));
|
||||
_adjacentTiles[direction] = adjacent;
|
||||
adjacent.UpdateAdjacent(direction.GetOpposite());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateAdjacent(Direction direction)
|
||||
{
|
||||
_adjacentTiles[direction] = _gridAtmosphereComponent.GetTile(GridIndices.Offset(direction));
|
||||
if (!_gridAtmosphereComponent.IsAirBlocked(GridIndices.Offset(direction)))
|
||||
_adjacentTiles[direction] = _gridAtmosphereComponent.GetTile(GridIndices.Offset(direction));
|
||||
}
|
||||
|
||||
private void LastShareCheck()
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
base.ExposeData(serializer);
|
||||
|
||||
serializer.DataField(ref _airBlocked, "airBlocked", true);
|
||||
serializer.DataField(ref _fixVacuum, "fixVacuum", false);
|
||||
serializer.DataField(ref _fixVacuum, "fixVacuum", true);
|
||||
}
|
||||
|
||||
public override void Initialize()
|
||||
@@ -57,15 +57,6 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
UpdatePosition();
|
||||
}
|
||||
|
||||
public override void OnRemove()
|
||||
{
|
||||
base.OnRemove();
|
||||
|
||||
_airBlocked = false;
|
||||
|
||||
UpdatePosition();
|
||||
}
|
||||
|
||||
public void MapInit()
|
||||
{
|
||||
_snapGrid.OnPositionChanged += OnTransformMove;
|
||||
@@ -80,6 +71,11 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
_airBlocked = false;
|
||||
|
||||
_snapGrid.OnPositionChanged -= OnTransformMove;
|
||||
|
||||
if(_fixVacuum)
|
||||
EntitySystem.Get<AtmosphereSystem>().GetGridAtmosphere(Owner.Transform.GridID)?
|
||||
.FixVacuum(_snapGrid.Position);
|
||||
|
||||
UpdatePosition();
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,6 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
[RegisterComponent, Serializable]
|
||||
public class GridAtmosphereComponent : Component, IGridAtmosphereComponent
|
||||
{
|
||||
[Robust.Shared.IoC.Dependency] private IGameTiming _gameTiming = default!;
|
||||
[Robust.Shared.IoC.Dependency] private IMapManager _mapManager = default!;
|
||||
|
||||
/// <summary>
|
||||
@@ -154,13 +153,14 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
if (tile == null)
|
||||
{
|
||||
tile = new TileAtmosphere(this, _grid.Index, indices, new GasMixture(GetVolumeForCells(1)){Temperature = Atmospherics.T20C});
|
||||
_tiles.Add(indices, tile);
|
||||
_tiles[indices] = tile;
|
||||
}
|
||||
|
||||
if (IsSpace(indices))
|
||||
{
|
||||
tile.Air = new GasMixture(GetVolumeForCells(1));
|
||||
tile.Air.MarkImmutable();
|
||||
_tiles[indices] = tile;
|
||||
|
||||
} else if (IsAirBlocked(indices))
|
||||
{
|
||||
@@ -174,17 +174,7 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
{
|
||||
if (tile.Air == null && obs.FixVacuum)
|
||||
{
|
||||
var adjacent = GetAdjacentTiles(indices);
|
||||
tile.Air = new GasMixture(GetVolumeForCells(1)){Temperature = Atmospherics.T20C};
|
||||
|
||||
var ratio = 1f / adjacent.Count;
|
||||
|
||||
foreach (var (direction, adj) in adjacent)
|
||||
{
|
||||
var mix = adj.Air.RemoveRatio(ratio);
|
||||
tile.Air.Merge(mix);
|
||||
adj.Air.Merge(mix);
|
||||
}
|
||||
FixVacuum(tile.GridIndices);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,6 +196,25 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
_invalidatedCoords.Clear();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void FixVacuum(MapIndices indices)
|
||||
{
|
||||
var tile = GetTile(indices);
|
||||
if (tile?.GridIndex != _grid.Index) return;
|
||||
var adjacent = GetAdjacentTiles(indices);
|
||||
tile.Air = new GasMixture(GetVolumeForCells(1)){Temperature = Atmospherics.T20C};
|
||||
_tiles[indices] = tile;
|
||||
|
||||
var ratio = 1f / adjacent.Count;
|
||||
|
||||
foreach (var (direction, adj) in adjacent)
|
||||
{
|
||||
var mix = adj.Air.RemoveRatio(ratio);
|
||||
tile.Air.Merge(mix);
|
||||
adj.Air.Merge(mix);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void AddActiveTile(TileAtmosphere tile)
|
||||
|
||||
@@ -16,9 +16,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
||||
[RegisterComponent]
|
||||
class VaporComponent : Component, ICollideBehavior
|
||||
{
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||
#pragma warning enable 649
|
||||
public override string Name => "Vapor";
|
||||
|
||||
[ViewVariables]
|
||||
@@ -66,7 +64,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
||||
{
|
||||
var worldBounds = collidable.WorldAABB;
|
||||
var mapGrid = _mapManager.GetGrid(Owner.Transform.GridID);
|
||||
|
||||
|
||||
var tiles = mapGrid.GetTilesIntersecting(worldBounds);
|
||||
var amount = _transferAmount / ReagentUnit.New(tiles.Count());
|
||||
foreach (var tile in tiles)
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
using Content.Shared.GameObjects.EntitySystems;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameObjects.Systems;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Utility;
|
||||
using Robust.Shared.ViewVariables;
|
||||
@@ -16,9 +14,6 @@ namespace Content.Server.GameObjects.Components.Construction
|
||||
[RegisterComponent]
|
||||
public class ConstructionComponent : Component, IExamine
|
||||
{
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly ILocalizationManager _loc;
|
||||
#pragma warning restore 649
|
||||
/// <inheritdoc />
|
||||
public override string Name => "Construction";
|
||||
|
||||
|
||||
@@ -217,7 +217,7 @@ namespace Content.Server.GameObjects.Components.Disposal
|
||||
public override void ExposeData(ObjectSerializer serializer)
|
||||
{
|
||||
base.ExposeData(serializer);
|
||||
serializer.DataField(ref _clangSound, "clangSound", "/Audio/effects/clang.ogg");
|
||||
serializer.DataField(ref _clangSound, "clangSound", "/Audio/Effects/clang.ogg");
|
||||
}
|
||||
|
||||
public override void Initialize()
|
||||
|
||||
@@ -94,7 +94,7 @@ namespace Content.Server.GameObjects.Components.Disposal
|
||||
collidable.Anchored;
|
||||
|
||||
[ViewVariables]
|
||||
private State State => _pressure >= 1 ? State.Ready : State.Pressurizing;
|
||||
private PressureState State => _pressure >= 1 ? PressureState.Ready : PressureState.Pressurizing;
|
||||
|
||||
[ViewVariables]
|
||||
private bool Engaged
|
||||
|
||||
@@ -42,6 +42,8 @@ namespace Content.Server.GameObjects.Components.GUI
|
||||
private string? _activeHand;
|
||||
private uint _nextHand;
|
||||
|
||||
public event Action? OnItemChanged;
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public string? ActiveHand
|
||||
{
|
||||
@@ -60,6 +62,8 @@ namespace Content.Server.GameObjects.Components.GUI
|
||||
|
||||
[ViewVariables] private readonly List<Hand> _hands = new List<Hand>();
|
||||
|
||||
public IEnumerable<string> Hands => _hands.Select(h => h.Name);
|
||||
|
||||
// Mostly arbitrary.
|
||||
public const float PickupRange = 2;
|
||||
|
||||
@@ -105,6 +109,12 @@ namespace Content.Server.GameObjects.Components.GUI
|
||||
return GetHand(handName)?.Entity?.GetComponent<ItemComponent>();
|
||||
}
|
||||
|
||||
public bool TryGetItem(string handName, [MaybeNullWhen(false)] out ItemComponent item)
|
||||
{
|
||||
item = GetItem(handName);
|
||||
return item != null;
|
||||
}
|
||||
|
||||
public ItemComponent? GetActiveHand => ActiveHand == null
|
||||
? null
|
||||
: GetItem(ActiveHand);
|
||||
@@ -136,6 +146,8 @@ namespace Content.Server.GameObjects.Components.GUI
|
||||
{
|
||||
if (PutInHand(item, hand, false))
|
||||
{
|
||||
OnItemChanged?.Invoke();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -156,6 +168,7 @@ namespace Content.Server.GameObjects.Components.GUI
|
||||
if (success)
|
||||
{
|
||||
item.Owner.Transform.LocalPosition = Vector2.Zero;
|
||||
OnItemChanged?.Invoke();
|
||||
}
|
||||
|
||||
_entitySystemManager.GetEntitySystem<InteractionSystem>().HandSelectedInteraction(Owner, item.Owner);
|
||||
@@ -250,6 +263,8 @@ namespace Content.Server.GameObjects.Components.GUI
|
||||
container.Insert(item.Owner);
|
||||
}
|
||||
|
||||
OnItemChanged?.Invoke();
|
||||
|
||||
Dirty();
|
||||
return true;
|
||||
}
|
||||
@@ -300,6 +315,8 @@ namespace Content.Server.GameObjects.Components.GUI
|
||||
container.Insert(item.Owner);
|
||||
}
|
||||
|
||||
OnItemChanged?.Invoke();
|
||||
|
||||
Dirty();
|
||||
return true;
|
||||
}
|
||||
@@ -364,6 +381,8 @@ namespace Content.Server.GameObjects.Components.GUI
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
OnItemChanged?.Invoke();
|
||||
|
||||
Dirty();
|
||||
return true;
|
||||
}
|
||||
@@ -415,6 +434,8 @@ namespace Content.Server.GameObjects.Components.GUI
|
||||
|
||||
ActiveHand ??= name;
|
||||
|
||||
OnItemChanged?.Invoke();
|
||||
|
||||
Dirty();
|
||||
}
|
||||
|
||||
@@ -435,6 +456,8 @@ namespace Content.Server.GameObjects.Components.GUI
|
||||
_activeHand = _hands.FirstOrDefault()?.Name;
|
||||
}
|
||||
|
||||
OnItemChanged?.Invoke();
|
||||
|
||||
Dirty();
|
||||
}
|
||||
|
||||
@@ -645,13 +668,13 @@ namespace Content.Server.GameObjects.Components.GUI
|
||||
|
||||
Dirty();
|
||||
|
||||
if (!message.Entity.TryGetComponent(out IPhysicsComponent physics))
|
||||
if (!message.Entity.TryGetComponent(out ICollidableComponent collidable))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// set velocity to zero
|
||||
physics.Stop();
|
||||
collidable.Stop();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,9 +33,13 @@ namespace Content.Server.GameObjects.Components.GUI
|
||||
#pragma warning restore 649
|
||||
|
||||
[ViewVariables]
|
||||
private readonly Dictionary<Slots, ContainerSlot> SlotContainers = new Dictionary<Slots, ContainerSlot>();
|
||||
private readonly Dictionary<Slots, ContainerSlot> _slotContainers = new Dictionary<Slots, ContainerSlot>();
|
||||
|
||||
private KeyValuePair<Slots, (EntityUid entity, bool fits)>? HoverEntity;
|
||||
private KeyValuePair<Slots, (EntityUid entity, bool fits)>? _hoverEntity;
|
||||
|
||||
public IEnumerable<Slots> Slots => _slotContainers.Keys;
|
||||
|
||||
public event Action OnItemChanged;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -43,7 +47,7 @@ namespace Content.Server.GameObjects.Components.GUI
|
||||
|
||||
foreach (var slotName in InventoryInstance.SlotMasks)
|
||||
{
|
||||
if (slotName != Slots.NONE)
|
||||
if (slotName != EquipmentSlotDefines.Slots.NONE)
|
||||
{
|
||||
AddSlot(slotName);
|
||||
}
|
||||
@@ -58,7 +62,7 @@ namespace Content.Server.GameObjects.Components.GUI
|
||||
{
|
||||
var multiplier = 1f;
|
||||
|
||||
foreach (var (slot, containerSlot) in SlotContainers)
|
||||
foreach (var (slot, containerSlot) in _slotContainers)
|
||||
{
|
||||
foreach (var entity in containerSlot.ContainedEntities)
|
||||
{
|
||||
@@ -81,7 +85,7 @@ namespace Content.Server.GameObjects.Components.GUI
|
||||
{
|
||||
var multiplier = 1f;
|
||||
|
||||
foreach (var (slot, containerSlot) in SlotContainers)
|
||||
foreach (var (slot, containerSlot) in _slotContainers)
|
||||
{
|
||||
foreach (var entity in containerSlot.ContainedEntities)
|
||||
{
|
||||
@@ -99,7 +103,7 @@ namespace Content.Server.GameObjects.Components.GUI
|
||||
bool IEffectBlocker.CanSlip()
|
||||
{
|
||||
if(Owner.TryGetComponent(out InventoryComponent inventoryComponent) &&
|
||||
inventoryComponent.TryGetSlotItem(Slots.SHOES, out ItemComponent shoes)
|
||||
inventoryComponent.TryGetSlotItem(EquipmentSlotDefines.Slots.SHOES, out ItemComponent shoes)
|
||||
)
|
||||
{
|
||||
return EffectBlockerSystem.CanSlip(shoes.Owner);
|
||||
@@ -110,7 +114,7 @@ namespace Content.Server.GameObjects.Components.GUI
|
||||
|
||||
public override void OnRemove()
|
||||
{
|
||||
var slots = SlotContainers.Keys.ToList();
|
||||
var slots = _slotContainers.Keys.ToList();
|
||||
foreach (var slot in slots)
|
||||
{
|
||||
RemoveSlot(slot);
|
||||
@@ -140,15 +144,15 @@ namespace Content.Server.GameObjects.Components.GUI
|
||||
}
|
||||
public T GetSlotItem<T>(Slots slot) where T : ItemComponent
|
||||
{
|
||||
if (!SlotContainers.ContainsKey(slot))
|
||||
if (!_slotContainers.ContainsKey(slot))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var containedEntity = SlotContainers[slot].ContainedEntity;
|
||||
var containedEntity = _slotContainers[slot].ContainedEntity;
|
||||
if (containedEntity?.Deleted == true)
|
||||
{
|
||||
SlotContainers[slot] = null;
|
||||
_slotContainers[slot] = null;
|
||||
containedEntity = null;
|
||||
Dirty();
|
||||
}
|
||||
@@ -169,7 +173,7 @@ namespace Content.Server.GameObjects.Components.GUI
|
||||
/// </remarks>
|
||||
/// <param name="slot">The slot to put the item in.</param>
|
||||
/// <param name="item">The item to insert into the slot.</param>
|
||||
/// <param name="reason">The translated reason why the item cannot be equiped, if this function returns false. Can be null.</param>
|
||||
/// <param name="reason">The translated reason why the item cannot be equipped, if this function returns false. Can be null.</param>
|
||||
/// <returns>True if the item was successfully inserted, false otherwise.</returns>
|
||||
public bool Equip(Slots slot, ItemComponent item, out string reason)
|
||||
{
|
||||
@@ -184,7 +188,7 @@ namespace Content.Server.GameObjects.Components.GUI
|
||||
return false;
|
||||
}
|
||||
|
||||
var inventorySlot = SlotContainers[slot];
|
||||
var inventorySlot = _slotContainers[slot];
|
||||
if (!inventorySlot.Insert(item.Owner))
|
||||
{
|
||||
return false;
|
||||
@@ -192,6 +196,8 @@ namespace Content.Server.GameObjects.Components.GUI
|
||||
|
||||
_entitySystemManager.GetEntitySystem<InteractionSystem>().EquippedInteraction(Owner, item.Owner, slot);
|
||||
|
||||
OnItemChanged?.Invoke();
|
||||
|
||||
Dirty();
|
||||
|
||||
return true;
|
||||
@@ -239,7 +245,7 @@ namespace Content.Server.GameObjects.Components.GUI
|
||||
reason = Loc.GetString("You can't equip this!");
|
||||
}
|
||||
|
||||
return pass && SlotContainers[slot].CanInsert(item.Owner);
|
||||
return pass && _slotContainers[slot].CanInsert(item.Owner);
|
||||
}
|
||||
|
||||
public bool CanEquip(Slots slot, ItemComponent item) => CanEquip(slot, item, out var _);
|
||||
@@ -258,7 +264,7 @@ namespace Content.Server.GameObjects.Components.GUI
|
||||
return false;
|
||||
}
|
||||
|
||||
var inventorySlot = SlotContainers[slot];
|
||||
var inventorySlot = _slotContainers[slot];
|
||||
var item = inventorySlot.ContainedEntity.GetComponent<ItemComponent>();
|
||||
if (!inventorySlot.Remove(inventorySlot.ContainedEntity))
|
||||
{
|
||||
@@ -271,6 +277,8 @@ namespace Content.Server.GameObjects.Components.GUI
|
||||
|
||||
_entitySystemManager.GetEntitySystem<InteractionSystem>().UnequippedInteraction(Owner, item.Owner, slot);
|
||||
|
||||
OnItemChanged?.Invoke();
|
||||
|
||||
Dirty();
|
||||
|
||||
return true;
|
||||
@@ -288,7 +296,7 @@ namespace Content.Server.GameObjects.Components.GUI
|
||||
if (!ActionBlockerSystem.CanUnequip(Owner))
|
||||
return false;
|
||||
|
||||
var InventorySlot = SlotContainers[slot];
|
||||
var InventorySlot = _slotContainers[slot];
|
||||
return InventorySlot.ContainedEntity != null && InventorySlot.CanRemove(InventorySlot.ContainedEntity);
|
||||
}
|
||||
|
||||
@@ -307,7 +315,12 @@ namespace Content.Server.GameObjects.Components.GUI
|
||||
}
|
||||
|
||||
Dirty();
|
||||
return SlotContainers[slot] = ContainerManagerComponent.Create<ContainerSlot>(GetSlotString(slot), Owner);
|
||||
|
||||
_slotContainers[slot] = ContainerManagerComponent.Create<ContainerSlot>(GetSlotString(slot), Owner);
|
||||
|
||||
OnItemChanged?.Invoke();
|
||||
|
||||
return _slotContainers[slot];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -331,7 +344,10 @@ namespace Content.Server.GameObjects.Components.GUI
|
||||
"Unable to remove slot as the contained clothing could not be dropped");
|
||||
}
|
||||
|
||||
SlotContainers.Remove(slot);
|
||||
_slotContainers.Remove(slot);
|
||||
|
||||
OnItemChanged?.Invoke();
|
||||
|
||||
Dirty();
|
||||
}
|
||||
|
||||
@@ -342,7 +358,7 @@ namespace Content.Server.GameObjects.Components.GUI
|
||||
/// <returns>True if the slot exists, false otherwise.</returns>
|
||||
public bool HasSlot(Slots slot)
|
||||
{
|
||||
return SlotContainers.ContainsKey(slot);
|
||||
return _slotContainers.ContainsKey(slot);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -354,7 +370,7 @@ namespace Content.Server.GameObjects.Components.GUI
|
||||
// make sure this is one of our containers.
|
||||
// Technically the correct way would be to enumerate the possible slot names
|
||||
// comparing with this container, but I might as well put the dictionary to good use.
|
||||
if (!(container is ContainerSlot slot) || !SlotContainers.ContainsValue(slot))
|
||||
if (!(container is ContainerSlot slot) || !_slotContainers.ContainsValue(slot))
|
||||
return;
|
||||
|
||||
if (entity.TryGetComponent(out ItemComponent itemComp))
|
||||
@@ -362,6 +378,8 @@ namespace Content.Server.GameObjects.Components.GUI
|
||||
itemComp.RemovedFromSlot();
|
||||
}
|
||||
|
||||
OnItemChanged?.Invoke();
|
||||
|
||||
Dirty();
|
||||
}
|
||||
|
||||
@@ -417,7 +435,7 @@ namespace Content.Server.GameObjects.Components.GUI
|
||||
if (activeHand != null && GetSlotItem(msg.Inventoryslot) == null)
|
||||
{
|
||||
var canEquip = CanEquip(msg.Inventoryslot, activeHand, out var reason);
|
||||
HoverEntity = new KeyValuePair<Slots, (EntityUid entity, bool fits)>(msg.Inventoryslot, (activeHand.Owner.Uid, canEquip));
|
||||
_hoverEntity = new KeyValuePair<Slots, (EntityUid entity, bool fits)>(msg.Inventoryslot, (activeHand.Owner.Uid, canEquip));
|
||||
|
||||
Dirty();
|
||||
}
|
||||
@@ -476,7 +494,7 @@ namespace Content.Server.GameObjects.Components.GUI
|
||||
public override ComponentState GetComponentState()
|
||||
{
|
||||
var list = new List<KeyValuePair<Slots, EntityUid>>();
|
||||
foreach (var (slot, container) in SlotContainers)
|
||||
foreach (var (slot, container) in _slotContainers)
|
||||
{
|
||||
if (container.ContainedEntity != null)
|
||||
{
|
||||
@@ -484,8 +502,8 @@ namespace Content.Server.GameObjects.Components.GUI
|
||||
}
|
||||
}
|
||||
|
||||
var hover = HoverEntity;
|
||||
HoverEntity = null;
|
||||
var hover = _hoverEntity;
|
||||
_hoverEntity = null;
|
||||
|
||||
return new InventoryComponentState(list, hover);
|
||||
}
|
||||
@@ -497,7 +515,7 @@ namespace Content.Server.GameObjects.Components.GUI
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var slot in SlotContainers.Values.ToList())
|
||||
foreach (var slot in _slotContainers.Values.ToList())
|
||||
{
|
||||
foreach (var entity in slot.ContainedEntities)
|
||||
{
|
||||
|
||||
372
Content.Server/GameObjects/Components/GUI/StrippableComponent.cs
Normal file
372
Content.Server/GameObjects/Components/GUI/StrippableComponent.cs
Normal file
@@ -0,0 +1,372 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using Content.Server.GameObjects.Components.Items.Storage;
|
||||
using Content.Server.GameObjects.EntitySystems.DoAfter;
|
||||
using Content.Server.Interfaces;
|
||||
using Content.Shared.GameObjects.Components.GUI;
|
||||
using Content.Shared.GameObjects.Components.Inventory;
|
||||
using Content.Shared.GameObjects.EntitySystems;
|
||||
using Content.Shared.Interfaces.GameObjects.Components;
|
||||
using Robust.Server.GameObjects.Components.UserInterface;
|
||||
using Robust.Server.Interfaces.GameObjects;
|
||||
using Robust.Server.Interfaces.Player;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameObjects.Systems;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.ViewVariables;
|
||||
using static Content.Shared.GameObjects.Components.Inventory.EquipmentSlotDefines;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.GUI
|
||||
{
|
||||
[RegisterComponent]
|
||||
public sealed class StrippableComponent : SharedStrippableComponent, IDragDrop
|
||||
{
|
||||
[Dependency] private IServerNotifyManager _notifyManager = default!;
|
||||
|
||||
public const float StripDelay = 2f;
|
||||
|
||||
[ViewVariables]
|
||||
private BoundUserInterface _userInterface;
|
||||
|
||||
private InventoryComponent _inventoryComponent;
|
||||
private HandsComponent _handsComponent;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
_userInterface = Owner.GetComponent<ServerUserInterfaceComponent>().GetBoundUserInterface(StrippingUiKey.Key);
|
||||
_userInterface.OnReceiveMessage += HandleUserInterfaceMessage;
|
||||
|
||||
_inventoryComponent = Owner.GetComponent<InventoryComponent>();
|
||||
_handsComponent = Owner.GetComponent<HandsComponent>();
|
||||
|
||||
_inventoryComponent.OnItemChanged += UpdateSubscribed;
|
||||
|
||||
// Initial update.
|
||||
UpdateSubscribed();
|
||||
}
|
||||
|
||||
private void UpdateSubscribed()
|
||||
{
|
||||
var inventory = GetInventorySlots();
|
||||
var hands = GetHandSlots();
|
||||
|
||||
_userInterface.SetState(new StrippingBoundUserInterfaceState(inventory, hands));
|
||||
}
|
||||
|
||||
public bool CanDragDrop(DragDropEventArgs eventArgs)
|
||||
{
|
||||
return eventArgs.User.HasComponent<HandsComponent>()
|
||||
&& eventArgs.Target != eventArgs.Dropped && eventArgs.Target == eventArgs.User;
|
||||
}
|
||||
|
||||
public bool DragDrop(DragDropEventArgs eventArgs)
|
||||
{
|
||||
if (!eventArgs.User.TryGetComponent(out IActorComponent actor)) return false;
|
||||
|
||||
OpenUserInterface(actor.playerSession);
|
||||
return true;
|
||||
}
|
||||
|
||||
private Dictionary<Slots, string> GetInventorySlots()
|
||||
{
|
||||
var dictionary = new Dictionary<Slots, string>();
|
||||
|
||||
foreach (var slot in _inventoryComponent.Slots)
|
||||
{
|
||||
dictionary[slot] = _inventoryComponent.GetSlotItem(slot)?.Owner.Name ?? "None";
|
||||
}
|
||||
|
||||
return dictionary;
|
||||
}
|
||||
|
||||
private Dictionary<string, string> GetHandSlots()
|
||||
{
|
||||
var dictionary = new Dictionary<string, string>();
|
||||
|
||||
foreach (var hand in _handsComponent.Hands)
|
||||
{
|
||||
dictionary[hand] = _handsComponent.GetItem(hand)?.Owner.Name ?? "None";
|
||||
}
|
||||
|
||||
return dictionary;
|
||||
}
|
||||
|
||||
private void OpenUserInterface(IPlayerSession session)
|
||||
{
|
||||
_userInterface.Open(session);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Places item in user's active hand to an inventory slot.
|
||||
/// </summary>
|
||||
private async void PlaceActiveHandItemInInventory(IEntity user, Slots slot)
|
||||
{
|
||||
var inventory = Owner.GetComponent<InventoryComponent>();
|
||||
var userHands = user.GetComponent<HandsComponent>();
|
||||
var item = userHands.GetActiveHand;
|
||||
|
||||
bool Check()
|
||||
{
|
||||
if (!ActionBlockerSystem.CanInteract(user))
|
||||
return false;
|
||||
|
||||
if (item == null)
|
||||
{
|
||||
_notifyManager.PopupMessageCursor(user, Loc.GetString("You aren't holding anything!"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!userHands.CanDrop(userHands.ActiveHand!))
|
||||
{
|
||||
_notifyManager.PopupMessageCursor(user, Loc.GetString("You can't drop that!"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!inventory.HasSlot(slot))
|
||||
return false;
|
||||
|
||||
if (inventory.TryGetSlotItem(slot, out ItemComponent _))
|
||||
{
|
||||
_notifyManager.PopupMessageCursor(user, Loc.GetString("{0:They} already {0:have} something there!", Owner));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!inventory.CanEquip(slot, item))
|
||||
{
|
||||
_notifyManager.PopupMessageCursor(user, Loc.GetString("{0:They} cannot equip that there!", Owner));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
var doAfterSystem = EntitySystem.Get<DoAfterSystem>();
|
||||
|
||||
var doAfterArgs = new DoAfterEventArgs(user, StripDelay, CancellationToken.None, Owner)
|
||||
{
|
||||
ExtraCheck = Check,
|
||||
BreakOnStun = true,
|
||||
BreakOnDamage = true,
|
||||
BreakOnTargetMove = true,
|
||||
BreakOnUserMove = true,
|
||||
NeedHand = true,
|
||||
};
|
||||
|
||||
var result = await doAfterSystem.DoAfter(doAfterArgs);
|
||||
if (result != DoAfterStatus.Finished) return;
|
||||
|
||||
userHands.Drop(item!.Owner, false);
|
||||
inventory.Equip(slot, item!.Owner);
|
||||
|
||||
UpdateSubscribed();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Places item in user's active hand in one of the entity's hands.
|
||||
/// </summary>
|
||||
private async void PlaceActiveHandItemInHands(IEntity user, string hand)
|
||||
{
|
||||
var hands = Owner.GetComponent<HandsComponent>();
|
||||
var userHands = user.GetComponent<HandsComponent>();
|
||||
var item = userHands.GetActiveHand;
|
||||
|
||||
bool Check()
|
||||
{
|
||||
if (!ActionBlockerSystem.CanInteract(user))
|
||||
return false;
|
||||
|
||||
if (item == null)
|
||||
{
|
||||
_notifyManager.PopupMessageCursor(user, Loc.GetString("You aren't holding anything!"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!userHands.CanDrop(userHands.ActiveHand!))
|
||||
{
|
||||
_notifyManager.PopupMessageCursor(user, Loc.GetString("You can't drop that!"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!hands.HasHand(hand))
|
||||
return false;
|
||||
|
||||
if (hands.TryGetItem(hand, out var _))
|
||||
{
|
||||
_notifyManager.PopupMessageCursor(user, Loc.GetString("{0:They} already {0:have} something there!", Owner));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!hands.CanPutInHand(item, hand))
|
||||
{
|
||||
_notifyManager.PopupMessageCursor(user, Loc.GetString("{0:They} cannot put that there!", Owner));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
var doAfterSystem = EntitySystem.Get<DoAfterSystem>();
|
||||
|
||||
var doAfterArgs = new DoAfterEventArgs(user, StripDelay, CancellationToken.None, Owner)
|
||||
{
|
||||
ExtraCheck = Check,
|
||||
BreakOnStun = true,
|
||||
BreakOnDamage = true,
|
||||
BreakOnTargetMove = true,
|
||||
BreakOnUserMove = true,
|
||||
NeedHand = true,
|
||||
};
|
||||
|
||||
var result = await doAfterSystem.DoAfter(doAfterArgs);
|
||||
if (result != DoAfterStatus.Finished) return;
|
||||
|
||||
userHands.Drop(hand, false);
|
||||
hands.PutInHand(item, hand, false);
|
||||
UpdateSubscribed();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Takes an item from the inventory and places it in the user's active hand.
|
||||
/// </summary>
|
||||
private async void TakeItemFromInventory(IEntity user, Slots slot)
|
||||
{
|
||||
var inventory = Owner.GetComponent<InventoryComponent>();
|
||||
var userHands = user.GetComponent<HandsComponent>();
|
||||
|
||||
bool Check()
|
||||
{
|
||||
if (!ActionBlockerSystem.CanInteract(user))
|
||||
return false;
|
||||
|
||||
if (!inventory.HasSlot(slot))
|
||||
return false;
|
||||
|
||||
if (!inventory.TryGetSlotItem(slot, out ItemComponent itemToTake))
|
||||
{
|
||||
_notifyManager.PopupMessageCursor(user, Loc.GetString("{0:They} {0:have} nothing there!", Owner));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!inventory.CanUnequip(slot))
|
||||
{
|
||||
_notifyManager.PopupMessageCursor(user, Loc.GetString("{0:They} cannot unequip that!", Owner));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
var doAfterSystem = EntitySystem.Get<DoAfterSystem>();
|
||||
|
||||
var doAfterArgs = new DoAfterEventArgs(user, StripDelay, CancellationToken.None, Owner)
|
||||
{
|
||||
ExtraCheck = Check,
|
||||
BreakOnStun = true,
|
||||
BreakOnDamage = true,
|
||||
BreakOnTargetMove = true,
|
||||
BreakOnUserMove = true,
|
||||
};
|
||||
|
||||
var result = await doAfterSystem.DoAfter(doAfterArgs);
|
||||
if (result != DoAfterStatus.Finished) return;
|
||||
|
||||
var item = inventory.GetSlotItem(slot);
|
||||
inventory.Unequip(slot);
|
||||
userHands.PutInHandOrDrop(item);
|
||||
UpdateSubscribed();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Takes an item from a hand and places it in the user's active hand.
|
||||
/// </summary>
|
||||
private async void TakeItemFromHands(IEntity user, string hand)
|
||||
{
|
||||
var hands = Owner.GetComponent<HandsComponent>();
|
||||
var userHands = user.GetComponent<HandsComponent>();
|
||||
|
||||
bool Check()
|
||||
{
|
||||
if (!ActionBlockerSystem.CanInteract(user))
|
||||
return false;
|
||||
|
||||
if (!hands.HasHand(hand))
|
||||
return false;
|
||||
|
||||
if (!hands.TryGetItem(hand, out var heldItem))
|
||||
{
|
||||
_notifyManager.PopupMessageCursor(user, Loc.GetString("{0:They} {0:have} nothing there!", Owner));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!hands.CanDrop(hand))
|
||||
{
|
||||
_notifyManager.PopupMessageCursor(user, Loc.GetString("{0:They} cannot drop that!", Owner));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
var doAfterSystem = EntitySystem.Get<DoAfterSystem>();
|
||||
|
||||
var doAfterArgs = new DoAfterEventArgs(user, StripDelay, CancellationToken.None, Owner)
|
||||
{
|
||||
ExtraCheck = Check,
|
||||
BreakOnStun = true,
|
||||
BreakOnDamage = true,
|
||||
BreakOnTargetMove = true,
|
||||
BreakOnUserMove = true,
|
||||
};
|
||||
|
||||
var result = await doAfterSystem.DoAfter(doAfterArgs);
|
||||
if (result != DoAfterStatus.Finished) return;
|
||||
|
||||
var item = hands.GetItem(hand);
|
||||
hands.Drop(hand, false);
|
||||
userHands.PutInHandOrDrop(item);
|
||||
UpdateSubscribed();
|
||||
}
|
||||
|
||||
private void HandleUserInterfaceMessage(ServerBoundUserInterfaceMessage obj)
|
||||
{
|
||||
var user = obj.Session.AttachedEntity;
|
||||
if (user == null || !(user.TryGetComponent(out HandsComponent userHands))) return;
|
||||
|
||||
var placingItem = userHands.GetActiveHand != null;
|
||||
|
||||
switch (obj.Message)
|
||||
{
|
||||
case StrippingInventoryButtonPressed inventoryMessage:
|
||||
var inventory = Owner.GetComponent<InventoryComponent>();
|
||||
|
||||
if (inventory.TryGetSlotItem(inventoryMessage.Slot, out ItemComponent _))
|
||||
placingItem = false;
|
||||
|
||||
if(placingItem)
|
||||
PlaceActiveHandItemInInventory(user, inventoryMessage.Slot);
|
||||
else
|
||||
TakeItemFromInventory(user, inventoryMessage.Slot);
|
||||
break;
|
||||
case StrippingHandButtonPressed handMessage:
|
||||
var hands = Owner.GetComponent<HandsComponent>();
|
||||
|
||||
if (hands.TryGetItem(handMessage.Hand, out _))
|
||||
placingItem = false;
|
||||
|
||||
if(placingItem)
|
||||
PlaceActiveHandItemInHands(user, handMessage.Hand);
|
||||
else
|
||||
TakeItemFromHands(user, handMessage.Hand);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,6 @@ using Content.Shared.GameObjects.EntitySystems;
|
||||
using Content.Shared.GameObjects.Verbs;
|
||||
using Content.Shared.Interfaces;
|
||||
using Content.Shared.Interfaces.GameObjects.Components;
|
||||
using Content.Shared.Physics;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Server.GameObjects.Components.Container;
|
||||
using Robust.Server.GameObjects.EntitySystems;
|
||||
@@ -50,8 +49,6 @@ namespace Content.Server.GameObjects.Components.Items.Storage
|
||||
private bool _occludesLight;
|
||||
private bool _open;
|
||||
private bool _isWeldedShut;
|
||||
private int _collisionMaskStorage;
|
||||
private int _collisionLayerStorage;
|
||||
|
||||
[ViewVariables]
|
||||
protected Container Contents;
|
||||
@@ -202,18 +199,13 @@ namespace Content.Server.GameObjects.Components.Items.Storage
|
||||
{
|
||||
if (!_isCollidableWhenOpen && Owner.TryGetComponent<ICollidableComponent>(out var collidableComponent))
|
||||
{
|
||||
var physShape = collidableComponent.PhysicsShapes[0];
|
||||
if (Open)
|
||||
{
|
||||
_collisionMaskStorage = physShape.CollisionMask;
|
||||
physShape.CollisionMask = (int)CollisionGroup.Impassable;
|
||||
_collisionLayerStorage = physShape.CollisionLayer;
|
||||
physShape.CollisionLayer = (int)CollisionGroup.None;
|
||||
collidableComponent.Hard = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
physShape.CollisionMask = _collisionMaskStorage;
|
||||
physShape.CollisionLayer = _collisionLayerStorage;
|
||||
collidableComponent.Hard = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@ using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameObjects.Components;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.Interfaces.Map;
|
||||
using Robust.Shared.Interfaces.Random;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
@@ -29,7 +28,6 @@ namespace Content.Server.GameObjects.Components.Items.Storage
|
||||
public override uint? NetID => ContentNetIDs.ITEM;
|
||||
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IRobustRandom _robustRandom;
|
||||
[Dependency] private readonly IMapManager _mapManager;
|
||||
#pragma warning restore 649
|
||||
|
||||
@@ -93,7 +91,7 @@ namespace Content.Server.GameObjects.Components.Items.Storage
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Owner.TryGetComponent(out PhysicsComponent physics) &&
|
||||
if (Owner.TryGetComponent(out CollidableComponent physics) &&
|
||||
physics.Anchored)
|
||||
{
|
||||
return false;
|
||||
|
||||
@@ -132,12 +132,12 @@ namespace Content.Server.GameObjects.Components.Mobs
|
||||
if (!HasMind)
|
||||
{
|
||||
message.AddMarkup(!dead
|
||||
? $"[color=red]" + Loc.GetString("{0:They} are totally catatonic. The stresses of life in deep-space must have been too much for {0:them}. Any recovery is unlikely.", Owner) + "[/color]"
|
||||
? $"[color=red]" + Loc.GetString("{0:They} {0:are} totally catatonic. The stresses of life in deep-space must have been too much for {0:them}. Any recovery is unlikely.", Owner) + "[/color]"
|
||||
: $"[color=purple]" + Loc.GetString("{0:Their} soul has departed.", Owner) + "[/color]");
|
||||
}
|
||||
else if (Mind?.Session == null)
|
||||
{
|
||||
message.AddMarkup("[color=yellow]" + Loc.GetString("{0:They} have a blank, absent-minded stare and appears completely unresponsive to anything. {0:They} may snap out of it soon.", Owner) + "[/color]");
|
||||
message.AddMarkup("[color=yellow]" + Loc.GetString("{0:They} {0:have} a blank, absent-minded stare and appears completely unresponsive to anything. {0:They} may snap out of it soon.", Owner) + "[/color]");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,9 +42,9 @@ namespace Content.Server.GameObjects.Components.Movement
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
// This component requires a physics component.
|
||||
if (!Owner.HasComponent<IPhysicsComponent>())
|
||||
Owner.AddComponent<PhysicsComponent>();
|
||||
// This component requires a collidable component.
|
||||
if (!Owner.HasComponent<ICollidableComponent>())
|
||||
Owner.AddComponent<CollidableComponent>();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -71,22 +71,15 @@ namespace Content.Server.GameObjects.Components.Movement
|
||||
_entityManager.TryGetEntity(grid.GridEntityId, out var gridEntity))
|
||||
{
|
||||
//TODO: Switch to shuttle component
|
||||
if (!gridEntity.TryGetComponent(out IPhysicsComponent physComp))
|
||||
if (!gridEntity.TryGetComponent(out ICollidableComponent collidable))
|
||||
{
|
||||
physComp = gridEntity.AddComponent<PhysicsComponent>();
|
||||
physComp.Mass = 1;
|
||||
collidable = gridEntity.AddComponent<CollidableComponent>();
|
||||
collidable.Mass = 1;
|
||||
collidable.CanCollide = true;
|
||||
collidable.PhysicsShapes.Add(new PhysShapeGrid(grid));
|
||||
}
|
||||
|
||||
//TODO: Is this always true?
|
||||
if (!gridEntity.HasComponent<ICollidableComponent>())
|
||||
{
|
||||
var collideComp = gridEntity.AddComponent<CollidableComponent>();
|
||||
collideComp.CanCollide = true;
|
||||
//collideComp.IsHardCollidable = true;
|
||||
collideComp.PhysicsShapes.Add(new PhysShapeGrid(grid));
|
||||
}
|
||||
|
||||
var controller = physComp.EnsureController<ShuttleController>();
|
||||
var controller = collidable.EnsureController<ShuttleController>();
|
||||
controller.Push(CalcNewVelocity(direction, enabled), CurrentWalkSpeed);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,9 +92,9 @@ namespace Content.Server.GameObjects.Components.Projectiles
|
||||
}
|
||||
|
||||
if (!entity.Deleted && entity.TryGetComponent(out CameraRecoilComponent recoilComponent)
|
||||
&& Owner.TryGetComponent(out IPhysicsComponent physicsComponent))
|
||||
&& Owner.TryGetComponent(out ICollidableComponent collidableComponent))
|
||||
{
|
||||
var direction = physicsComponent.LinearVelocity.Normalized;
|
||||
var direction = collidableComponent.LinearVelocity.Normalized;
|
||||
recoilComponent.Kick(direction);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ namespace Content.Server.GameObjects.Components.Projectiles
|
||||
|
||||
public void StartThrow(Vector2 direction, float speed)
|
||||
{
|
||||
var comp = Owner.GetComponent<IPhysicsComponent>();
|
||||
var comp = Owner.GetComponent<ICollidableComponent>();
|
||||
comp.Status = BodyStatus.InAir;
|
||||
|
||||
var controller = comp.EnsureController<ThrownController>();
|
||||
|
||||
@@ -21,9 +21,9 @@ namespace Content.Server.GameObjects.Components.Rotatable
|
||||
|
||||
private void TryRotate(IEntity user, Angle angle)
|
||||
{
|
||||
if (Owner.TryGetComponent(out IPhysicsComponent physics))
|
||||
if (Owner.TryGetComponent(out ICollidableComponent collidable))
|
||||
{
|
||||
if (physics.Anchored)
|
||||
if (collidable.Anchored)
|
||||
{
|
||||
_notifyManager.PopupMessage(Owner.Transform.GridPosition, user, _localizationManager.GetString("It's stuck."));
|
||||
return;
|
||||
|
||||
@@ -5,7 +5,6 @@ using Content.Server.GameObjects.Components.Damage;
|
||||
using Content.Server.GameObjects.Components.Mobs;
|
||||
using Content.Server.GameObjects.Components.Projectiles;
|
||||
using Content.Server.GameObjects.Components.Weapon.Ranged.Ammunition;
|
||||
using Content.Server.Interfaces;
|
||||
using Content.Shared.Audio;
|
||||
using Content.Shared.GameObjects.Components.Weapons.Ranged;
|
||||
using Content.Shared.GameObjects.EntitySystems;
|
||||
@@ -43,7 +42,6 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Barrels
|
||||
#pragma warning disable 649
|
||||
[Dependency] private IGameTiming _gameTiming;
|
||||
[Dependency] private IRobustRandom _robustRandom;
|
||||
[Dependency] private readonly IServerNotifyManager _notifyManager;
|
||||
#pragma warning restore 649
|
||||
|
||||
public override FireRateSelector FireRateSelector => _fireRateSelector;
|
||||
@@ -385,15 +383,15 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Barrels
|
||||
projectileAngle = angle;
|
||||
}
|
||||
|
||||
var physicsComponent = projectile.GetComponent<IPhysicsComponent>();
|
||||
physicsComponent.Status = BodyStatus.InAir;
|
||||
var collidableComponent = projectile.GetComponent<ICollidableComponent>();
|
||||
collidableComponent.Status = BodyStatus.InAir;
|
||||
projectile.Transform.GridPosition = Owner.Transform.GridPosition;
|
||||
|
||||
var projectileComponent = projectile.GetComponent<ProjectileComponent>();
|
||||
projectileComponent.IgnoreEntity(shooter);
|
||||
|
||||
projectile
|
||||
.GetComponent<IPhysicsComponent>()
|
||||
.GetComponent<ICollidableComponent>()
|
||||
.EnsureController<BulletController>()
|
||||
.LinearVelocity = projectileAngle.ToVec() * velocity;
|
||||
|
||||
|
||||
@@ -27,7 +27,6 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Steering
|
||||
|
||||
#pragma warning disable 649
|
||||
[Dependency] private IMapManager _mapManager;
|
||||
[Dependency] private IEntityManager _entityManager;
|
||||
[Dependency] private IPauseManager _pauseManager;
|
||||
#pragma warning restore 649
|
||||
private PathfindingSystem _pathfindingSystem;
|
||||
|
||||
@@ -17,18 +17,14 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
[UsedImplicitly]
|
||||
public class AtmosphereSystem : EntitySystem
|
||||
{
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
[Dependency] private readonly IPauseManager _pauseManager = default!;
|
||||
#pragma warning restore 649
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
_mapManager.TileChanged += OnTileChanged;
|
||||
EntityQuery = new MultipleTypeEntityQuery(new List<Type>(){typeof(IGridAtmosphereComponent)});
|
||||
}
|
||||
|
||||
public IGridAtmosphereComponent? GetGridAtmosphere(GridId gridId)
|
||||
@@ -36,7 +32,7 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
// TODO Return space grid atmosphere for invalid grids or grids with no atmos
|
||||
var grid = _mapManager.GetGrid(gridId);
|
||||
|
||||
if (!_entityManager.TryGetEntity(grid.GridEntityId, out var gridEnt)) return null;
|
||||
if (!EntityManager.TryGetEntity(grid.GridEntityId, out var gridEnt)) return null;
|
||||
|
||||
return gridEnt.TryGetComponent(out IGridAtmosphereComponent atmos) ? atmos : null;
|
||||
}
|
||||
@@ -45,13 +41,12 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
{
|
||||
base.Update(frameTime);
|
||||
|
||||
foreach (var gridEnt in RelevantEntities)
|
||||
foreach (var (mapGridComponent, gridAtmosphereComponent) in EntityManager.ComponentManager.EntityQuery<IMapGridComponent, IGridAtmosphereComponent>())
|
||||
{
|
||||
var grid = gridEnt.GetComponent<IMapGridComponent>();
|
||||
if (_pauseManager.IsGridPaused(grid.GridIndex))
|
||||
if (_pauseManager.IsGridPaused(mapGridComponent.GridIndex))
|
||||
continue;
|
||||
|
||||
gridEnt.GetComponent<IGridAtmosphereComponent>().Update(frameTime);
|
||||
gridAtmosphereComponent.Update(frameTime);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ using Robust.Server.Interfaces.Player;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Server.GameObjects.EntitySystems.Click
|
||||
@@ -19,7 +20,7 @@ namespace Content.Server.GameObjects.EntitySystems.Click
|
||||
static ExamineSystem()
|
||||
{
|
||||
_entityNotFoundMessage = new FormattedMessage();
|
||||
_entityNotFoundMessage.AddText("That entity doesn't exist");
|
||||
_entityNotFoundMessage.AddText(Loc.GetString("That entity doesn't exist"));
|
||||
}
|
||||
|
||||
public override void Initialize()
|
||||
|
||||
@@ -58,23 +58,13 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
foreach (var entity in RelevantEntities)
|
||||
foreach (var (moverComponent, collidableComponent) in EntityManager.ComponentManager.EntityQuery<IMoverComponent, ICollidableComponent>())
|
||||
{
|
||||
var entity = moverComponent.Owner;
|
||||
if (_pauseManager.IsEntityPaused(entity))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var mover = entity.GetComponent<IMoverComponent>();
|
||||
var physics = entity.GetComponent<IPhysicsComponent>();
|
||||
if (entity.TryGetComponent<ICollidableComponent>(out var collider))
|
||||
{
|
||||
UpdateKinematics(entity.Transform, mover, physics, collider);
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateKinematics(entity.Transform, mover, physics);
|
||||
}
|
||||
UpdateKinematics(entity.Transform, moverComponent, collidableComponent);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,7 +83,7 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
ev.Entity.RemoveComponent<PlayerInputMoverComponent>();
|
||||
}
|
||||
|
||||
if (ev.Entity.TryGetComponent(out IPhysicsComponent physics) &&
|
||||
if (ev.Entity.TryGetComponent(out ICollidableComponent physics) &&
|
||||
physics.TryGetController(out MoverController controller))
|
||||
{
|
||||
controller.StopMoving();
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Reflection;
|
||||
using Content.Shared.GameObjects.Verbs;
|
||||
using Robust.Server.Interfaces.Player;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameObjects.Systems;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
@@ -37,6 +38,12 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
var session = eventArgs.SenderSession;
|
||||
var userEntity = session.AttachedEntity;
|
||||
|
||||
if (userEntity == null)
|
||||
{
|
||||
Logger.Warning($"{nameof(UseVerb)} called by player {session} with no attached entity.");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var (component, verb) in VerbUtility.GetVerbs(entity))
|
||||
{
|
||||
if ($"{component.GetType()}:{verb.GetType()}" != use.VerbKey)
|
||||
@@ -44,14 +51,14 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
continue;
|
||||
}
|
||||
|
||||
if (verb.RequireInteractionRange)
|
||||
if (verb.RequireInteractionRange && !VerbUtility.InVerbUseRange(userEntity, entity))
|
||||
{
|
||||
var distanceSquared = (userEntity.Transform.WorldPosition - entity.Transform.WorldPosition)
|
||||
.LengthSquared;
|
||||
if (distanceSquared > VerbUtility.InteractionRangeSquared)
|
||||
{
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (verb.BlockedByContainers && !userEntity.IsInSameOrNoContainer(entity))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
verb.Activate(userEntity, component);
|
||||
@@ -65,14 +72,15 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
continue;
|
||||
}
|
||||
|
||||
if (globalVerb.RequireInteractionRange)
|
||||
if (globalVerb.RequireInteractionRange &&
|
||||
!VerbUtility.InVerbUseRange(userEntity, entity))
|
||||
{
|
||||
var distanceSquared = (userEntity.Transform.WorldPosition - entity.Transform.WorldPosition)
|
||||
.LengthSquared;
|
||||
if (distanceSquared > VerbUtility.InteractionRangeSquared)
|
||||
{
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (globalVerb.BlockedByContainers && !userEntity.IsInSameOrNoContainer(entity))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
globalVerb.Activate(userEntity, entity);
|
||||
@@ -92,6 +100,12 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
|
||||
var userEntity = player.AttachedEntity;
|
||||
|
||||
if (userEntity == null)
|
||||
{
|
||||
Logger.Warning($"{nameof(UseVerb)} called by player {player} with no attached entity.");
|
||||
return;
|
||||
}
|
||||
|
||||
var data = new List<VerbsResponseMessage.NetVerbData>();
|
||||
//Get verbs, component dependent.
|
||||
foreach (var (component, verb) in VerbUtility.GetVerbs(entity))
|
||||
@@ -99,6 +113,9 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
if (verb.RequireInteractionRange && !VerbUtility.InVerbUseRange(userEntity, entity))
|
||||
continue;
|
||||
|
||||
if (verb.BlockedByContainers && !userEntity.IsInSameOrNoContainer(entity))
|
||||
continue;
|
||||
|
||||
var verbData = verb.GetData(userEntity, component);
|
||||
if (verbData.IsInvisible)
|
||||
continue;
|
||||
@@ -113,6 +130,9 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
if (globalVerb.RequireInteractionRange && !VerbUtility.InVerbUseRange(userEntity, entity))
|
||||
continue;
|
||||
|
||||
if (globalVerb.BlockedByContainers && !userEntity.IsInSameOrNoContainer(entity))
|
||||
continue;
|
||||
|
||||
var verbData = globalVerb.GetData(userEntity, entity);
|
||||
if (verbData.IsInvisible)
|
||||
continue;
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace Content.Server.GameTicking.GamePresets
|
||||
for (var i = 0; i < numTraitors; i++)
|
||||
{
|
||||
IPlayerSession traitor;
|
||||
if(prefList.Count() == 0)
|
||||
if(prefList.Count == 0)
|
||||
{
|
||||
traitor = _random.PickAndTake(list);
|
||||
Logger.InfoS("preset", "Insufficient preferred traitors, picking at random.");
|
||||
|
||||
@@ -264,7 +264,7 @@ namespace Content.Server.GameTicking
|
||||
// Spawn everybody in!
|
||||
foreach (var (player, job) in assignedJobs)
|
||||
{
|
||||
SpawnPlayer(player, job, false);
|
||||
SpawnPlayer(player, profiles[player.Name], job, false);
|
||||
}
|
||||
|
||||
// Time to start the preset.
|
||||
@@ -344,7 +344,7 @@ namespace Content.Server.GameTicking
|
||||
if (LobbyEnabled)
|
||||
_playerJoinLobby(targetPlayer);
|
||||
else
|
||||
SpawnPlayer(targetPlayer);
|
||||
SpawnPlayerAsync(targetPlayer);
|
||||
}
|
||||
|
||||
public void MakeObserve(IPlayerSession player)
|
||||
@@ -358,7 +358,7 @@ namespace Content.Server.GameTicking
|
||||
{
|
||||
if (!_playersInLobby.ContainsKey(player)) return;
|
||||
|
||||
SpawnPlayer(player, jobId);
|
||||
SpawnPlayerAsync(player, jobId);
|
||||
}
|
||||
|
||||
public void ToggleReady(IPlayerSession player, bool ready)
|
||||
@@ -620,7 +620,7 @@ namespace Content.Server.GameTicking
|
||||
|
||||
_playerJoinLobby(player);
|
||||
}
|
||||
|
||||
|
||||
EntitySystem.Get<PathfindingSystem>().ResettingCleanup();
|
||||
EntitySystem.Get<AiReachableSystem>().ResettingCleanup();
|
||||
EntitySystem.Get<WireHackingSystem>().ResetLayouts();
|
||||
@@ -684,13 +684,13 @@ namespace Content.Server.GameTicking
|
||||
return;
|
||||
}
|
||||
|
||||
SpawnPlayer(session);
|
||||
SpawnPlayerAsync(session);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (data.Mind.CurrentEntity == null)
|
||||
{
|
||||
SpawnPlayer(session);
|
||||
SpawnPlayerAsync(session);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -744,14 +744,22 @@ namespace Content.Server.GameTicking
|
||||
}, _updateShutdownCts.Token);
|
||||
}
|
||||
|
||||
private async void SpawnPlayer(IPlayerSession session, string jobId = null, bool lateJoin = true)
|
||||
private async void SpawnPlayerAsync(IPlayerSession session, string jobId = null, bool lateJoin = true)
|
||||
{
|
||||
_playerJoinGame(session);
|
||||
|
||||
var character = (HumanoidCharacterProfile) (await _prefsManager
|
||||
.GetPreferencesAsync(session.SessionId.Username))
|
||||
.SelectedCharacter;
|
||||
|
||||
SpawnPlayer(session, character, jobId, lateJoin);
|
||||
}
|
||||
|
||||
private void SpawnPlayer(IPlayerSession session,
|
||||
HumanoidCharacterProfile character,
|
||||
string jobId = null,
|
||||
bool lateJoin = true)
|
||||
{
|
||||
_playerJoinGame(session);
|
||||
|
||||
var data = session.ContentData();
|
||||
data.WipeMind();
|
||||
data.Mind = new Mind(session.SessionId)
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace Content.Server.GlobalVerbs
|
||||
public class ControlMobVerb : GlobalVerb
|
||||
{
|
||||
public override bool RequireInteractionRange => false;
|
||||
public override bool BlockedByContainers => false;
|
||||
|
||||
public override void GetData(IEntity user, IEntity target, VerbData data)
|
||||
{
|
||||
|
||||
@@ -16,6 +16,7 @@ namespace Content.Server.GlobalVerbs
|
||||
class RejuvenateVerb : GlobalVerb
|
||||
{
|
||||
public override bool RequireInteractionRange => false;
|
||||
public override bool BlockedByContainers => false;
|
||||
|
||||
public override void GetData(IEntity user, IEntity target, VerbData data)
|
||||
{
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
using System;
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Content.Server.GameObjects;
|
||||
using Content.Server.GameObjects.Components.GUI;
|
||||
using Content.Server.GameObjects.Components.Items.Storage;
|
||||
using Content.Shared.GameObjects.Components.Inventory;
|
||||
using Content.Shared.GameObjects.Components.Items;
|
||||
using Content.Shared.GameObjects.EntitySystems;
|
||||
using Robust.Server.GameObjects.Components.Container;
|
||||
@@ -12,10 +17,20 @@ namespace Content.Server.Interfaces.GameObjects.Components.Items
|
||||
{
|
||||
public interface IHandsComponent : ISharedHandsComponent
|
||||
{
|
||||
/// <summary>
|
||||
/// Invoked when the hand contents changes or when a hand is added/removed.
|
||||
/// </summary>
|
||||
event Action? OnItemChanged;
|
||||
|
||||
/// <summary>
|
||||
/// The hands in this component.
|
||||
/// </summary>
|
||||
IEnumerable<string> Hands { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The hand name of the currently active hand.
|
||||
/// </summary>
|
||||
string ActiveHand { get; set; }
|
||||
string? ActiveHand { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Enumerates over every held item.
|
||||
@@ -27,12 +42,20 @@ namespace Content.Server.Interfaces.GameObjects.Components.Items
|
||||
/// </summary>
|
||||
/// <param name="handName">The name of the hand to get.</param>
|
||||
/// <returns>The item in the held, null if no item is held</returns>
|
||||
ItemComponent GetItem(string handName);
|
||||
ItemComponent? GetItem(string handName);
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to get an item in a hand.
|
||||
/// </summary>
|
||||
/// <param name="handName">The name of the hand to get.</param>
|
||||
/// <param name="item">The item in the held, null if no item is held</param>
|
||||
/// <returns>Whether it was holding an item</returns>
|
||||
bool TryGetItem(string handName, [MaybeNullWhen(false)] out ItemComponent item);
|
||||
|
||||
/// <summary>
|
||||
/// Gets item held by the current active hand
|
||||
/// </summary>
|
||||
ItemComponent GetActiveHand { get; }
|
||||
ItemComponent? GetActiveHand { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Puts an item into any empty hand, preferring the active hand.
|
||||
@@ -78,7 +101,7 @@ namespace Content.Server.Interfaces.GameObjects.Components.Items
|
||||
/// <returns>
|
||||
/// true if the entity is held, false otherwise
|
||||
/// </returns>
|
||||
bool TryHand(IEntity entity, out string handName);
|
||||
bool TryHand(IEntity entity, [MaybeNullWhen(false)] out string handName);
|
||||
|
||||
/// <summary>
|
||||
/// Drops the item contained in the slot to the same position as our entity.
|
||||
|
||||
@@ -85,7 +85,7 @@ namespace Content.Server.Throw
|
||||
projComp.StartThrow(angle.ToVec(), spd);
|
||||
|
||||
if (throwSourceEnt != null &&
|
||||
throwSourceEnt.TryGetComponent<IPhysicsComponent>(out var physics) &&
|
||||
throwSourceEnt.TryGetComponent<ICollidableComponent>(out var physics) &&
|
||||
physics.TryGetController(out MoverController mover))
|
||||
{
|
||||
var physicsMgr = IoCManager.Resolve<IPhysicsManager>();
|
||||
@@ -136,7 +136,7 @@ namespace Content.Server.Throw
|
||||
var distance = (targetLoc.ToMapPos(mapManager) - sourceLoc.ToMapPos(mapManager)).Length;
|
||||
var throwDuration = ThrownItemComponent.DefaultThrowTime;
|
||||
var mass = 1f;
|
||||
if (thrownEnt.TryGetComponent(out IPhysicsComponent physicsComponent))
|
||||
if (thrownEnt.TryGetComponent(out ICollidableComponent physicsComponent))
|
||||
{
|
||||
mass = physicsComponent.Mass;
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ namespace Content.Shared.GameObjects.Components.Disposal
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum State
|
||||
public enum PressureState
|
||||
{
|
||||
Ready,
|
||||
Pressurizing
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Content.Shared.GameObjects.Components.Inventory;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameObjects.Components.UserInterface;
|
||||
using Robust.Shared.Serialization;
|
||||
using static Content.Shared.GameObjects.Components.Inventory.EquipmentSlotDefines;
|
||||
|
||||
namespace Content.Shared.GameObjects.Components.GUI
|
||||
{
|
||||
public class SharedStrippableComponent : Component
|
||||
{
|
||||
public override string Name => "Strippable";
|
||||
|
||||
[NetSerializable, Serializable]
|
||||
public enum StrippingUiKey
|
||||
{
|
||||
Key,
|
||||
}
|
||||
}
|
||||
|
||||
[NetSerializable, Serializable]
|
||||
public class StrippingInventoryButtonPressed : BoundUserInterfaceMessage
|
||||
{
|
||||
public Slots Slot { get; }
|
||||
|
||||
public StrippingInventoryButtonPressed(Slots slot)
|
||||
{
|
||||
Slot = slot;
|
||||
}
|
||||
}
|
||||
|
||||
[NetSerializable, Serializable]
|
||||
public class StrippingHandButtonPressed : BoundUserInterfaceMessage
|
||||
{
|
||||
public string Hand { get; }
|
||||
|
||||
public StrippingHandButtonPressed(string hand)
|
||||
{
|
||||
Hand = hand;
|
||||
}
|
||||
}
|
||||
|
||||
[NetSerializable, Serializable]
|
||||
public class StrippingBoundUserInterfaceState : BoundUserInterfaceState
|
||||
{
|
||||
public Dictionary<Slots, string> Inventory { get; }
|
||||
public Dictionary<string, string> Hands { get; }
|
||||
|
||||
public StrippingBoundUserInterfaceState(Dictionary<Slots, string> inventory, Dictionary<string, string> hands)
|
||||
{
|
||||
Inventory = inventory;
|
||||
Hands = hands;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -142,11 +142,11 @@ namespace Content.Shared.GameObjects.Components.Movement
|
||||
/// <inheritdoc />
|
||||
public override void OnAdd()
|
||||
{
|
||||
// This component requires that the entity has a PhysicsComponent.
|
||||
if (!Owner.HasComponent<IPhysicsComponent>())
|
||||
// This component requires that the entity has a CollidableComponent.
|
||||
if (!Owner.HasComponent<ICollidableComponent>())
|
||||
Logger.Error(
|
||||
$"[ECS] {Owner.Prototype?.Name} - {nameof(SharedPlayerInputMoverComponent)} requires" +
|
||||
$" {nameof(IPhysicsComponent)}. ");
|
||||
$" {nameof(ICollidableComponent)}. ");
|
||||
|
||||
base.OnAdd();
|
||||
}
|
||||
|
||||
@@ -50,13 +50,12 @@ namespace Content.Shared.GameObjects.Components.Movement
|
||||
|| _slipped.Contains(entity.Uid)
|
||||
|| !entity.TryGetComponent(out SharedStunnableComponent stun)
|
||||
|| !entity.TryGetComponent(out ICollidableComponent otherBody)
|
||||
|| !entity.TryGetComponent(out IPhysicsComponent otherPhysics)
|
||||
|| !Owner.TryGetComponent(out ICollidableComponent body))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (otherPhysics.LinearVelocity.Length < RequiredSlipSpeed || stun.KnockedDown)
|
||||
if (otherBody.LinearVelocity.Length < RequiredSlipSpeed || stun.KnockedDown)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using Content.Shared.GameObjects.Components.Mobs;
|
||||
using System;
|
||||
using Content.Shared.GameObjects.Components.Mobs;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.GameObjects.Systems;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.Maths;
|
||||
@@ -22,6 +24,15 @@ namespace Content.Shared.GameObjects.EntitySystems
|
||||
public const float ExamineRangeSquared = ExamineRange * ExamineRange;
|
||||
protected const float ExamineDetailsRange = 3f;
|
||||
|
||||
private static bool IsInDetailsRange(IEntity examiner, IEntity entity)
|
||||
{
|
||||
return Get<SharedInteractionSystem>()
|
||||
.InRangeUnobstructed(examiner.Transform.MapPosition, entity.Transform.MapPosition,
|
||||
ExamineDetailsRange, predicate: entity0 => entity0 == examiner || entity0 == entity,
|
||||
ignoreInsideBlocker: true) &&
|
||||
examiner.IsInSameOrNoContainer(entity);
|
||||
}
|
||||
|
||||
[Pure]
|
||||
protected static bool CanExamine(IEntity examiner, IEntity examined)
|
||||
{
|
||||
@@ -40,9 +51,16 @@ namespace Content.Shared.GameObjects.EntitySystems
|
||||
return false;
|
||||
}
|
||||
|
||||
Func<IEntity, bool> predicate = entity => entity == examiner || entity == examined;
|
||||
|
||||
if (ContainerHelpers.TryGetContainer(examiner, out var container))
|
||||
{
|
||||
predicate += entity => entity == container.Owner;
|
||||
}
|
||||
|
||||
return Get<SharedInteractionSystem>()
|
||||
.InRangeUnobstructed(examiner.Transform.MapPosition, examined.Transform.MapPosition,
|
||||
ExamineRange, predicate: entity => entity == examiner || entity == examined, ignoreInsideBlocker:true);
|
||||
ExamineRange, predicate: predicate, ignoreInsideBlocker:true);
|
||||
}
|
||||
|
||||
public static FormattedMessage GetExamineText(IEntity entity, IEntity examiner)
|
||||
@@ -60,15 +78,11 @@ namespace Content.Shared.GameObjects.EntitySystems
|
||||
|
||||
message.PushColor(Color.DarkGray);
|
||||
|
||||
var inDetailsRange = Get<SharedInteractionSystem>()
|
||||
.InRangeUnobstructed(examiner.Transform.MapPosition, entity.Transform.MapPosition,
|
||||
ExamineDetailsRange, predicate: entity0 => entity0 == examiner || entity0 == entity, ignoreInsideBlocker: true);
|
||||
|
||||
//Add component statuses from components that report one
|
||||
foreach (var examineComponent in entity.GetAllComponents<IExamine>())
|
||||
{
|
||||
var subMessage = new FormattedMessage();
|
||||
examineComponent.Examine(subMessage, inDetailsRange);
|
||||
examineComponent.Examine(subMessage, IsInDetailsRange(examiner, entity));
|
||||
if (subMessage.Tags.Count == 0)
|
||||
continue;
|
||||
|
||||
|
||||
@@ -29,8 +29,6 @@ namespace Content.Shared.GameObjects.EntitySystems
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
EntityQuery = new TypeEntityQuery(typeof(IMoverComponent));
|
||||
|
||||
var moveUpCmdHandler = new MoverDirInputCmdHandler(Direction.North);
|
||||
var moveLeftCmdHandler = new MoverDirInputCmdHandler(Direction.West);
|
||||
var moveRightCmdHandler = new MoverDirInputCmdHandler(Direction.East);
|
||||
@@ -54,18 +52,17 @@ namespace Content.Shared.GameObjects.EntitySystems
|
||||
base.Shutdown();
|
||||
}
|
||||
|
||||
protected void UpdateKinematics(ITransformComponent transform, IMoverComponent mover, IPhysicsComponent physics,
|
||||
ICollidableComponent? collider = null)
|
||||
protected void UpdateKinematics(ITransformComponent transform, IMoverComponent mover, ICollidableComponent collidable)
|
||||
{
|
||||
physics.EnsureController<MoverController>();
|
||||
collidable.EnsureController<MoverController>();
|
||||
|
||||
var weightless = !transform.Owner.HasComponent<MovementIgnoreGravityComponent>() &&
|
||||
_physicsManager.IsWeightless(transform.GridPosition);
|
||||
|
||||
if (weightless && collider != null)
|
||||
if (weightless)
|
||||
{
|
||||
// No gravity: is our entity touching anything?
|
||||
var touching = IsAroundCollider(transform, mover, collider);
|
||||
var touching = IsAroundCollider(transform, mover, collidable);
|
||||
|
||||
if (!touching)
|
||||
{
|
||||
@@ -78,18 +75,16 @@ namespace Content.Shared.GameObjects.EntitySystems
|
||||
var combined = walkDir + sprintDir;
|
||||
if (combined.LengthSquared < 0.001 || !ActionBlockerSystem.CanMove(mover.Owner) && !weightless)
|
||||
{
|
||||
if (physics.TryGetController(out MoverController controller))
|
||||
if (collidable.TryGetController(out MoverController controller))
|
||||
{
|
||||
controller.StopMoving();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//Console.WriteLine($"{IoCManager.Resolve<IGameTiming>().TickStamp}: {combined}");
|
||||
|
||||
if (weightless)
|
||||
{
|
||||
if (physics.TryGetController(out MoverController controller))
|
||||
if (collidable.TryGetController(out MoverController controller))
|
||||
{
|
||||
controller.Push(combined, mover.CurrentPushSpeed);
|
||||
}
|
||||
@@ -99,12 +94,13 @@ namespace Content.Shared.GameObjects.EntitySystems
|
||||
}
|
||||
|
||||
var total = walkDir * mover.CurrentWalkSpeed + sprintDir * mover.CurrentSprintSpeed;
|
||||
//Console.WriteLine($"{walkDir} ({mover.CurrentWalkSpeed}) + {sprintDir} ({mover.CurrentSprintSpeed}): {total}");
|
||||
|
||||
{if (physics.TryGetController(out MoverController controller))
|
||||
{
|
||||
controller.Move(total, 1);
|
||||
}}
|
||||
if (collidable.TryGetController(out MoverController controller))
|
||||
{
|
||||
controller.Move(total, 1);
|
||||
}
|
||||
}
|
||||
|
||||
transform.LocalRotation = total.GetDir().ToAngle();
|
||||
|
||||
|
||||
@@ -20,6 +20,12 @@ namespace Content.Shared.GameObjects.Verbs
|
||||
/// </summary>
|
||||
public virtual bool RequireInteractionRange => true;
|
||||
|
||||
/// <summary>
|
||||
/// If true, this verb requires both the user and the entity on which
|
||||
/// this verb resides to be in the same container or no container.
|
||||
/// </summary>
|
||||
public virtual bool BlockedByContainers => true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the visible verb data for the user.
|
||||
/// </summary>
|
||||
|
||||
@@ -20,6 +20,12 @@ namespace Content.Shared.GameObjects.Verbs
|
||||
/// </summary>
|
||||
public virtual bool RequireInteractionRange => true;
|
||||
|
||||
/// <summary>
|
||||
/// If true, this verb requires both the user and the entity on which
|
||||
/// this verb resides to be in the same container or no container.
|
||||
/// </summary>
|
||||
public virtual bool BlockedByContainers => true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the visible verb data for the user.
|
||||
/// </summary>
|
||||
|
||||
@@ -18,7 +18,6 @@ namespace Content.Shared.Health.BodySystem.Mechanism
|
||||
private string _name;
|
||||
private string _description;
|
||||
private string _examineMessage;
|
||||
private string _spritePath;
|
||||
private string _rsiPath;
|
||||
private string _rsiState;
|
||||
private int _durability;
|
||||
|
||||
@@ -20,6 +20,7 @@ namespace Content.Shared.Physics
|
||||
VaultImpassable = 1 << 3, // 8 Things that cannot be jumped over, not half walls or tables
|
||||
SmallImpassable = 1 << 4, // 16 Things a smaller object - a cat, a crab - can't go through - a wall, but not a computer terminal or a table
|
||||
Clickable = 1 << 5, // 32 Temporary "dummy" layer to ensure that objects can still be clicked even if they don't collide with anything (you can't interact with objects that have no layer, including items)
|
||||
GhostImpassable = 1 << 6, // 64 Things impassible by ghosts/observers, ie blessed tiles or forcefields
|
||||
|
||||
MapGrid = MapGridHelpers.CollisionGroup, // Map grids, like shuttles. This is the actual grid itself, not the walls or other entities connected to the grid.
|
||||
|
||||
|
||||
@@ -7,6 +7,12 @@
|
||||
- type: Mind
|
||||
- type: Physics
|
||||
mass: 5
|
||||
- type: Collidable
|
||||
shapes:
|
||||
- !type:PhysShapeAabb
|
||||
bounds: "-0.35,-0.35,0.35,0.35"
|
||||
mask:
|
||||
- GhostImpassable
|
||||
- type: Eye
|
||||
zoom: 0.5, 0.5
|
||||
drawFov: false
|
||||
|
||||
@@ -144,6 +144,12 @@
|
||||
- type: Pullable
|
||||
- type: CanSeeGases
|
||||
- type: DoAfter
|
||||
- type: Strippable
|
||||
- type: UserInterface
|
||||
interfaces:
|
||||
- key: enum.StrippingUiKey.Key
|
||||
type: StrippableBoundUserInterface
|
||||
|
||||
|
||||
- type: entity
|
||||
save: false
|
||||
|
||||
Submodule RobustToolbox updated: 5819e5ee92...1934428c95
@@ -71,10 +71,12 @@
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Soundfont/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=soundfonts/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Spawner/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Strippable/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=stunnable/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=superconduction/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=swsl/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=underplating/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=unequip/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=unexcite/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=uplink/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Wirecutter/@EntryIndexedValue">True</s:Boolean>
|
||||
|
||||
Reference in New Issue
Block a user