More DoAfter Changes (#14609)
* DoAfters * Compact Clone() * Fix mice and cuffables * Try generalize attempt events * moves climbabledoafter event to shared, fixes issue with climbable target * Fix merge (cuffing) * Make all events netserializable * handful of doafter events moved * moves the rest of the events to their respective shared folders * Changes all mentions of server doafter to shared * stop stripping cancellation * fix merge errors * draw paused doafters * handle unpausing * missing netserializable ref * removes break on stun reference * removes cuffing state reference * Fix tools * Fix door prying. * Fix construction * Fix dumping * Fix wielding assert * fix rev * Fix test * more test fixes --------- Co-authored-by: keronshb <keronshb@live.com>
This commit is contained in:
@@ -25,7 +25,6 @@ public sealed class CuffableSystem : SharedCuffableSystem
|
|||||||
if (args.Current is not HandcuffComponentState state)
|
if (args.Current is not HandcuffComponentState state)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
component.Cuffing = state.Cuffing;
|
|
||||||
component.OverlayIconState = state.IconState;
|
component.OverlayIconState = state.IconState;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,7 +40,6 @@ public sealed class CuffableSystem : SharedCuffableSystem
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
component.CanStillInteract = cuffState.CanStillInteract;
|
component.CanStillInteract = cuffState.CanStillInteract;
|
||||||
component.Uncuffing = cuffState.Uncuffing;
|
|
||||||
_actionBlocker.UpdateCanMove(uid);
|
_actionBlocker.UpdateCanMove(uid);
|
||||||
|
|
||||||
var ev = new CuffedStateChangeEvent();
|
var ev = new CuffedStateChangeEvent();
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using Robust.Client.GameObjects;
|
|||||||
using Robust.Client.Graphics;
|
using Robust.Client.Graphics;
|
||||||
using Robust.Shared.Enums;
|
using Robust.Shared.Enums;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
|
using Robust.Shared.Timing;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
namespace Content.Client.DoAfter;
|
namespace Content.Client.DoAfter;
|
||||||
@@ -10,17 +11,30 @@ namespace Content.Client.DoAfter;
|
|||||||
public sealed class DoAfterOverlay : Overlay
|
public sealed class DoAfterOverlay : Overlay
|
||||||
{
|
{
|
||||||
private readonly IEntityManager _entManager;
|
private readonly IEntityManager _entManager;
|
||||||
|
private readonly IGameTiming _timing;
|
||||||
private readonly SharedTransformSystem _transform;
|
private readonly SharedTransformSystem _transform;
|
||||||
|
private readonly MetaDataSystem _meta;
|
||||||
|
|
||||||
private readonly Texture _barTexture;
|
private readonly Texture _barTexture;
|
||||||
private readonly ShaderInstance _shader;
|
private readonly ShaderInstance _shader;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Flash time for cancelled DoAfters
|
||||||
|
/// </summary>
|
||||||
|
private const float FlashTime = 0.125f;
|
||||||
|
|
||||||
|
// Hardcoded width of the progress bar because it doesn't match the texture.
|
||||||
|
private const float StartX = 2;
|
||||||
|
private const float EndX = 22f;
|
||||||
|
|
||||||
public override OverlaySpace Space => OverlaySpace.WorldSpaceBelowFOV;
|
public override OverlaySpace Space => OverlaySpace.WorldSpaceBelowFOV;
|
||||||
|
|
||||||
public DoAfterOverlay(IEntityManager entManager, IPrototypeManager protoManager)
|
public DoAfterOverlay(IEntityManager entManager, IPrototypeManager protoManager, IGameTiming timing)
|
||||||
{
|
{
|
||||||
_entManager = entManager;
|
_entManager = entManager;
|
||||||
|
_timing = timing;
|
||||||
_transform = _entManager.EntitySysManager.GetEntitySystem<SharedTransformSystem>();
|
_transform = _entManager.EntitySysManager.GetEntitySystem<SharedTransformSystem>();
|
||||||
|
_meta = _entManager.EntitySysManager.GetEntitySystem<MetaDataSystem>();
|
||||||
var sprite = new SpriteSpecifier.Rsi(new ResourcePath("/Textures/Interface/Misc/progress_bar.rsi"), "icon");
|
var sprite = new SpriteSpecifier.Rsi(new ResourcePath("/Textures/Interface/Misc/progress_bar.rsi"), "icon");
|
||||||
_barTexture = _entManager.EntitySysManager.GetEntitySystem<SpriteSystem>().Frame0(sprite);
|
_barTexture = _entManager.EntitySysManager.GetEntitySystem<SpriteSystem>().Frame0(sprite);
|
||||||
|
|
||||||
@@ -31,7 +45,6 @@ public sealed class DoAfterOverlay : Overlay
|
|||||||
{
|
{
|
||||||
var handle = args.WorldHandle;
|
var handle = args.WorldHandle;
|
||||||
var rotation = args.Viewport.Eye?.Rotation ?? Angle.Zero;
|
var rotation = args.Viewport.Eye?.Rotation ?? Angle.Zero;
|
||||||
var spriteQuery = _entManager.GetEntityQuery<SpriteComponent>();
|
|
||||||
var xformQuery = _entManager.GetEntityQuery<TransformComponent>();
|
var xformQuery = _entManager.GetEntityQuery<TransformComponent>();
|
||||||
|
|
||||||
// If you use the display UI scale then need to set max(1f, displayscale) because 0 is valid.
|
// If you use the display UI scale then need to set max(1f, displayscale) because 0 is valid.
|
||||||
@@ -40,43 +53,42 @@ public sealed class DoAfterOverlay : Overlay
|
|||||||
var rotationMatrix = Matrix3.CreateRotation(-rotation);
|
var rotationMatrix = Matrix3.CreateRotation(-rotation);
|
||||||
handle.UseShader(_shader);
|
handle.UseShader(_shader);
|
||||||
|
|
||||||
// TODO: Need active DoAfter component (or alternatively just make DoAfter itself active)
|
var curTime = _timing.CurTime;
|
||||||
foreach (var comp in _entManager.EntityQuery<DoAfterComponent>(true))
|
|
||||||
{
|
var bounds = args.WorldAABB.Enlarged(5f);
|
||||||
if (comp.DoAfters.Count == 0 ||
|
|
||||||
!xformQuery.TryGetComponent(comp.Owner, out var xform) ||
|
var metaQuery = _entManager.GetEntityQuery<MetaDataComponent>();
|
||||||
xform.MapID != args.MapId)
|
var enumerator = _entManager.AllEntityQueryEnumerator<ActiveDoAfterComponent, DoAfterComponent, SpriteComponent, TransformComponent>();
|
||||||
{
|
while (enumerator.MoveNext(out var uid, out _, out var comp, out var sprite, out var xform))
|
||||||
continue;
|
{
|
||||||
}
|
if (xform.MapID != args.MapId)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (comp.DoAfters.Count == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var worldPosition = _transform.GetWorldPosition(xform, xformQuery);
|
||||||
|
if (!bounds.Contains(worldPosition))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// If the entity is paused, we will draw the do-after as it was when the entity got paused.
|
||||||
|
var meta = metaQuery.GetComponent(uid);
|
||||||
|
var time = meta.EntityPaused
|
||||||
|
? curTime - _meta.GetPauseTime(uid, meta)
|
||||||
|
: curTime;
|
||||||
|
|
||||||
var worldPosition = _transform.GetWorldPosition(xform);
|
|
||||||
var index = 0;
|
|
||||||
var worldMatrix = Matrix3.CreateTranslation(worldPosition);
|
var worldMatrix = Matrix3.CreateTranslation(worldPosition);
|
||||||
|
Matrix3.Multiply(scaleMatrix, worldMatrix, out var scaledWorld);
|
||||||
|
Matrix3.Multiply(rotationMatrix, scaledWorld, out var matty);
|
||||||
|
handle.SetTransform(matty);
|
||||||
|
|
||||||
|
var offset = 0f;
|
||||||
|
|
||||||
foreach (var doAfter in comp.DoAfters.Values)
|
foreach (var doAfter in comp.DoAfters.Values)
|
||||||
{
|
{
|
||||||
var elapsed = doAfter.Elapsed;
|
|
||||||
var displayRatio = MathF.Min(1.0f,
|
|
||||||
(float)elapsed.TotalSeconds / doAfter.Delay);
|
|
||||||
|
|
||||||
Matrix3.Multiply(scaleMatrix, worldMatrix, out var scaledWorld);
|
|
||||||
Matrix3.Multiply(rotationMatrix, scaledWorld, out var matty);
|
|
||||||
|
|
||||||
handle.SetTransform(matty);
|
|
||||||
var offset = _barTexture.Height / scale * index;
|
|
||||||
|
|
||||||
// Use the sprite itself if we know its bounds. This means short or tall sprites don't get overlapped
|
// Use the sprite itself if we know its bounds. This means short or tall sprites don't get overlapped
|
||||||
// by the bar.
|
// by the bar.
|
||||||
float yOffset;
|
float yOffset = sprite.Bounds.Height / 2f + 0.05f;
|
||||||
if (spriteQuery.TryGetComponent(comp.Owner, out var sprite))
|
|
||||||
{
|
|
||||||
yOffset = sprite.Bounds.Height / 2f + 0.05f;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
yOffset = 0.5f;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Position above the entity (we've already applied the matrix transform to the entity itself)
|
// Position above the entity (we've already applied the matrix transform to the entity itself)
|
||||||
// Offset by the texture size for every do_after we have.
|
// Offset by the texture size for every do_after we have.
|
||||||
@@ -86,33 +98,30 @@ public sealed class DoAfterOverlay : Overlay
|
|||||||
// Draw the underlying bar texture
|
// Draw the underlying bar texture
|
||||||
handle.DrawTexture(_barTexture, position);
|
handle.DrawTexture(_barTexture, position);
|
||||||
|
|
||||||
// Draw the bar itself
|
|
||||||
var cancelled = doAfter.Cancelled;
|
|
||||||
Color color;
|
Color color;
|
||||||
const float flashTime = 0.125f;
|
float elapsedRatio;
|
||||||
|
|
||||||
// if we're cancelled then flick red / off.
|
// if we're cancelled then flick red / off.
|
||||||
if (cancelled)
|
if (doAfter.CancelledTime != null)
|
||||||
{
|
{
|
||||||
var flash = Math.Floor((float)doAfter.CancelledElapsed.TotalSeconds / flashTime) % 2 == 0;
|
var elapsed = doAfter.CancelledTime.Value - doAfter.StartTime;
|
||||||
|
elapsedRatio = (float) Math.Min(1, elapsed.TotalSeconds / doAfter.Args.Delay.TotalSeconds);
|
||||||
|
var cancelElapsed = (time - doAfter.CancelledTime.Value).TotalSeconds;
|
||||||
|
var flash = Math.Floor(cancelElapsed / FlashTime) % 2 == 0;
|
||||||
color = new Color(1f, 0f, 0f, flash ? 1f : 0f);
|
color = new Color(1f, 0f, 0f, flash ? 1f : 0f);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
color = GetProgressColor(displayRatio);
|
var elapsed = time - doAfter.StartTime;
|
||||||
|
elapsedRatio = (float) Math.Min(1, elapsed.TotalSeconds / doAfter.Args.Delay.TotalSeconds);
|
||||||
|
color = GetProgressColor(elapsedRatio);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hardcoded width of the progress bar because it doesn't match the texture.
|
var xProgress = (EndX - StartX) * elapsedRatio + StartX;
|
||||||
const float startX = 2f;
|
var box = new Box2(new Vector2(StartX, 3f) / EyeManager.PixelsPerMeter, new Vector2(xProgress, 4f) / EyeManager.PixelsPerMeter);
|
||||||
const float endX = 22f;
|
|
||||||
|
|
||||||
var xProgress = (endX - startX) * displayRatio + startX;
|
|
||||||
|
|
||||||
var box = new Box2(new Vector2(startX, 3f) / EyeManager.PixelsPerMeter, new Vector2(xProgress, 4f) / EyeManager.PixelsPerMeter);
|
|
||||||
box = box.Translated(position);
|
box = box.Translated(position);
|
||||||
handle.DrawRect(box, color);
|
handle.DrawRect(box, color);
|
||||||
|
offset += _barTexture.Height / scale;
|
||||||
index++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
using Content.Shared.DoAfter;
|
using Content.Shared.DoAfter;
|
||||||
|
using Content.Shared.Hands.Components;
|
||||||
using Robust.Client.Graphics;
|
using Robust.Client.Graphics;
|
||||||
using Robust.Client.Player;
|
using Robust.Client.Player;
|
||||||
using Robust.Shared.GameStates;
|
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Utility;
|
|
||||||
|
|
||||||
namespace Content.Client.DoAfter;
|
namespace Content.Client.DoAfter;
|
||||||
|
|
||||||
@@ -16,19 +15,12 @@ public sealed class DoAfterSystem : SharedDoAfterSystem
|
|||||||
[Dependency] private readonly IOverlayManager _overlay = default!;
|
[Dependency] private readonly IOverlayManager _overlay = default!;
|
||||||
[Dependency] private readonly IPlayerManager _player = default!;
|
[Dependency] private readonly IPlayerManager _player = default!;
|
||||||
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
||||||
|
[Dependency] private readonly MetaDataSystem _metadata = default!;
|
||||||
/// <summary>
|
|
||||||
/// We'll use an excess time so stuff like finishing effects can show.
|
|
||||||
/// </summary>
|
|
||||||
public const float ExcessTime = 0.5f;
|
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
UpdatesOutsidePrediction = true;
|
_overlay.AddOverlay(new DoAfterOverlay(EntityManager, _prototype, GameTiming));
|
||||||
SubscribeNetworkEvent<CancelledDoAfterMessage>(OnCancelledDoAfter);
|
|
||||||
SubscribeLocalEvent<DoAfterComponent, ComponentHandleState>(OnDoAfterHandleState);
|
|
||||||
_overlay.AddOverlay(new DoAfterOverlay(EntityManager, _prototype));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Shutdown()
|
public override void Shutdown()
|
||||||
@@ -37,147 +29,26 @@ public sealed class DoAfterSystem : SharedDoAfterSystem
|
|||||||
_overlay.RemoveOverlay<DoAfterOverlay>();
|
_overlay.RemoveOverlay<DoAfterOverlay>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDoAfterHandleState(EntityUid uid, DoAfterComponent component, ref ComponentHandleState args)
|
|
||||||
{
|
|
||||||
if (args.Current is not DoAfterComponentState state)
|
|
||||||
return;
|
|
||||||
|
|
||||||
foreach (var (_, doAfter) in state.DoAfters)
|
|
||||||
{
|
|
||||||
if (component.DoAfters.ContainsKey(doAfter.ID))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
component.DoAfters.Add(doAfter.ID, doAfter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnCancelledDoAfter(CancelledDoAfterMessage ev)
|
|
||||||
{
|
|
||||||
if (!TryComp<DoAfterComponent>(ev.Uid, out var doAfter))
|
|
||||||
return;
|
|
||||||
|
|
||||||
Cancel(doAfter, ev.ID);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Remove a DoAfter without showing a cancellation graphic.
|
|
||||||
/// </summary>
|
|
||||||
public void Remove(DoAfterComponent component, Shared.DoAfter.DoAfter doAfter, bool found = false)
|
|
||||||
{
|
|
||||||
component.DoAfters.Remove(doAfter.ID);
|
|
||||||
component.CancelledDoAfters.Remove(doAfter.ID);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Mark a DoAfter as cancelled and show a cancellation graphic.
|
|
||||||
/// </summary>
|
|
||||||
/// Actual removal is handled by DoAfterEntitySystem.
|
|
||||||
public void Cancel(DoAfterComponent component, byte id)
|
|
||||||
{
|
|
||||||
if (component.CancelledDoAfters.ContainsKey(id))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!component.DoAfters.ContainsKey(id))
|
|
||||||
return;
|
|
||||||
|
|
||||||
var doAfterMessage = component.DoAfters[id];
|
|
||||||
doAfterMessage.Cancelled = true;
|
|
||||||
doAfterMessage.CancelledTime = GameTiming.CurTime;
|
|
||||||
component.CancelledDoAfters.Add(id, doAfterMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO separate DoAfter & ActiveDoAfter components for the entity query.
|
|
||||||
public override void Update(float frameTime)
|
public override void Update(float frameTime)
|
||||||
{
|
{
|
||||||
if (!GameTiming.IsFirstTimePredicted)
|
// Currently this only predicts do afters initiated by the player.
|
||||||
return;
|
|
||||||
|
// TODO maybe predict do-afters if the local player is the target of some other players do-after? Specifically
|
||||||
|
// ones that depend on the target not moving, because the cancellation of those do afters should be readily
|
||||||
|
// predictable by clients.
|
||||||
|
|
||||||
var playerEntity = _player.LocalPlayer?.ControlledEntity;
|
var playerEntity = _player.LocalPlayer?.ControlledEntity;
|
||||||
|
|
||||||
foreach (var (comp, xform) in EntityQuery<DoAfterComponent, TransformComponent>())
|
if (!TryComp(playerEntity, out ActiveDoAfterComponent? active))
|
||||||
{
|
return;
|
||||||
var doAfters = comp.DoAfters;
|
|
||||||
|
|
||||||
if (doAfters.Count == 0)
|
if (_metadata.EntityPaused(playerEntity.Value))
|
||||||
continue;
|
return;
|
||||||
|
|
||||||
var userGrid = xform.Coordinates;
|
var time = GameTiming.CurTime;
|
||||||
var toRemove = new RemQueue<Shared.DoAfter.DoAfter>();
|
var comp = Comp<DoAfterComponent>(playerEntity.Value);
|
||||||
|
var xformQuery = GetEntityQuery<TransformComponent>();
|
||||||
// Check cancellations / finishes
|
var handsQuery = GetEntityQuery<SharedHandsComponent>();
|
||||||
foreach (var (id, doAfter) in doAfters)
|
Update(playerEntity.Value, active, comp, time, xformQuery, handsQuery);
|
||||||
{
|
|
||||||
// If we've passed the final time (after the excess to show completion graphic) then remove.
|
|
||||||
if ((float)doAfter.Elapsed.TotalSeconds + (float)doAfter.CancelledElapsed.TotalSeconds >
|
|
||||||
doAfter.Delay + ExcessTime)
|
|
||||||
{
|
|
||||||
toRemove.Add(doAfter);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (doAfter.Cancelled)
|
|
||||||
{
|
|
||||||
doAfter.CancelledElapsed = GameTiming.CurTime - doAfter.CancelledTime;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
doAfter.Elapsed = GameTiming.CurTime - doAfter.StartTime;
|
|
||||||
|
|
||||||
// Well we finished so don't try to predict cancels.
|
|
||||||
if ((float)doAfter.Elapsed.TotalSeconds > doAfter.Delay)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Predictions
|
|
||||||
if (comp.Owner != playerEntity)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// TODO: Add these back in when I work out some system for changing the accumulation rate
|
|
||||||
// based on ping. Right now these would show as cancelled near completion if we moved at the end
|
|
||||||
// despite succeeding.
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (doAfter.EventArgs.BreakOnUserMove)
|
|
||||||
{
|
|
||||||
if (!userGrid.InRange(EntityManager, doAfter.UserGrid, doAfter.EventArgs.MovementThreshold))
|
|
||||||
{
|
|
||||||
Cancel(comp, id);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (doAfter.EventArgs.BreakOnTargetMove)
|
|
||||||
{
|
|
||||||
if (!Deleted(doAfter.EventArgs.Target) &&
|
|
||||||
!Transform(doAfter.EventArgs.Target.Value).Coordinates.InRange(EntityManager,
|
|
||||||
doAfter.TargetGrid,
|
|
||||||
doAfter.EventArgs.MovementThreshold))
|
|
||||||
{
|
|
||||||
Cancel(comp, id);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var doAfter in toRemove)
|
|
||||||
{
|
|
||||||
Remove(comp, doAfter);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove cancelled DoAfters after ExcessTime has elapsed
|
|
||||||
var toRemoveCancelled = new RemQueue<Shared.DoAfter.DoAfter>();
|
|
||||||
|
|
||||||
foreach (var (_, doAfter) in comp.CancelledDoAfters)
|
|
||||||
{
|
|
||||||
var cancelledElapsed = (float)doAfter.CancelledElapsed.TotalSeconds;
|
|
||||||
|
|
||||||
if (cancelledElapsed > ExcessTime)
|
|
||||||
toRemoveCancelled.Add(doAfter);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var doAfter in toRemoveCancelled)
|
|
||||||
{
|
|
||||||
Remove(comp, doAfter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ public sealed class CryoPodSystem: SharedCryoPodSystem
|
|||||||
SubscribeLocalEvent<CryoPodComponent, GetVerbsEvent<AlternativeVerb>>(AddAlternativeVerbs);
|
SubscribeLocalEvent<CryoPodComponent, GetVerbsEvent<AlternativeVerb>>(AddAlternativeVerbs);
|
||||||
SubscribeLocalEvent<CryoPodComponent, GotEmaggedEvent>(OnEmagged);
|
SubscribeLocalEvent<CryoPodComponent, GotEmaggedEvent>(OnEmagged);
|
||||||
SubscribeLocalEvent<CryoPodComponent, CryoPodPryFinished>(OnCryoPodPryFinished);
|
SubscribeLocalEvent<CryoPodComponent, CryoPodPryFinished>(OnCryoPodPryFinished);
|
||||||
SubscribeLocalEvent<CryoPodComponent, CryoPodPryInterrupted>(OnCryoPodPryInterrupted);
|
|
||||||
|
|
||||||
SubscribeLocalEvent<CryoPodComponent, AppearanceChangeEvent>(OnAppearanceChange);
|
SubscribeLocalEvent<CryoPodComponent, AppearanceChangeEvent>(OnAppearanceChange);
|
||||||
SubscribeLocalEvent<InsideCryoPodComponent, ComponentStartup>(OnCryoPodInsertion);
|
SubscribeLocalEvent<InsideCryoPodComponent, ComponentStartup>(OnCryoPodInsertion);
|
||||||
|
|||||||
@@ -20,10 +20,22 @@ public sealed class AlertsUIController : UIController, IOnStateEntered<GameplayS
|
|||||||
|
|
||||||
var gameplayStateLoad = UIManager.GetUIController<GameplayStateLoadController>();
|
var gameplayStateLoad = UIManager.GetUIController<GameplayStateLoadController>();
|
||||||
gameplayStateLoad.OnScreenLoad += OnScreenLoad;
|
gameplayStateLoad.OnScreenLoad += OnScreenLoad;
|
||||||
|
gameplayStateLoad.OnScreenUnload += OnScreenUnload;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnScreenUnload()
|
||||||
|
{
|
||||||
|
var widget = UI;
|
||||||
|
if (widget != null)
|
||||||
|
widget.AlertPressed -= OnAlertPressed;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnScreenLoad()
|
private void OnScreenLoad()
|
||||||
{
|
{
|
||||||
|
var widget = UI;
|
||||||
|
if (widget != null)
|
||||||
|
widget.AlertPressed += OnAlertPressed;
|
||||||
|
|
||||||
SyncAlerts();
|
SyncAlerts();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,14 +55,6 @@ public sealed class AlertsUIController : UIController, IOnStateEntered<GameplayS
|
|||||||
{
|
{
|
||||||
UI?.SyncControls(system, system.AlertOrder, e);
|
UI?.SyncControls(system, system.AlertOrder, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The UI can change underneath us if the user switches between HUD layouts
|
|
||||||
// So ensure we're subscribed to the AlertPressed callback.
|
|
||||||
if (UI != null)
|
|
||||||
{
|
|
||||||
UI.AlertPressed -= OnAlertPressed; // Ensure we don't hook into the callback twice
|
|
||||||
UI.AlertPressed += OnAlertPressed;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnSystemLoaded(ClientAlertsSystem system)
|
public void OnSystemLoaded(ClientAlertsSystem system)
|
||||||
@@ -65,13 +69,9 @@ public sealed class AlertsUIController : UIController, IOnStateEntered<GameplayS
|
|||||||
system.ClearAlerts -= SystemOnClearAlerts;
|
system.ClearAlerts -= SystemOnClearAlerts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void OnStateEntered(GameplayState state)
|
public void OnStateEntered(GameplayState state)
|
||||||
{
|
{
|
||||||
if (UI != null)
|
|
||||||
{
|
|
||||||
UI.AlertPressed += OnAlertPressed;
|
|
||||||
}
|
|
||||||
|
|
||||||
// initially populate the frame if system is available
|
// initially populate the frame if system is available
|
||||||
SyncAlerts();
|
SyncAlerts();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
using System.Threading;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Content.Server.DoAfter;
|
|
||||||
using Content.Shared.DoAfter;
|
using Content.Shared.DoAfter;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.IoC;
|
using Robust.Shared.IoC;
|
||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
|
using Robust.Shared.Reflection;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
using Robust.Shared.Timing;
|
using Robust.Shared.Timing;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
namespace Content.IntegrationTests.Tests.DoAfter
|
namespace Content.IntegrationTests.Tests.DoAfter
|
||||||
{
|
{
|
||||||
@@ -22,24 +24,41 @@ namespace Content.IntegrationTests.Tests.DoAfter
|
|||||||
- type: DoAfter
|
- type: DoAfter
|
||||||
";
|
";
|
||||||
|
|
||||||
public sealed class TestDoAfterSystem : EntitySystem
|
private sealed class TestDoAfterEvent : DoAfterEvent
|
||||||
{
|
{
|
||||||
public override void Initialize()
|
public override DoAfterEvent Clone()
|
||||||
{
|
{
|
||||||
SubscribeLocalEvent<DoAfterEvent<TestDoAfterData>>(OnTestDoAfterFinishEvent);
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnTestDoAfterFinishEvent(DoAfterEvent<TestDoAfterData> ev)
|
|
||||||
{
|
|
||||||
ev.AdditionalData.Cancelled = ev.Cancelled;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private sealed class TestDoAfterData
|
|
||||||
{
|
|
||||||
public bool Cancelled;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task TestSerializable()
|
||||||
|
{
|
||||||
|
await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true});
|
||||||
|
var server = pairTracker.Pair.Server;
|
||||||
|
await server.WaitIdleAsync();
|
||||||
|
var refMan = server.ResolveDependency<IReflectionManager>();
|
||||||
|
|
||||||
|
await server.WaitPost(() =>
|
||||||
|
{
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
|
foreach (var type in refMan.GetAllChildren<DoAfterEvent>(true))
|
||||||
|
{
|
||||||
|
if (type.IsAbstract || type == typeof(TestDoAfterEvent))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Assert.That(type.HasCustomAttribute<NetSerializableAttribute>()
|
||||||
|
&& type.HasCustomAttribute<SerializableAttribute>(),
|
||||||
|
$"{nameof(DoAfterEvent)} is not NetSerializable. Event: {type.Name}");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
await pairTracker.CleanReturnAsync();
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public async Task TestFinished()
|
public async Task TestFinished()
|
||||||
{
|
{
|
||||||
@@ -48,21 +67,21 @@ namespace Content.IntegrationTests.Tests.DoAfter
|
|||||||
await server.WaitIdleAsync();
|
await server.WaitIdleAsync();
|
||||||
|
|
||||||
var entityManager = server.ResolveDependency<IEntityManager>();
|
var entityManager = server.ResolveDependency<IEntityManager>();
|
||||||
var doAfterSystem = entityManager.EntitySysManager.GetEntitySystem<DoAfterSystem>();
|
var doAfterSystem = entityManager.EntitySysManager.GetEntitySystem<SharedDoAfterSystem>();
|
||||||
var data = new TestDoAfterData();
|
var ev = new TestDoAfterEvent();
|
||||||
|
|
||||||
// That it finishes successfully
|
// That it finishes successfully
|
||||||
await server.WaitPost(() =>
|
await server.WaitPost(() =>
|
||||||
{
|
{
|
||||||
var tickTime = 1.0f / IoCManager.Resolve<IGameTiming>().TickRate;
|
var tickTime = 1.0f / IoCManager.Resolve<IGameTiming>().TickRate;
|
||||||
var mob = entityManager.SpawnEntity("Dummy", MapCoordinates.Nullspace);
|
var mob = entityManager.SpawnEntity("Dummy", MapCoordinates.Nullspace);
|
||||||
var cancelToken = new CancellationTokenSource();
|
var args = new DoAfterArgs(mob, tickTime / 2, ev, null) { Broadcast = true };
|
||||||
var args = new DoAfterEventArgs(mob, tickTime / 2, cancelToken.Token) { Broadcast = true };
|
Assert.That(doAfterSystem.TryStartDoAfter(args));
|
||||||
doAfterSystem.DoAfter(args, data);
|
Assert.That(ev.Cancelled, Is.False);
|
||||||
});
|
});
|
||||||
|
|
||||||
await server.WaitRunTicks(1);
|
await server.WaitRunTicks(1);
|
||||||
Assert.That(data.Cancelled, Is.False);
|
Assert.That(ev.Cancelled, Is.False);
|
||||||
|
|
||||||
await pairTracker.CleanReturnAsync();
|
await pairTracker.CleanReturnAsync();
|
||||||
}
|
}
|
||||||
@@ -73,22 +92,32 @@ namespace Content.IntegrationTests.Tests.DoAfter
|
|||||||
await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes});
|
await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes});
|
||||||
var server = pairTracker.Pair.Server;
|
var server = pairTracker.Pair.Server;
|
||||||
var entityManager = server.ResolveDependency<IEntityManager>();
|
var entityManager = server.ResolveDependency<IEntityManager>();
|
||||||
var doAfterSystem = entityManager.EntitySysManager.GetEntitySystem<DoAfterSystem>();
|
var doAfterSystem = entityManager.EntitySysManager.GetEntitySystem<SharedDoAfterSystem>();
|
||||||
var data = new TestDoAfterData();
|
DoAfterId? id = default;
|
||||||
|
var ev = new TestDoAfterEvent();
|
||||||
|
|
||||||
|
|
||||||
await server.WaitPost(() =>
|
await server.WaitPost(() =>
|
||||||
{
|
{
|
||||||
var tickTime = 1.0f / IoCManager.Resolve<IGameTiming>().TickRate;
|
var tickTime = 1.0f / IoCManager.Resolve<IGameTiming>().TickRate;
|
||||||
|
|
||||||
var mob = entityManager.SpawnEntity("Dummy", MapCoordinates.Nullspace);
|
var mob = entityManager.SpawnEntity("Dummy", MapCoordinates.Nullspace);
|
||||||
var cancelToken = new CancellationTokenSource();
|
var args = new DoAfterArgs(mob, tickTime * 2, ev, null) { Broadcast = true };
|
||||||
var args = new DoAfterEventArgs(mob, tickTime * 2, cancelToken.Token) { Broadcast = true };
|
|
||||||
doAfterSystem.DoAfter(args, data);
|
if (!doAfterSystem.TryStartDoAfter(args, out id))
|
||||||
cancelToken.Cancel();
|
{
|
||||||
|
Assert.Fail();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.That(!ev.Cancelled);
|
||||||
|
doAfterSystem.Cancel(id);
|
||||||
|
Assert.That(ev.Cancelled);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
await server.WaitRunTicks(3);
|
await server.WaitRunTicks(3);
|
||||||
Assert.That(data.Cancelled, Is.True);
|
Assert.That(ev.Cancelled);
|
||||||
|
|
||||||
await pairTracker.CleanReturnAsync();
|
await pairTracker.CleanReturnAsync();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using Content.Server.Administration.Logs;
|
using Content.Server.Administration.Logs;
|
||||||
using Content.Server.DoAfter;
|
|
||||||
using Content.Server.Popups;
|
using Content.Server.Popups;
|
||||||
using Content.Server.UserInterface;
|
using Content.Server.UserInterface;
|
||||||
using Content.Shared.AirlockPainter;
|
using Content.Shared.AirlockPainter;
|
||||||
@@ -10,7 +9,6 @@ using Content.Shared.Doors.Components;
|
|||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Shared.Player;
|
|
||||||
|
|
||||||
namespace Content.Server.AirlockPainter
|
namespace Content.Server.AirlockPainter
|
||||||
{
|
{
|
||||||
@@ -22,7 +20,7 @@ namespace Content.Server.AirlockPainter
|
|||||||
{
|
{
|
||||||
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
|
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
|
||||||
[Dependency] private readonly UserInterfaceSystem _userInterfaceSystem = default!;
|
[Dependency] private readonly UserInterfaceSystem _userInterfaceSystem = default!;
|
||||||
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
|
||||||
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
||||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||||
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
||||||
@@ -34,23 +32,21 @@ namespace Content.Server.AirlockPainter
|
|||||||
SubscribeLocalEvent<AirlockPainterComponent, AfterInteractEvent>(AfterInteractOn);
|
SubscribeLocalEvent<AirlockPainterComponent, AfterInteractEvent>(AfterInteractOn);
|
||||||
SubscribeLocalEvent<AirlockPainterComponent, ActivateInWorldEvent>(OnActivate);
|
SubscribeLocalEvent<AirlockPainterComponent, ActivateInWorldEvent>(OnActivate);
|
||||||
SubscribeLocalEvent<AirlockPainterComponent, AirlockPainterSpritePickedMessage>(OnSpritePicked);
|
SubscribeLocalEvent<AirlockPainterComponent, AirlockPainterSpritePickedMessage>(OnSpritePicked);
|
||||||
SubscribeLocalEvent<AirlockPainterComponent, DoAfterEvent<AirlockPainterData>>(OnDoAfter);
|
SubscribeLocalEvent<AirlockPainterComponent, AirlockPainterDoAfterEvent>(OnDoAfter);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDoAfter(EntityUid uid, AirlockPainterComponent component, DoAfterEvent<AirlockPainterData> args)
|
private void OnDoAfter(EntityUid uid, AirlockPainterComponent component, AirlockPainterDoAfterEvent args)
|
||||||
{
|
|
||||||
if (args.Handled || args.Cancelled)
|
|
||||||
{
|
{
|
||||||
component.IsSpraying = false;
|
component.IsSpraying = false;
|
||||||
|
|
||||||
|
if (args.Handled || args.Cancelled)
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
if (args.Args.Target != null)
|
if (args.Args.Target != null)
|
||||||
{
|
{
|
||||||
_audio.Play(component.SpraySound, Filter.Pvs(uid, entityManager:EntityManager), uid, true);
|
_audio.PlayPvs(component.SpraySound, uid);
|
||||||
_appearance.SetData(args.Args.Target.Value, DoorVisuals.BaseRSI, args.AdditionalData.Sprite);
|
_appearance.SetData(args.Args.Target.Value, DoorVisuals.BaseRSI, args.Sprite);
|
||||||
_adminLogger.Add(LogType.Action, LogImpact.Low, $"{ToPrettyString(args.Args.User):user} painted {ToPrettyString(args.Args.Target.Value):target}");
|
_adminLogger.Add(LogType.Action, LogImpact.Low, $"{ToPrettyString(args.Args.User):user} painted {ToPrettyString(args.Args.Target.Value):target}");
|
||||||
component.IsSpraying = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
args.Handled = true;
|
args.Handled = true;
|
||||||
@@ -88,16 +84,14 @@ namespace Content.Server.AirlockPainter
|
|||||||
}
|
}
|
||||||
component.IsSpraying = true;
|
component.IsSpraying = true;
|
||||||
|
|
||||||
var airlockPainterData = new AirlockPainterData(sprite);
|
var doAfterEventArgs = new DoAfterArgs(args.User, component.SprayTime, new AirlockPainterDoAfterEvent(sprite), uid, target: target, used: uid)
|
||||||
var doAfterEventArgs = new DoAfterEventArgs(args.User, component.SprayTime, target:target, used:uid)
|
|
||||||
{
|
{
|
||||||
BreakOnTargetMove = true,
|
BreakOnTargetMove = true,
|
||||||
BreakOnUserMove = true,
|
BreakOnUserMove = true,
|
||||||
BreakOnDamage = true,
|
BreakOnDamage = true,
|
||||||
BreakOnStun = true,
|
|
||||||
NeedHand = true,
|
NeedHand = true,
|
||||||
};
|
};
|
||||||
_doAfterSystem.DoAfter(doAfterEventArgs, airlockPainterData);
|
_doAfterSystem.TryStartDoAfter(doAfterEventArgs);
|
||||||
|
|
||||||
// Log attempt
|
// Log attempt
|
||||||
_adminLogger.Add(LogType.Action, LogImpact.Low, $"{ToPrettyString(args.User):user} is painting {ToPrettyString(uid):target} to '{style}' at {Transform(uid).Coordinates:targetlocation}");
|
_adminLogger.Add(LogType.Action, LogImpact.Low, $"{ToPrettyString(args.User):user} is painting {ToPrettyString(uid):target} to '{style}' at {Transform(uid).Coordinates:targetlocation}");
|
||||||
@@ -118,10 +112,5 @@ namespace Content.Server.AirlockPainter
|
|||||||
_userInterfaceSystem.TrySetUiState(uid, AirlockPainterUiKey.Key,
|
_userInterfaceSystem.TrySetUiState(uid, AirlockPainterUiKey.Key,
|
||||||
new AirlockPainterBoundUserInterfaceState(component.Index));
|
new AirlockPainterBoundUserInterfaceState(component.Index));
|
||||||
}
|
}
|
||||||
|
|
||||||
private record struct AirlockPainterData(string Sprite)
|
|
||||||
{
|
|
||||||
public string Sprite = Sprite;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ public sealed class RemoveEnsnare : IAlertClick
|
|||||||
if (!entManager.TryGetComponent(ensnare, out EnsnaringComponent? ensnaringComponent))
|
if (!entManager.TryGetComponent(ensnare, out EnsnaringComponent? ensnaringComponent))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
entManager.EntitySysManager.GetEntitySystem<EnsnareableSystem>().TryFree(player, ensnare, ensnaringComponent);
|
entManager.EntitySysManager.GetEntitySystem<EnsnareableSystem>().TryFree(player, player, ensnare, ensnaringComponent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,5 @@ namespace Content.Server.Animals.Components
|
|||||||
public float UpdateRate = 5;
|
public float UpdateRate = 5;
|
||||||
|
|
||||||
public float AccumulatedFrameTime;
|
public float AccumulatedFrameTime;
|
||||||
|
|
||||||
public bool BeingMilked;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
using Content.Server.Animals.Components;
|
using Content.Server.Animals.Components;
|
||||||
using Content.Server.Chemistry.Components.SolutionManager;
|
using Content.Server.Chemistry.Components.SolutionManager;
|
||||||
using Content.Server.Chemistry.EntitySystems;
|
using Content.Server.Chemistry.EntitySystems;
|
||||||
using Content.Server.DoAfter;
|
|
||||||
using Content.Server.Nutrition.Components;
|
using Content.Server.Nutrition.Components;
|
||||||
using Content.Server.Popups;
|
using Content.Server.Popups;
|
||||||
using Content.Shared.DoAfter;
|
using Content.Shared.DoAfter;
|
||||||
using Content.Shared.IdentityManagement;
|
using Content.Shared.IdentityManagement;
|
||||||
using Content.Shared.Nutrition.Components;
|
using Content.Shared.Nutrition.Components;
|
||||||
using Content.Shared.Popups;
|
using Content.Shared.Popups;
|
||||||
|
using Content.Shared.Udder;
|
||||||
using Content.Shared.Verbs;
|
using Content.Shared.Verbs;
|
||||||
|
|
||||||
namespace Content.Server.Animals.Systems
|
namespace Content.Server.Animals.Systems
|
||||||
@@ -18,7 +18,7 @@ namespace Content.Server.Animals.Systems
|
|||||||
internal sealed class UdderSystem : EntitySystem
|
internal sealed class UdderSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!;
|
[Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!;
|
||||||
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
|
||||||
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
@@ -26,7 +26,7 @@ namespace Content.Server.Animals.Systems
|
|||||||
base.Initialize();
|
base.Initialize();
|
||||||
|
|
||||||
SubscribeLocalEvent<UdderComponent, GetVerbsEvent<AlternativeVerb>>(AddMilkVerb);
|
SubscribeLocalEvent<UdderComponent, GetVerbsEvent<AlternativeVerb>>(AddMilkVerb);
|
||||||
SubscribeLocalEvent<UdderComponent, DoAfterEvent>(OnDoAfter);
|
SubscribeLocalEvent<UdderComponent, MilkingDoAfterEvent>(OnDoAfter);
|
||||||
}
|
}
|
||||||
public override void Update(float frameTime)
|
public override void Update(float frameTime)
|
||||||
{
|
{
|
||||||
@@ -64,38 +64,21 @@ namespace Content.Server.Animals.Systems
|
|||||||
if (!Resolve(uid, ref udder))
|
if (!Resolve(uid, ref udder))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (udder.BeingMilked)
|
var doargs = new DoAfterArgs(userUid, 5, new MilkingDoAfterEvent(), uid, uid, used: containerUid)
|
||||||
{
|
|
||||||
_popupSystem.PopupEntity(Loc.GetString("udder-system-already-milking"), uid, userUid);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
udder.BeingMilked = true;
|
|
||||||
|
|
||||||
var doargs = new DoAfterEventArgs(userUid, 5, target:uid, used:containerUid)
|
|
||||||
{
|
{
|
||||||
BreakOnUserMove = true,
|
BreakOnUserMove = true,
|
||||||
BreakOnDamage = true,
|
BreakOnDamage = true,
|
||||||
BreakOnStun = true,
|
|
||||||
BreakOnTargetMove = true,
|
BreakOnTargetMove = true,
|
||||||
MovementThreshold = 1.0f
|
MovementThreshold = 1.0f,
|
||||||
};
|
};
|
||||||
|
|
||||||
_doAfterSystem.DoAfter(doargs);
|
_doAfterSystem.TryStartDoAfter(doargs);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDoAfter(EntityUid uid, UdderComponent component, DoAfterEvent args)
|
private void OnDoAfter(EntityUid uid, UdderComponent component, MilkingDoAfterEvent args)
|
||||||
{
|
{
|
||||||
if (args.Cancelled)
|
if (args.Cancelled || args.Handled || args.Args.Used == null)
|
||||||
{
|
|
||||||
component.BeingMilked = false;
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
if (args.Handled || args.Args.Used == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
component.BeingMilked = false;
|
|
||||||
|
|
||||||
if (!_solutionContainerSystem.TryGetSolution(uid, component.TargetSolutionName, out var solution))
|
if (!_solutionContainerSystem.TryGetSolution(uid, component.TargetSolutionName, out var solution))
|
||||||
return;
|
return;
|
||||||
@@ -103,6 +86,7 @@ namespace Content.Server.Animals.Systems
|
|||||||
if (!_solutionContainerSystem.TryGetRefillableSolution(args.Args.Used.Value, out var targetSolution))
|
if (!_solutionContainerSystem.TryGetRefillableSolution(args.Args.Used.Value, out var targetSolution))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
args.Handled = true;
|
||||||
var quantity = solution.Volume;
|
var quantity = solution.Volume;
|
||||||
if(quantity == 0)
|
if(quantity == 0)
|
||||||
{
|
{
|
||||||
@@ -118,8 +102,6 @@ namespace Content.Server.Animals.Systems
|
|||||||
|
|
||||||
_popupSystem.PopupEntity(Loc.GetString("udder-system-success", ("amount", quantity), ("target", Identity.Entity(args.Args.Used.Value, EntityManager))), uid,
|
_popupSystem.PopupEntity(Loc.GetString("udder-system-success", ("amount", quantity), ("target", Identity.Entity(args.Args.Used.Value, EntityManager))), uid,
|
||||||
args.Args.User, PopupType.Medium);
|
args.Args.User, PopupType.Medium);
|
||||||
|
|
||||||
args.Handled = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddMilkVerb(EntityUid uid, UdderComponent component, GetVerbsEvent<AlternativeVerb> args)
|
private void AddMilkVerb(EntityUid uid, UdderComponent component, GetVerbsEvent<AlternativeVerb> args)
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ public sealed partial class AnomalySystem
|
|||||||
{
|
{
|
||||||
SubscribeLocalEvent<AnomalyScannerComponent, BoundUIOpenedEvent>(OnScannerUiOpened);
|
SubscribeLocalEvent<AnomalyScannerComponent, BoundUIOpenedEvent>(OnScannerUiOpened);
|
||||||
SubscribeLocalEvent<AnomalyScannerComponent, AfterInteractEvent>(OnScannerAfterInteract);
|
SubscribeLocalEvent<AnomalyScannerComponent, AfterInteractEvent>(OnScannerAfterInteract);
|
||||||
SubscribeLocalEvent<AnomalyScannerComponent, DoAfterEvent>(OnDoAfter);
|
SubscribeLocalEvent<AnomalyScannerComponent, ScannerDoAfterEvent>(OnDoAfter);
|
||||||
|
|
||||||
SubscribeLocalEvent<AnomalyShutdownEvent>(OnScannerAnomalyShutdown);
|
SubscribeLocalEvent<AnomalyShutdownEvent>(OnScannerAnomalyShutdown);
|
||||||
SubscribeLocalEvent<AnomalySeverityChangedEvent>(OnScannerAnomalySeverityChanged);
|
SubscribeLocalEvent<AnomalySeverityChangedEvent>(OnScannerAnomalySeverityChanged);
|
||||||
@@ -81,7 +81,7 @@ public sealed partial class AnomalySystem
|
|||||||
if (!HasComp<AnomalyComponent>(target))
|
if (!HasComp<AnomalyComponent>(target))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_doAfter.DoAfter(new DoAfterEventArgs(args.User, component.ScanDoAfterDuration, target:target, used:uid)
|
_doAfter.TryStartDoAfter(new DoAfterArgs(args.User, component.ScanDoAfterDuration, new ScannerDoAfterEvent(), uid, target: target, used: uid)
|
||||||
{
|
{
|
||||||
DistanceThreshold = 2f
|
DistanceThreshold = 2f
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
using Content.Server.Anomaly.Components;
|
using Content.Server.Anomaly.Components;
|
||||||
using Content.Server.Atmos.EntitySystems;
|
using Content.Server.Atmos.EntitySystems;
|
||||||
using Content.Server.Audio;
|
using Content.Server.Audio;
|
||||||
using Content.Server.DoAfter;
|
|
||||||
using Content.Server.Explosion.EntitySystems;
|
using Content.Server.Explosion.EntitySystems;
|
||||||
using Content.Server.Materials;
|
using Content.Server.Materials;
|
||||||
using Content.Server.Radio.EntitySystems;
|
using Content.Server.Radio.EntitySystems;
|
||||||
using Content.Shared.Anomaly;
|
using Content.Shared.Anomaly;
|
||||||
using Content.Shared.Anomaly.Components;
|
using Content.Shared.Anomaly.Components;
|
||||||
|
using Content.Shared.DoAfter;
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Shared.Configuration;
|
using Robust.Shared.Configuration;
|
||||||
using Robust.Shared.Physics.Events;
|
using Robust.Shared.Physics.Events;
|
||||||
@@ -24,7 +24,7 @@ public sealed partial class AnomalySystem : SharedAnomalySystem
|
|||||||
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
||||||
[Dependency] private readonly AmbientSoundSystem _ambient = default!;
|
[Dependency] private readonly AmbientSoundSystem _ambient = default!;
|
||||||
[Dependency] private readonly AtmosphereSystem _atmosphere = default!;
|
[Dependency] private readonly AtmosphereSystem _atmosphere = default!;
|
||||||
[Dependency] private readonly DoAfterSystem _doAfter = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
|
||||||
[Dependency] private readonly ExplosionSystem _explosion = default!;
|
[Dependency] private readonly ExplosionSystem _explosion = default!;
|
||||||
[Dependency] private readonly MaterialStorageSystem _material = default!;
|
[Dependency] private readonly MaterialStorageSystem _material = default!;
|
||||||
[Dependency] private readonly RadioSystem _radio = default!;
|
[Dependency] private readonly RadioSystem _radio = default!;
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ using Robust.Shared.Containers;
|
|||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
using Content.Shared.Verbs;
|
using Content.Shared.Verbs;
|
||||||
using Content.Server.Popups;
|
using Content.Server.Popups;
|
||||||
using Content.Server.DoAfter;
|
|
||||||
using Content.Shared.DoAfter;
|
using Content.Shared.DoAfter;
|
||||||
|
using Content.Shared.Internals;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
namespace Content.Server.Body.Systems;
|
namespace Content.Server.Body.Systems;
|
||||||
@@ -20,7 +20,7 @@ public sealed class InternalsSystem : EntitySystem
|
|||||||
[Dependency] private readonly IPrototypeManager _protoManager = default!;
|
[Dependency] private readonly IPrototypeManager _protoManager = default!;
|
||||||
[Dependency] private readonly AlertsSystem _alerts = default!;
|
[Dependency] private readonly AlertsSystem _alerts = default!;
|
||||||
[Dependency] private readonly AtmosphereSystem _atmos = default!;
|
[Dependency] private readonly AtmosphereSystem _atmos = default!;
|
||||||
[Dependency] private readonly DoAfterSystem _doAfter = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
|
||||||
[Dependency] private readonly GasTankSystem _gasTank = default!;
|
[Dependency] private readonly GasTankSystem _gasTank = default!;
|
||||||
[Dependency] private readonly HandsSystem _hands = default!;
|
[Dependency] private readonly HandsSystem _hands = default!;
|
||||||
[Dependency] private readonly InventorySystem _inventory = default!;
|
[Dependency] private readonly InventorySystem _inventory = default!;
|
||||||
@@ -34,7 +34,7 @@ public sealed class InternalsSystem : EntitySystem
|
|||||||
SubscribeLocalEvent<InternalsComponent, ComponentStartup>(OnInternalsStartup);
|
SubscribeLocalEvent<InternalsComponent, ComponentStartup>(OnInternalsStartup);
|
||||||
SubscribeLocalEvent<InternalsComponent, ComponentShutdown>(OnInternalsShutdown);
|
SubscribeLocalEvent<InternalsComponent, ComponentShutdown>(OnInternalsShutdown);
|
||||||
SubscribeLocalEvent<InternalsComponent, GetVerbsEvent<InteractionVerb>>(OnGetInteractionVerbs);
|
SubscribeLocalEvent<InternalsComponent, GetVerbsEvent<InteractionVerb>>(OnGetInteractionVerbs);
|
||||||
SubscribeLocalEvent<InternalsComponent, DoAfterEvent<InternalsData>>(OnDoAfter);
|
SubscribeLocalEvent<InternalsComponent, InternalsDoAfterEvent>(OnDoAfter);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnGetInteractionVerbs(EntityUid uid, InternalsComponent component, GetVerbsEvent<InteractionVerb> args)
|
private void OnGetInteractionVerbs(EntityUid uid, InternalsComponent component, GetVerbsEvent<InteractionVerb> args)
|
||||||
@@ -85,24 +85,19 @@ public sealed class InternalsSystem : EntitySystem
|
|||||||
|
|
||||||
var isUser = uid == user;
|
var isUser = uid == user;
|
||||||
|
|
||||||
var internalsData = new InternalsData();
|
|
||||||
|
|
||||||
if (!force)
|
if (!force)
|
||||||
{
|
{
|
||||||
// Is the target not you? If yes, use a do-after to give them time to respond.
|
// Is the target not you? If yes, use a do-after to give them time to respond.
|
||||||
//If no, do a short delay. There's no reason it should be beyond 1 second.
|
//If no, do a short delay. There's no reason it should be beyond 1 second.
|
||||||
var delay = !isUser ? internals.Delay : 1.0f;
|
var delay = !isUser ? internals.Delay : 1.0f;
|
||||||
|
|
||||||
_doAfter.DoAfter(new DoAfterEventArgs(user, delay, target:uid)
|
_doAfter.TryStartDoAfter(new DoAfterArgs(user, delay, new InternalsDoAfterEvent(), uid, target: uid)
|
||||||
{
|
{
|
||||||
BreakOnUserMove = true,
|
BreakOnUserMove = true,
|
||||||
BreakOnDamage = true,
|
BreakOnDamage = true,
|
||||||
BreakOnStun = true,
|
|
||||||
BreakOnTargetMove = true,
|
BreakOnTargetMove = true,
|
||||||
MovementThreshold = 0.1f,
|
MovementThreshold = 0.1f,
|
||||||
RaiseOnUser = isUser,
|
});
|
||||||
RaiseOnTarget = !isUser
|
|
||||||
}, internalsData);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -110,12 +105,12 @@ public sealed class InternalsSystem : EntitySystem
|
|||||||
_gasTank.ConnectToInternals(tank);
|
_gasTank.ConnectToInternals(tank);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDoAfter(EntityUid uid, InternalsComponent component, DoAfterEvent<InternalsData> args)
|
private void OnDoAfter(EntityUid uid, InternalsComponent component, InternalsDoAfterEvent args)
|
||||||
{
|
{
|
||||||
if (args.Cancelled || args.Handled)
|
if (args.Cancelled || args.Handled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ToggleInternals(uid, args.Args.User, true, component);
|
ToggleInternals(uid, args.User, true, component);
|
||||||
|
|
||||||
args.Handled = true;
|
args.Handled = true;
|
||||||
}
|
}
|
||||||
@@ -266,9 +261,4 @@ public sealed class InternalsSystem : EntitySystem
|
|||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private record struct InternalsData
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
using Content.Server.Botany.Components;
|
using Content.Server.Botany.Components;
|
||||||
using Content.Server.DoAfter;
|
|
||||||
using Content.Server.Popups;
|
using Content.Server.Popups;
|
||||||
using Content.Shared.DoAfter;
|
using Content.Shared.DoAfter;
|
||||||
using Content.Shared.Examine;
|
using Content.Shared.Examine;
|
||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
|
using Content.Shared.Swab;
|
||||||
|
|
||||||
namespace Content.Server.Botany.Systems;
|
namespace Content.Server.Botany.Systems;
|
||||||
|
|
||||||
public sealed class BotanySwabSystem : EntitySystem
|
public sealed class BotanySwabSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
|
||||||
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
||||||
[Dependency] private readonly MutationSystem _mutationSystem = default!;
|
[Dependency] private readonly MutationSystem _mutationSystem = default!;
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@ public sealed class BotanySwabSystem : EntitySystem
|
|||||||
base.Initialize();
|
base.Initialize();
|
||||||
SubscribeLocalEvent<BotanySwabComponent, ExaminedEvent>(OnExamined);
|
SubscribeLocalEvent<BotanySwabComponent, ExaminedEvent>(OnExamined);
|
||||||
SubscribeLocalEvent<BotanySwabComponent, AfterInteractEvent>(OnAfterInteract);
|
SubscribeLocalEvent<BotanySwabComponent, AfterInteractEvent>(OnAfterInteract);
|
||||||
SubscribeLocalEvent<BotanySwabComponent, DoAfterEvent>(OnDoAfter);
|
SubscribeLocalEvent<BotanySwabComponent, BotanySwabDoAfterEvent>(OnDoAfter);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -44,12 +44,11 @@ public sealed class BotanySwabSystem : EntitySystem
|
|||||||
if (args.Target == null || !args.CanReach || !HasComp<PlantHolderComponent>(args.Target))
|
if (args.Target == null || !args.CanReach || !HasComp<PlantHolderComponent>(args.Target))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_doAfterSystem.DoAfter(new DoAfterEventArgs(args.User, swab.SwabDelay, target: args.Target, used: uid)
|
_doAfterSystem.TryStartDoAfter(new DoAfterArgs(args.User, swab.SwabDelay, new BotanySwabDoAfterEvent(), uid, target: args.Target, used: uid)
|
||||||
{
|
{
|
||||||
Broadcast = true,
|
Broadcast = true,
|
||||||
BreakOnTargetMove = true,
|
BreakOnTargetMove = true,
|
||||||
BreakOnUserMove = true,
|
BreakOnUserMove = true,
|
||||||
BreakOnStun = true,
|
|
||||||
NeedHand = true
|
NeedHand = true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -57,9 +56,9 @@ public sealed class BotanySwabSystem : EntitySystem
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Save seed data or cross-pollenate.
|
/// Save seed data or cross-pollenate.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void OnDoAfter(EntityUid uid, BotanySwabComponent component, DoAfterEvent args)
|
private void OnDoAfter(EntityUid uid, BotanySwabComponent swab, DoAfterEvent args)
|
||||||
{
|
{
|
||||||
if (args.Cancelled || args.Handled || !TryComp<PlantHolderComponent>(args.Args.Target, out var plant) || !TryComp<BotanySwabComponent>(args.Args.Used, out var swab))
|
if (args.Cancelled || args.Handled || !TryComp<PlantHolderComponent>(args.Args.Target, out var plant))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (swab.SeedData == null)
|
if (swab.SeedData == null)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using Content.Server.Body.Components;
|
using Content.Server.Body.Components;
|
||||||
using Content.Server.Chemistry.Components;
|
using Content.Server.Chemistry.Components;
|
||||||
using Content.Server.Chemistry.Components.SolutionManager;
|
using Content.Server.Chemistry.Components.SolutionManager;
|
||||||
|
using Content.Shared.Chemistry;
|
||||||
using Content.Shared.Chemistry.Components;
|
using Content.Shared.Chemistry.Components;
|
||||||
using Content.Shared.Chemistry.Reagent;
|
using Content.Shared.Chemistry.Reagent;
|
||||||
using Content.Shared.Database;
|
using Content.Shared.Database;
|
||||||
@@ -28,7 +29,7 @@ public sealed partial class ChemistrySystem
|
|||||||
{
|
{
|
||||||
SubscribeLocalEvent<InjectorComponent, GetVerbsEvent<AlternativeVerb>>(AddSetTransferVerbs);
|
SubscribeLocalEvent<InjectorComponent, GetVerbsEvent<AlternativeVerb>>(AddSetTransferVerbs);
|
||||||
SubscribeLocalEvent<InjectorComponent, SolutionChangedEvent>(OnSolutionChange);
|
SubscribeLocalEvent<InjectorComponent, SolutionChangedEvent>(OnSolutionChange);
|
||||||
SubscribeLocalEvent<InjectorComponent, DoAfterEvent>(OnInjectDoAfter);
|
SubscribeLocalEvent<InjectorComponent, InjectorDoAfterEvent>(OnInjectDoAfter);
|
||||||
SubscribeLocalEvent<InjectorComponent, ComponentStartup>(OnInjectorStartup);
|
SubscribeLocalEvent<InjectorComponent, ComponentStartup>(OnInjectorStartup);
|
||||||
SubscribeLocalEvent<InjectorComponent, UseInHandEvent>(OnInjectorUse);
|
SubscribeLocalEvent<InjectorComponent, UseInHandEvent>(OnInjectorUse);
|
||||||
SubscribeLocalEvent<InjectorComponent, AfterInteractEvent>(OnInjectorAfterInteract);
|
SubscribeLocalEvent<InjectorComponent, AfterInteractEvent>(OnInjectorAfterInteract);
|
||||||
@@ -129,18 +130,10 @@ public sealed partial class ChemistrySystem
|
|||||||
|
|
||||||
private void OnInjectDoAfter(EntityUid uid, InjectorComponent component, DoAfterEvent args)
|
private void OnInjectDoAfter(EntityUid uid, InjectorComponent component, DoAfterEvent args)
|
||||||
{
|
{
|
||||||
if (args.Cancelled)
|
if (args.Cancelled || args.Handled || args.Args.Target == null)
|
||||||
{
|
|
||||||
component.IsInjecting = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args.Handled || args.Args.Target == null)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
UseInjector(args.Args.Target.Value, args.Args.User, uid, component);
|
UseInjector(args.Args.Target.Value, args.Args.User, uid, component);
|
||||||
|
|
||||||
component.IsInjecting = false;
|
|
||||||
args.Handled = true;
|
args.Handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,10 +216,6 @@ public sealed partial class ChemistrySystem
|
|||||||
if (!_solutions.TryGetSolution(injector, InjectorComponent.SolutionName, out var solution))
|
if (!_solutions.TryGetSolution(injector, InjectorComponent.SolutionName, out var solution))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
//If it found it's injecting
|
|
||||||
if (component.IsInjecting)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var actualDelay = MathF.Max(component.Delay, 1f);
|
var actualDelay = MathF.Max(component.Delay, 1f);
|
||||||
|
|
||||||
// Injections take 1 second longer per additional 5u
|
// Injections take 1 second longer per additional 5u
|
||||||
@@ -269,17 +258,12 @@ public sealed partial class ChemistrySystem
|
|||||||
_adminLogger.Add(LogType.Ingestion, $"{EntityManager.ToPrettyString(user):user} is attempting to inject themselves with a solution {SolutionContainerSystem.ToPrettyString(solution):solution}.");
|
_adminLogger.Add(LogType.Ingestion, $"{EntityManager.ToPrettyString(user):user} is attempting to inject themselves with a solution {SolutionContainerSystem.ToPrettyString(solution):solution}.");
|
||||||
}
|
}
|
||||||
|
|
||||||
component.IsInjecting = true;
|
_doAfter.TryStartDoAfter(new DoAfterArgs(user, actualDelay, new InjectorDoAfterEvent(), injector, target: target, used: injector)
|
||||||
|
|
||||||
_doAfter.DoAfter(new DoAfterEventArgs(user, actualDelay, target:target, used:injector)
|
|
||||||
{
|
{
|
||||||
RaiseOnTarget = isTarget,
|
|
||||||
RaiseOnUser = !isTarget,
|
|
||||||
BreakOnUserMove = true,
|
BreakOnUserMove = true,
|
||||||
BreakOnDamage = true,
|
BreakOnDamage = true,
|
||||||
BreakOnStun = true,
|
|
||||||
BreakOnTargetMove = true,
|
BreakOnTargetMove = true,
|
||||||
MovementThreshold = 0.1f
|
MovementThreshold = 0.1f,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -434,4 +418,5 @@ public sealed partial class ChemistrySystem
|
|||||||
Dirty(component);
|
Dirty(component);
|
||||||
AfterDraw(component, injector);
|
AfterDraw(component, injector);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
using Content.Server.Administration.Logs;
|
using Content.Server.Administration.Logs;
|
||||||
using Content.Server.Body.Systems;
|
using Content.Server.Body.Systems;
|
||||||
using Content.Server.DoAfter;
|
|
||||||
using Content.Server.Interaction;
|
using Content.Server.Interaction;
|
||||||
using Content.Server.Popups;
|
using Content.Server.Popups;
|
||||||
using Content.Shared.CombatMode;
|
using Content.Shared.CombatMode;
|
||||||
using Content.Shared.Chemistry;
|
using Content.Shared.Chemistry;
|
||||||
|
using Content.Shared.DoAfter;
|
||||||
using Content.Shared.Mobs.Systems;
|
using Content.Shared.Mobs.Systems;
|
||||||
|
|
||||||
namespace Content.Server.Chemistry.EntitySystems;
|
namespace Content.Server.Chemistry.EntitySystems;
|
||||||
@@ -15,7 +15,7 @@ public sealed partial class ChemistrySystem : EntitySystem
|
|||||||
[Dependency] private readonly IEntityManager _entMan = default!;
|
[Dependency] private readonly IEntityManager _entMan = default!;
|
||||||
[Dependency] private readonly InteractionSystem _interaction = default!;
|
[Dependency] private readonly InteractionSystem _interaction = default!;
|
||||||
[Dependency] private readonly BloodstreamSystem _blood = default!;
|
[Dependency] private readonly BloodstreamSystem _blood = default!;
|
||||||
[Dependency] private readonly DoAfterSystem _doAfter = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
|
||||||
[Dependency] private readonly PopupSystem _popup = default!;
|
[Dependency] private readonly PopupSystem _popup = default!;
|
||||||
[Dependency] private readonly ReactiveSystem _reactiveSystem = default!;
|
[Dependency] private readonly ReactiveSystem _reactiveSystem = default!;
|
||||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||||
|
|||||||
@@ -317,11 +317,11 @@ public sealed partial class SolutionContainerSystem : EntitySystem
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryGetSolution(EntityUid uid, string name,
|
public bool TryGetSolution([NotNullWhen(true)] EntityUid? uid, string name,
|
||||||
[NotNullWhen(true)] out Solution? solution,
|
[NotNullWhen(true)] out Solution? solution,
|
||||||
SolutionContainerManagerComponent? solutionsMgr = null)
|
SolutionContainerManagerComponent? solutionsMgr = null)
|
||||||
{
|
{
|
||||||
if (!Resolve(uid, ref solutionsMgr, false))
|
if (uid == null || !Resolve(uid.Value, ref solutionsMgr, false))
|
||||||
{
|
{
|
||||||
solution = null;
|
solution = null;
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
using Content.Server.Body.Systems;
|
using Content.Server.Body.Systems;
|
||||||
using Content.Server.Climbing.Components;
|
using Content.Server.Climbing.Components;
|
||||||
using Content.Server.DoAfter;
|
|
||||||
using Content.Server.Interaction;
|
using Content.Server.Interaction;
|
||||||
using Content.Server.Popups;
|
using Content.Server.Popups;
|
||||||
using Content.Server.Stunnable;
|
using Content.Server.Stunnable;
|
||||||
@@ -36,7 +35,7 @@ public sealed class ClimbSystem : SharedClimbSystem
|
|||||||
[Dependency] private readonly ActionBlockerSystem _actionBlockerSystem = default!;
|
[Dependency] private readonly ActionBlockerSystem _actionBlockerSystem = default!;
|
||||||
[Dependency] private readonly BodySystem _bodySystem = default!;
|
[Dependency] private readonly BodySystem _bodySystem = default!;
|
||||||
[Dependency] private readonly DamageableSystem _damageableSystem = default!;
|
[Dependency] private readonly DamageableSystem _damageableSystem = default!;
|
||||||
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
|
||||||
[Dependency] private readonly FixtureSystem _fixtureSystem = default!;
|
[Dependency] private readonly FixtureSystem _fixtureSystem = default!;
|
||||||
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
||||||
[Dependency] private readonly InteractionSystem _interactionSystem = default!;
|
[Dependency] private readonly InteractionSystem _interactionSystem = default!;
|
||||||
@@ -57,7 +56,7 @@ public sealed class ClimbSystem : SharedClimbSystem
|
|||||||
SubscribeLocalEvent<ClimbableComponent, GetVerbsEvent<AlternativeVerb>>(AddClimbableVerb);
|
SubscribeLocalEvent<ClimbableComponent, GetVerbsEvent<AlternativeVerb>>(AddClimbableVerb);
|
||||||
SubscribeLocalEvent<ClimbableComponent, DragDropTargetEvent>(OnClimbableDragDrop);
|
SubscribeLocalEvent<ClimbableComponent, DragDropTargetEvent>(OnClimbableDragDrop);
|
||||||
|
|
||||||
SubscribeLocalEvent<ClimbingComponent, DoAfterEvent<ClimbExtraEvent>>(OnDoAfter);
|
SubscribeLocalEvent<ClimbingComponent, ClimbDoAfterEvent>(OnDoAfter);
|
||||||
SubscribeLocalEvent<ClimbingComponent, EndCollideEvent>(OnClimbEndCollide);
|
SubscribeLocalEvent<ClimbingComponent, EndCollideEvent>(OnClimbEndCollide);
|
||||||
SubscribeLocalEvent<ClimbingComponent, BuckleChangeEvent>(OnBuckleChange);
|
SubscribeLocalEvent<ClimbingComponent, BuckleChangeEvent>(OnBuckleChange);
|
||||||
SubscribeLocalEvent<ClimbingComponent, ComponentGetState>(OnClimbingGetState);
|
SubscribeLocalEvent<ClimbingComponent, ComponentGetState>(OnClimbingGetState);
|
||||||
@@ -114,22 +113,17 @@ public sealed class ClimbSystem : SharedClimbSystem
|
|||||||
if (_bonkSystem.TryBonk(entityToMove, climbable))
|
if (_bonkSystem.TryBonk(entityToMove, climbable))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var ev = new ClimbExtraEvent();
|
var args = new DoAfterArgs(user, component.ClimbDelay, new ClimbDoAfterEvent(), entityToMove, target: climbable, used: entityToMove)
|
||||||
|
|
||||||
var args = new DoAfterEventArgs(user, component.ClimbDelay, target: climbable, used: entityToMove)
|
|
||||||
{
|
{
|
||||||
BreakOnTargetMove = true,
|
BreakOnTargetMove = true,
|
||||||
BreakOnUserMove = true,
|
BreakOnUserMove = true,
|
||||||
BreakOnDamage = true,
|
BreakOnDamage = true
|
||||||
BreakOnStun = true,
|
|
||||||
RaiseOnUser = false,
|
|
||||||
RaiseOnTarget = false,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
_doAfterSystem.DoAfter(args, ev);
|
_doAfterSystem.TryStartDoAfter(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDoAfter(EntityUid uid, ClimbingComponent component, DoAfterEvent<ClimbExtraEvent> args)
|
private void OnDoAfter(EntityUid uid, ClimbingComponent component, ClimbDoAfterEvent args)
|
||||||
{
|
{
|
||||||
if (args.Handled || args.Cancelled || args.Args.Target == null || args.Args.Used == null)
|
if (args.Handled || args.Cancelled || args.Args.Target == null || args.Args.Used == null)
|
||||||
return;
|
return;
|
||||||
@@ -436,10 +430,6 @@ public sealed class ClimbSystem : SharedClimbSystem
|
|||||||
_fixtureRemoveQueue.Clear();
|
_fixtureRemoveQueue.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
private sealed class ClimbExtraEvent : EntityEventArgs
|
|
||||||
{
|
|
||||||
//Honestly this is only here because otherwise this activates on every single doafter on a human
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using Content.Server.Pulling;
|
|||||||
using Content.Shared.Construction.Components;
|
using Content.Shared.Construction.Components;
|
||||||
using Content.Shared.Construction.EntitySystems;
|
using Content.Shared.Construction.EntitySystems;
|
||||||
using Content.Shared.Database;
|
using Content.Shared.Database;
|
||||||
|
using Content.Shared.DoAfter;
|
||||||
using Content.Shared.Examine;
|
using Content.Shared.Examine;
|
||||||
using Content.Shared.Pulling.Components;
|
using Content.Shared.Pulling.Components;
|
||||||
using Content.Shared.Tools;
|
using Content.Shared.Tools;
|
||||||
@@ -40,23 +41,29 @@ namespace Content.Server.Construction
|
|||||||
|
|
||||||
private void OnUnanchorComplete(EntityUid uid, AnchorableComponent component, TryUnanchorCompletedEvent args)
|
private void OnUnanchorComplete(EntityUid uid, AnchorableComponent component, TryUnanchorCompletedEvent args)
|
||||||
{
|
{
|
||||||
|
if (args.Cancelled || args.Used is not { } used)
|
||||||
|
return;
|
||||||
|
|
||||||
var xform = Transform(uid);
|
var xform = Transform(uid);
|
||||||
|
|
||||||
RaiseLocalEvent(uid, new BeforeUnanchoredEvent(args.User, args.Using));
|
RaiseLocalEvent(uid, new BeforeUnanchoredEvent(args.User, used));
|
||||||
xform.Anchored = false;
|
xform.Anchored = false;
|
||||||
RaiseLocalEvent(uid, new UserUnanchoredEvent(args.User, args.Using));
|
RaiseLocalEvent(uid, new UserUnanchoredEvent(args.User, used));
|
||||||
|
|
||||||
_popup.PopupEntity(Loc.GetString("anchorable-unanchored"), uid);
|
_popup.PopupEntity(Loc.GetString("anchorable-unanchored"), uid);
|
||||||
|
|
||||||
_adminLogger.Add(
|
_adminLogger.Add(
|
||||||
LogType.Unanchor,
|
LogType.Unanchor,
|
||||||
LogImpact.Low,
|
LogImpact.Low,
|
||||||
$"{EntityManager.ToPrettyString(args.User):user} unanchored {EntityManager.ToPrettyString(uid):anchored} using {EntityManager.ToPrettyString(args.Using):using}"
|
$"{EntityManager.ToPrettyString(args.User):user} unanchored {EntityManager.ToPrettyString(uid):anchored} using {EntityManager.ToPrettyString(used):using}"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnAnchorComplete(EntityUid uid, AnchorableComponent component, TryAnchorCompletedEvent args)
|
private void OnAnchorComplete(EntityUid uid, AnchorableComponent component, TryAnchorCompletedEvent args)
|
||||||
{
|
{
|
||||||
|
if (args.Cancelled || args.Used is not { } used)
|
||||||
|
return;
|
||||||
|
|
||||||
var xform = Transform(uid);
|
var xform = Transform(uid);
|
||||||
if (TryComp<PhysicsComponent>(uid, out var anchorBody) &&
|
if (TryComp<PhysicsComponent>(uid, out var anchorBody) &&
|
||||||
!TileFree(xform.Coordinates, anchorBody))
|
!TileFree(xform.Coordinates, anchorBody))
|
||||||
@@ -78,16 +85,16 @@ namespace Content.Server.Construction
|
|||||||
if (component.Snap)
|
if (component.Snap)
|
||||||
xform.Coordinates = xform.Coordinates.SnapToGrid(EntityManager, _mapManager);
|
xform.Coordinates = xform.Coordinates.SnapToGrid(EntityManager, _mapManager);
|
||||||
|
|
||||||
RaiseLocalEvent(uid, new BeforeAnchoredEvent(args.User, args.Using));
|
RaiseLocalEvent(uid, new BeforeAnchoredEvent(args.User, used));
|
||||||
xform.Anchored = true;
|
xform.Anchored = true;
|
||||||
RaiseLocalEvent(uid, new UserAnchoredEvent(args.User, args.Using));
|
RaiseLocalEvent(uid, new UserAnchoredEvent(args.User, used));
|
||||||
|
|
||||||
_popup.PopupEntity(Loc.GetString("anchorable-anchored"), uid);
|
_popup.PopupEntity(Loc.GetString("anchorable-anchored"), uid);
|
||||||
|
|
||||||
_adminLogger.Add(
|
_adminLogger.Add(
|
||||||
LogType.Anchor,
|
LogType.Anchor,
|
||||||
LogImpact.Low,
|
LogImpact.Low,
|
||||||
$"{EntityManager.ToPrettyString(args.User):user} anchored {EntityManager.ToPrettyString(uid):anchored} using {EntityManager.ToPrettyString(args.Using):using}"
|
$"{EntityManager.ToPrettyString(args.User):user} anchored {EntityManager.ToPrettyString(uid):anchored} using {EntityManager.ToPrettyString(used):using}"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,8 +189,7 @@ namespace Content.Server.Construction
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var toolEvData = new ToolEventData(new TryAnchorCompletedEvent(userUid, usingUid), targetEntity:uid);
|
_tool.UseTool(usingUid, userUid, uid, anchorable.Delay, usingTool.Qualities, new TryAnchorCompletedEvent());
|
||||||
_tool.UseTool(usingUid, userUid, uid, anchorable.Delay, usingTool.Qualities, toolEvData);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -204,8 +210,7 @@ namespace Content.Server.Construction
|
|||||||
if (!Valid(uid, userUid, usingUid, false))
|
if (!Valid(uid, userUid, usingUid, false))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var toolEvData = new ToolEventData(new TryUnanchorCompletedEvent(userUid, usingUid), targetEntity:uid);
|
_tool.UseTool(usingUid, userUid, uid, anchorable.Delay, usingTool.Qualities, new TryUnanchorCompletedEvent());
|
||||||
_tool.UseTool(usingUid, userUid, uid, anchorable.Delay, usingTool.Qualities, toolEvData);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -236,32 +241,5 @@ namespace Content.Server.Construction
|
|||||||
_adminLogger.Add(LogType.Anchor, LogImpact.Low, $"{ToPrettyString(userUid):user} is trying to anchor {ToPrettyString(uid):entity} to {transform.Coordinates:targetlocation}");
|
_adminLogger.Add(LogType.Anchor, LogImpact.Low, $"{ToPrettyString(userUid):user} is trying to anchor {ToPrettyString(uid):entity} to {transform.Coordinates:targetlocation}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private abstract class AnchorEvent : EntityEventArgs
|
|
||||||
{
|
|
||||||
public EntityUid User;
|
|
||||||
public EntityUid Using;
|
|
||||||
|
|
||||||
protected AnchorEvent(EntityUid userUid, EntityUid usingUid)
|
|
||||||
{
|
|
||||||
User = userUid;
|
|
||||||
Using = usingUid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private sealed class TryUnanchorCompletedEvent : AnchorEvent
|
|
||||||
{
|
|
||||||
public TryUnanchorCompletedEvent(EntityUid userUid, EntityUid usingUid) : base(userUid, usingUid)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private sealed class TryAnchorCompletedEvent : AnchorEvent
|
|
||||||
{
|
|
||||||
public TryAnchorCompletedEvent(EntityUid userUid, EntityUid usingUid) : base(userUid, usingUid)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Content.Shared.Construction.Prototypes;
|
using Content.Shared.Construction.Prototypes;
|
||||||
|
using Content.Shared.DoAfter;
|
||||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||||
|
|
||||||
namespace Content.Server.Construction.Components
|
namespace Content.Server.Construction.Components
|
||||||
@@ -33,10 +34,12 @@ namespace Content.Server.Construction.Components
|
|||||||
[DataField("deconstructionTarget")]
|
[DataField("deconstructionTarget")]
|
||||||
public string? DeconstructionNode { get; set; } = "start";
|
public string? DeconstructionNode { get; set; } = "start";
|
||||||
|
|
||||||
[ViewVariables]
|
[DataField("doAfter")]
|
||||||
public bool WaitingDoAfter { get; set; } = false;
|
public DoAfterId? DoAfter;
|
||||||
|
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
|
// TODO Force flush interaction queue before serializing to YAML.
|
||||||
|
// Otherwise you can end up with entities stuck in invalid states (e.g., waiting for DoAfters).
|
||||||
public readonly Queue<object> InteractionQueue = new();
|
public readonly Queue<object> InteractionQueue = new();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,5 @@ namespace Content.Server.Construction.Components
|
|||||||
|
|
||||||
[DataField("qualityNeeded", customTypeSerializer:typeof(PrototypeIdSerializer<ToolQualityPrototype>))]
|
[DataField("qualityNeeded", customTypeSerializer:typeof(PrototypeIdSerializer<ToolQualityPrototype>))]
|
||||||
public string QualityNeeded = "Welding";
|
public string QualityNeeded = "Welding";
|
||||||
|
|
||||||
public bool BeingWelded;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -227,10 +227,9 @@ namespace Content.Server.Construction
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var doAfterArgs = new DoAfterEventArgs(user, doAfterTime)
|
var doAfterArgs = new DoAfterArgs(user, doAfterTime, new AwaitedDoAfterEvent(), null)
|
||||||
{
|
{
|
||||||
BreakOnDamage = true,
|
BreakOnDamage = true,
|
||||||
BreakOnStun = true,
|
|
||||||
BreakOnTargetMove = false,
|
BreakOnTargetMove = false,
|
||||||
BreakOnUserMove = true,
|
BreakOnUserMove = true,
|
||||||
NeedHand = false,
|
NeedHand = false,
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ using Content.Shared.DoAfter;
|
|||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
using Content.Shared.Tools.Components;
|
using Content.Shared.Tools.Components;
|
||||||
using Robust.Shared.Containers;
|
using Robust.Shared.Containers;
|
||||||
|
using Robust.Shared.Map;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
#if EXCEPTION_TOLERANCE
|
#if EXCEPTION_TOLERANCE
|
||||||
// ReSharper disable once RedundantUsingDirective
|
// ReSharper disable once RedundantUsingDirective
|
||||||
@@ -29,19 +30,7 @@ namespace Content.Server.Construction
|
|||||||
|
|
||||||
private void InitializeInteractions()
|
private void InitializeInteractions()
|
||||||
{
|
{
|
||||||
#region DoAfter Subscriptions
|
SubscribeLocalEvent<ConstructionComponent, ConstructionInteractDoAfterEvent>(EnqueueEvent);
|
||||||
|
|
||||||
// DoAfter handling.
|
|
||||||
// The ConstructionDoAfter events are meant to be raised either directed or broadcast.
|
|
||||||
// If they're raised broadcast, we will re-raise them as directed on the target.
|
|
||||||
// This allows us to easily use the DoAfter system for our purposes.
|
|
||||||
SubscribeLocalEvent<ConstructionDoAfterComplete>(OnDoAfterComplete);
|
|
||||||
SubscribeLocalEvent<ConstructionDoAfterCancelled>(OnDoAfterCancelled);
|
|
||||||
SubscribeLocalEvent<ConstructionComponent, ConstructionDoAfterComplete>(EnqueueEvent);
|
|
||||||
SubscribeLocalEvent<ConstructionComponent, ConstructionDoAfterCancelled>(EnqueueEvent);
|
|
||||||
SubscribeLocalEvent<ConstructionComponent, DoAfterEvent<ConstructionData>>(OnDoAfter);
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
// Event handling. Add your subscriptions here! Just make sure they're all handled by EnqueueEvent.
|
// Event handling. Add your subscriptions here! Just make sure they're all handled by EnqueueEvent.
|
||||||
SubscribeLocalEvent<ConstructionComponent, InteractUsingEvent>(EnqueueEvent, new []{typeof(AnchorableSystem)});
|
SubscribeLocalEvent<ConstructionComponent, InteractUsingEvent>(EnqueueEvent, new []{typeof(AnchorableSystem)});
|
||||||
@@ -158,11 +147,13 @@ namespace Content.Server.Construction
|
|||||||
if (!CheckConditions(uid, edge.Conditions))
|
if (!CheckConditions(uid, edge.Conditions))
|
||||||
return HandleResult.False;
|
return HandleResult.False;
|
||||||
|
|
||||||
// We can only perform the "step completed" logic if this returns true.
|
var handle = HandleStep(uid, ev, step, validation, out var user, construction);
|
||||||
if (HandleStep(uid, ev, step, validation, out var user, construction)
|
if (handle is not HandleResult.True)
|
||||||
is var handle and not HandleResult.True)
|
|
||||||
return handle;
|
return handle;
|
||||||
|
|
||||||
|
// Handle step should never handle the interaction during validation.
|
||||||
|
DebugTools.Assert(!validation);
|
||||||
|
|
||||||
// We increase the step index, meaning we move to the next step!
|
// We increase the step index, meaning we move to the next step!
|
||||||
construction.StepIndex++;
|
construction.StepIndex++;
|
||||||
|
|
||||||
@@ -198,10 +189,12 @@ namespace Content.Server.Construction
|
|||||||
|
|
||||||
// Let HandleInteraction actually handle the event for this step.
|
// Let HandleInteraction actually handle the event for this step.
|
||||||
// We can only perform the rest of our logic if it returns true.
|
// We can only perform the rest of our logic if it returns true.
|
||||||
if (HandleInteraction(uid, ev, step, validation, out user, construction)
|
var handle = HandleInteraction(uid, ev, step, validation, out user, construction);
|
||||||
is var handle and not HandleResult.True)
|
if (handle is not HandleResult.True)
|
||||||
return handle;
|
return handle;
|
||||||
|
|
||||||
|
DebugTools.Assert(!validation);
|
||||||
|
|
||||||
// Actually perform the step completion actions, since the step was handled correctly.
|
// Actually perform the step completion actions, since the step was handled correctly.
|
||||||
PerformActions(uid, user, step.Completed);
|
PerformActions(uid, user, step.Completed);
|
||||||
|
|
||||||
@@ -225,48 +218,29 @@ namespace Content.Server.Construction
|
|||||||
return HandleResult.False;
|
return HandleResult.False;
|
||||||
|
|
||||||
// Whether this event is being re-handled after a DoAfter or not. Check DoAfterState for more info.
|
// Whether this event is being re-handled after a DoAfter or not. Check DoAfterState for more info.
|
||||||
var doAfterState = validation ? DoAfterState.Validation : DoAfterState.None;
|
var doAfterState = DoAfterState.None;
|
||||||
|
|
||||||
// Custom data from a prior HandleInteraction where a DoAfter was called...
|
|
||||||
object? doAfterData = null;
|
|
||||||
|
|
||||||
// The DoAfter events can only perform special logic when we're not validating events.
|
// The DoAfter events can only perform special logic when we're not validating events.
|
||||||
|
if (ev is ConstructionInteractDoAfterEvent interactDoAfter)
|
||||||
|
{
|
||||||
if (!validation)
|
if (!validation)
|
||||||
{
|
construction.DoAfter = null;
|
||||||
// Some events are handled specially... Such as doAfter.
|
|
||||||
switch (ev)
|
|
||||||
{
|
|
||||||
case ConstructionDoAfterComplete complete:
|
|
||||||
{
|
|
||||||
// DoAfter completed!
|
|
||||||
ev = complete.WrappedEvent;
|
|
||||||
doAfterState = DoAfterState.Completed;
|
|
||||||
doAfterData = complete.CustomData;
|
|
||||||
construction.WaitingDoAfter = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case ConstructionDoAfterCancelled cancelled:
|
if (interactDoAfter.Cancelled)
|
||||||
{
|
|
||||||
// DoAfter failed!
|
|
||||||
ev = cancelled.WrappedEvent;
|
|
||||||
doAfterState = DoAfterState.Cancelled;
|
|
||||||
doAfterData = cancelled.CustomData;
|
|
||||||
construction.WaitingDoAfter = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can't perform any interactions while we're waiting for a DoAfter...
|
|
||||||
// This also makes any event validation fail.
|
|
||||||
if (construction.WaitingDoAfter)
|
|
||||||
return HandleResult.False;
|
return HandleResult.False;
|
||||||
|
|
||||||
|
ev = new InteractUsingEvent(
|
||||||
|
interactDoAfter.User,
|
||||||
|
interactDoAfter.Used!.Value,
|
||||||
|
uid,
|
||||||
|
interactDoAfter.ClickLocation);
|
||||||
|
|
||||||
|
doAfterState = DoAfterState.Completed;
|
||||||
|
}
|
||||||
|
|
||||||
// The cases in this switch will handle the interaction and return
|
// The cases in this switch will handle the interaction and return
|
||||||
switch (step)
|
switch (step)
|
||||||
{
|
{
|
||||||
|
|
||||||
// --- CONSTRUCTION STEP EVENT HANDLING START ---
|
// --- CONSTRUCTION STEP EVENT HANDLING START ---
|
||||||
#region Construction Step Event Handling
|
#region Construction Step Event Handling
|
||||||
// So you want to create your own custom step for construction?
|
// So you want to create your own custom step for construction?
|
||||||
@@ -282,14 +256,16 @@ namespace Content.Server.Construction
|
|||||||
if (ev is not InteractUsingEvent interactUsing)
|
if (ev is not InteractUsingEvent interactUsing)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
if (construction.DoAfter != null && !validation)
|
||||||
|
{
|
||||||
|
_doAfterSystem.Cancel(construction.DoAfter);
|
||||||
|
return HandleResult.False;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Sanity checks.
|
// TODO: Sanity checks.
|
||||||
|
|
||||||
user = interactUsing.User;
|
user = interactUsing.User;
|
||||||
|
|
||||||
// If this step's DoAfter was cancelled, we just fail the interaction.
|
|
||||||
if (doAfterState == DoAfterState.Cancelled)
|
|
||||||
return HandleResult.False;
|
|
||||||
|
|
||||||
var insert = interactUsing.Used;
|
var insert = interactUsing.Used;
|
||||||
|
|
||||||
// Since many things inherit this step, we delegate the "is this entity valid?" logic to them.
|
// Since many things inherit this step, we delegate the "is this entity valid?" logic to them.
|
||||||
@@ -298,29 +274,34 @@ namespace Content.Server.Construction
|
|||||||
return HandleResult.False;
|
return HandleResult.False;
|
||||||
|
|
||||||
// If we're only testing whether this step would be handled by the given event, then we're done.
|
// If we're only testing whether this step would be handled by the given event, then we're done.
|
||||||
if (doAfterState == DoAfterState.Validation)
|
if (validation)
|
||||||
return HandleResult.Validated;
|
return HandleResult.Validated;
|
||||||
|
|
||||||
// If we still haven't completed this step's DoAfter...
|
// If we still haven't completed this step's DoAfter...
|
||||||
if (doAfterState == DoAfterState.None && insertStep.DoAfter > 0)
|
if (doAfterState == DoAfterState.None && insertStep.DoAfter > 0)
|
||||||
{
|
{
|
||||||
// These events will be broadcast and handled by this very same system, that will
|
var doAfterEv = new ConstructionInteractDoAfterEvent(interactUsing);
|
||||||
// raise them directed to the target. These events wrap the original event.
|
|
||||||
var constructionData = new ConstructionData(new ConstructionDoAfterComplete(uid, ev), new ConstructionDoAfterCancelled(uid, ev));
|
var doAfterEventArgs = new DoAfterArgs(interactUsing.User, step.DoAfter, doAfterEv, uid, uid, interactUsing.Used)
|
||||||
var doAfterEventArgs = new DoAfterEventArgs(interactUsing.User, step.DoAfter, target: interactUsing.Target)
|
|
||||||
{
|
{
|
||||||
BreakOnDamage = false,
|
BreakOnDamage = false,
|
||||||
BreakOnStun = true,
|
|
||||||
BreakOnTargetMove = true,
|
BreakOnTargetMove = true,
|
||||||
BreakOnUserMove = true,
|
BreakOnUserMove = true,
|
||||||
NeedHand = true
|
NeedHand = true
|
||||||
};
|
};
|
||||||
|
|
||||||
_doAfterSystem.DoAfter(doAfterEventArgs, constructionData);
|
var started = _doAfterSystem.TryStartDoAfter(doAfterEventArgs, out construction.DoAfter);
|
||||||
|
|
||||||
// To properly signal that we're waiting for a DoAfter, we have to set the flag on the component
|
if (!started)
|
||||||
// and then also return the DoAfter HandleResult.
|
return HandleResult.False;
|
||||||
construction.WaitingDoAfter = true;
|
|
||||||
|
#if DEBUG
|
||||||
|
// Verify that the resulting DoAfter event will be handled by the current construction state.
|
||||||
|
// if it can't what is even the point of raising this DoAfter?
|
||||||
|
doAfterEv.DoAfter = new(default, doAfterEventArgs, default);
|
||||||
|
var result = HandleInteraction(uid, doAfterEv, step, validation: true, out _, construction);
|
||||||
|
DebugTools.Assert(result == HandleResult.Validated);
|
||||||
|
#endif
|
||||||
return HandleResult.DoAfter;
|
return HandleResult.DoAfter;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -362,40 +343,47 @@ namespace Content.Server.Construction
|
|||||||
if (ev is not InteractUsingEvent interactUsing)
|
if (ev is not InteractUsingEvent interactUsing)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
if (construction.DoAfter != null && !validation)
|
||||||
|
{
|
||||||
|
_doAfterSystem.Cancel(construction.DoAfter);
|
||||||
|
return HandleResult.False;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Sanity checks.
|
// TODO: Sanity checks.
|
||||||
|
|
||||||
user = interactUsing.User;
|
user = interactUsing.User;
|
||||||
|
|
||||||
// If we're validating whether this event handles the step...
|
// If we're validating whether this event handles the step...
|
||||||
if (doAfterState == DoAfterState.Validation)
|
if (validation)
|
||||||
{
|
{
|
||||||
// Then we only really need to check whether the tool entity has that quality or not.
|
// Then we only really need to check whether the tool entity has that quality or not.
|
||||||
|
// TODO fuel consumption?
|
||||||
return _toolSystem.HasQuality(interactUsing.Used, toolInsertStep.Tool)
|
return _toolSystem.HasQuality(interactUsing.Used, toolInsertStep.Tool)
|
||||||
? HandleResult.Validated : HandleResult.False;
|
? HandleResult.Validated
|
||||||
|
: HandleResult.False;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we're handling an event after its DoAfter finished...
|
// If we're handling an event after its DoAfter finished...
|
||||||
if (doAfterState != DoAfterState.None)
|
if (doAfterState == DoAfterState.Completed)
|
||||||
return doAfterState == DoAfterState.Completed ? HandleResult.True : HandleResult.False;
|
|
||||||
|
|
||||||
var toolEvData = new ToolEventData(new ConstructionDoAfterComplete(uid, ev), toolInsertStep.Fuel, new ConstructionDoAfterCancelled(uid, ev));
|
|
||||||
|
|
||||||
if(!_toolSystem.UseTool(interactUsing.Used, interactUsing.User, uid, toolInsertStep.DoAfter, new [] {toolInsertStep.Tool}, toolEvData))
|
|
||||||
return HandleResult.False;
|
|
||||||
|
|
||||||
// In the case we're not waiting for a doAfter, then this step is complete!
|
|
||||||
if (toolInsertStep.DoAfter <= 0)
|
|
||||||
return HandleResult.True;
|
return HandleResult.True;
|
||||||
|
|
||||||
construction.WaitingDoAfter = true;
|
var result = _toolSystem.UseTool(
|
||||||
return HandleResult.DoAfter;
|
interactUsing.Used,
|
||||||
|
interactUsing.User,
|
||||||
|
uid,
|
||||||
|
TimeSpan.FromSeconds(toolInsertStep.DoAfter),
|
||||||
|
new [] { toolInsertStep.Tool },
|
||||||
|
new ConstructionInteractDoAfterEvent(interactUsing),
|
||||||
|
out construction.DoAfter,
|
||||||
|
fuel: toolInsertStep.Fuel);
|
||||||
|
|
||||||
|
return construction.DoAfter != null ? HandleResult.DoAfter : HandleResult.False;
|
||||||
}
|
}
|
||||||
|
|
||||||
case TemperatureConstructionGraphStep temperatureChangeStep:
|
case TemperatureConstructionGraphStep temperatureChangeStep:
|
||||||
{
|
{
|
||||||
if (ev is not OnTemperatureChangeEvent) {
|
if (ev is not OnTemperatureChangeEvent)
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
if (TryComp<TemperatureComponent>(uid, out var tempComp))
|
if (TryComp<TemperatureComponent>(uid, out var tempComp))
|
||||||
{
|
{
|
||||||
@@ -550,7 +538,8 @@ namespace Content.Server.Construction
|
|||||||
/// in which case they will also be set as handled.</remarks>
|
/// in which case they will also be set as handled.</remarks>
|
||||||
private void EnqueueEvent(EntityUid uid, ConstructionComponent construction, object args)
|
private void EnqueueEvent(EntityUid uid, ConstructionComponent construction, object args)
|
||||||
{
|
{
|
||||||
// Handled events get treated specially.
|
// For handled events, we will check if the event leads to a valid construction interaction.
|
||||||
|
// If it does, we mark the event as handled and then enqueue it as normal.
|
||||||
if (args is HandledEntityEventArgs handled)
|
if (args is HandledEntityEventArgs handled)
|
||||||
{
|
{
|
||||||
// If they're already handled, we do nothing.
|
// If they're already handled, we do nothing.
|
||||||
@@ -572,95 +561,6 @@ namespace Content.Server.Construction
|
|||||||
if (_queuedUpdates.Add(uid))
|
if (_queuedUpdates.Add(uid))
|
||||||
_constructionUpdateQueue.Enqueue(uid);
|
_constructionUpdateQueue.Enqueue(uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDoAfter(EntityUid uid, ConstructionComponent component, DoAfterEvent<ConstructionData> args)
|
|
||||||
{
|
|
||||||
if (!Exists(args.Args.Target) || args.Handled)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (args.Cancelled)
|
|
||||||
{
|
|
||||||
RaiseLocalEvent(args.Args.Target.Value, args.AdditionalData.CancelEvent);
|
|
||||||
args.Handled = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
RaiseLocalEvent(args.Args.Target.Value, args.AdditionalData.CompleteEvent);
|
|
||||||
args.Handled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnDoAfterComplete(ConstructionDoAfterComplete ev)
|
|
||||||
{
|
|
||||||
// Make extra sure the target entity exists...
|
|
||||||
if (!Exists(ev.TargetUid))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Re-raise this event, but directed on the target UID.
|
|
||||||
RaiseLocalEvent(ev.TargetUid, ev, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnDoAfterCancelled(ConstructionDoAfterCancelled ev)
|
|
||||||
{
|
|
||||||
// Make extra sure the target entity exists...
|
|
||||||
if (!Exists(ev.TargetUid))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Re-raise this event, but directed on the target UID.
|
|
||||||
RaiseLocalEvent(ev.TargetUid, ev, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Event Definitions
|
|
||||||
|
|
||||||
private sealed class ConstructionData
|
|
||||||
{
|
|
||||||
public readonly object CompleteEvent;
|
|
||||||
public readonly object CancelEvent;
|
|
||||||
|
|
||||||
public ConstructionData(object completeEvent, object cancelEvent)
|
|
||||||
{
|
|
||||||
CompleteEvent = completeEvent;
|
|
||||||
CancelEvent = cancelEvent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This event signals that a construction interaction's DoAfter has completed successfully.
|
|
||||||
/// This wraps the original event and also keeps some custom data that event handlers might need.
|
|
||||||
/// </summary>
|
|
||||||
private sealed class ConstructionDoAfterComplete : EntityEventArgs
|
|
||||||
{
|
|
||||||
public readonly EntityUid TargetUid;
|
|
||||||
public readonly object WrappedEvent;
|
|
||||||
public readonly object? CustomData;
|
|
||||||
|
|
||||||
public ConstructionDoAfterComplete(EntityUid targetUid, object wrappedEvent, object? customData = null)
|
|
||||||
{
|
|
||||||
TargetUid = targetUid;
|
|
||||||
WrappedEvent = wrappedEvent;
|
|
||||||
CustomData = customData;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This event signals that a construction interaction's DoAfter has failed or has been cancelled.
|
|
||||||
/// This wraps the original event and also keeps some custom data that event handlers might need.
|
|
||||||
/// </summary>
|
|
||||||
private sealed class ConstructionDoAfterCancelled : EntityEventArgs
|
|
||||||
{
|
|
||||||
public readonly EntityUid TargetUid;
|
|
||||||
public readonly object WrappedEvent;
|
|
||||||
public readonly object? CustomData;
|
|
||||||
|
|
||||||
public ConstructionDoAfterCancelled(EntityUid targetUid, object wrappedEvent, object? customData = null)
|
|
||||||
{
|
|
||||||
TargetUid = targetUid;
|
|
||||||
WrappedEvent = wrappedEvent;
|
|
||||||
CustomData = customData;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Internal Enum Definitions
|
#region Internal Enum Definitions
|
||||||
@@ -676,23 +576,11 @@ namespace Content.Server.Construction
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
None,
|
None,
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// If Validation, we want to validate whether the specified event would handle the step or not.
|
|
||||||
/// Will NOT modify the construction state at all.
|
|
||||||
/// </summary>
|
|
||||||
Validation,
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// If Completed, this is the second (and last) time we're seeing this event, and
|
/// If Completed, this is the second (and last) time we're seeing this event, and
|
||||||
/// the doAfter that was called the first time successfully completed. Handle completion logic now.
|
/// the doAfter that was called the first time successfully completed. Handle completion logic now.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Completed,
|
Completed
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// If Cancelled, this is the second (and last) time we're seeing this event, and
|
|
||||||
/// the doAfter that was called the first time was cancelled. Handle cleanup logic now.
|
|
||||||
/// </summary>
|
|
||||||
Cancelled
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using Content.Server.Construction.Components;
|
using Content.Server.Construction.Components;
|
||||||
using Content.Server.DoAfter;
|
|
||||||
using Content.Server.Stack;
|
using Content.Server.Stack;
|
||||||
using Content.Shared.Construction;
|
using Content.Shared.Construction;
|
||||||
|
using Content.Shared.DoAfter;
|
||||||
using Content.Shared.Tools;
|
using Content.Shared.Tools;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Server.Containers;
|
using Robust.Server.Containers;
|
||||||
@@ -19,7 +19,7 @@ namespace Content.Server.Construction
|
|||||||
[Dependency] private readonly ILogManager _logManager = default!;
|
[Dependency] private readonly ILogManager _logManager = default!;
|
||||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||||
[Dependency] private readonly IRobustRandom _robustRandom = default!;
|
[Dependency] private readonly IRobustRandom _robustRandom = default!;
|
||||||
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
|
||||||
[Dependency] private readonly ContainerSystem _container = default!;
|
[Dependency] private readonly ContainerSystem _container = default!;
|
||||||
[Dependency] private readonly StackSystem _stackSystem = default!;
|
[Dependency] private readonly StackSystem _stackSystem = default!;
|
||||||
[Dependency] private readonly SharedToolSystem _toolSystem = default!;
|
[Dependency] private readonly SharedToolSystem _toolSystem = default!;
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Server.Construction.Components;
|
using Content.Server.Construction.Components;
|
||||||
using Content.Server.DoAfter;
|
|
||||||
using Content.Server.Storage.Components;
|
using Content.Server.Storage.Components;
|
||||||
using Content.Server.Storage.EntitySystems;
|
using Content.Server.Storage.EntitySystems;
|
||||||
using Content.Shared.DoAfter;
|
using Content.Shared.DoAfter;
|
||||||
using Content.Shared.Construction.Components;
|
using Content.Shared.Construction.Components;
|
||||||
|
using Content.Shared.Exchanger;
|
||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
using Content.Shared.Popups;
|
using Content.Shared.Popups;
|
||||||
using Robust.Shared.Containers;
|
using Robust.Shared.Containers;
|
||||||
@@ -16,7 +16,7 @@ namespace Content.Server.Construction;
|
|||||||
public sealed class PartExchangerSystem : EntitySystem
|
public sealed class PartExchangerSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly ConstructionSystem _construction = default!;
|
[Dependency] private readonly ConstructionSystem _construction = default!;
|
||||||
[Dependency] private readonly DoAfterSystem _doAfter = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
|
||||||
[Dependency] private readonly SharedPopupSystem _popup = default!;
|
[Dependency] private readonly SharedPopupSystem _popup = default!;
|
||||||
[Dependency] private readonly SharedContainerSystem _container = default!;
|
[Dependency] private readonly SharedContainerSystem _container = default!;
|
||||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||||
@@ -26,18 +26,14 @@ public sealed class PartExchangerSystem : EntitySystem
|
|||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
SubscribeLocalEvent<PartExchangerComponent, AfterInteractEvent>(OnAfterInteract);
|
SubscribeLocalEvent<PartExchangerComponent, AfterInteractEvent>(OnAfterInteract);
|
||||||
SubscribeLocalEvent<PartExchangerComponent, DoAfterEvent>(OnDoAfter);
|
SubscribeLocalEvent<PartExchangerComponent, ExchangerDoAfterEvent>(OnDoAfter);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDoAfter(EntityUid uid, PartExchangerComponent component, DoAfterEvent args)
|
private void OnDoAfter(EntityUid uid, PartExchangerComponent component, DoAfterEvent args)
|
||||||
{
|
{
|
||||||
|
component.AudioStream?.Stop();
|
||||||
if (args.Cancelled || args.Handled || args.Args.Target == null)
|
if (args.Cancelled || args.Handled || args.Args.Target == null)
|
||||||
{
|
|
||||||
component.AudioStream?.Stop();
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
component.AudioStream?.Stop();
|
|
||||||
|
|
||||||
if (!TryComp<MachineComponent>(args.Args.Target.Value, out var machine))
|
if (!TryComp<MachineComponent>(args.Args.Target.Value, out var machine))
|
||||||
return;
|
return;
|
||||||
@@ -112,11 +108,11 @@ public sealed class PartExchangerSystem : EntitySystem
|
|||||||
|
|
||||||
component.AudioStream = _audio.PlayPvs(component.ExchangeSound, uid);
|
component.AudioStream = _audio.PlayPvs(component.ExchangeSound, uid);
|
||||||
|
|
||||||
_doAfter.DoAfter(new DoAfterEventArgs(args.User, component.ExchangeDuration, target:args.Target, used:args.Used)
|
_doAfter.TryStartDoAfter(new DoAfterArgs(args.User, component.ExchangeDuration, new ExchangerDoAfterEvent(), uid, target: args.Target, used: uid)
|
||||||
{
|
{
|
||||||
BreakOnDamage = true,
|
BreakOnDamage = true,
|
||||||
BreakOnStun = true,
|
|
||||||
BreakOnUserMove = true
|
BreakOnUserMove = true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
using Content.Server.Construction.Components;
|
using Content.Server.Construction.Components;
|
||||||
using Content.Server.Stack;
|
using Content.Server.Stack;
|
||||||
|
using Content.Shared.Construction;
|
||||||
|
using Content.Shared.DoAfter;
|
||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
using Content.Shared.Stacks;
|
using Content.Shared.Stacks;
|
||||||
using Content.Shared.Tools;
|
using Content.Shared.Tools;
|
||||||
using Content.Shared.Tools.Components;
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
namespace Content.Server.Construction
|
namespace Content.Server.Construction
|
||||||
{
|
{
|
||||||
@@ -15,29 +17,22 @@ namespace Content.Server.Construction
|
|||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
SubscribeLocalEvent<WelderRefinableComponent, InteractUsingEvent>(OnInteractUsing);
|
SubscribeLocalEvent<WelderRefinableComponent, InteractUsingEvent>(OnInteractUsing);
|
||||||
|
SubscribeLocalEvent<WelderRefinableComponent, WelderRefineDoAfterEvent>(OnDoAfter);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void OnInteractUsing(EntityUid uid, WelderRefinableComponent component, InteractUsingEvent args)
|
private void OnInteractUsing(EntityUid uid, WelderRefinableComponent component, InteractUsingEvent args)
|
||||||
{
|
{
|
||||||
// check if object is welder
|
if (args.Handled)
|
||||||
if (!HasComp<ToolComponent>(args.Used))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// check if someone is already welding object
|
args.Handled = _toolSystem.UseTool(args.Used, args.User, uid, component.RefineTime, component.QualityNeeded, new WelderRefineDoAfterEvent(), component.RefineFuel);
|
||||||
if (component.BeingWelded)
|
|
||||||
return;
|
|
||||||
|
|
||||||
component.BeingWelded = true;
|
|
||||||
|
|
||||||
var toolEvData = new ToolEventData(null);
|
|
||||||
|
|
||||||
if (!_toolSystem.UseTool(args.Used, args.User, uid, component.RefineTime, component.QualityNeeded, toolEvData, component.RefineFuel))
|
|
||||||
{
|
|
||||||
// failed to veld - abort refine
|
|
||||||
component.BeingWelded = false;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnDoAfter(EntityUid uid, WelderRefinableComponent component, WelderRefineDoAfterEvent args)
|
||||||
|
{
|
||||||
|
if (args.Cancelled)
|
||||||
|
return;
|
||||||
|
|
||||||
// get last owner coordinates and delete it
|
// get last owner coordinates and delete it
|
||||||
var resultPosition = Transform(uid).Coordinates;
|
var resultPosition = Transform(uid).Coordinates;
|
||||||
EntityManager.DeleteEntity(uid);
|
EntityManager.DeleteEntity(uid);
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ namespace Content.Server.Cuffs
|
|||||||
|
|
||||||
private void OnHandcuffGetState(EntityUid uid, HandcuffComponent component, ref ComponentGetState args)
|
private void OnHandcuffGetState(EntityUid uid, HandcuffComponent component, ref ComponentGetState args)
|
||||||
{
|
{
|
||||||
args.State = new HandcuffComponentState(component.OverlayIconState, component.Cuffing);
|
args.State = new HandcuffComponentState(component.OverlayIconState);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnCuffableGetState(EntityUid uid, CuffableComponent component, ref ComponentGetState args)
|
private void OnCuffableGetState(EntityUid uid, CuffableComponent component, ref ComponentGetState args)
|
||||||
@@ -33,7 +33,6 @@ namespace Content.Server.Cuffs
|
|||||||
TryComp(component.LastAddedCuffs, out cuffs);
|
TryComp(component.LastAddedCuffs, out cuffs);
|
||||||
args.State = new CuffableComponentState(component.CuffedHandCount,
|
args.State = new CuffableComponentState(component.CuffedHandCount,
|
||||||
component.CanStillInteract,
|
component.CanStillInteract,
|
||||||
component.Uncuffing,
|
|
||||||
cuffs?.CuffedRSI,
|
cuffs?.CuffedRSI,
|
||||||
$"{cuffs?.OverlayIconState}-{component.CuffedHandCount}",
|
$"{cuffs?.OverlayIconState}-{component.CuffedHandCount}",
|
||||||
cuffs?.Color);
|
cuffs?.Color);
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ using Content.Shared.Disease;
|
|||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
using Content.Shared.Inventory;
|
using Content.Shared.Inventory;
|
||||||
using Content.Shared.Examine;
|
using Content.Shared.Examine;
|
||||||
using Content.Server.DoAfter;
|
|
||||||
using Content.Server.Popups;
|
using Content.Server.Popups;
|
||||||
using Content.Server.Hands.Components;
|
using Content.Server.Hands.Components;
|
||||||
using Content.Server.Nutrition.EntitySystems;
|
using Content.Server.Nutrition.EntitySystems;
|
||||||
@@ -18,7 +17,7 @@ using Content.Shared.Tools.Components;
|
|||||||
using Content.Server.Station.Systems;
|
using Content.Server.Station.Systems;
|
||||||
using Content.Shared.DoAfter;
|
using Content.Shared.DoAfter;
|
||||||
using Content.Shared.IdentityManagement;
|
using Content.Shared.IdentityManagement;
|
||||||
using Robust.Server.GameObjects;
|
using Content.Shared.Swab;
|
||||||
|
|
||||||
namespace Content.Server.Disease
|
namespace Content.Server.Disease
|
||||||
{
|
{
|
||||||
@@ -27,7 +26,7 @@ namespace Content.Server.Disease
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class DiseaseDiagnosisSystem : EntitySystem
|
public sealed class DiseaseDiagnosisSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
|
||||||
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
||||||
[Dependency] private readonly IRobustRandom _random = default!;
|
[Dependency] private readonly IRobustRandom _random = default!;
|
||||||
[Dependency] private readonly InventorySystem _inventorySystem = default!;
|
[Dependency] private readonly InventorySystem _inventorySystem = default!;
|
||||||
@@ -47,7 +46,7 @@ namespace Content.Server.Disease
|
|||||||
// Private Events
|
// Private Events
|
||||||
SubscribeLocalEvent<DiseaseDiagnoserComponent, DiseaseMachineFinishedEvent>(OnDiagnoserFinished);
|
SubscribeLocalEvent<DiseaseDiagnoserComponent, DiseaseMachineFinishedEvent>(OnDiagnoserFinished);
|
||||||
SubscribeLocalEvent<DiseaseVaccineCreatorComponent, DiseaseMachineFinishedEvent>(OnVaccinatorFinished);
|
SubscribeLocalEvent<DiseaseVaccineCreatorComponent, DiseaseMachineFinishedEvent>(OnVaccinatorFinished);
|
||||||
SubscribeLocalEvent<DiseaseSwabComponent, DoAfterEvent>(OnSwabDoAfter);
|
SubscribeLocalEvent<DiseaseSwabComponent, DiseaseSwabDoAfterEvent>(OnSwabDoAfter);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Queue<EntityUid> AddQueue = new();
|
private Queue<EntityUid> AddQueue = new();
|
||||||
@@ -116,15 +115,10 @@ namespace Content.Server.Disease
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var isTarget = args.User != args.Target;
|
_doAfterSystem.TryStartDoAfter(new DoAfterArgs(args.User, swab.SwabDelay, new DiseaseSwabDoAfterEvent(), uid, target: args.Target, used: uid)
|
||||||
|
|
||||||
_doAfterSystem.DoAfter(new DoAfterEventArgs(args.User, swab.SwabDelay, target: args.Target, used: uid)
|
|
||||||
{
|
{
|
||||||
RaiseOnTarget = isTarget,
|
|
||||||
RaiseOnUser = !isTarget,
|
|
||||||
BreakOnTargetMove = true,
|
BreakOnTargetMove = true,
|
||||||
BreakOnUserMove = true,
|
BreakOnUserMove = true,
|
||||||
BreakOnStun = true,
|
|
||||||
NeedHand = true
|
NeedHand = true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
using Content.Server.Body.Systems;
|
using Content.Server.Body.Systems;
|
||||||
using Content.Server.Chat.Systems;
|
using Content.Server.Chat.Systems;
|
||||||
using Content.Server.Disease.Components;
|
using Content.Server.Disease.Components;
|
||||||
using Content.Server.DoAfter;
|
|
||||||
using Content.Server.Nutrition.EntitySystems;
|
using Content.Server.Nutrition.EntitySystems;
|
||||||
using Content.Server.Popups;
|
using Content.Server.Popups;
|
||||||
using Content.Shared.Clothing.Components;
|
using Content.Shared.Clothing.Components;
|
||||||
@@ -37,7 +36,7 @@ namespace Content.Server.Disease
|
|||||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||||
[Dependency] private readonly ISerializationManager _serializationManager = default!;
|
[Dependency] private readonly ISerializationManager _serializationManager = default!;
|
||||||
[Dependency] private readonly IRobustRandom _random = default!;
|
[Dependency] private readonly IRobustRandom _random = default!;
|
||||||
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
|
||||||
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
||||||
[Dependency] private readonly EntityLookupSystem _lookup = default!;
|
[Dependency] private readonly EntityLookupSystem _lookup = default!;
|
||||||
[Dependency] private readonly SharedInteractionSystem _interactionSystem = default!;
|
[Dependency] private readonly SharedInteractionSystem _interactionSystem = default!;
|
||||||
@@ -58,7 +57,7 @@ namespace Content.Server.Disease
|
|||||||
// Handling stuff from other systems
|
// Handling stuff from other systems
|
||||||
SubscribeLocalEvent<DiseaseCarrierComponent, ApplyMetabolicMultiplierEvent>(OnApplyMetabolicMultiplier);
|
SubscribeLocalEvent<DiseaseCarrierComponent, ApplyMetabolicMultiplierEvent>(OnApplyMetabolicMultiplier);
|
||||||
// Private events stuff
|
// Private events stuff
|
||||||
SubscribeLocalEvent<DiseaseVaccineComponent, DoAfterEvent>(OnDoAfter);
|
SubscribeLocalEvent<DiseaseVaccineComponent, VaccineDoAfterEvent>(OnDoAfter);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Queue<EntityUid> AddQueue = new();
|
private Queue<EntityUid> AddQueue = new();
|
||||||
@@ -276,20 +275,21 @@ namespace Content.Server.Disease
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void OnAfterInteract(EntityUid uid, DiseaseVaccineComponent vaxx, AfterInteractEvent args)
|
private void OnAfterInteract(EntityUid uid, DiseaseVaccineComponent vaxx, AfterInteractEvent args)
|
||||||
{
|
{
|
||||||
if (args.Target == null || !args.CanReach)
|
if (args.Target == null || !args.CanReach || args.Handled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
args.Handled = true;
|
||||||
|
|
||||||
if (vaxx.Used)
|
if (vaxx.Used)
|
||||||
{
|
{
|
||||||
_popupSystem.PopupEntity(Loc.GetString("vaxx-already-used"), args.User, args.User);
|
_popupSystem.PopupEntity(Loc.GetString("vaxx-already-used"), args.User, args.User);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_doAfterSystem.DoAfter(new DoAfterEventArgs(args.User, vaxx.InjectDelay, target: args.Target, used:uid)
|
_doAfterSystem.TryStartDoAfter(new DoAfterArgs(args.User, vaxx.InjectDelay, new VaccineDoAfterEvent(), uid, target: args.Target, used: uid)
|
||||||
{
|
{
|
||||||
BreakOnTargetMove = true,
|
BreakOnTargetMove = true,
|
||||||
BreakOnUserMove = true,
|
BreakOnUserMove = true,
|
||||||
BreakOnStun = true,
|
|
||||||
NeedHand = true
|
NeedHand = true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ using Content.Server.Administration.Logs;
|
|||||||
using Content.Server.Atmos.EntitySystems;
|
using Content.Server.Atmos.EntitySystems;
|
||||||
using Content.Server.Disposal.Tube.Components;
|
using Content.Server.Disposal.Tube.Components;
|
||||||
using Content.Server.Disposal.Unit.Components;
|
using Content.Server.Disposal.Unit.Components;
|
||||||
using Content.Server.DoAfter;
|
|
||||||
using Content.Server.Hands.Components;
|
using Content.Server.Hands.Components;
|
||||||
using Content.Server.Popups;
|
using Content.Server.Popups;
|
||||||
using Content.Server.Power.Components;
|
using Content.Server.Power.Components;
|
||||||
@@ -42,7 +41,7 @@ namespace Content.Server.Disposal.Unit.EntitySystems
|
|||||||
[Dependency] private readonly ActionBlockerSystem _actionBlockerSystem = default!;
|
[Dependency] private readonly ActionBlockerSystem _actionBlockerSystem = default!;
|
||||||
[Dependency] private readonly AppearanceSystem _appearance = default!;
|
[Dependency] private readonly AppearanceSystem _appearance = default!;
|
||||||
[Dependency] private readonly AtmosphereSystem _atmosSystem = default!;
|
[Dependency] private readonly AtmosphereSystem _atmosSystem = default!;
|
||||||
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
|
||||||
[Dependency] private readonly EntityLookupSystem _lookup = default!;
|
[Dependency] private readonly EntityLookupSystem _lookup = default!;
|
||||||
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
||||||
[Dependency] private readonly SharedContainerSystem _containerSystem = default!;
|
[Dependency] private readonly SharedContainerSystem _containerSystem = default!;
|
||||||
@@ -79,7 +78,7 @@ namespace Content.Server.Disposal.Unit.EntitySystems
|
|||||||
SubscribeLocalEvent<DisposalUnitComponent, GetVerbsEvent<Verb>>(AddClimbInsideVerb);
|
SubscribeLocalEvent<DisposalUnitComponent, GetVerbsEvent<Verb>>(AddClimbInsideVerb);
|
||||||
|
|
||||||
// Units
|
// Units
|
||||||
SubscribeLocalEvent<DisposalUnitComponent, DoAfterEvent>(OnDoAfter);
|
SubscribeLocalEvent<DisposalUnitComponent, DisposalDoAfterEvent>(OnDoAfter);
|
||||||
|
|
||||||
//UI
|
//UI
|
||||||
SubscribeLocalEvent<DisposalUnitComponent, SharedDisposalUnitComponent.UiButtonPressedMessage>(OnUiButtonPressed);
|
SubscribeLocalEvent<DisposalUnitComponent, SharedDisposalUnitComponent.UiButtonPressedMessage>(OnUiButtonPressed);
|
||||||
@@ -489,19 +488,15 @@ namespace Content.Server.Disposal.Unit.EntitySystems
|
|||||||
|
|
||||||
// Can't check if our target AND disposals moves currently so we'll just check target.
|
// Can't check if our target AND disposals moves currently so we'll just check target.
|
||||||
// if you really want to check if disposals moves then add a predicate.
|
// if you really want to check if disposals moves then add a predicate.
|
||||||
var doAfterArgs = new DoAfterEventArgs(userId.Value, delay, target:toInsertId, used:unitId)
|
var doAfterArgs = new DoAfterArgs(userId.Value, delay, new DisposalDoAfterEvent(), unitId, target: toInsertId, used: unitId)
|
||||||
{
|
{
|
||||||
BreakOnDamage = true,
|
BreakOnDamage = true,
|
||||||
BreakOnStun = true,
|
|
||||||
BreakOnTargetMove = true,
|
BreakOnTargetMove = true,
|
||||||
BreakOnUserMove = true,
|
BreakOnUserMove = true,
|
||||||
NeedHand = false,
|
NeedHand = false
|
||||||
RaiseOnTarget = false,
|
|
||||||
RaiseOnUser = false,
|
|
||||||
RaiseOnUsed = true,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
_doAfterSystem.DoAfter(doAfterArgs);
|
_doAfterSystem.TryStartDoAfter(doAfterArgs);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using Content.Shared.DoAfter;
|
using Content.Shared.DoAfter;
|
||||||
using Content.Shared.Mobs;
|
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
|
|
||||||
namespace Content.Server.DoAfter;
|
namespace Content.Server.DoAfter;
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ using Content.Server.Power.EntitySystems;
|
|||||||
using Content.Shared.Tools;
|
using Content.Shared.Tools;
|
||||||
using Robust.Shared.Physics.Components;
|
using Robust.Shared.Physics.Components;
|
||||||
using Robust.Shared.Physics.Events;
|
using Robust.Shared.Physics.Events;
|
||||||
|
using Content.Shared.DoAfter;
|
||||||
|
|
||||||
namespace Content.Server.Doors.Systems;
|
namespace Content.Server.Doors.Systems;
|
||||||
|
|
||||||
@@ -41,8 +42,7 @@ public sealed class DoorSystem : SharedDoorSystem
|
|||||||
// Mob prying doors
|
// Mob prying doors
|
||||||
SubscribeLocalEvent<DoorComponent, GetVerbsEvent<AlternativeVerb>>(OnDoorAltVerb);
|
SubscribeLocalEvent<DoorComponent, GetVerbsEvent<AlternativeVerb>>(OnDoorAltVerb);
|
||||||
|
|
||||||
SubscribeLocalEvent<DoorComponent, PryFinishedEvent>(OnPryFinished);
|
SubscribeLocalEvent<DoorComponent, DoorPryDoAfterEvent>(OnPryFinished);
|
||||||
SubscribeLocalEvent<DoorComponent, PryCancelledEvent>(OnPryCancelled);
|
|
||||||
SubscribeLocalEvent<DoorComponent, WeldableAttemptEvent>(OnWeldAttempt);
|
SubscribeLocalEvent<DoorComponent, WeldableAttemptEvent>(OnWeldAttempt);
|
||||||
SubscribeLocalEvent<DoorComponent, WeldableChangedEvent>(OnWeldChanged);
|
SubscribeLocalEvent<DoorComponent, WeldableChangedEvent>(OnWeldChanged);
|
||||||
SubscribeLocalEvent<DoorComponent, GotEmaggedEvent>(OnEmagged);
|
SubscribeLocalEvent<DoorComponent, GotEmaggedEvent>(OnEmagged);
|
||||||
@@ -174,9 +174,6 @@ public sealed class DoorSystem : SharedDoorSystem
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool TryPryDoor(EntityUid target, EntityUid tool, EntityUid user, DoorComponent door, bool force = false)
|
public bool TryPryDoor(EntityUid target, EntityUid tool, EntityUid user, DoorComponent door, bool force = false)
|
||||||
{
|
{
|
||||||
if (door.BeingPried)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (door.State == DoorState.Welded)
|
if (door.State == DoorState.Welded)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -194,20 +191,14 @@ public sealed class DoorSystem : SharedDoorSystem
|
|||||||
var modEv = new DoorGetPryTimeModifierEvent(user);
|
var modEv = new DoorGetPryTimeModifierEvent(user);
|
||||||
RaiseLocalEvent(target, modEv, false);
|
RaiseLocalEvent(target, modEv, false);
|
||||||
|
|
||||||
door.BeingPried = true;
|
_toolSystem.UseTool(tool, user, target, modEv.PryTimeModifier * door.PryTime, door.PryingQuality, new DoorPryDoAfterEvent());
|
||||||
var toolEvData = new ToolEventData(new PryFinishedEvent(), cancelledEv: new PryCancelledEvent(),targetEntity: target);
|
|
||||||
_toolSystem.UseTool(tool, user, target, modEv.PryTimeModifier * door.PryTime, new[] { door.PryingQuality }, toolEvData);
|
|
||||||
return true; // we might not actually succeeded, but a do-after has started
|
return true; // we might not actually succeeded, but a do-after has started
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnPryCancelled(EntityUid uid, DoorComponent door, PryCancelledEvent args)
|
private void OnPryFinished(EntityUid uid, DoorComponent door, DoAfterEvent args)
|
||||||
{
|
{
|
||||||
door.BeingPried = false;
|
if (args.Cancelled)
|
||||||
}
|
return;
|
||||||
|
|
||||||
private void OnPryFinished(EntityUid uid, DoorComponent door, PryFinishedEvent args)
|
|
||||||
{
|
|
||||||
door.BeingPried = false;
|
|
||||||
|
|
||||||
if (door.State == DoorState.Closed)
|
if (door.State == DoorState.Closed)
|
||||||
StartOpening(uid, door);
|
StartOpening(uid, door);
|
||||||
@@ -309,6 +300,3 @@ public sealed class DoorSystem : SharedDoorSystem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class PryFinishedEvent : EntityEventArgs { }
|
|
||||||
public sealed class PryCancelledEvent : EntityEventArgs { }
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
using Content.Server.Body.Systems;
|
using Content.Server.Body.Systems;
|
||||||
using Content.Server.DoAfter;
|
|
||||||
using Content.Server.Popups;
|
using Content.Server.Popups;
|
||||||
using Content.Shared.Actions;
|
using Content.Shared.Actions;
|
||||||
using Content.Shared.Chemistry.Components;
|
using Content.Shared.Chemistry.Components;
|
||||||
using Robust.Shared.Containers;
|
using Robust.Shared.Containers;
|
||||||
using Robust.Shared.Player;
|
using Robust.Shared.Player;
|
||||||
using System.Threading;
|
|
||||||
using Content.Server.Chat.Systems;
|
using Content.Server.Chat.Systems;
|
||||||
using Content.Server.GameTicking;
|
using Content.Server.GameTicking;
|
||||||
using Content.Server.GameTicking.Rules;
|
using Content.Server.GameTicking.Rules;
|
||||||
@@ -33,7 +31,7 @@ namespace Content.Server.Dragon
|
|||||||
[Dependency] private readonly ITileDefinitionManager _tileDef = default!;
|
[Dependency] private readonly ITileDefinitionManager _tileDef = default!;
|
||||||
[Dependency] private readonly ChatSystem _chat = default!;
|
[Dependency] private readonly ChatSystem _chat = default!;
|
||||||
[Dependency] private readonly SharedActionsSystem _actionsSystem = default!;
|
[Dependency] private readonly SharedActionsSystem _actionsSystem = default!;
|
||||||
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
|
||||||
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
||||||
[Dependency] private readonly BloodstreamSystem _bloodstreamSystem = default!;
|
[Dependency] private readonly BloodstreamSystem _bloodstreamSystem = default!;
|
||||||
[Dependency] private readonly MovementSpeedModifierSystem _movement = default!;
|
[Dependency] private readonly MovementSpeedModifierSystem _movement = default!;
|
||||||
@@ -63,7 +61,7 @@ namespace Content.Server.Dragon
|
|||||||
SubscribeLocalEvent<DragonComponent, DragonSpawnRiftActionEvent>(OnDragonRift);
|
SubscribeLocalEvent<DragonComponent, DragonSpawnRiftActionEvent>(OnDragonRift);
|
||||||
SubscribeLocalEvent<DragonComponent, RefreshMovementSpeedModifiersEvent>(OnDragonMove);
|
SubscribeLocalEvent<DragonComponent, RefreshMovementSpeedModifiersEvent>(OnDragonMove);
|
||||||
|
|
||||||
SubscribeLocalEvent<DragonComponent, DoAfterEvent>(OnDoAfter);
|
SubscribeLocalEvent<DragonComponent, DragonDevourDoAfterEvent>(OnDoAfter);
|
||||||
|
|
||||||
SubscribeLocalEvent<DragonComponent, MobStateChangedEvent>(OnMobStateChanged);
|
SubscribeLocalEvent<DragonComponent, MobStateChangedEvent>(OnMobStateChanged);
|
||||||
|
|
||||||
@@ -75,7 +73,7 @@ namespace Content.Server.Dragon
|
|||||||
SubscribeLocalEvent<RoundEndTextAppendEvent>(OnRiftRoundEnd);
|
SubscribeLocalEvent<RoundEndTextAppendEvent>(OnRiftRoundEnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDoAfter(EntityUid uid, DragonComponent component, DoAfterEvent args)
|
private void OnDoAfter(EntityUid uid, DragonComponent component, DragonDevourDoAfterEvent args)
|
||||||
{
|
{
|
||||||
if (args.Handled || args.Cancelled)
|
if (args.Handled || args.Cancelled)
|
||||||
return;
|
return;
|
||||||
@@ -95,8 +93,7 @@ namespace Content.Server.Dragon
|
|||||||
else if (args.Args.Target != null)
|
else if (args.Args.Target != null)
|
||||||
EntityManager.QueueDeleteEntity(args.Args.Target.Value);
|
EntityManager.QueueDeleteEntity(args.Args.Target.Value);
|
||||||
|
|
||||||
if (component.SoundDevour != null)
|
_audioSystem.PlayPvs(component.SoundDevour, uid);
|
||||||
_audioSystem.PlayPvs(component.SoundDevour, uid, component.SoundDevour.Params);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Update(float frameTime)
|
public override void Update(float frameTime)
|
||||||
@@ -355,11 +352,10 @@ namespace Content.Server.Dragon
|
|||||||
case MobState.Critical:
|
case MobState.Critical:
|
||||||
case MobState.Dead:
|
case MobState.Dead:
|
||||||
|
|
||||||
_doAfterSystem.DoAfter(new DoAfterEventArgs(uid, component.DevourTime, target:target)
|
_doAfterSystem.TryStartDoAfter(new DoAfterArgs(uid, component.DevourTime, new DragonDevourDoAfterEvent(), uid, target: target, used: uid)
|
||||||
{
|
{
|
||||||
BreakOnTargetMove = true,
|
BreakOnTargetMove = true,
|
||||||
BreakOnUserMove = true,
|
BreakOnUserMove = true,
|
||||||
BreakOnStun = true,
|
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -375,11 +371,10 @@ namespace Content.Server.Dragon
|
|||||||
if (component.SoundStructureDevour != null)
|
if (component.SoundStructureDevour != null)
|
||||||
_audioSystem.PlayPvs(component.SoundStructureDevour, uid, component.SoundStructureDevour.Params);
|
_audioSystem.PlayPvs(component.SoundStructureDevour, uid, component.SoundStructureDevour.Params);
|
||||||
|
|
||||||
_doAfterSystem.DoAfter(new DoAfterEventArgs(uid, component.StructureDevourTime, target:target)
|
_doAfterSystem.TryStartDoAfter(new DoAfterArgs(uid, component.StructureDevourTime, new DragonDevourDoAfterEvent(), uid, target: target, used: uid)
|
||||||
{
|
{
|
||||||
BreakOnTargetMove = true,
|
BreakOnTargetMove = true,
|
||||||
BreakOnUserMove = true,
|
BreakOnUserMove = true,
|
||||||
BreakOnStun = true,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,5 @@ namespace Content.Server.Engineering.Components
|
|||||||
|
|
||||||
[DataField("doAfter")]
|
[DataField("doAfter")]
|
||||||
public float DoAfterTime = 0;
|
public float DoAfterTime = 0;
|
||||||
|
|
||||||
public CancellationTokenSource TokenSource { get; } = new();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
using Content.Server.DoAfter;
|
|
||||||
using Content.Server.Engineering.Components;
|
using Content.Server.Engineering.Components;
|
||||||
using Content.Shared.DoAfter;
|
using Content.Shared.DoAfter;
|
||||||
using Content.Shared.Hands.EntitySystems;
|
using Content.Shared.Hands.EntitySystems;
|
||||||
@@ -41,18 +40,16 @@ namespace Content.Server.Engineering.EntitySystems
|
|||||||
if (string.IsNullOrEmpty(component.Prototype))
|
if (string.IsNullOrEmpty(component.Prototype))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (component.DoAfterTime > 0 && TryGet<DoAfterSystem>(out var doAfterSystem))
|
if (component.DoAfterTime > 0 && TryGet<SharedDoAfterSystem>(out var doAfterSystem))
|
||||||
{
|
{
|
||||||
var doAfterArgs = new DoAfterEventArgs(user, component.DoAfterTime, component.TokenSource.Token)
|
var doAfterArgs = new DoAfterArgs(user, component.DoAfterTime, new AwaitedDoAfterEvent(), null)
|
||||||
{
|
{
|
||||||
BreakOnUserMove = true,
|
BreakOnUserMove = true,
|
||||||
BreakOnStun = true,
|
|
||||||
};
|
};
|
||||||
var result = await doAfterSystem.WaitDoAfter(doAfterArgs);
|
var result = await doAfterSystem.WaitDoAfter(doAfterArgs);
|
||||||
|
|
||||||
if (result != DoAfterStatus.Finished)
|
if (result != DoAfterStatus.Finished)
|
||||||
return;
|
return;
|
||||||
component.TokenSource.Cancel();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (component.Deleted || Deleted(component.Owner))
|
if (component.Deleted || Deleted(component.Owner))
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using Content.Server.Coordinates.Helpers;
|
using Content.Server.Coordinates.Helpers;
|
||||||
using Content.Server.DoAfter;
|
|
||||||
using Content.Server.Engineering.Components;
|
using Content.Server.Engineering.Components;
|
||||||
using Content.Server.Stack;
|
using Content.Server.Stack;
|
||||||
using Content.Shared.DoAfter;
|
using Content.Shared.DoAfter;
|
||||||
@@ -15,7 +14,7 @@ namespace Content.Server.Engineering.EntitySystems
|
|||||||
public sealed class SpawnAfterInteractSystem : EntitySystem
|
public sealed class SpawnAfterInteractSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||||
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
|
||||||
[Dependency] private readonly StackSystem _stackSystem = default!;
|
[Dependency] private readonly StackSystem _stackSystem = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
@@ -46,11 +45,9 @@ namespace Content.Server.Engineering.EntitySystems
|
|||||||
|
|
||||||
if (component.DoAfterTime > 0)
|
if (component.DoAfterTime > 0)
|
||||||
{
|
{
|
||||||
var doAfterArgs = new DoAfterEventArgs(args.User, component.DoAfterTime)
|
var doAfterArgs = new DoAfterArgs(args.User, component.DoAfterTime, new AwaitedDoAfterEvent(), null)
|
||||||
{
|
{
|
||||||
BreakOnUserMove = true,
|
BreakOnUserMove = true,
|
||||||
BreakOnStun = true,
|
|
||||||
PostCheck = IsTileClear,
|
|
||||||
};
|
};
|
||||||
var result = await _doAfterSystem.WaitDoAfter(doAfterArgs);
|
var result = await _doAfterSystem.WaitDoAfter(doAfterArgs);
|
||||||
|
|
||||||
@@ -58,7 +55,7 @@ namespace Content.Server.Engineering.EntitySystems
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (component.Deleted || Deleted(component.Owner))
|
if (component.Deleted || !IsTileClear())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (EntityManager.TryGetComponent<StackComponent?>(component.Owner, out var stackComp)
|
if (EntityManager.TryGetComponent<StackComponent?>(component.Owner, out var stackComp)
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
using System.Threading;
|
|
||||||
using Content.Server.DoAfter;
|
|
||||||
using Content.Shared.Alert;
|
using Content.Shared.Alert;
|
||||||
using Content.Shared.DoAfter;
|
using Content.Shared.DoAfter;
|
||||||
|
using Content.Shared.Ensnaring;
|
||||||
using Content.Shared.Ensnaring.Components;
|
using Content.Shared.Ensnaring.Components;
|
||||||
using Content.Shared.IdentityManagement;
|
using Content.Shared.IdentityManagement;
|
||||||
using Content.Shared.StepTrigger.Systems;
|
using Content.Shared.StepTrigger.Systems;
|
||||||
@@ -11,7 +10,7 @@ namespace Content.Server.Ensnaring;
|
|||||||
|
|
||||||
public sealed partial class EnsnareableSystem
|
public sealed partial class EnsnareableSystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly DoAfterSystem _doAfter = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
|
||||||
[Dependency] private readonly AlertsSystem _alerts = default!;
|
[Dependency] private readonly AlertsSystem _alerts = default!;
|
||||||
|
|
||||||
public void InitializeEnsnaring()
|
public void InitializeEnsnaring()
|
||||||
@@ -74,40 +73,35 @@ public sealed partial class EnsnareableSystem
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Used where you want to try to free an entity with the <see cref="EnsnareableComponent"/>
|
/// Used where you want to try to free an entity with the <see cref="EnsnareableComponent"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="target">The entity that will be free</param>
|
/// <param name="target">The entity that will be freed</param>
|
||||||
|
/// <param name="user">The entity that is freeing the target</param>
|
||||||
/// <param name="ensnare">The entity used to ensnare</param>
|
/// <param name="ensnare">The entity used to ensnare</param>
|
||||||
/// <param name="component">The ensnaring component</param>
|
/// <param name="component">The ensnaring component</param>
|
||||||
public void TryFree(EntityUid target, EntityUid ensnare, EnsnaringComponent component, EntityUid? user = null)
|
public void TryFree(EntityUid target, EntityUid user, EntityUid ensnare, EnsnaringComponent component)
|
||||||
{
|
{
|
||||||
//Don't do anything if they don't have the ensnareable component.
|
//Don't do anything if they don't have the ensnareable component.
|
||||||
if (!HasComp<EnsnareableComponent>(target))
|
if (!HasComp<EnsnareableComponent>(target))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var isOwner = !(user != null && target != user);
|
var freeTime = user == target ? component.BreakoutTime : component.FreeTime;
|
||||||
var freeTime = isOwner ? component.BreakoutTime : component.FreeTime;
|
var breakOnMove = user != target || !component.CanMoveBreakout;
|
||||||
bool breakOnMove;
|
|
||||||
|
|
||||||
if (isOwner)
|
var doAfterEventArgs = new DoAfterArgs(user, freeTime, new EnsnareableDoAfterEvent(), target, target: target, used: ensnare)
|
||||||
breakOnMove = !component.CanMoveBreakout;
|
|
||||||
else
|
|
||||||
breakOnMove = true;
|
|
||||||
|
|
||||||
var doAfterEventArgs = new DoAfterEventArgs(target, freeTime, target: target, used:ensnare)
|
|
||||||
{
|
{
|
||||||
BreakOnUserMove = breakOnMove,
|
BreakOnUserMove = breakOnMove,
|
||||||
BreakOnTargetMove = breakOnMove,
|
BreakOnTargetMove = breakOnMove,
|
||||||
BreakOnDamage = false,
|
BreakOnDamage = false,
|
||||||
BreakOnStun = true,
|
NeedHand = true,
|
||||||
NeedHand = true
|
BlockDuplicate = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
_doAfter.DoAfter(doAfterEventArgs);
|
if (!_doAfter.TryStartDoAfter(doAfterEventArgs))
|
||||||
|
return;
|
||||||
|
|
||||||
if (isOwner)
|
if (user == target)
|
||||||
_popup.PopupEntity(Loc.GetString("ensnare-component-try-free", ("ensnare", ensnare)), target, target);
|
_popup.PopupEntity(Loc.GetString("ensnare-component-try-free", ("ensnare", ensnare)), target, target);
|
||||||
|
else
|
||||||
if (!isOwner && user != null)
|
_popup.PopupEntity(Loc.GetString("ensnare-component-try-free-other", ("ensnare", ensnare), ("user", Identity.Entity(target, EntityManager))), user, user);
|
||||||
_popup.PopupEntity(Loc.GetString("ensnare-component-try-free-other", ("ensnare", ensnare), ("user", Identity.Entity(target, EntityManager))), user.Value, user.Value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ public sealed partial class EnsnareableSystem : SharedEnsnareableSystem
|
|||||||
InitializeEnsnaring();
|
InitializeEnsnaring();
|
||||||
|
|
||||||
SubscribeLocalEvent<EnsnareableComponent, ComponentInit>(OnEnsnareableInit);
|
SubscribeLocalEvent<EnsnareableComponent, ComponentInit>(OnEnsnareableInit);
|
||||||
SubscribeLocalEvent<EnsnareableComponent, DoAfterEvent>(OnDoAfter);
|
SubscribeLocalEvent<EnsnareableComponent, EnsnareableDoAfterEvent>(OnDoAfter);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnEnsnareableInit(EntityUid uid, EnsnareableComponent component, ComponentInit args)
|
private void OnEnsnareableInit(EntityUid uid, EnsnareableComponent component, ComponentInit args)
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
using System.Linq;
|
|
||||||
using Content.Server.Chemistry.Components.SolutionManager;
|
using Content.Server.Chemistry.Components.SolutionManager;
|
||||||
using Content.Server.Chemistry.EntitySystems;
|
using Content.Server.Chemistry.EntitySystems;
|
||||||
using Content.Server.DoAfter;
|
|
||||||
using Content.Server.Fluids.Components;
|
using Content.Server.Fluids.Components;
|
||||||
using Content.Server.Popups;
|
using Content.Server.Popups;
|
||||||
using Content.Shared.Chemistry.Components;
|
using Content.Shared.Chemistry.Components;
|
||||||
@@ -20,7 +18,7 @@ namespace Content.Server.Fluids.EntitySystems;
|
|||||||
[UsedImplicitly]
|
[UsedImplicitly]
|
||||||
public sealed class MoppingSystem : SharedMoppingSystem
|
public sealed class MoppingSystem : SharedMoppingSystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
|
||||||
[Dependency] private readonly SpillableSystem _spillableSystem = default!;
|
[Dependency] private readonly SpillableSystem _spillableSystem = default!;
|
||||||
[Dependency] private readonly TagSystem _tagSystem = default!;
|
[Dependency] private readonly TagSystem _tagSystem = default!;
|
||||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||||
@@ -35,8 +33,8 @@ public sealed class MoppingSystem : SharedMoppingSystem
|
|||||||
base.Initialize();
|
base.Initialize();
|
||||||
SubscribeLocalEvent<AbsorbentComponent, ComponentInit>(OnAbsorbentInit);
|
SubscribeLocalEvent<AbsorbentComponent, ComponentInit>(OnAbsorbentInit);
|
||||||
SubscribeLocalEvent<AbsorbentComponent, AfterInteractEvent>(OnAfterInteract);
|
SubscribeLocalEvent<AbsorbentComponent, AfterInteractEvent>(OnAfterInteract);
|
||||||
|
SubscribeLocalEvent<AbsorbentComponent, AbsorbantDoAfterEvent>(OnDoAfter);
|
||||||
SubscribeLocalEvent<AbsorbentComponent, SolutionChangedEvent>(OnAbsorbentSolutionChange);
|
SubscribeLocalEvent<AbsorbentComponent, SolutionChangedEvent>(OnAbsorbentSolutionChange);
|
||||||
SubscribeLocalEvent<AbsorbentComponent, DoAfterEvent<AbsorbantData>>(OnDoAfter);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnAbsorbentInit(EntityUid uid, AbsorbentComponent component, ComponentInit args)
|
private void OnAbsorbentInit(EntityUid uid, AbsorbentComponent component, ComponentInit args)
|
||||||
@@ -256,48 +254,34 @@ public sealed class MoppingSystem : SharedMoppingSystem
|
|||||||
if (!component.InteractingEntities.Add(target))
|
if (!component.InteractingEntities.Add(target))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var aborbantData = new AbsorbantData(targetSolution, msg, sfx, transferAmount);
|
var ev = new AbsorbantDoAfterEvent(targetSolution, msg, sfx, transferAmount);
|
||||||
|
|
||||||
var doAfterArgs = new DoAfterEventArgs(user, delay, target: target, used:used)
|
var doAfterArgs = new DoAfterArgs(user, delay, ev, used, target: target, used: used)
|
||||||
{
|
{
|
||||||
BreakOnUserMove = true,
|
BreakOnUserMove = true,
|
||||||
BreakOnStun = true,
|
|
||||||
BreakOnDamage = true,
|
BreakOnDamage = true,
|
||||||
MovementThreshold = 0.2f
|
MovementThreshold = 0.2f
|
||||||
};
|
};
|
||||||
|
|
||||||
_doAfterSystem.DoAfter(doAfterArgs, aborbantData);
|
_doAfterSystem.TryStartDoAfter(doAfterArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDoAfter(EntityUid uid, AbsorbentComponent component, DoAfterEvent<AbsorbantData> args)
|
private void OnDoAfter(EntityUid uid, AbsorbentComponent component, AbsorbantDoAfterEvent args)
|
||||||
{
|
{
|
||||||
if (args.Args.Target == null)
|
if (args.Target == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (args.Cancelled)
|
component.InteractingEntities.Remove(args.Target.Value);
|
||||||
{
|
|
||||||
//Remove the interacting entities or else it breaks the mop
|
|
||||||
component.InteractingEntities.Remove(args.Args.Target.Value);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args.Handled)
|
if (args.Cancelled || args.Handled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_audio.PlayPvs(args.AdditionalData.Sound, uid);
|
_audio.PlayPvs(args.Sound, uid);
|
||||||
_popups.PopupEntity(Loc.GetString(args.AdditionalData.Message, ("target", args.Args.Target.Value), ("used", uid)), uid);
|
_popups.PopupEntity(Loc.GetString(args.Message, ("target", args.Target.Value), ("used", uid)), uid);
|
||||||
_solutionSystem.TryTransferSolution(args.Args.Target.Value, uid, args.AdditionalData.TargetSolution,
|
_solutionSystem.TryTransferSolution(args.Target.Value, uid, args.TargetSolution,
|
||||||
AbsorbentComponent.SolutionName, args.AdditionalData.TransferAmount);
|
AbsorbentComponent.SolutionName, args.TransferAmount);
|
||||||
component.InteractingEntities.Remove(args.Args.Target.Value);
|
component.InteractingEntities.Remove(args.Target.Value);
|
||||||
|
|
||||||
args.Handled = true;
|
args.Handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private record struct AbsorbantData(string TargetSolution, string Message, SoundSpecifier Sound, FixedPoint2 TransferAmount)
|
|
||||||
{
|
|
||||||
public readonly string TargetSolution = TargetSolution;
|
|
||||||
public readonly string Message = Message;
|
|
||||||
public readonly SoundSpecifier Sound = Sound;
|
|
||||||
public readonly FixedPoint2 TransferAmount = TransferAmount;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
using Content.Server.Administration.Logs;
|
using Content.Server.Administration.Logs;
|
||||||
using Content.Server.Chemistry.EntitySystems;
|
using Content.Server.Chemistry.EntitySystems;
|
||||||
using Content.Server.DoAfter;
|
|
||||||
using Content.Server.Fluids.Components;
|
using Content.Server.Fluids.Components;
|
||||||
using Content.Server.Nutrition.Components;
|
using Content.Server.Nutrition.Components;
|
||||||
using Content.Shared.Chemistry.Components;
|
using Content.Shared.Chemistry.Components;
|
||||||
@@ -17,6 +16,7 @@ using Robust.Shared.Prototypes;
|
|||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Shared.DoAfter;
|
using Content.Shared.DoAfter;
|
||||||
|
using Content.Shared.Spillable;
|
||||||
|
|
||||||
namespace Content.Server.Fluids.EntitySystems;
|
namespace Content.Server.Fluids.EntitySystems;
|
||||||
|
|
||||||
@@ -29,7 +29,7 @@ public sealed class SpillableSystem : EntitySystem
|
|||||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||||
[Dependency] private readonly EntityLookupSystem _entityLookup = default!;
|
[Dependency] private readonly EntityLookupSystem _entityLookup = default!;
|
||||||
[Dependency] private readonly IAdminLogManager _adminLogger= default!;
|
[Dependency] private readonly IAdminLogManager _adminLogger= default!;
|
||||||
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
@@ -38,7 +38,7 @@ public sealed class SpillableSystem : EntitySystem
|
|||||||
SubscribeLocalEvent<SpillableComponent, GetVerbsEvent<Verb>>(AddSpillVerb);
|
SubscribeLocalEvent<SpillableComponent, GetVerbsEvent<Verb>>(AddSpillVerb);
|
||||||
SubscribeLocalEvent<SpillableComponent, GotEquippedEvent>(OnGotEquipped);
|
SubscribeLocalEvent<SpillableComponent, GotEquippedEvent>(OnGotEquipped);
|
||||||
SubscribeLocalEvent<SpillableComponent, SolutionSpikeOverflowEvent>(OnSpikeOverflow);
|
SubscribeLocalEvent<SpillableComponent, SolutionSpikeOverflowEvent>(OnSpikeOverflow);
|
||||||
SubscribeLocalEvent<SpillableComponent, DoAfterEvent>(OnDoAfter);
|
SubscribeLocalEvent<SpillableComponent, SpillDoAfterEvent>(OnDoAfter);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnSpikeOverflow(EntityUid uid, SpillableComponent component, SolutionSpikeOverflowEvent args)
|
private void OnSpikeOverflow(EntityUid uid, SpillableComponent component, SolutionSpikeOverflowEvent args)
|
||||||
@@ -128,29 +128,17 @@ public sealed class SpillableSystem : EntitySystem
|
|||||||
Verb verb = new();
|
Verb verb = new();
|
||||||
verb.Text = Loc.GetString("spill-target-verb-get-data-text");
|
verb.Text = Loc.GetString("spill-target-verb-get-data-text");
|
||||||
// TODO VERB ICONS spill icon? pouring out a glass/beaker?
|
// TODO VERB ICONS spill icon? pouring out a glass/beaker?
|
||||||
if (component.SpillDelay == null)
|
|
||||||
{
|
|
||||||
verb.Act = () =>
|
verb.Act = () =>
|
||||||
{
|
{
|
||||||
var puddleSolution = _solutionContainerSystem.SplitSolution(args.Target,
|
_doAfterSystem.TryStartDoAfter(new DoAfterArgs(args.User, component.SpillDelay ?? 0, new SpillDoAfterEvent(), uid, target: uid)
|
||||||
solution, solution.Volume);
|
|
||||||
SpillAt(puddleSolution, Transform(args.Target).Coordinates, "PuddleSmear");
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
verb.Act = () =>
|
|
||||||
{
|
|
||||||
_doAfterSystem.DoAfter(new DoAfterEventArgs(args.User, component.SpillDelay.Value, target:uid)
|
|
||||||
{
|
{
|
||||||
BreakOnTargetMove = true,
|
BreakOnTargetMove = true,
|
||||||
BreakOnUserMove = true,
|
BreakOnUserMove = true,
|
||||||
BreakOnDamage = true,
|
BreakOnDamage = true,
|
||||||
BreakOnStun = true,
|
NeedHand = true,
|
||||||
NeedHand = true
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
|
||||||
verb.Impact = LogImpact.Medium; // dangerous reagent reaction are logged separately.
|
verb.Impact = LogImpact.Medium; // dangerous reagent reaction are logged separately.
|
||||||
verb.DoContactInteraction = true;
|
verb.DoContactInteraction = true;
|
||||||
args.Verbs.Add(verb);
|
args.Verbs.Add(verb);
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
using Content.Shared.Examine;
|
using Content.Shared.Examine;
|
||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
using Content.Shared.Inventory;
|
using Content.Shared.Inventory;
|
||||||
using Content.Server.DoAfter;
|
|
||||||
using Content.Server.Popups;
|
using Content.Server.Popups;
|
||||||
using Content.Shared.DoAfter;
|
using Content.Shared.DoAfter;
|
||||||
|
using Content.Shared.Forensics;
|
||||||
using Content.Shared.IdentityManagement;
|
using Content.Shared.IdentityManagement;
|
||||||
using Robust.Shared.Serialization;
|
|
||||||
|
|
||||||
namespace Content.Server.Forensics
|
namespace Content.Server.Forensics
|
||||||
{
|
{
|
||||||
@@ -14,7 +13,7 @@ namespace Content.Server.Forensics
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class ForensicPadSystem : EntitySystem
|
public sealed class ForensicPadSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
|
||||||
[Dependency] private readonly InventorySystem _inventory = default!;
|
[Dependency] private readonly InventorySystem _inventory = default!;
|
||||||
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
||||||
|
|
||||||
@@ -23,7 +22,7 @@ namespace Content.Server.Forensics
|
|||||||
base.Initialize();
|
base.Initialize();
|
||||||
SubscribeLocalEvent<ForensicPadComponent, ExaminedEvent>(OnExamined);
|
SubscribeLocalEvent<ForensicPadComponent, ExaminedEvent>(OnExamined);
|
||||||
SubscribeLocalEvent<ForensicPadComponent, AfterInteractEvent>(OnAfterInteract);
|
SubscribeLocalEvent<ForensicPadComponent, AfterInteractEvent>(OnAfterInteract);
|
||||||
SubscribeLocalEvent<ForensicPadComponent, DoAfterEvent<ForensicPadData>>(OnDoAfter);
|
SubscribeLocalEvent<ForensicPadComponent, ForensicPadDoAfterEvent>(OnDoAfter);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnExamined(EntityUid uid, ForensicPadComponent component, ExaminedEvent args)
|
private void OnExamined(EntityUid uid, ForensicPadComponent component, ExaminedEvent args)
|
||||||
@@ -79,25 +78,21 @@ namespace Content.Server.Forensics
|
|||||||
|
|
||||||
private void StartScan(EntityUid used, EntityUid user, EntityUid target, ForensicPadComponent pad, string sample)
|
private void StartScan(EntityUid used, EntityUid user, EntityUid target, ForensicPadComponent pad, string sample)
|
||||||
{
|
{
|
||||||
var padData = new ForensicPadData(sample);
|
var ev = new ForensicPadDoAfterEvent(sample);
|
||||||
|
|
||||||
var doAfterEventArgs = new DoAfterEventArgs(user, pad.ScanDelay, target: target, used: used)
|
var doAfterEventArgs = new DoAfterArgs(user, pad.ScanDelay, ev, used, target: target, used: used)
|
||||||
{
|
{
|
||||||
BreakOnTargetMove = true,
|
BreakOnTargetMove = true,
|
||||||
BreakOnUserMove = true,
|
BreakOnUserMove = true,
|
||||||
BreakOnStun = true,
|
NeedHand = true
|
||||||
NeedHand = true,
|
|
||||||
RaiseOnUser = false
|
|
||||||
};
|
};
|
||||||
|
|
||||||
_doAfterSystem.DoAfter(doAfterEventArgs, padData);
|
_doAfterSystem.TryStartDoAfter(doAfterEventArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDoAfter(EntityUid uid, ForensicPadComponent component, DoAfterEvent<ForensicPadData> args)
|
private void OnDoAfter(EntityUid uid, ForensicPadComponent padComponent, ForensicPadDoAfterEvent args)
|
||||||
{
|
{
|
||||||
if (args.Handled
|
if (args.Handled || args.Cancelled)
|
||||||
|| args.Cancelled
|
|
||||||
|| !EntityManager.TryGetComponent(args.Args.Used, out ForensicPadComponent? padComponent))
|
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -110,20 +105,10 @@ namespace Content.Server.Forensics
|
|||||||
MetaData(uid).EntityName = Loc.GetString("forensic-pad-gloves-name", ("entity", args.Args.Target));
|
MetaData(uid).EntityName = Loc.GetString("forensic-pad-gloves-name", ("entity", args.Args.Target));
|
||||||
}
|
}
|
||||||
|
|
||||||
padComponent.Sample = args.AdditionalData.Sample;
|
padComponent.Sample = args.Sample;
|
||||||
padComponent.Used = true;
|
padComponent.Used = true;
|
||||||
|
|
||||||
args.Handled = true;
|
args.Handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private sealed class ForensicPadData
|
|
||||||
{
|
|
||||||
public string Sample;
|
|
||||||
|
|
||||||
public ForensicPadData(string sample)
|
|
||||||
{
|
|
||||||
Sample = sample;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ using System.Text; // todo: remove this stinky LINQy
|
|||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
using Robust.Shared.Timing;
|
using Robust.Shared.Timing;
|
||||||
using Content.Server.DoAfter;
|
|
||||||
using Content.Server.Paper;
|
using Content.Server.Paper;
|
||||||
using Content.Server.Popups;
|
using Content.Server.Popups;
|
||||||
using Content.Server.UserInterface;
|
using Content.Server.UserInterface;
|
||||||
@@ -18,7 +17,7 @@ namespace Content.Server.Forensics
|
|||||||
public sealed class ForensicScannerSystem : EntitySystem
|
public sealed class ForensicScannerSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||||
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
|
||||||
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
|
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
|
||||||
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
||||||
[Dependency] private readonly PaperSystem _paperSystem = default!;
|
[Dependency] private readonly PaperSystem _paperSystem = default!;
|
||||||
@@ -39,7 +38,7 @@ namespace Content.Server.Forensics
|
|||||||
SubscribeLocalEvent<ForensicScannerComponent, GetVerbsEvent<UtilityVerb>>(OnUtilityVerb);
|
SubscribeLocalEvent<ForensicScannerComponent, GetVerbsEvent<UtilityVerb>>(OnUtilityVerb);
|
||||||
SubscribeLocalEvent<ForensicScannerComponent, ForensicScannerPrintMessage>(OnPrint);
|
SubscribeLocalEvent<ForensicScannerComponent, ForensicScannerPrintMessage>(OnPrint);
|
||||||
SubscribeLocalEvent<ForensicScannerComponent, ForensicScannerClearMessage>(OnClear);
|
SubscribeLocalEvent<ForensicScannerComponent, ForensicScannerClearMessage>(OnClear);
|
||||||
SubscribeLocalEvent<ForensicScannerComponent, DoAfterEvent>(OnDoAfter);
|
SubscribeLocalEvent<ForensicScannerComponent, ForensicScannerDoAfterEvent>(OnDoAfter);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateUserInterface(EntityUid uid, ForensicScannerComponent component)
|
private void UpdateUserInterface(EntityUid uid, ForensicScannerComponent component)
|
||||||
@@ -91,11 +90,10 @@ namespace Content.Server.Forensics
|
|||||||
/// </remarks>
|
/// </remarks>
|
||||||
private void StartScan(EntityUid uid, ForensicScannerComponent component, EntityUid user, EntityUid target)
|
private void StartScan(EntityUid uid, ForensicScannerComponent component, EntityUid user, EntityUid target)
|
||||||
{
|
{
|
||||||
_doAfterSystem.DoAfter(new DoAfterEventArgs(user, component.ScanDelay, target: target, used: uid)
|
_doAfterSystem.TryStartDoAfter(new DoAfterArgs(user, component.ScanDelay, new ForensicScannerDoAfterEvent(), uid, target: target, used: uid)
|
||||||
{
|
{
|
||||||
BreakOnTargetMove = true,
|
BreakOnTargetMove = true,
|
||||||
BreakOnUserMove = true,
|
BreakOnUserMove = true,
|
||||||
BreakOnStun = true,
|
|
||||||
NeedHand = true
|
NeedHand = true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ namespace Content.Server.Gatherable.Components
|
|||||||
public int MaxGatheringEntities = 1;
|
public int MaxGatheringEntities = 1;
|
||||||
|
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
|
[DataField("gatheringEntities")]
|
||||||
public readonly List<EntityUid> GatheringEntities = new();
|
public readonly List<EntityUid> GatheringEntities = new();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,8 @@
|
|||||||
using System.Threading;
|
|
||||||
using Content.Server.Destructible;
|
using Content.Server.Destructible;
|
||||||
using Content.Server.DoAfter;
|
|
||||||
using Content.Server.Gatherable.Components;
|
using Content.Server.Gatherable.Components;
|
||||||
using Content.Shared.Damage;
|
|
||||||
using Content.Shared.DoAfter;
|
using Content.Shared.DoAfter;
|
||||||
using Content.Shared.Destructible;
|
|
||||||
using Content.Shared.EntityList;
|
using Content.Shared.EntityList;
|
||||||
|
using Content.Shared.Gatherable;
|
||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
using Content.Shared.Tag;
|
using Content.Shared.Tag;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
@@ -17,9 +14,8 @@ public sealed class GatherableSystem : EntitySystem
|
|||||||
{
|
{
|
||||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||||
[Dependency] private readonly IRobustRandom _random = default!;
|
[Dependency] private readonly IRobustRandom _random = default!;
|
||||||
[Dependency] private readonly DamageableSystem _damageableSystem = default!;
|
|
||||||
[Dependency] private readonly DestructibleSystem _destructible = default!;
|
[Dependency] private readonly DestructibleSystem _destructible = default!;
|
||||||
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
|
||||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||||
[Dependency] private readonly TagSystem _tagSystem = default!;
|
[Dependency] private readonly TagSystem _tagSystem = default!;
|
||||||
|
|
||||||
@@ -28,7 +24,7 @@ public sealed class GatherableSystem : EntitySystem
|
|||||||
base.Initialize();
|
base.Initialize();
|
||||||
|
|
||||||
SubscribeLocalEvent<GatherableComponent, InteractUsingEvent>(OnInteractUsing);
|
SubscribeLocalEvent<GatherableComponent, InteractUsingEvent>(OnInteractUsing);
|
||||||
SubscribeLocalEvent<GatherableComponent, DoAfterEvent>(OnDoAfter);
|
SubscribeLocalEvent<GatherableComponent, GatherableDoAfterEvent>(OnDoAfter);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnInteractUsing(EntityUid uid, GatherableComponent component, InteractUsingEvent args)
|
private void OnInteractUsing(EntityUid uid, GatherableComponent component, InteractUsingEvent args)
|
||||||
@@ -44,33 +40,29 @@ public sealed class GatherableSystem : EntitySystem
|
|||||||
var damageTime = (damageRequired / tool.Damage.Total).Float();
|
var damageTime = (damageRequired / tool.Damage.Total).Float();
|
||||||
damageTime = Math.Max(1f, damageTime);
|
damageTime = Math.Max(1f, damageTime);
|
||||||
|
|
||||||
var doAfter = new DoAfterEventArgs(args.User, damageTime, target: uid, used: args.Used)
|
var doAfter = new DoAfterArgs(args.User, damageTime, new GatherableDoAfterEvent(), uid, target: uid, used: args.Used)
|
||||||
{
|
{
|
||||||
BreakOnDamage = true,
|
BreakOnDamage = true,
|
||||||
BreakOnStun = true,
|
|
||||||
BreakOnTargetMove = true,
|
BreakOnTargetMove = true,
|
||||||
BreakOnUserMove = true,
|
BreakOnUserMove = true,
|
||||||
MovementThreshold = 0.25f,
|
MovementThreshold = 0.25f,
|
||||||
};
|
};
|
||||||
|
|
||||||
_doAfterSystem.DoAfter(doAfter);
|
_doAfterSystem.TryStartDoAfter(doAfter);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDoAfter(EntityUid uid, GatherableComponent component, DoAfterEvent args)
|
private void OnDoAfter(EntityUid uid, GatherableComponent component, GatherableDoAfterEvent args)
|
||||||
{
|
{
|
||||||
if(!TryComp<GatheringToolComponent>(args.Args.Used, out var tool) || args.Args.Target == null)
|
if(!TryComp<GatheringToolComponent>(args.Args.Used, out var tool) || args.Args.Target == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (args.Handled || args.Cancelled)
|
|
||||||
{
|
|
||||||
tool.GatheringEntities.Remove(args.Args.Target.Value);
|
tool.GatheringEntities.Remove(args.Args.Target.Value);
|
||||||
|
if (args.Handled || args.Cancelled)
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
// Complete the gathering process
|
// Complete the gathering process
|
||||||
_destructible.DestroyEntity(args.Args.Target.Value);
|
_destructible.DestroyEntity(args.Args.Target.Value);
|
||||||
_audio.PlayPvs(tool.GatheringSound, args.Args.Target.Value);
|
_audio.PlayPvs(tool.GatheringSound, args.Args.Target.Value);
|
||||||
tool.GatheringEntities.Remove(args.Args.Target.Value);
|
|
||||||
|
|
||||||
// Spawn the loot!
|
// Spawn the loot!
|
||||||
if (component.MappedLoot == null)
|
if (component.MappedLoot == null)
|
||||||
|
|||||||
@@ -28,7 +28,5 @@ namespace Content.Server.Guardian
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("delay")]
|
[DataField("delay")]
|
||||||
public float InjectionDelay = 5f;
|
public float InjectionDelay = 5f;
|
||||||
|
|
||||||
public bool Injecting = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
using Content.Server.DoAfter;
|
|
||||||
using Content.Server.Popups;
|
using Content.Server.Popups;
|
||||||
using Content.Shared.Actions;
|
using Content.Shared.Actions;
|
||||||
using Content.Shared.Audio;
|
using Content.Shared.Audio;
|
||||||
using Content.Shared.Damage;
|
using Content.Shared.Damage;
|
||||||
using Content.Shared.DoAfter;
|
using Content.Shared.DoAfter;
|
||||||
using Content.Shared.Examine;
|
using Content.Shared.Examine;
|
||||||
|
using Content.Shared.Guardian;
|
||||||
using Content.Shared.Hands.EntitySystems;
|
using Content.Shared.Hands.EntitySystems;
|
||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
using Content.Shared.Interaction.Events;
|
using Content.Shared.Interaction.Events;
|
||||||
@@ -22,7 +22,7 @@ namespace Content.Server.Guardian
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class GuardianSystem : EntitySystem
|
public sealed class GuardianSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
|
||||||
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
||||||
[Dependency] private readonly DamageableSystem _damageSystem = default!;
|
[Dependency] private readonly DamageableSystem _damageSystem = default!;
|
||||||
[Dependency] private readonly SharedActionsSystem _actionSystem = default!;
|
[Dependency] private readonly SharedActionsSystem _actionSystem = default!;
|
||||||
@@ -35,7 +35,7 @@ namespace Content.Server.Guardian
|
|||||||
SubscribeLocalEvent<GuardianCreatorComponent, UseInHandEvent>(OnCreatorUse);
|
SubscribeLocalEvent<GuardianCreatorComponent, UseInHandEvent>(OnCreatorUse);
|
||||||
SubscribeLocalEvent<GuardianCreatorComponent, AfterInteractEvent>(OnCreatorInteract);
|
SubscribeLocalEvent<GuardianCreatorComponent, AfterInteractEvent>(OnCreatorInteract);
|
||||||
SubscribeLocalEvent<GuardianCreatorComponent, ExaminedEvent>(OnCreatorExamine);
|
SubscribeLocalEvent<GuardianCreatorComponent, ExaminedEvent>(OnCreatorExamine);
|
||||||
SubscribeLocalEvent<GuardianCreatorComponent, DoAfterEvent>(OnDoAfter);
|
SubscribeLocalEvent<GuardianCreatorComponent, GuardianCreatorDoAfterEvent>(OnDoAfter);
|
||||||
|
|
||||||
SubscribeLocalEvent<GuardianComponent, MoveEvent>(OnGuardianMove);
|
SubscribeLocalEvent<GuardianComponent, MoveEvent>(OnGuardianMove);
|
||||||
SubscribeLocalEvent<GuardianComponent, DamageChangedEvent>(OnGuardianDamaged);
|
SubscribeLocalEvent<GuardianComponent, DamageChangedEvent>(OnGuardianDamaged);
|
||||||
@@ -161,12 +161,7 @@ namespace Content.Server.Guardian
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (component.Injecting)
|
_doAfterSystem.TryStartDoAfter(new DoAfterArgs(user, component.InjectionDelay, new GuardianCreatorDoAfterEvent(), injector, target: target, used: injector)
|
||||||
return;
|
|
||||||
|
|
||||||
component.Injecting = true;
|
|
||||||
|
|
||||||
_doAfterSystem.DoAfter(new DoAfterEventArgs(user, component.InjectionDelay, target: target, used: injector)
|
|
||||||
{
|
{
|
||||||
BreakOnTargetMove = true,
|
BreakOnTargetMove = true,
|
||||||
BreakOnUserMove = true
|
BreakOnUserMove = true
|
||||||
@@ -179,10 +174,7 @@ namespace Content.Server.Guardian
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (args.Cancelled || component.Deleted || component.Used || !_handsSystem.IsHolding(args.Args.User, uid, out _) || HasComp<GuardianHostComponent>(args.Args.Target))
|
if (args.Cancelled || component.Deleted || component.Used || !_handsSystem.IsHolding(args.Args.User, uid, out _) || HasComp<GuardianHostComponent>(args.Args.Target))
|
||||||
{
|
|
||||||
component.Injecting = false;
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
var hostXform = Transform(args.Args.Target.Value);
|
var hostXform = Transform(args.Args.Target.Value);
|
||||||
var host = EnsureComp<GuardianHostComponent>(args.Args.Target.Value);
|
var host = EnsureComp<GuardianHostComponent>(args.Args.Target.Value);
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
using System.Threading;
|
|
||||||
using Content.Server.DoAfter;
|
|
||||||
using Content.Server.Guardian;
|
using Content.Server.Guardian;
|
||||||
using Content.Server.Popups;
|
using Content.Server.Popups;
|
||||||
using Content.Shared.DoAfter;
|
using Content.Shared.DoAfter;
|
||||||
using Content.Shared.Hands;
|
|
||||||
using Content.Shared.IdentityManagement;
|
using Content.Shared.IdentityManagement;
|
||||||
using Content.Shared.Implants;
|
using Content.Shared.Implants;
|
||||||
using Content.Shared.Implants.Components;
|
using Content.Shared.Implants.Components;
|
||||||
@@ -18,7 +15,7 @@ namespace Content.Server.Implants;
|
|||||||
public sealed partial class ImplanterSystem : SharedImplanterSystem
|
public sealed partial class ImplanterSystem : SharedImplanterSystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly PopupSystem _popup = default!;
|
[Dependency] private readonly PopupSystem _popup = default!;
|
||||||
[Dependency] private readonly DoAfterSystem _doAfter = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
|
||||||
[Dependency] private readonly SharedContainerSystem _container = default!;
|
[Dependency] private readonly SharedContainerSystem _container = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
@@ -26,12 +23,11 @@ public sealed partial class ImplanterSystem : SharedImplanterSystem
|
|||||||
base.Initialize();
|
base.Initialize();
|
||||||
InitializeImplanted();
|
InitializeImplanted();
|
||||||
|
|
||||||
SubscribeLocalEvent<ImplanterComponent, HandDeselectedEvent>(OnHandDeselect);
|
|
||||||
SubscribeLocalEvent<ImplanterComponent, AfterInteractEvent>(OnImplanterAfterInteract);
|
SubscribeLocalEvent<ImplanterComponent, AfterInteractEvent>(OnImplanterAfterInteract);
|
||||||
SubscribeLocalEvent<ImplanterComponent, ComponentGetState>(OnImplanterGetState);
|
SubscribeLocalEvent<ImplanterComponent, ComponentGetState>(OnImplanterGetState);
|
||||||
|
|
||||||
SubscribeLocalEvent<ImplanterComponent, DoAfterEvent<ImplantEvent>>(OnImplant);
|
SubscribeLocalEvent<ImplanterComponent, ImplantEvent>(OnImplant);
|
||||||
SubscribeLocalEvent<ImplanterComponent, DoAfterEvent<DrawEvent>>(OnDraw);
|
SubscribeLocalEvent<ImplanterComponent, DrawEvent>(OnDraw);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnImplanterAfterInteract(EntityUid uid, ImplanterComponent component, AfterInteractEvent args)
|
private void OnImplanterAfterInteract(EntityUid uid, ImplanterComponent component, AfterInteractEvent args)
|
||||||
@@ -62,12 +58,6 @@ public sealed partial class ImplanterSystem : SharedImplanterSystem
|
|||||||
args.Handled = true;
|
args.Handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnHandDeselect(EntityUid uid, ImplanterComponent component, HandDeselectedEvent args)
|
|
||||||
{
|
|
||||||
component.CancelToken?.Cancel();
|
|
||||||
component.CancelToken = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Attempt to implant someone else.
|
/// Attempt to implant someone else.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -77,27 +67,21 @@ public sealed partial class ImplanterSystem : SharedImplanterSystem
|
|||||||
/// <param name="implanter">The implanter being used</param>
|
/// <param name="implanter">The implanter being used</param>
|
||||||
public void TryImplant(ImplanterComponent component, EntityUid user, EntityUid target, EntityUid implanter)
|
public void TryImplant(ImplanterComponent component, EntityUid user, EntityUid target, EntityUid implanter)
|
||||||
{
|
{
|
||||||
if (component.CancelToken != null)
|
var args = new DoAfterArgs(user, component.ImplantTime, new ImplantEvent(), implanter, target: target, used: implanter)
|
||||||
|
{
|
||||||
|
BreakOnUserMove = true,
|
||||||
|
BreakOnTargetMove = true,
|
||||||
|
BreakOnDamage = true,
|
||||||
|
NeedHand = true,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!_doAfter.TryStartDoAfter(args))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_popup.PopupEntity(Loc.GetString("injector-component-injecting-user"), target, user);
|
_popup.PopupEntity(Loc.GetString("injector-component-injecting-user"), target, user);
|
||||||
|
|
||||||
var userName = Identity.Entity(user, EntityManager);
|
var userName = Identity.Entity(user, EntityManager);
|
||||||
_popup.PopupEntity(Loc.GetString("implanter-component-implanting-target", ("user", userName)), user, target, PopupType.LargeCaution);
|
_popup.PopupEntity(Loc.GetString("implanter-component-implanting-target", ("user", userName)), user, target, PopupType.LargeCaution);
|
||||||
|
|
||||||
component.CancelToken?.Cancel();
|
|
||||||
component.CancelToken = new CancellationTokenSource();
|
|
||||||
|
|
||||||
var implantEvent = new ImplantEvent();
|
|
||||||
|
|
||||||
_doAfter.DoAfter(new DoAfterEventArgs(user, component.ImplantTime, component.CancelToken.Token,target:target, used:implanter)
|
|
||||||
{
|
|
||||||
BreakOnUserMove = true,
|
|
||||||
BreakOnTargetMove = true,
|
|
||||||
BreakOnDamage = true,
|
|
||||||
BreakOnStun = true,
|
|
||||||
NeedHand = true
|
|
||||||
}, implantEvent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -110,21 +94,17 @@ public sealed partial class ImplanterSystem : SharedImplanterSystem
|
|||||||
//TODO: Remove when surgery is in
|
//TODO: Remove when surgery is in
|
||||||
public void TryDraw(ImplanterComponent component, EntityUid user, EntityUid target, EntityUid implanter)
|
public void TryDraw(ImplanterComponent component, EntityUid user, EntityUid target, EntityUid implanter)
|
||||||
{
|
{
|
||||||
_popup.PopupEntity(Loc.GetString("injector-component-injecting-user"), target, user);
|
var args = new DoAfterArgs(user, component.DrawTime, new DrawEvent(), implanter, target: target, used: implanter)
|
||||||
|
|
||||||
component.CancelToken?.Cancel();
|
|
||||||
component.CancelToken = new CancellationTokenSource();
|
|
||||||
|
|
||||||
var drawEvent = new DrawEvent();
|
|
||||||
|
|
||||||
_doAfter.DoAfter(new DoAfterEventArgs(user, component.DrawTime, target:target,used:implanter)
|
|
||||||
{
|
{
|
||||||
BreakOnUserMove = true,
|
BreakOnUserMove = true,
|
||||||
BreakOnTargetMove = true,
|
BreakOnTargetMove = true,
|
||||||
BreakOnDamage = true,
|
BreakOnDamage = true,
|
||||||
BreakOnStun = true,
|
NeedHand = true,
|
||||||
NeedHand = true
|
};
|
||||||
}, drawEvent);
|
|
||||||
|
if (_doAfter.TryStartDoAfter(args))
|
||||||
|
_popup.PopupEntity(Loc.GetString("injector-component-injecting-user"), target, user);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnImplanterGetState(EntityUid uid, ImplanterComponent component, ref ComponentGetState args)
|
private void OnImplanterGetState(EntityUid uid, ImplanterComponent component, ref ComponentGetState args)
|
||||||
@@ -132,47 +112,23 @@ public sealed partial class ImplanterSystem : SharedImplanterSystem
|
|||||||
args.State = new ImplanterComponentState(component.CurrentMode, component.ImplantOnly);
|
args.State = new ImplanterComponentState(component.CurrentMode, component.ImplantOnly);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnImplant(EntityUid uid, ImplanterComponent component, DoAfterEvent<ImplantEvent> args)
|
private void OnImplant(EntityUid uid, ImplanterComponent component, ImplantEvent args)
|
||||||
{
|
{
|
||||||
if (args.Cancelled)
|
if (args.Cancelled || args.Handled || args.Target == null || args.Used == null)
|
||||||
{
|
|
||||||
component.CancelToken = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args.Handled || args.Args.Target == null || args.Args.Used == null)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Implant(args.Args.Used.Value, args.Args.Target.Value, component);
|
Implant(args.Used.Value, args.Target.Value, component);
|
||||||
|
|
||||||
args.Handled = true;
|
args.Handled = true;
|
||||||
component.CancelToken = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDraw(EntityUid uid, ImplanterComponent component, DoAfterEvent<DrawEvent> args)
|
private void OnDraw(EntityUid uid, ImplanterComponent component, DrawEvent args)
|
||||||
{
|
{
|
||||||
if (args.Cancelled)
|
if (args.Cancelled || args.Handled || args.Used == null || args.Target == null)
|
||||||
{
|
|
||||||
component.CancelToken = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args.Handled || args.Args.Used == null || args.Args.Target == null)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Draw(args.Args.Used.Value, args.Args.User, args.Args.Target.Value, component);
|
Draw(args.Used.Value, args.User, args.Target.Value, component);
|
||||||
|
|
||||||
args.Handled = true;
|
args.Handled = true;
|
||||||
component.CancelToken = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private sealed class ImplantEvent : EntityEventArgs
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private sealed class DrawEvent : EntityEventArgs
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using Content.Server.Administration.Logs;
|
using Content.Server.Administration.Logs;
|
||||||
using Content.Server.DoAfter;
|
|
||||||
using Content.Server.Kitchen.Components;
|
using Content.Server.Kitchen.Components;
|
||||||
using Content.Server.Popups;
|
using Content.Server.Popups;
|
||||||
using Content.Shared.Database;
|
using Content.Shared.Database;
|
||||||
@@ -25,7 +24,7 @@ namespace Content.Server.Kitchen.EntitySystems
|
|||||||
public sealed class KitchenSpikeSystem : SharedKitchenSpikeSystem
|
public sealed class KitchenSpikeSystem : SharedKitchenSpikeSystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
||||||
[Dependency] private readonly DoAfterSystem _doAfter = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
|
||||||
[Dependency] private readonly IAdminLogManager _logger = default!;
|
[Dependency] private readonly IAdminLogManager _logger = default!;
|
||||||
[Dependency] private readonly MobStateSystem _mobStateSystem = default!;
|
[Dependency] private readonly MobStateSystem _mobStateSystem = default!;
|
||||||
[Dependency] private readonly IRobustRandom _random = default!;
|
[Dependency] private readonly IRobustRandom _random = default!;
|
||||||
@@ -43,7 +42,7 @@ namespace Content.Server.Kitchen.EntitySystems
|
|||||||
SubscribeLocalEvent<KitchenSpikeComponent, DragDropTargetEvent>(OnDragDrop);
|
SubscribeLocalEvent<KitchenSpikeComponent, DragDropTargetEvent>(OnDragDrop);
|
||||||
|
|
||||||
//DoAfter
|
//DoAfter
|
||||||
SubscribeLocalEvent<KitchenSpikeComponent, DoAfterEvent>(OnDoAfter);
|
SubscribeLocalEvent<KitchenSpikeComponent, SpikeDoAfterEvent>(OnDoAfter);
|
||||||
|
|
||||||
SubscribeLocalEvent<KitchenSpikeComponent, SuicideEvent>(OnSuicide);
|
SubscribeLocalEvent<KitchenSpikeComponent, SuicideEvent>(OnSuicide);
|
||||||
|
|
||||||
@@ -251,16 +250,15 @@ namespace Content.Server.Kitchen.EntitySystems
|
|||||||
butcherable.BeingButchered = true;
|
butcherable.BeingButchered = true;
|
||||||
component.InUse = true;
|
component.InUse = true;
|
||||||
|
|
||||||
var doAfterArgs = new DoAfterEventArgs(userUid, component.SpikeDelay + butcherable.ButcherDelay, target:victimUid, used:uid)
|
var doAfterArgs = new DoAfterArgs(userUid, component.SpikeDelay + butcherable.ButcherDelay, new SpikeDoAfterEvent(), uid, target: victimUid, used: uid)
|
||||||
{
|
{
|
||||||
BreakOnTargetMove = true,
|
BreakOnTargetMove = true,
|
||||||
BreakOnUserMove = true,
|
BreakOnUserMove = true,
|
||||||
BreakOnDamage = true,
|
BreakOnDamage = true,
|
||||||
BreakOnStun = true,
|
|
||||||
NeedHand = true
|
NeedHand = true
|
||||||
};
|
};
|
||||||
|
|
||||||
_doAfter.DoAfter(doAfterArgs);
|
_doAfter.TryStartDoAfter(doAfterArgs);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using Content.Server.Body.Systems;
|
using Content.Server.Body.Systems;
|
||||||
using Content.Server.DoAfter;
|
|
||||||
using Content.Server.Kitchen.Components;
|
using Content.Server.Kitchen.Components;
|
||||||
using Content.Shared.Body.Components;
|
using Content.Shared.Body.Components;
|
||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
@@ -9,6 +8,7 @@ using Content.Shared.Storage;
|
|||||||
using Content.Shared.Verbs;
|
using Content.Shared.Verbs;
|
||||||
using Content.Shared.Destructible;
|
using Content.Shared.Destructible;
|
||||||
using Content.Shared.DoAfter;
|
using Content.Shared.DoAfter;
|
||||||
|
using Content.Shared.Kitchen;
|
||||||
using Content.Shared.Mobs.Components;
|
using Content.Shared.Mobs.Components;
|
||||||
using Content.Shared.Mobs.Systems;
|
using Content.Shared.Mobs.Systems;
|
||||||
using Robust.Server.Containers;
|
using Robust.Server.Containers;
|
||||||
@@ -21,7 +21,7 @@ public sealed class SharpSystem : EntitySystem
|
|||||||
{
|
{
|
||||||
[Dependency] private readonly BodySystem _bodySystem = default!;
|
[Dependency] private readonly BodySystem _bodySystem = default!;
|
||||||
[Dependency] private readonly SharedDestructibleSystem _destructibleSystem = default!;
|
[Dependency] private readonly SharedDestructibleSystem _destructibleSystem = default!;
|
||||||
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
|
||||||
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
|
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
|
||||||
[Dependency] private readonly ContainerSystem _containerSystem = default!;
|
[Dependency] private readonly ContainerSystem _containerSystem = default!;
|
||||||
[Dependency] private readonly MobStateSystem _mobStateSystem = default!;
|
[Dependency] private readonly MobStateSystem _mobStateSystem = default!;
|
||||||
@@ -32,7 +32,7 @@ public sealed class SharpSystem : EntitySystem
|
|||||||
base.Initialize();
|
base.Initialize();
|
||||||
|
|
||||||
SubscribeLocalEvent<SharpComponent, AfterInteractEvent>(OnAfterInteract);
|
SubscribeLocalEvent<SharpComponent, AfterInteractEvent>(OnAfterInteract);
|
||||||
SubscribeLocalEvent<SharpComponent, DoAfterEvent>(OnDoAfter);
|
SubscribeLocalEvent<SharpComponent, SharpDoAfterEvent>(OnDoAfter);
|
||||||
|
|
||||||
SubscribeLocalEvent<ButcherableComponent, GetVerbsEvent<InteractionVerb>>(OnGetInteractionVerbs);
|
SubscribeLocalEvent<ButcherableComponent, GetVerbsEvent<InteractionVerb>>(OnGetInteractionVerbs);
|
||||||
}
|
}
|
||||||
@@ -63,16 +63,15 @@ public sealed class SharpSystem : EntitySystem
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
var doAfter =
|
var doAfter =
|
||||||
new DoAfterEventArgs(user, sharp.ButcherDelayModifier * butcher.ButcherDelay, target: target, used: knife)
|
new DoAfterArgs(user, sharp.ButcherDelayModifier * butcher.ButcherDelay, new SharpDoAfterEvent(), knife, target: target, used: knife)
|
||||||
{
|
{
|
||||||
BreakOnTargetMove = true,
|
BreakOnTargetMove = true,
|
||||||
BreakOnUserMove = true,
|
BreakOnUserMove = true,
|
||||||
BreakOnDamage = true,
|
BreakOnDamage = true,
|
||||||
BreakOnStun = true,
|
|
||||||
NeedHand = true
|
NeedHand = true
|
||||||
};
|
};
|
||||||
|
|
||||||
_doAfterSystem.DoAfter(doAfter);
|
_doAfterSystem.TryStartDoAfter(doAfter);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDoAfter(EntityUid uid, SharpComponent component, DoAfterEvent args)
|
private void OnDoAfter(EntityUid uid, SharpComponent component, DoAfterEvent args)
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
using Content.Server.Administration.Logs;
|
using Content.Server.Administration.Logs;
|
||||||
using Content.Server.DeviceNetwork;
|
using Content.Server.DeviceNetwork;
|
||||||
using Content.Server.DeviceNetwork.Systems;
|
using Content.Server.DeviceNetwork.Systems;
|
||||||
using Content.Server.DoAfter;
|
|
||||||
using Content.Server.Ghost;
|
using Content.Server.Ghost;
|
||||||
using Content.Server.Light.Components;
|
using Content.Server.Light.Components;
|
||||||
using Content.Server.MachineLinking.Events;
|
using Content.Server.MachineLinking.Events;
|
||||||
@@ -40,7 +39,7 @@ namespace Content.Server.Light.EntitySystems
|
|||||||
[Dependency] private readonly SharedHandsSystem _handsSystem = default!;
|
[Dependency] private readonly SharedHandsSystem _handsSystem = default!;
|
||||||
[Dependency] private readonly SignalLinkerSystem _signalSystem = default!;
|
[Dependency] private readonly SignalLinkerSystem _signalSystem = default!;
|
||||||
[Dependency] private readonly SharedContainerSystem _containerSystem = default!;
|
[Dependency] private readonly SharedContainerSystem _containerSystem = default!;
|
||||||
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
|
||||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||||
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
||||||
|
|
||||||
@@ -63,8 +62,7 @@ namespace Content.Server.Light.EntitySystems
|
|||||||
|
|
||||||
SubscribeLocalEvent<PoweredLightComponent, PowerChangedEvent>(OnPowerChanged);
|
SubscribeLocalEvent<PoweredLightComponent, PowerChangedEvent>(OnPowerChanged);
|
||||||
|
|
||||||
SubscribeLocalEvent<PoweredLightComponent, DoAfterEvent>(OnDoAfter);
|
SubscribeLocalEvent<PoweredLightComponent, PoweredLightDoAfterEvent>(OnDoAfter);
|
||||||
|
|
||||||
SubscribeLocalEvent<PoweredLightComponent, EmpPulseEvent>(OnEmpPulse);
|
SubscribeLocalEvent<PoweredLightComponent, EmpPulseEvent>(OnEmpPulse);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,11 +138,10 @@ namespace Content.Server.Light.EntitySystems
|
|||||||
}
|
}
|
||||||
|
|
||||||
// removing a working bulb, so require a delay
|
// removing a working bulb, so require a delay
|
||||||
_doAfterSystem.DoAfter(new DoAfterEventArgs(userUid, light.EjectBulbDelay, target:uid)
|
_doAfterSystem.TryStartDoAfter(new DoAfterArgs(userUid, light.EjectBulbDelay, new PoweredLightDoAfterEvent(), uid, target: uid)
|
||||||
{
|
{
|
||||||
BreakOnUserMove = true,
|
BreakOnUserMove = true,
|
||||||
BreakOnDamage = true,
|
BreakOnDamage = true,
|
||||||
BreakOnStun = true
|
|
||||||
});
|
});
|
||||||
|
|
||||||
args.Handled = true;
|
args.Handled = true;
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
using System.Threading;
|
|
||||||
using Content.Server.Body.Components;
|
using Content.Server.Body.Components;
|
||||||
using Content.Server.Body.Systems;
|
using Content.Server.Body.Systems;
|
||||||
using Content.Server.Coordinates.Helpers;
|
using Content.Server.Coordinates.Helpers;
|
||||||
using Content.Server.DoAfter;
|
|
||||||
using Content.Server.Doors.Systems;
|
using Content.Server.Doors.Systems;
|
||||||
using Content.Server.Magic.Events;
|
using Content.Server.Magic.Events;
|
||||||
using Content.Server.Weapons.Ranged.Systems;
|
using Content.Server.Weapons.Ranged.Systems;
|
||||||
@@ -13,6 +11,7 @@ using Content.Shared.DoAfter;
|
|||||||
using Content.Shared.Doors.Components;
|
using Content.Shared.Doors.Components;
|
||||||
using Content.Shared.Doors.Systems;
|
using Content.Shared.Doors.Systems;
|
||||||
using Content.Shared.Interaction.Events;
|
using Content.Shared.Interaction.Events;
|
||||||
|
using Content.Shared.Magic;
|
||||||
using Content.Shared.Maps;
|
using Content.Shared.Maps;
|
||||||
using Content.Shared.Physics;
|
using Content.Shared.Physics;
|
||||||
using Content.Shared.Spawners.Components;
|
using Content.Shared.Spawners.Components;
|
||||||
@@ -42,7 +41,7 @@ public sealed class MagicSystem : EntitySystem
|
|||||||
[Dependency] private readonly EntityLookupSystem _lookup = default!;
|
[Dependency] private readonly EntityLookupSystem _lookup = default!;
|
||||||
[Dependency] private readonly SharedDoorSystem _doorSystem = default!;
|
[Dependency] private readonly SharedDoorSystem _doorSystem = default!;
|
||||||
[Dependency] private readonly SharedActionsSystem _actionsSystem = default!;
|
[Dependency] private readonly SharedActionsSystem _actionsSystem = default!;
|
||||||
[Dependency] private readonly DoAfterSystem _doAfter = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
|
||||||
[Dependency] private readonly GunSystem _gunSystem = default!;
|
[Dependency] private readonly GunSystem _gunSystem = default!;
|
||||||
[Dependency] private readonly PhysicsSystem _physics = default!;
|
[Dependency] private readonly PhysicsSystem _physics = default!;
|
||||||
[Dependency] private readonly SharedTransformSystem _transformSystem = default!;
|
[Dependency] private readonly SharedTransformSystem _transformSystem = default!;
|
||||||
@@ -54,7 +53,7 @@ public sealed class MagicSystem : EntitySystem
|
|||||||
|
|
||||||
SubscribeLocalEvent<SpellbookComponent, ComponentInit>(OnInit);
|
SubscribeLocalEvent<SpellbookComponent, ComponentInit>(OnInit);
|
||||||
SubscribeLocalEvent<SpellbookComponent, UseInHandEvent>(OnUse);
|
SubscribeLocalEvent<SpellbookComponent, UseInHandEvent>(OnUse);
|
||||||
SubscribeLocalEvent<SpellbookComponent, DoAfterEvent>(OnDoAfter);
|
SubscribeLocalEvent<SpellbookComponent, SpellbookDoAfterEvent>(OnDoAfter);
|
||||||
|
|
||||||
SubscribeLocalEvent<InstantSpawnSpellEvent>(OnInstantSpawn);
|
SubscribeLocalEvent<InstantSpawnSpellEvent>(OnInstantSpawn);
|
||||||
SubscribeLocalEvent<TeleportSpellEvent>(OnTeleportSpell);
|
SubscribeLocalEvent<TeleportSpellEvent>(OnTeleportSpell);
|
||||||
@@ -111,16 +110,15 @@ public sealed class MagicSystem : EntitySystem
|
|||||||
|
|
||||||
private void AttemptLearn(EntityUid uid, SpellbookComponent component, UseInHandEvent args)
|
private void AttemptLearn(EntityUid uid, SpellbookComponent component, UseInHandEvent args)
|
||||||
{
|
{
|
||||||
var doAfterEventArgs = new DoAfterEventArgs(args.User, component.LearnTime, target:uid)
|
var doAfterEventArgs = new DoAfterArgs(args.User, component.LearnTime, new SpellbookDoAfterEvent(), uid, target: uid)
|
||||||
{
|
{
|
||||||
BreakOnTargetMove = true,
|
BreakOnTargetMove = true,
|
||||||
BreakOnUserMove = true,
|
BreakOnUserMove = true,
|
||||||
BreakOnDamage = true,
|
BreakOnDamage = true,
|
||||||
BreakOnStun = true,
|
|
||||||
NeedHand = true //What, are you going to read with your eyes only??
|
NeedHand = true //What, are you going to read with your eyes only??
|
||||||
};
|
};
|
||||||
|
|
||||||
_doAfter.DoAfter(doAfterEventArgs);
|
_doAfter.TryStartDoAfter(doAfterEventArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Spells
|
#region Spells
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Server.DoAfter;
|
|
||||||
using Content.Server.Interaction;
|
using Content.Server.Interaction;
|
||||||
using Content.Server.Mech.Components;
|
using Content.Server.Mech.Components;
|
||||||
using Content.Server.Mech.Equipment.Components;
|
using Content.Server.Mech.Equipment.Components;
|
||||||
using Content.Server.Mech.Systems;
|
using Content.Server.Mech.Systems;
|
||||||
using Content.Shared.DoAfter;
|
using Content.Shared.DoAfter;
|
||||||
using Content.Shared.Construction.Components;
|
|
||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
using Content.Shared.Mech;
|
using Content.Shared.Mech;
|
||||||
using Content.Shared.Mech.Equipment.Components;
|
using Content.Shared.Mech.Equipment.Components;
|
||||||
@@ -26,7 +24,7 @@ public sealed class MechGrabberSystem : EntitySystem
|
|||||||
{
|
{
|
||||||
[Dependency] private readonly SharedContainerSystem _container = default!;
|
[Dependency] private readonly SharedContainerSystem _container = default!;
|
||||||
[Dependency] private readonly MechSystem _mech = default!;
|
[Dependency] private readonly MechSystem _mech = default!;
|
||||||
[Dependency] private readonly DoAfterSystem _doAfter = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
|
||||||
[Dependency] private readonly InteractionSystem _interaction = default!;
|
[Dependency] private readonly InteractionSystem _interaction = default!;
|
||||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||||
[Dependency] private readonly TransformSystem _transform = default!;
|
[Dependency] private readonly TransformSystem _transform = default!;
|
||||||
@@ -41,7 +39,7 @@ public sealed class MechGrabberSystem : EntitySystem
|
|||||||
SubscribeLocalEvent<MechGrabberComponent, AttemptRemoveMechEquipmentEvent>(OnAttemptRemove);
|
SubscribeLocalEvent<MechGrabberComponent, AttemptRemoveMechEquipmentEvent>(OnAttemptRemove);
|
||||||
|
|
||||||
SubscribeLocalEvent<MechGrabberComponent, InteractNoHandEvent>(OnInteract);
|
SubscribeLocalEvent<MechGrabberComponent, InteractNoHandEvent>(OnInteract);
|
||||||
SubscribeLocalEvent<MechGrabberComponent, DoAfterEvent>(OnMechGrab);
|
SubscribeLocalEvent<MechGrabberComponent, GrabberDoAfterEvent>(OnMechGrab);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnGrabberMessage(EntityUid uid, MechGrabberComponent component, MechEquipmentUiMessageRelayEvent args)
|
private void OnGrabberMessage(EntityUid uid, MechGrabberComponent component, MechEquipmentUiMessageRelayEvent args)
|
||||||
@@ -150,7 +148,7 @@ public sealed class MechGrabberSystem : EntitySystem
|
|||||||
|
|
||||||
args.Handled = true;
|
args.Handled = true;
|
||||||
component.AudioStream = _audio.PlayPvs(component.GrabSound, uid);
|
component.AudioStream = _audio.PlayPvs(component.GrabSound, uid);
|
||||||
_doAfter.DoAfter(new DoAfterEventArgs(args.User, component.GrabDelay, target:target, used:uid)
|
_doAfter.TryStartDoAfter(new DoAfterArgs(args.User, component.GrabDelay, new GrabberDoAfterEvent(), uid, target: target, used: uid)
|
||||||
{
|
{
|
||||||
BreakOnTargetMove = true,
|
BreakOnTargetMove = true,
|
||||||
BreakOnUserMove = true
|
BreakOnUserMove = true
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using Content.Server.DoAfter;
|
using Content.Server.Mech.Components;
|
||||||
using Content.Server.Mech.Components;
|
|
||||||
using Content.Server.Popups;
|
using Content.Server.Popups;
|
||||||
using Content.Shared.DoAfter;
|
using Content.Shared.DoAfter;
|
||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
@@ -13,14 +12,14 @@ namespace Content.Server.Mech.Systems;
|
|||||||
public sealed class MechEquipmentSystem : EntitySystem
|
public sealed class MechEquipmentSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly MechSystem _mech = default!;
|
[Dependency] private readonly MechSystem _mech = default!;
|
||||||
[Dependency] private readonly DoAfterSystem _doAfter = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
|
||||||
[Dependency] private readonly PopupSystem _popup = default!;
|
[Dependency] private readonly PopupSystem _popup = default!;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
SubscribeLocalEvent<MechEquipmentComponent, AfterInteractEvent>(OnUsed);
|
SubscribeLocalEvent<MechEquipmentComponent, AfterInteractEvent>(OnUsed);
|
||||||
SubscribeLocalEvent<MechEquipmentComponent, DoAfterEvent<InsertEquipmentEvent>>(OnInsertEquipment);
|
SubscribeLocalEvent<MechEquipmentComponent, InsertEquipmentEvent>(OnInsertEquipment);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnUsed(EntityUid uid, MechEquipmentComponent component, AfterInteractEvent args)
|
private void OnUsed(EntityUid uid, MechEquipmentComponent component, AfterInteractEvent args)
|
||||||
@@ -46,18 +45,16 @@ public sealed class MechEquipmentSystem : EntitySystem
|
|||||||
|
|
||||||
_popup.PopupEntity(Loc.GetString("mech-equipment-begin-install", ("item", uid)), mech);
|
_popup.PopupEntity(Loc.GetString("mech-equipment-begin-install", ("item", uid)), mech);
|
||||||
|
|
||||||
var insertEquipment = new InsertEquipmentEvent();
|
var doAfterEventArgs = new DoAfterArgs(args.User, component.InstallDuration, new InsertEquipmentEvent(), uid, target: mech, used: uid)
|
||||||
var doAfterEventArgs = new DoAfterEventArgs(args.User, component.InstallDuration, target: mech, used: uid)
|
|
||||||
{
|
{
|
||||||
BreakOnStun = true,
|
|
||||||
BreakOnTargetMove = true,
|
BreakOnTargetMove = true,
|
||||||
BreakOnUserMove = true
|
BreakOnUserMove = true
|
||||||
};
|
};
|
||||||
|
|
||||||
_doAfter.DoAfter(doAfterEventArgs, insertEquipment);
|
_doAfter.TryStartDoAfter(doAfterEventArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnInsertEquipment(EntityUid uid, MechEquipmentComponent component, DoAfterEvent<InsertEquipmentEvent> args)
|
private void OnInsertEquipment(EntityUid uid, MechEquipmentComponent component, InsertEquipmentEvent args)
|
||||||
{
|
{
|
||||||
if (args.Handled || args.Cancelled || args.Args.Target == null)
|
if (args.Handled || args.Cancelled || args.Args.Target == null)
|
||||||
return;
|
return;
|
||||||
@@ -67,9 +64,4 @@ public sealed class MechEquipmentSystem : EntitySystem
|
|||||||
|
|
||||||
args.Handled = true;
|
args.Handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private sealed class InsertEquipmentEvent : EntityEventArgs
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Server.Atmos.EntitySystems;
|
using Content.Server.Atmos.EntitySystems;
|
||||||
using Content.Server.DoAfter;
|
|
||||||
using Content.Server.Mech.Components;
|
using Content.Server.Mech.Components;
|
||||||
using Content.Server.Power.Components;
|
using Content.Server.Power.Components;
|
||||||
using Content.Shared.ActionBlocker;
|
using Content.Shared.ActionBlocker;
|
||||||
@@ -27,7 +26,7 @@ public sealed class MechSystem : SharedMechSystem
|
|||||||
[Dependency] private readonly AtmosphereSystem _atmosphere = default!;
|
[Dependency] private readonly AtmosphereSystem _atmosphere = default!;
|
||||||
[Dependency] private readonly ContainerSystem _container = default!;
|
[Dependency] private readonly ContainerSystem _container = default!;
|
||||||
[Dependency] private readonly DamageableSystem _damageable = default!;
|
[Dependency] private readonly DamageableSystem _damageable = default!;
|
||||||
[Dependency] private readonly DoAfterSystem _doAfter = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
|
||||||
[Dependency] private readonly IMapManager _map = default!;
|
[Dependency] private readonly IMapManager _map = default!;
|
||||||
[Dependency] private readonly UserInterfaceSystem _ui = default!;
|
[Dependency] private readonly UserInterfaceSystem _ui = default!;
|
||||||
[Dependency] private readonly ActionBlockerSystem _actionBlocker = default!;
|
[Dependency] private readonly ActionBlockerSystem _actionBlocker = default!;
|
||||||
@@ -45,9 +44,9 @@ public sealed class MechSystem : SharedMechSystem
|
|||||||
SubscribeLocalEvent<MechComponent, MapInitEvent>(OnMapInit);
|
SubscribeLocalEvent<MechComponent, MapInitEvent>(OnMapInit);
|
||||||
SubscribeLocalEvent<MechComponent, GetVerbsEvent<AlternativeVerb>>(OnAlternativeVerb);
|
SubscribeLocalEvent<MechComponent, GetVerbsEvent<AlternativeVerb>>(OnAlternativeVerb);
|
||||||
SubscribeLocalEvent<MechComponent, MechOpenUiEvent>(OnOpenUi);
|
SubscribeLocalEvent<MechComponent, MechOpenUiEvent>(OnOpenUi);
|
||||||
SubscribeLocalEvent<MechComponent, DoAfterEvent<RemoveBatteryEvent>>(OnRemoveBattery);
|
SubscribeLocalEvent<MechComponent, RemoveBatteryEvent>(OnRemoveBattery);
|
||||||
SubscribeLocalEvent<MechComponent, DoAfterEvent<MechEntryEvent>>(OnMechEntry);
|
SubscribeLocalEvent<MechComponent, MechEntryEvent>(OnMechEntry);
|
||||||
SubscribeLocalEvent<MechComponent, DoAfterEvent<MechExitEvent>>(OnMechExit);
|
SubscribeLocalEvent<MechComponent, MechExitEvent>(OnMechExit);
|
||||||
|
|
||||||
SubscribeLocalEvent<MechComponent, DamageChangedEvent>(OnDamageChanged);
|
SubscribeLocalEvent<MechComponent, DamageChangedEvent>(OnDamageChanged);
|
||||||
SubscribeLocalEvent<MechComponent, MechEquipmentRemoveMessage>(OnRemoveEquipmentMessage);
|
SubscribeLocalEvent<MechComponent, MechEquipmentRemoveMessage>(OnRemoveEquipmentMessage);
|
||||||
@@ -84,22 +83,17 @@ public sealed class MechSystem : SharedMechSystem
|
|||||||
|
|
||||||
if (TryComp<ToolComponent>(args.Used, out var tool) && tool.Qualities.Contains("Prying") && component.BatterySlot.ContainedEntity != null)
|
if (TryComp<ToolComponent>(args.Used, out var tool) && tool.Qualities.Contains("Prying") && component.BatterySlot.ContainedEntity != null)
|
||||||
{
|
{
|
||||||
var removeBattery = new RemoveBatteryEvent();
|
var doAfterEventArgs = new DoAfterArgs(args.User, component.BatteryRemovalDelay, new RemoveBatteryEvent(), uid, target: uid, used: args.Target)
|
||||||
|
|
||||||
var doAfterEventArgs = new DoAfterEventArgs(args.User, component.BatteryRemovalDelay, target: uid, used: args.Target)
|
|
||||||
{
|
{
|
||||||
BreakOnTargetMove = true,
|
BreakOnTargetMove = true,
|
||||||
BreakOnUserMove = true,
|
BreakOnUserMove = true,
|
||||||
RaiseOnTarget = true,
|
|
||||||
RaiseOnUsed = false,
|
|
||||||
RaiseOnUser = false,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
_doAfter.DoAfter(doAfterEventArgs, removeBattery);
|
_doAfter.TryStartDoAfter(doAfterEventArgs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnRemoveBattery(EntityUid uid, MechComponent component, DoAfterEvent<RemoveBatteryEvent> args)
|
private void OnRemoveBattery(EntityUid uid, MechComponent component, RemoveBatteryEvent args)
|
||||||
{
|
{
|
||||||
if (args.Cancelled || args.Handled)
|
if (args.Cancelled || args.Handled)
|
||||||
return;
|
return;
|
||||||
@@ -166,17 +160,12 @@ public sealed class MechSystem : SharedMechSystem
|
|||||||
Text = Loc.GetString("mech-verb-enter"),
|
Text = Loc.GetString("mech-verb-enter"),
|
||||||
Act = () =>
|
Act = () =>
|
||||||
{
|
{
|
||||||
var mechEntryEvent = new MechEntryEvent();
|
var doAfterEventArgs = new DoAfterArgs(args.User, component.EntryDelay, new MechEntryEvent(), uid, target: uid)
|
||||||
var doAfterEventArgs = new DoAfterEventArgs(args.User, component.EntryDelay, target: uid)
|
|
||||||
{
|
{
|
||||||
BreakOnUserMove = true,
|
BreakOnUserMove = true,
|
||||||
BreakOnStun = true,
|
|
||||||
RaiseOnTarget = true,
|
|
||||||
RaiseOnUsed = false,
|
|
||||||
RaiseOnUser = false,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
_doAfter.DoAfter(doAfterEventArgs, mechEntryEvent);
|
_doAfter.TryStartDoAfter(doAfterEventArgs);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
var openUiVerb = new AlternativeVerb //can't hijack someone else's mech
|
var openUiVerb = new AlternativeVerb //can't hijack someone else's mech
|
||||||
@@ -201,25 +190,20 @@ public sealed class MechSystem : SharedMechSystem
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var mechExitEvent = new MechExitEvent();
|
var doAfterEventArgs = new DoAfterArgs(args.User, component.ExitDelay, new MechExitEvent(), uid, target: uid)
|
||||||
var doAfterEventArgs = new DoAfterEventArgs(args.User, component.ExitDelay, target: uid)
|
|
||||||
{
|
{
|
||||||
BreakOnUserMove = true,
|
BreakOnUserMove = true,
|
||||||
BreakOnTargetMove = true,
|
BreakOnTargetMove = true,
|
||||||
BreakOnStun = true,
|
|
||||||
RaiseOnTarget = true,
|
|
||||||
RaiseOnUsed = false,
|
|
||||||
RaiseOnUser = false,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
_doAfter.DoAfter(doAfterEventArgs, mechExitEvent);
|
_doAfter.TryStartDoAfter(doAfterEventArgs);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
args.Verbs.Add(ejectVerb);
|
args.Verbs.Add(ejectVerb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnMechEntry(EntityUid uid, MechComponent component, DoAfterEvent<MechEntryEvent> args)
|
private void OnMechEntry(EntityUid uid, MechComponent component, MechEntryEvent args)
|
||||||
{
|
{
|
||||||
if (args.Cancelled || args.Handled)
|
if (args.Cancelled || args.Handled)
|
||||||
return;
|
return;
|
||||||
@@ -230,7 +214,7 @@ public sealed class MechSystem : SharedMechSystem
|
|||||||
args.Handled = true;
|
args.Handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnMechExit(EntityUid uid, MechComponent component, DoAfterEvent<MechExitEvent> args)
|
private void OnMechExit(EntityUid uid, MechComponent component, MechExitEvent args)
|
||||||
{
|
{
|
||||||
if (args.Cancelled || args.Handled)
|
if (args.Cancelled || args.Handled)
|
||||||
return;
|
return;
|
||||||
@@ -454,27 +438,4 @@ public sealed class MechSystem : SharedMechSystem
|
|||||||
args.Handled = true;
|
args.Handled = true;
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Event raised when the battery is successfully removed from the mech,
|
|
||||||
/// on both success and failure
|
|
||||||
/// </summary>
|
|
||||||
private sealed class RemoveBatteryEvent : EntityEventArgs
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Event raised when a person enters a mech, on both success and failure
|
|
||||||
/// </summary>
|
|
||||||
private sealed class MechEntryEvent : EntityEventArgs
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Event raised when a person removes someone from a mech,
|
|
||||||
/// on both success and failure
|
|
||||||
/// </summary>
|
|
||||||
private sealed class MechExitEvent : EntityEventArgs
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
using System.Threading;
|
|
||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
using Content.Shared.Audio;
|
using Content.Shared.Audio;
|
||||||
using Content.Shared.Jittering;
|
using Content.Shared.Jittering;
|
||||||
@@ -14,7 +13,6 @@ using Content.Server.Fluids.EntitySystems;
|
|||||||
using Content.Server.Body.Components;
|
using Content.Server.Body.Components;
|
||||||
using Content.Server.Climbing;
|
using Content.Server.Climbing;
|
||||||
using Content.Server.Construction;
|
using Content.Server.Construction;
|
||||||
using Content.Server.DoAfter;
|
|
||||||
using Content.Server.Materials;
|
using Content.Server.Materials;
|
||||||
using Content.Server.Mind.Components;
|
using Content.Server.Mind.Components;
|
||||||
using Content.Shared.DoAfter;
|
using Content.Shared.DoAfter;
|
||||||
@@ -27,7 +25,7 @@ using Robust.Shared.Random;
|
|||||||
using Robust.Shared.Configuration;
|
using Robust.Shared.Configuration;
|
||||||
using Robust.Server.Player;
|
using Robust.Server.Player;
|
||||||
using Robust.Shared.Physics.Components;
|
using Robust.Shared.Physics.Components;
|
||||||
using Content.Shared.Humanoid;
|
using Content.Shared.Medical;
|
||||||
|
|
||||||
namespace Content.Server.Medical.BiomassReclaimer
|
namespace Content.Server.Medical.BiomassReclaimer
|
||||||
{
|
{
|
||||||
@@ -43,7 +41,7 @@ namespace Content.Server.Medical.BiomassReclaimer
|
|||||||
[Dependency] private readonly ThrowingSystem _throwing = default!;
|
[Dependency] private readonly ThrowingSystem _throwing = default!;
|
||||||
[Dependency] private readonly IRobustRandom _robustRandom = default!;
|
[Dependency] private readonly IRobustRandom _robustRandom = default!;
|
||||||
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
|
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
|
||||||
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
|
||||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||||
[Dependency] private readonly MaterialStorageSystem _material = default!;
|
[Dependency] private readonly MaterialStorageSystem _material = default!;
|
||||||
|
|
||||||
@@ -97,7 +95,7 @@ namespace Content.Server.Medical.BiomassReclaimer
|
|||||||
SubscribeLocalEvent<BiomassReclaimerComponent, UpgradeExamineEvent>(OnUpgradeExamine);
|
SubscribeLocalEvent<BiomassReclaimerComponent, UpgradeExamineEvent>(OnUpgradeExamine);
|
||||||
SubscribeLocalEvent<BiomassReclaimerComponent, PowerChangedEvent>(OnPowerChanged);
|
SubscribeLocalEvent<BiomassReclaimerComponent, PowerChangedEvent>(OnPowerChanged);
|
||||||
SubscribeLocalEvent<BiomassReclaimerComponent, SuicideEvent>(OnSuicide);
|
SubscribeLocalEvent<BiomassReclaimerComponent, SuicideEvent>(OnSuicide);
|
||||||
SubscribeLocalEvent<BiomassReclaimerComponent, DoAfterEvent>(OnDoAfter);
|
SubscribeLocalEvent<BiomassReclaimerComponent, ReclaimerDoAfterEvent>(OnDoAfter);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnSuicide(EntityUid uid, BiomassReclaimerComponent component, SuicideEvent args)
|
private void OnSuicide(EntityUid uid, BiomassReclaimerComponent component, SuicideEvent args)
|
||||||
@@ -152,11 +150,10 @@ namespace Content.Server.Medical.BiomassReclaimer
|
|||||||
if (!HasComp<MobStateComponent>(args.Used) || !CanGib(uid, args.Used, component))
|
if (!HasComp<MobStateComponent>(args.Used) || !CanGib(uid, args.Used, component))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_doAfterSystem.DoAfter(new DoAfterEventArgs(args.User, 7f, target:args.Target, used:args.Used)
|
_doAfterSystem.TryStartDoAfter(new DoAfterArgs(args.User, 7f, new ReclaimerDoAfterEvent(), uid, target: args.Target, used: args.Used)
|
||||||
{
|
{
|
||||||
BreakOnTargetMove = true,
|
BreakOnTargetMove = true,
|
||||||
BreakOnUserMove = true,
|
BreakOnUserMove = true,
|
||||||
BreakOnStun = true,
|
|
||||||
NeedHand = true
|
NeedHand = true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
using System.Threading;
|
|
||||||
using Content.Shared.Damage;
|
using Content.Shared.Damage;
|
||||||
using Content.Shared.Damage.Prototypes;
|
using Content.Shared.Damage.Prototypes;
|
||||||
|
using Content.Shared.DoAfter;
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||||
|
|
||||||
@@ -39,12 +39,6 @@ namespace Content.Server.Medical.Components
|
|||||||
[DataField("delay")]
|
[DataField("delay")]
|
||||||
public float Delay = 3f;
|
public float Delay = 3f;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Cancel token to prevent rapid healing
|
|
||||||
/// </summary>
|
|
||||||
[DataField("cancelToken")]
|
|
||||||
public CancellationTokenSource? CancelToken;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Delay multiplier when healing yourself.
|
/// Delay multiplier when healing yourself.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ using Content.Server.Body.Systems;
|
|||||||
using Content.Server.Chemistry.Components.SolutionManager;
|
using Content.Server.Chemistry.Components.SolutionManager;
|
||||||
using Content.Server.Chemistry.EntitySystems;
|
using Content.Server.Chemistry.EntitySystems;
|
||||||
using Content.Server.Climbing;
|
using Content.Server.Climbing;
|
||||||
using Content.Server.DoAfter;
|
|
||||||
using Content.Server.Medical.Components;
|
using Content.Server.Medical.Components;
|
||||||
using Content.Server.NodeContainer;
|
using Content.Server.NodeContainer;
|
||||||
using Content.Server.NodeContainer.NodeGroups;
|
using Content.Server.NodeContainer.NodeGroups;
|
||||||
@@ -26,7 +25,6 @@ using Content.Shared.Interaction;
|
|||||||
using Content.Shared.Medical.Cryogenics;
|
using Content.Shared.Medical.Cryogenics;
|
||||||
using Content.Shared.MedicalScanner;
|
using Content.Shared.MedicalScanner;
|
||||||
using Content.Shared.Tools;
|
using Content.Shared.Tools;
|
||||||
using Content.Shared.Tools.Components;
|
|
||||||
using Content.Shared.Verbs;
|
using Content.Shared.Verbs;
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Shared.Timing;
|
using Robust.Shared.Timing;
|
||||||
@@ -42,7 +40,7 @@ public sealed partial class CryoPodSystem: SharedCryoPodSystem
|
|||||||
[Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!;
|
[Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!;
|
||||||
[Dependency] private readonly BloodstreamSystem _bloodstreamSystem = default!;
|
[Dependency] private readonly BloodstreamSystem _bloodstreamSystem = default!;
|
||||||
[Dependency] private readonly UserInterfaceSystem _userInterfaceSystem = default!;
|
[Dependency] private readonly UserInterfaceSystem _userInterfaceSystem = default!;
|
||||||
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
|
||||||
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
|
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
|
||||||
[Dependency] private readonly SharedToolSystem _toolSystem = default!;
|
[Dependency] private readonly SharedToolSystem _toolSystem = default!;
|
||||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||||
@@ -56,9 +54,8 @@ public sealed partial class CryoPodSystem: SharedCryoPodSystem
|
|||||||
SubscribeLocalEvent<CryoPodComponent, ComponentInit>(OnComponentInit);
|
SubscribeLocalEvent<CryoPodComponent, ComponentInit>(OnComponentInit);
|
||||||
SubscribeLocalEvent<CryoPodComponent, GetVerbsEvent<AlternativeVerb>>(AddAlternativeVerbs);
|
SubscribeLocalEvent<CryoPodComponent, GetVerbsEvent<AlternativeVerb>>(AddAlternativeVerbs);
|
||||||
SubscribeLocalEvent<CryoPodComponent, GotEmaggedEvent>(OnEmagged);
|
SubscribeLocalEvent<CryoPodComponent, GotEmaggedEvent>(OnEmagged);
|
||||||
SubscribeLocalEvent<CryoPodComponent, DoAfterEvent>(OnDoAfter);
|
SubscribeLocalEvent<CryoPodComponent, CryoPodDragFinished>(OnDragFinished);
|
||||||
SubscribeLocalEvent<CryoPodComponent, CryoPodPryFinished>(OnCryoPodPryFinished);
|
SubscribeLocalEvent<CryoPodComponent, CryoPodPryFinished>(OnCryoPodPryFinished);
|
||||||
SubscribeLocalEvent<CryoPodComponent, CryoPodPryInterrupted>(OnCryoPodPryInterrupted);
|
|
||||||
|
|
||||||
SubscribeLocalEvent<CryoPodComponent, AtmosDeviceUpdateEvent>(OnCryoPodUpdateAtmosphere);
|
SubscribeLocalEvent<CryoPodComponent, AtmosDeviceUpdateEvent>(OnCryoPodUpdateAtmosphere);
|
||||||
SubscribeLocalEvent<CryoPodComponent, DragDropTargetEvent>(HandleDragDropOn);
|
SubscribeLocalEvent<CryoPodComponent, DragDropTargetEvent>(HandleDragDropOn);
|
||||||
@@ -130,25 +127,23 @@ public sealed partial class CryoPodSystem: SharedCryoPodSystem
|
|||||||
if (cryoPodComponent.BodyContainer.ContainedEntity != null)
|
if (cryoPodComponent.BodyContainer.ContainedEntity != null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var doAfterArgs = new DoAfterEventArgs(args.User, cryoPodComponent.EntryDelay, target:args.Dragged, used:uid)
|
var doAfterArgs = new DoAfterArgs(args.User, cryoPodComponent.EntryDelay, new CryoPodDragFinished(), uid, target: args.Dragged, used: uid)
|
||||||
{
|
{
|
||||||
BreakOnDamage = true,
|
BreakOnDamage = true,
|
||||||
BreakOnStun = true,
|
|
||||||
BreakOnTargetMove = true,
|
BreakOnTargetMove = true,
|
||||||
BreakOnUserMove = true,
|
BreakOnUserMove = true,
|
||||||
NeedHand = false,
|
NeedHand = false,
|
||||||
};
|
};
|
||||||
_doAfterSystem.DoAfter(doAfterArgs);
|
_doAfterSystem.TryStartDoAfter(doAfterArgs);
|
||||||
args.Handled = true;
|
args.Handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDoAfter(EntityUid uid, CryoPodComponent component, DoAfterEvent args)
|
private void OnDragFinished(EntityUid uid, CryoPodComponent component, CryoPodDragFinished args)
|
||||||
{
|
{
|
||||||
if (args.Cancelled || args.Handled || args.Args.Target == null)
|
if (args.Cancelled || args.Handled || args.Args.Target == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
InsertBody(uid, args.Args.Target.Value, component);
|
InsertBody(uid, args.Args.Target.Value, component);
|
||||||
|
|
||||||
args.Handled = true;
|
args.Handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,18 +174,7 @@ public sealed partial class CryoPodSystem: SharedCryoPodSystem
|
|||||||
if (args.Handled || !cryoPodComponent.Locked || cryoPodComponent.BodyContainer.ContainedEntity == null)
|
if (args.Handled || !cryoPodComponent.Locked || cryoPodComponent.BodyContainer.ContainedEntity == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (TryComp(args.Used, out ToolComponent? tool)
|
args.Handled = _toolSystem.UseTool(args.Used, args.User, uid, cryoPodComponent.PryDelay, "Prying", new CryoPodPryFinished());
|
||||||
&& tool.Qualities.Contains("Prying")) // Why aren't those enums?
|
|
||||||
{
|
|
||||||
if (cryoPodComponent.IsPrying)
|
|
||||||
return;
|
|
||||||
cryoPodComponent.IsPrying = true;
|
|
||||||
|
|
||||||
var toolEvData = new ToolEventData(new CryoPodPryFinished(), targetEntity:uid);
|
|
||||||
_toolSystem.UseTool(args.Used, args.User, uid, cryoPodComponent.PryDelay, new [] {"Prying"}, toolEvData);
|
|
||||||
|
|
||||||
args.Handled = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnExamined(EntityUid uid, CryoPodComponent component, ExaminedEvent args)
|
private void OnExamined(EntityUid uid, CryoPodComponent component, ExaminedEvent args)
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
using System.Threading;
|
|
||||||
using Content.Server.Administration.Logs;
|
using Content.Server.Administration.Logs;
|
||||||
using Content.Server.Body.Systems;
|
using Content.Server.Body.Systems;
|
||||||
using Content.Server.DoAfter;
|
|
||||||
using Content.Server.Medical.Components;
|
using Content.Server.Medical.Components;
|
||||||
using Content.Server.Stack;
|
using Content.Server.Stack;
|
||||||
using Content.Shared.Audio;
|
using Content.Shared.Audio;
|
||||||
using Content.Shared.Damage;
|
using Content.Shared.Damage;
|
||||||
using Content.Shared.Database;
|
using Content.Shared.Database;
|
||||||
using Content.Shared.DoAfter;
|
using Content.Shared.DoAfter;
|
||||||
|
using Content.Shared.FixedPoint;
|
||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
using Content.Shared.Interaction.Events;
|
using Content.Shared.Interaction.Events;
|
||||||
|
using Content.Shared.Medical;
|
||||||
using Content.Shared.Mobs;
|
using Content.Shared.Mobs;
|
||||||
using Content.Shared.Mobs.Components;
|
using Content.Shared.Mobs.Components;
|
||||||
using Content.Shared.Mobs.Systems;
|
using Content.Shared.Mobs.Systems;
|
||||||
@@ -24,7 +24,7 @@ public sealed class HealingSystem : EntitySystem
|
|||||||
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
|
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
|
||||||
[Dependency] private readonly DamageableSystem _damageable = default!;
|
[Dependency] private readonly DamageableSystem _damageable = default!;
|
||||||
[Dependency] private readonly BloodstreamSystem _bloodstreamSystem = default!;
|
[Dependency] private readonly BloodstreamSystem _bloodstreamSystem = default!;
|
||||||
[Dependency] private readonly DoAfterSystem _doAfter = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
|
||||||
[Dependency] private readonly IRobustRandom _random = default!;
|
[Dependency] private readonly IRobustRandom _random = default!;
|
||||||
[Dependency] private readonly StackSystem _stacks = default!;
|
[Dependency] private readonly StackSystem _stacks = default!;
|
||||||
[Dependency] private readonly SharedInteractionSystem _interactionSystem = default!;
|
[Dependency] private readonly SharedInteractionSystem _interactionSystem = default!;
|
||||||
@@ -36,45 +36,43 @@ public sealed class HealingSystem : EntitySystem
|
|||||||
base.Initialize();
|
base.Initialize();
|
||||||
SubscribeLocalEvent<HealingComponent, UseInHandEvent>(OnHealingUse);
|
SubscribeLocalEvent<HealingComponent, UseInHandEvent>(OnHealingUse);
|
||||||
SubscribeLocalEvent<HealingComponent, AfterInteractEvent>(OnHealingAfterInteract);
|
SubscribeLocalEvent<HealingComponent, AfterInteractEvent>(OnHealingAfterInteract);
|
||||||
SubscribeLocalEvent<DamageableComponent, DoAfterEvent<HealingData>>(OnDoAfter);
|
SubscribeLocalEvent<DamageableComponent, HealingDoAfterEvent>(OnDoAfter);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDoAfter(EntityUid uid, DamageableComponent component, DoAfterEvent<HealingData> args)
|
private void OnDoAfter(EntityUid uid, DamageableComponent component, HealingDoAfterEvent args)
|
||||||
{
|
{
|
||||||
if (args.Cancelled)
|
if (!TryComp(args.Used, out HealingComponent? healing))
|
||||||
{
|
|
||||||
args.AdditionalData.HealingComponent.CancelToken = null;
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
if (args.Handled || args.Cancelled || _mobStateSystem.IsDead(uid) || args.Args.Used == null)
|
if (args.Handled || args.Cancelled || _mobStateSystem.IsDead(uid))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (component.DamageContainerID is not null && !component.DamageContainerID.Equals(component.DamageContainerID))
|
if (component.DamageContainerID is not null && !component.DamageContainerID.Equals(component.DamageContainerID))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Heal some bloodloss damage.
|
// Heal some bloodloss damage.
|
||||||
if (args.AdditionalData.HealingComponent.BloodlossModifier != 0)
|
if (healing.BloodlossModifier != 0)
|
||||||
_bloodstreamSystem.TryModifyBleedAmount(uid, args.AdditionalData.HealingComponent.BloodlossModifier);
|
_bloodstreamSystem.TryModifyBleedAmount(uid, healing.BloodlossModifier);
|
||||||
|
|
||||||
var healed = _damageable.TryChangeDamage(uid, args.AdditionalData.HealingComponent.Damage, true, origin: args.Args.User);
|
var healed = _damageable.TryChangeDamage(uid, healing.Damage, true, origin: args.Args.User);
|
||||||
|
|
||||||
if (healed == null)
|
if (healed == null && healing.BloodlossModifier != 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
var total = healed?.Total ?? FixedPoint2.Zero;
|
||||||
|
|
||||||
// Reverify that we can heal the damage.
|
// Reverify that we can heal the damage.
|
||||||
_stacks.Use(args.Args.Used.Value, 1, args.AdditionalData.Stack);
|
_stacks.Use(args.Used.Value, 1);
|
||||||
|
|
||||||
if (uid != args.Args.User)
|
|
||||||
_adminLogger.Add(LogType.Healed, $"{EntityManager.ToPrettyString(args.Args.User):user} healed {EntityManager.ToPrettyString(uid):target} for {healed.Total:damage} damage");
|
|
||||||
|
|
||||||
|
if (uid != args.User)
|
||||||
|
_adminLogger.Add(LogType.Healed,
|
||||||
|
$"{EntityManager.ToPrettyString(args.User):user} healed {EntityManager.ToPrettyString(uid):target} for {total:damage} damage");
|
||||||
else
|
else
|
||||||
_adminLogger.Add(LogType.Healed, $"{EntityManager.ToPrettyString(args.Args.User):user} healed themselves for {healed.Total:damage} damage");
|
_adminLogger.Add(LogType.Healed,
|
||||||
|
$"{EntityManager.ToPrettyString(args.User):user} healed themselves for {total:damage} damage");
|
||||||
|
|
||||||
if (args.AdditionalData.HealingComponent.HealingEndSound != null)
|
_audio.PlayPvs(healing.HealingEndSound, uid, AudioHelpers.WithVariation(0.125f, _random).WithVolume(-5f));
|
||||||
_audio.PlayPvs(args.AdditionalData.HealingComponent.HealingEndSound, uid, AudioHelpers.WithVariation(0.125f, _random).WithVolume(-5f));
|
|
||||||
|
|
||||||
args.AdditionalData.HealingComponent.CancelToken = null;
|
|
||||||
args.Handled = true;
|
args.Handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,13 +96,14 @@ public sealed class HealingSystem : EntitySystem
|
|||||||
|
|
||||||
private bool TryHeal(EntityUid uid, EntityUid user, EntityUid target, HealingComponent component)
|
private bool TryHeal(EntityUid uid, EntityUid user, EntityUid target, HealingComponent component)
|
||||||
{
|
{
|
||||||
if (_mobStateSystem.IsDead(target) || !TryComp<DamageableComponent>(target, out var targetDamage) || component.CancelToken != null)
|
if (_mobStateSystem.IsDead(target) || !TryComp<DamageableComponent>(target, out var targetDamage))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (targetDamage.TotalDamage == 0)
|
if (targetDamage.TotalDamage == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (component.DamageContainerID is not null && !component.DamageContainerID.Equals(targetDamage.DamageContainerID))
|
if (component.DamageContainerID is not null &&
|
||||||
|
!component.DamageContainerID.Equals(targetDamage.DamageContainerID))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (user != target && !_interactionSystem.InRangeUnobstructed(user, target, popup: true))
|
if (user != target && !_interactionSystem.InRangeUnobstructed(user, target, popup: true))
|
||||||
@@ -114,7 +113,8 @@ public sealed class HealingSystem : EntitySystem
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (component.HealingBeginSound != null)
|
if (component.HealingBeginSound != null)
|
||||||
_audio.PlayPvs(component.HealingBeginSound, uid, AudioHelpers.WithVariation(0.125f, _random).WithVolume(-5f));
|
_audio.PlayPvs(component.HealingBeginSound, uid,
|
||||||
|
AudioHelpers.WithVariation(0.125f, _random).WithVolume(-5f));
|
||||||
|
|
||||||
var isNotSelf = user != target;
|
var isNotSelf = user != target;
|
||||||
|
|
||||||
@@ -122,27 +122,18 @@ public sealed class HealingSystem : EntitySystem
|
|||||||
? component.Delay
|
? component.Delay
|
||||||
: component.Delay * GetScaledHealingPenalty(user, component);
|
: component.Delay * GetScaledHealingPenalty(user, component);
|
||||||
|
|
||||||
component.CancelToken = new CancellationTokenSource();
|
var doAfterEventArgs =
|
||||||
|
new DoAfterArgs(user, delay, new HealingDoAfterEvent(), target, target: target, used: uid)
|
||||||
var healingData = new HealingData(component, stack);
|
|
||||||
|
|
||||||
var doAfterEventArgs = new DoAfterEventArgs(user, delay, cancelToken: component.CancelToken.Token,target: target, used: uid)
|
|
||||||
{
|
{
|
||||||
//Raise the event on the target if it's not self, otherwise raise it on self.
|
//Raise the event on the target if it's not self, otherwise raise it on self.
|
||||||
RaiseOnTarget = isNotSelf,
|
|
||||||
RaiseOnUser = !isNotSelf,
|
|
||||||
BreakOnUserMove = true,
|
BreakOnUserMove = true,
|
||||||
BreakOnTargetMove = true,
|
BreakOnTargetMove = true,
|
||||||
// Didn't break on damage as they may be trying to prevent it and
|
// Didn't break on damage as they may be trying to prevent it and
|
||||||
// not being able to heal your own ticking damage would be frustrating.
|
// not being able to heal your own ticking damage would be frustrating.
|
||||||
BreakOnStun = true,
|
|
||||||
NeedHand = true,
|
NeedHand = true,
|
||||||
// Juusstt in case damageble gets removed it avoids having to re-cancel the token. Won't need this when DoAfterEvent<T> gets added.
|
|
||||||
PostCheck = () => true
|
|
||||||
};
|
};
|
||||||
|
|
||||||
_doAfter.DoAfter(doAfterEventArgs, healingData);
|
_doAfter.TryStartDoAfter(doAfterEventArgs);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,7 +146,8 @@ public sealed class HealingSystem : EntitySystem
|
|||||||
public float GetScaledHealingPenalty(EntityUid uid, HealingComponent component)
|
public float GetScaledHealingPenalty(EntityUid uid, HealingComponent component)
|
||||||
{
|
{
|
||||||
var output = component.Delay;
|
var output = component.Delay;
|
||||||
if (!TryComp<MobThresholdsComponent>(uid, out var mobThreshold) || !TryComp<DamageableComponent>(uid, out var damageable))
|
if (!TryComp<MobThresholdsComponent>(uid, out var mobThreshold) ||
|
||||||
|
!TryComp<DamageableComponent>(uid, out var damageable))
|
||||||
return output;
|
return output;
|
||||||
if (!_mobThresholdSystem.TryGetThresholdForState(uid, MobState.Critical, out var amount, mobThreshold))
|
if (!_mobThresholdSystem.TryGetThresholdForState(uid, MobState.Critical, out var amount, mobThreshold))
|
||||||
return 1;
|
return 1;
|
||||||
@@ -165,10 +157,4 @@ public sealed class HealingSystem : EntitySystem
|
|||||||
var modifier = percentDamage * (component.SelfHealPenaltyMultiplier - 1) + 1;
|
var modifier = percentDamage * (component.SelfHealPenaltyMultiplier - 1) + 1;
|
||||||
return Math.Max(modifier, 1);
|
return Math.Max(modifier, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
private record struct HealingData(HealingComponent HealingComponent, StackComponent Stack)
|
|
||||||
{
|
|
||||||
public HealingComponent HealingComponent = HealingComponent;
|
|
||||||
public StackComponent Stack = Stack;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
using Content.Server.DoAfter;
|
|
||||||
using Content.Server.Medical.Components;
|
using Content.Server.Medical.Components;
|
||||||
using Content.Server.Disease;
|
using Content.Server.Disease;
|
||||||
using Content.Server.Popups;
|
using Content.Server.Popups;
|
||||||
@@ -6,6 +5,7 @@ using Content.Shared.Damage;
|
|||||||
using Content.Shared.DoAfter;
|
using Content.Shared.DoAfter;
|
||||||
using Content.Shared.IdentityManagement;
|
using Content.Shared.IdentityManagement;
|
||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
|
using Content.Shared.MedicalScanner;
|
||||||
using Content.Shared.Mobs.Components;
|
using Content.Shared.Mobs.Components;
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
using static Content.Shared.MedicalScanner.SharedHealthAnalyzerComponent;
|
using static Content.Shared.MedicalScanner.SharedHealthAnalyzerComponent;
|
||||||
@@ -16,7 +16,7 @@ namespace Content.Server.Medical
|
|||||||
{
|
{
|
||||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||||
[Dependency] private readonly DiseaseSystem _disease = default!;
|
[Dependency] private readonly DiseaseSystem _disease = default!;
|
||||||
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
|
||||||
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
||||||
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
|
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@ namespace Content.Server.Medical
|
|||||||
base.Initialize();
|
base.Initialize();
|
||||||
SubscribeLocalEvent<HealthAnalyzerComponent, ActivateInWorldEvent>(HandleActivateInWorld);
|
SubscribeLocalEvent<HealthAnalyzerComponent, ActivateInWorldEvent>(HandleActivateInWorld);
|
||||||
SubscribeLocalEvent<HealthAnalyzerComponent, AfterInteractEvent>(OnAfterInteract);
|
SubscribeLocalEvent<HealthAnalyzerComponent, AfterInteractEvent>(OnAfterInteract);
|
||||||
SubscribeLocalEvent<HealthAnalyzerComponent, DoAfterEvent>(OnDoAfter);
|
SubscribeLocalEvent<HealthAnalyzerComponent, HealthAnalyzerDoAfterEvent>(OnDoAfter);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleActivateInWorld(EntityUid uid, HealthAnalyzerComponent healthAnalyzer, ActivateInWorldEvent args)
|
private void HandleActivateInWorld(EntityUid uid, HealthAnalyzerComponent healthAnalyzer, ActivateInWorldEvent args)
|
||||||
@@ -40,11 +40,10 @@ namespace Content.Server.Medical
|
|||||||
|
|
||||||
_audio.PlayPvs(healthAnalyzer.ScanningBeginSound, uid);
|
_audio.PlayPvs(healthAnalyzer.ScanningBeginSound, uid);
|
||||||
|
|
||||||
_doAfterSystem.DoAfter(new DoAfterEventArgs(args.User, healthAnalyzer.ScanDelay, target: args.Target, used:uid)
|
_doAfterSystem.TryStartDoAfter(new DoAfterArgs(args.User, healthAnalyzer.ScanDelay, new HealthAnalyzerDoAfterEvent(), uid, target: args.Target, used: uid)
|
||||||
{
|
{
|
||||||
BreakOnTargetMove = true,
|
BreakOnTargetMove = true,
|
||||||
BreakOnUserMove = true,
|
BreakOnUserMove = true,
|
||||||
BreakOnStun = true,
|
|
||||||
NeedHand = true
|
NeedHand = true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using Content.Server.Body.Components;
|
using Content.Server.Body.Components;
|
||||||
using Content.Server.DoAfter;
|
|
||||||
using Content.Server.Medical.Components;
|
using Content.Server.Medical.Components;
|
||||||
using Content.Server.Popups;
|
using Content.Server.Popups;
|
||||||
using Content.Shared.Actions;
|
using Content.Shared.Actions;
|
||||||
@@ -11,6 +10,7 @@ using Content.Shared.Verbs;
|
|||||||
using Content.Shared.Mobs.Components;
|
using Content.Shared.Mobs.Components;
|
||||||
using Content.Shared.Mobs.Systems;
|
using Content.Shared.Mobs.Systems;
|
||||||
using Content.Shared.DoAfter;
|
using Content.Shared.DoAfter;
|
||||||
|
using Content.Shared.Medical;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
namespace Content.Server.Medical
|
namespace Content.Server.Medical
|
||||||
@@ -18,7 +18,7 @@ namespace Content.Server.Medical
|
|||||||
public sealed class StethoscopeSystem : EntitySystem
|
public sealed class StethoscopeSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
||||||
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
|
||||||
[Dependency] private readonly MobStateSystem _mobStateSystem = default!;
|
[Dependency] private readonly MobStateSystem _mobStateSystem = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
@@ -29,7 +29,7 @@ namespace Content.Server.Medical
|
|||||||
SubscribeLocalEvent<WearingStethoscopeComponent, GetVerbsEvent<InnateVerb>>(AddStethoscopeVerb);
|
SubscribeLocalEvent<WearingStethoscopeComponent, GetVerbsEvent<InnateVerb>>(AddStethoscopeVerb);
|
||||||
SubscribeLocalEvent<StethoscopeComponent, GetItemActionsEvent>(OnGetActions);
|
SubscribeLocalEvent<StethoscopeComponent, GetItemActionsEvent>(OnGetActions);
|
||||||
SubscribeLocalEvent<StethoscopeComponent, StethoscopeActionEvent>(OnStethoscopeAction);
|
SubscribeLocalEvent<StethoscopeComponent, StethoscopeActionEvent>(OnStethoscopeAction);
|
||||||
SubscribeLocalEvent<StethoscopeComponent, DoAfterEvent>(OnDoAfter);
|
SubscribeLocalEvent<StethoscopeComponent, StethoscopeDoAfterEvent>(OnDoAfter);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -103,11 +103,10 @@ namespace Content.Server.Medical
|
|||||||
// construct the doafter and start it
|
// construct the doafter and start it
|
||||||
private void StartListening(EntityUid scope, EntityUid user, EntityUid target, StethoscopeComponent comp)
|
private void StartListening(EntityUid scope, EntityUid user, EntityUid target, StethoscopeComponent comp)
|
||||||
{
|
{
|
||||||
_doAfterSystem.DoAfter(new DoAfterEventArgs(user, comp.Delay, target: target, used:scope)
|
_doAfterSystem.TryStartDoAfter(new DoAfterArgs(user, comp.Delay, new StethoscopeDoAfterEvent(), scope, target: target, used: scope)
|
||||||
{
|
{
|
||||||
BreakOnTargetMove = true,
|
BreakOnTargetMove = true,
|
||||||
BreakOnUserMove = true,
|
BreakOnUserMove = true,
|
||||||
BreakOnStun = true,
|
|
||||||
NeedHand = true
|
NeedHand = true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -99,7 +99,8 @@ public sealed partial class NPCSteeringSystem
|
|||||||
if (doorQuery.TryGetComponent(ent, out var door) && door.State != DoorState.Open)
|
if (doorQuery.TryGetComponent(ent, out var door) && door.State != DoorState.Open)
|
||||||
{
|
{
|
||||||
// TODO: Use the verb.
|
// TODO: Use the verb.
|
||||||
if (door.State != DoorState.Opening && !door.BeingPried)
|
|
||||||
|
if (door.State != DoorState.Opening)
|
||||||
_doors.TryPryDoor(ent, uid, uid, door, true);
|
_doors.TryPryDoor(ent, uid, uid, door, true);
|
||||||
|
|
||||||
return SteeringObstacleStatus.Continuing;
|
return SteeringObstacleStatus.Continuing;
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ using Content.Server.AlertLevel;
|
|||||||
using Content.Server.Audio;
|
using Content.Server.Audio;
|
||||||
using Content.Server.Chat.Systems;
|
using Content.Server.Chat.Systems;
|
||||||
using Content.Server.Coordinates.Helpers;
|
using Content.Server.Coordinates.Helpers;
|
||||||
using Content.Server.DoAfter;
|
|
||||||
using Content.Server.Explosion.EntitySystems;
|
using Content.Server.Explosion.EntitySystems;
|
||||||
using Content.Server.Popups;
|
using Content.Server.Popups;
|
||||||
using Content.Server.Station.Systems;
|
using Content.Server.Station.Systems;
|
||||||
@@ -28,7 +27,7 @@ namespace Content.Server.Nuke
|
|||||||
[Dependency] private readonly StationSystem _stationSystem = default!;
|
[Dependency] private readonly StationSystem _stationSystem = default!;
|
||||||
[Dependency] private readonly ServerGlobalSoundSystem _soundSystem = default!;
|
[Dependency] private readonly ServerGlobalSoundSystem _soundSystem = default!;
|
||||||
[Dependency] private readonly ChatSystem _chatSystem = default!;
|
[Dependency] private readonly ChatSystem _chatSystem = default!;
|
||||||
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
|
||||||
[Dependency] private readonly IRobustRandom _random = default!;
|
[Dependency] private readonly IRobustRandom _random = default!;
|
||||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||||
[Dependency] private readonly UserInterfaceSystem _ui = default!;
|
[Dependency] private readonly UserInterfaceSystem _ui = default!;
|
||||||
@@ -67,7 +66,7 @@ namespace Content.Server.Nuke
|
|||||||
SubscribeLocalEvent<NukeComponent, NukeKeypadEnterMessage>(OnEnterButtonPressed);
|
SubscribeLocalEvent<NukeComponent, NukeKeypadEnterMessage>(OnEnterButtonPressed);
|
||||||
|
|
||||||
// Doafter events
|
// Doafter events
|
||||||
SubscribeLocalEvent<NukeComponent, DoAfterEvent>(OnDoAfter);
|
SubscribeLocalEvent<NukeComponent, NukeDisarmDoAfterEvent>(OnDoAfter);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnInit(EntityUid uid, NukeComponent component, ComponentInit args)
|
private void OnInit(EntityUid uid, NukeComponent component, ComponentInit args)
|
||||||
@@ -559,16 +558,17 @@ namespace Content.Server.Nuke
|
|||||||
|
|
||||||
private void DisarmBombDoafter(EntityUid uid, EntityUid user, NukeComponent nuke)
|
private void DisarmBombDoafter(EntityUid uid, EntityUid user, NukeComponent nuke)
|
||||||
{
|
{
|
||||||
var doafter = new DoAfterEventArgs(user, nuke.DisarmDoafterLength, target: uid)
|
var doafter = new DoAfterArgs(user, nuke.DisarmDoafterLength, new NukeDisarmDoAfterEvent(), uid, target: uid)
|
||||||
{
|
{
|
||||||
BreakOnDamage = true,
|
BreakOnDamage = true,
|
||||||
BreakOnStun = true,
|
|
||||||
BreakOnTargetMove = true,
|
BreakOnTargetMove = true,
|
||||||
BreakOnUserMove = true,
|
BreakOnUserMove = true,
|
||||||
NeedHand = true
|
NeedHand = true
|
||||||
};
|
};
|
||||||
|
|
||||||
_doAfterSystem.DoAfter(doafter);
|
if (!_doAfterSystem.TryStartDoAfter(doafter))
|
||||||
|
return;
|
||||||
|
|
||||||
_popups.PopupEntity(Loc.GetString("nuke-component-doafter-warning"), user,
|
_popups.PopupEntity(Loc.GetString("nuke-component-doafter-warning"), user,
|
||||||
user, PopupType.LargeCaution);
|
user, PopupType.LargeCaution);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Content.Server.Nutrition.EntitySystems;
|
using Content.Server.Nutrition.EntitySystems;
|
||||||
|
using Content.Shared.DoAfter;
|
||||||
using Content.Shared.FixedPoint;
|
using Content.Shared.FixedPoint;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
@@ -34,19 +35,6 @@ namespace Content.Server.Nutrition.Components
|
|||||||
[DataField("burstSound")]
|
[DataField("burstSound")]
|
||||||
public SoundSpecifier BurstSound = new SoundPathSpecifier("/Audio/Effects/flash_bang.ogg");
|
public SoundSpecifier BurstSound = new SoundPathSpecifier("/Audio/Effects/flash_bang.ogg");
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Is this drink being forced on someone else?
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
[DataField("forceDrink")]
|
|
||||||
public bool ForceDrink;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Is the entity currently drinking or trying to make someone else drink?
|
|
||||||
/// </summary>
|
|
||||||
[DataField("drinking")]
|
|
||||||
public bool Drinking;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// How long it takes to drink this yourself.
|
/// How long it takes to drink this yourself.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Content.Server.Chemistry.EntitySystems;
|
using Content.Server.Chemistry.EntitySystems;
|
||||||
using Content.Server.Nutrition.EntitySystems;
|
using Content.Server.Nutrition.EntitySystems;
|
||||||
|
using Content.Shared.DoAfter;
|
||||||
using Content.Shared.FixedPoint;
|
using Content.Shared.FixedPoint;
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
@@ -40,18 +41,6 @@ namespace Content.Server.Nutrition.Components
|
|||||||
[DataField("eatMessage")]
|
[DataField("eatMessage")]
|
||||||
public string EatMessage = "food-nom";
|
public string EatMessage = "food-nom";
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Is this entity being forcefed?
|
|
||||||
/// </summary>
|
|
||||||
[DataField("forceFeed")]
|
|
||||||
public bool ForceFeed;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Is this entity eating or being fed?
|
|
||||||
/// </summary>
|
|
||||||
[DataField(("eating"))]
|
|
||||||
public bool Eating;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// How long it takes to eat the food personally.
|
/// How long it takes to eat the food personally.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ using Content.Server.Body.Components;
|
|||||||
using Content.Server.Body.Systems;
|
using Content.Server.Body.Systems;
|
||||||
using Content.Server.Chemistry.Components.SolutionManager;
|
using Content.Server.Chemistry.Components.SolutionManager;
|
||||||
using Content.Server.Chemistry.EntitySystems;
|
using Content.Server.Chemistry.EntitySystems;
|
||||||
using Content.Server.DoAfter;
|
|
||||||
using Content.Server.Fluids.EntitySystems;
|
using Content.Server.Fluids.EntitySystems;
|
||||||
using Content.Server.Forensics;
|
using Content.Server.Forensics;
|
||||||
using Content.Server.Nutrition.Components;
|
using Content.Server.Nutrition.Components;
|
||||||
@@ -10,7 +9,6 @@ using Content.Server.Popups;
|
|||||||
using Content.Shared.Administration.Logs;
|
using Content.Shared.Administration.Logs;
|
||||||
using Content.Shared.Body.Components;
|
using Content.Shared.Body.Components;
|
||||||
using Content.Shared.Chemistry;
|
using Content.Shared.Chemistry;
|
||||||
using Content.Shared.Chemistry.Components;
|
|
||||||
using Content.Shared.Chemistry.Reagent;
|
using Content.Shared.Chemistry.Reagent;
|
||||||
using Content.Shared.Database;
|
using Content.Shared.Database;
|
||||||
using Content.Shared.DoAfter;
|
using Content.Shared.DoAfter;
|
||||||
@@ -21,6 +19,7 @@ using Content.Shared.Interaction;
|
|||||||
using Content.Shared.Interaction.Events;
|
using Content.Shared.Interaction.Events;
|
||||||
using Content.Shared.Mobs.Components;
|
using Content.Shared.Mobs.Components;
|
||||||
using Content.Shared.Mobs.Systems;
|
using Content.Shared.Mobs.Systems;
|
||||||
|
using Content.Shared.Nutrition;
|
||||||
using Content.Shared.Nutrition.Components;
|
using Content.Shared.Nutrition.Components;
|
||||||
using Content.Shared.Throwing;
|
using Content.Shared.Throwing;
|
||||||
using Content.Shared.Verbs;
|
using Content.Shared.Verbs;
|
||||||
@@ -42,7 +41,7 @@ namespace Content.Server.Nutrition.EntitySystems
|
|||||||
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
||||||
[Dependency] private readonly BodySystem _bodySystem = default!;
|
[Dependency] private readonly BodySystem _bodySystem = default!;
|
||||||
[Dependency] private readonly StomachSystem _stomachSystem = default!;
|
[Dependency] private readonly StomachSystem _stomachSystem = default!;
|
||||||
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
|
||||||
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
|
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
|
||||||
[Dependency] private readonly MobStateSystem _mobStateSystem = default!;
|
[Dependency] private readonly MobStateSystem _mobStateSystem = default!;
|
||||||
[Dependency] private readonly SpillableSystem _spillableSystem = default!;
|
[Dependency] private readonly SpillableSystem _spillableSystem = default!;
|
||||||
@@ -55,6 +54,7 @@ namespace Content.Server.Nutrition.EntitySystems
|
|||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
|
|
||||||
|
// TODO add InteractNoHandEvent for entities like mice.
|
||||||
SubscribeLocalEvent<DrinkComponent, SolutionChangedEvent>(OnSolutionChange);
|
SubscribeLocalEvent<DrinkComponent, SolutionChangedEvent>(OnSolutionChange);
|
||||||
SubscribeLocalEvent<DrinkComponent, ComponentInit>(OnDrinkInit);
|
SubscribeLocalEvent<DrinkComponent, ComponentInit>(OnDrinkInit);
|
||||||
SubscribeLocalEvent<DrinkComponent, LandEvent>(HandleLand);
|
SubscribeLocalEvent<DrinkComponent, LandEvent>(HandleLand);
|
||||||
@@ -63,7 +63,7 @@ namespace Content.Server.Nutrition.EntitySystems
|
|||||||
SubscribeLocalEvent<DrinkComponent, GetVerbsEvent<AlternativeVerb>>(AddDrinkVerb);
|
SubscribeLocalEvent<DrinkComponent, GetVerbsEvent<AlternativeVerb>>(AddDrinkVerb);
|
||||||
SubscribeLocalEvent<DrinkComponent, ExaminedEvent>(OnExamined);
|
SubscribeLocalEvent<DrinkComponent, ExaminedEvent>(OnExamined);
|
||||||
SubscribeLocalEvent<DrinkComponent, SolutionTransferAttemptEvent>(OnTransferAttempt);
|
SubscribeLocalEvent<DrinkComponent, SolutionTransferAttemptEvent>(OnTransferAttempt);
|
||||||
SubscribeLocalEvent<DrinkComponent, DoAfterEvent<DrinkData>>(OnDoAfter);
|
SubscribeLocalEvent<DrinkComponent, ConsumeDoAfterEvent>(OnDoAfter);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsEmpty(EntityUid uid, DrinkComponent? component = null)
|
public bool IsEmpty(EntityUid uid, DrinkComponent? component = null)
|
||||||
@@ -218,7 +218,7 @@ namespace Content.Server.Nutrition.EntitySystems
|
|||||||
|
|
||||||
private bool TryDrink(EntityUid user, EntityUid target, DrinkComponent drink, EntityUid item)
|
private bool TryDrink(EntityUid user, EntityUid target, DrinkComponent drink, EntityUid item)
|
||||||
{
|
{
|
||||||
if (!EntityManager.HasComponent<BodyComponent>(target) || drink.Drinking)
|
if (!EntityManager.HasComponent<BodyComponent>(target))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!drink.Opened)
|
if (!drink.Opened)
|
||||||
@@ -236,16 +236,18 @@ namespace Content.Server.Nutrition.EntitySystems
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (drinkSolution.Name == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (_foodSystem.IsMouthBlocked(target, user))
|
if (_foodSystem.IsMouthBlocked(target, user))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (!_interactionSystem.InRangeUnobstructed(user, item, popup: true))
|
if (!_interactionSystem.InRangeUnobstructed(user, item, popup: true))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
drink.Drinking = true;
|
var forceDrink = user != target;
|
||||||
drink.ForceDrink = user != target;
|
|
||||||
|
|
||||||
if (drink.ForceDrink)
|
if (forceDrink)
|
||||||
{
|
{
|
||||||
var userName = Identity.Entity(user, EntityManager);
|
var userName = Identity.Entity(user, EntityManager);
|
||||||
|
|
||||||
@@ -263,53 +265,51 @@ namespace Content.Server.Nutrition.EntitySystems
|
|||||||
|
|
||||||
var flavors = _flavorProfileSystem.GetLocalizedFlavorsMessage(user, drinkSolution);
|
var flavors = _flavorProfileSystem.GetLocalizedFlavorsMessage(user, drinkSolution);
|
||||||
|
|
||||||
var drinkData = new DrinkData(drinkSolution, flavors);
|
var doAfterEventArgs = new DoAfterArgs(
|
||||||
|
user,
|
||||||
var doAfterEventArgs = new DoAfterEventArgs(user, drink.ForceDrink ? drink.ForceFeedDelay : drink.Delay,
|
forceDrink ? drink.ForceFeedDelay : drink.Delay,
|
||||||
target: target, used: item)
|
new ConsumeDoAfterEvent(drinkSolution.Name, flavors),
|
||||||
|
eventTarget: item,
|
||||||
|
target: target,
|
||||||
|
used: item)
|
||||||
{
|
{
|
||||||
RaiseOnTarget = user != target,
|
BreakOnUserMove = forceDrink,
|
||||||
RaiseOnUser = false,
|
|
||||||
BreakOnUserMove = drink.ForceDrink,
|
|
||||||
BreakOnDamage = true,
|
BreakOnDamage = true,
|
||||||
BreakOnStun = true,
|
BreakOnTargetMove = forceDrink,
|
||||||
BreakOnTargetMove = drink.ForceDrink,
|
|
||||||
MovementThreshold = 0.01f,
|
MovementThreshold = 0.01f,
|
||||||
DistanceThreshold = 1.0f,
|
DistanceThreshold = 1.0f,
|
||||||
NeedHand = true
|
// Mice and the like can eat without hands.
|
||||||
|
// TODO maybe set this based on some CanEatWithoutHands event or component?
|
||||||
|
NeedHand = forceDrink,
|
||||||
};
|
};
|
||||||
|
|
||||||
_doAfterSystem.DoAfter(doAfterEventArgs, drinkData);
|
_doAfterSystem.TryStartDoAfter(doAfterEventArgs);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Raised directed at a victim when someone has force fed them a drink.
|
/// Raised directed at a victim when someone has force fed them a drink.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void OnDoAfter(EntityUid uid, DrinkComponent component, DoAfterEvent<DrinkData> args)
|
private void OnDoAfter(EntityUid uid, DrinkComponent component, ConsumeDoAfterEvent args)
|
||||||
{
|
{
|
||||||
if (args.Cancelled)
|
if (args.Handled || args.Cancelled || component.Deleted)
|
||||||
{
|
|
||||||
component.ForceDrink = false;
|
|
||||||
component.Drinking = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args.Handled || component.Deleted)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!TryComp<BodyComponent>(args.Args.Target, out var body))
|
if (!TryComp<BodyComponent>(args.Args.Target, out var body))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
component.Drinking = false;
|
if (!_solutionContainerSystem.TryGetSolution(args.Used, args.Solution, out var solution))
|
||||||
|
return;
|
||||||
|
|
||||||
var transferAmount = FixedPoint2.Min(component.TransferAmount, args.AdditionalData.DrinkSolution.Volume);
|
var transferAmount = FixedPoint2.Min(component.TransferAmount, solution.Volume);
|
||||||
var drained = _solutionContainerSystem.Drain(uid, args.AdditionalData.DrinkSolution, transferAmount);
|
var drained = _solutionContainerSystem.Drain(uid, solution, transferAmount);
|
||||||
|
var forceDrink = args.User != args.Target;
|
||||||
|
|
||||||
|
//var forceDrink = args.Args.Target.Value != args.Args.User;
|
||||||
|
|
||||||
if (!_bodySystem.TryGetBodyOrganComponents<StomachComponent>(args.Args.Target.Value, out var stomachs, body))
|
if (!_bodySystem.TryGetBodyOrganComponents<StomachComponent>(args.Args.Target.Value, out var stomachs, body))
|
||||||
{
|
{
|
||||||
_popupSystem.PopupEntity(component.ForceDrink ? Loc.GetString("drink-component-try-use-drink-cannot-drink-other") : Loc.GetString("drink-component-try-use-drink-had-enough"), args.Args.Target.Value, args.Args.User);
|
_popupSystem.PopupEntity(forceDrink ? Loc.GetString("drink-component-try-use-drink-cannot-drink-other") : Loc.GetString("drink-component-try-use-drink-had-enough"), args.Args.Target.Value, args.Args.User);
|
||||||
|
|
||||||
if (HasComp<RefillableSolutionComponent>(args.Args.Target.Value))
|
if (HasComp<RefillableSolutionComponent>(args.Args.Target.Value))
|
||||||
{
|
{
|
||||||
@@ -318,7 +318,7 @@ namespace Content.Server.Nutrition.EntitySystems
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_solutionContainerSystem.Refill(args.Args.Target.Value, args.AdditionalData.DrinkSolution, drained);
|
_solutionContainerSystem.Refill(args.Args.Target.Value, solution, drained);
|
||||||
args.Handled = true;
|
args.Handled = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -330,21 +330,21 @@ namespace Content.Server.Nutrition.EntitySystems
|
|||||||
{
|
{
|
||||||
_popupSystem.PopupEntity(Loc.GetString("drink-component-try-use-drink-had-enough"), args.Args.Target.Value, args.Args.Target.Value);
|
_popupSystem.PopupEntity(Loc.GetString("drink-component-try-use-drink-had-enough"), args.Args.Target.Value, args.Args.Target.Value);
|
||||||
|
|
||||||
if (component.ForceDrink)
|
if (forceDrink)
|
||||||
{
|
{
|
||||||
_popupSystem.PopupEntity(Loc.GetString("drink-component-try-use-drink-had-enough-other"), args.Args.Target.Value, args.Args.User);
|
_popupSystem.PopupEntity(Loc.GetString("drink-component-try-use-drink-had-enough-other"), args.Args.Target.Value, args.Args.User);
|
||||||
_spillableSystem.SpillAt(args.Args.Target.Value, drained, "PuddleSmear");
|
_spillableSystem.SpillAt(args.Args.Target.Value, drained, "PuddleSmear");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
_solutionContainerSystem.TryAddSolution(uid, args.AdditionalData.DrinkSolution, drained);
|
_solutionContainerSystem.TryAddSolution(uid, solution, drained);
|
||||||
|
|
||||||
args.Handled = true;
|
args.Handled = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var flavors = args.AdditionalData.FlavorMessage;
|
var flavors = args.FlavorMessage;
|
||||||
|
|
||||||
if (component.ForceDrink)
|
if (forceDrink)
|
||||||
{
|
{
|
||||||
var targetName = Identity.Entity(args.Args.Target.Value, EntityManager);
|
var targetName = Identity.Entity(args.Args.Target.Value, EntityManager);
|
||||||
var userName = Identity.Entity(args.Args.User, EntityManager);
|
var userName = Identity.Entity(args.Args.User, EntityManager);
|
||||||
@@ -372,11 +372,9 @@ namespace Content.Server.Nutrition.EntitySystems
|
|||||||
|
|
||||||
_audio.PlayPvs(_audio.GetSound(component.UseSound), args.Args.Target.Value, AudioParams.Default.WithVolume(-2f));
|
_audio.PlayPvs(_audio.GetSound(component.UseSound), args.Args.Target.Value, AudioParams.Default.WithVolume(-2f));
|
||||||
|
|
||||||
_reaction.DoEntityReaction(args.Args.Target.Value, args.AdditionalData.DrinkSolution, ReactionMethod.Ingestion);
|
_reaction.DoEntityReaction(args.Args.Target.Value, solution, ReactionMethod.Ingestion);
|
||||||
//TODO: Grab the stomach UIDs somehow without using Owner
|
//TODO: Grab the stomach UIDs somehow without using Owner
|
||||||
_stomachSystem.TryTransferSolution(firstStomach.Value.Comp.Owner, drained, firstStomach.Value.Comp);
|
_stomachSystem.TryTransferSolution(firstStomach.Value.Comp.Owner, drained, firstStomach.Value.Comp);
|
||||||
|
|
||||||
component.ForceDrink = false;
|
|
||||||
args.Handled = true;
|
args.Handled = true;
|
||||||
|
|
||||||
var comp = EnsureComp<ForensicsComponent>(uid);
|
var comp = EnsureComp<ForensicsComponent>(uid);
|
||||||
@@ -421,11 +419,5 @@ namespace Content.Server.Nutrition.EntitySystems
|
|||||||
|
|
||||||
return remainingString;
|
return remainingString;
|
||||||
}
|
}
|
||||||
|
|
||||||
private record struct DrinkData(Solution DrinkSolution, string FlavorMessage)
|
|
||||||
{
|
|
||||||
public readonly Solution DrinkSolution = DrinkSolution;
|
|
||||||
public readonly string FlavorMessage = FlavorMessage;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
using Content.Server.Body.Components;
|
using Content.Server.Body.Components;
|
||||||
using Content.Server.Body.Systems;
|
using Content.Server.Body.Systems;
|
||||||
using Content.Server.Chemistry.EntitySystems;
|
using Content.Server.Chemistry.EntitySystems;
|
||||||
using Content.Server.DoAfter;
|
|
||||||
using Content.Server.Hands.Components;
|
using Content.Server.Hands.Components;
|
||||||
using Content.Server.Nutrition.Components;
|
using Content.Server.Nutrition.Components;
|
||||||
using Content.Server.Popups;
|
using Content.Server.Popups;
|
||||||
using Content.Shared.Administration.Logs;
|
using Content.Shared.Administration.Logs;
|
||||||
using Content.Shared.Body.Components;
|
using Content.Shared.Body.Components;
|
||||||
using Content.Shared.Chemistry;
|
using Content.Shared.Chemistry;
|
||||||
using Content.Shared.Chemistry.Components;
|
|
||||||
using Content.Shared.Chemistry.Reagent;
|
using Content.Shared.Chemistry.Reagent;
|
||||||
using Content.Shared.Database;
|
using Content.Shared.Database;
|
||||||
using Content.Shared.DoAfter;
|
using Content.Shared.DoAfter;
|
||||||
@@ -20,6 +18,7 @@ using Content.Shared.Interaction.Events;
|
|||||||
using Content.Shared.Inventory;
|
using Content.Shared.Inventory;
|
||||||
using Content.Shared.Mobs.Components;
|
using Content.Shared.Mobs.Components;
|
||||||
using Content.Shared.Mobs.Systems;
|
using Content.Shared.Mobs.Systems;
|
||||||
|
using Content.Shared.Nutrition;
|
||||||
using Content.Shared.Verbs;
|
using Content.Shared.Verbs;
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
using Robust.Shared.Player;
|
using Robust.Shared.Player;
|
||||||
@@ -39,7 +38,7 @@ namespace Content.Server.Nutrition.EntitySystems
|
|||||||
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
||||||
[Dependency] private readonly MobStateSystem _mobStateSystem = default!;
|
[Dependency] private readonly MobStateSystem _mobStateSystem = default!;
|
||||||
[Dependency] private readonly UtensilSystem _utensilSystem = default!;
|
[Dependency] private readonly UtensilSystem _utensilSystem = default!;
|
||||||
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
|
||||||
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
|
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
|
||||||
[Dependency] private readonly InventorySystem _inventorySystem = default!;
|
[Dependency] private readonly InventorySystem _inventorySystem = default!;
|
||||||
[Dependency] private readonly SharedInteractionSystem _interactionSystem = default!;
|
[Dependency] private readonly SharedInteractionSystem _interactionSystem = default!;
|
||||||
@@ -51,10 +50,11 @@ namespace Content.Server.Nutrition.EntitySystems
|
|||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
|
|
||||||
|
// TODO add InteractNoHandEvent for entities like mice.
|
||||||
SubscribeLocalEvent<FoodComponent, UseInHandEvent>(OnUseFoodInHand);
|
SubscribeLocalEvent<FoodComponent, UseInHandEvent>(OnUseFoodInHand);
|
||||||
SubscribeLocalEvent<FoodComponent, AfterInteractEvent>(OnFeedFood);
|
SubscribeLocalEvent<FoodComponent, AfterInteractEvent>(OnFeedFood);
|
||||||
SubscribeLocalEvent<FoodComponent, GetVerbsEvent<AlternativeVerb>>(AddEatVerb);
|
SubscribeLocalEvent<FoodComponent, GetVerbsEvent<AlternativeVerb>>(AddEatVerb);
|
||||||
SubscribeLocalEvent<FoodComponent, DoAfterEvent<FoodData>>(OnDoAfter);
|
SubscribeLocalEvent<FoodComponent, ConsumeDoAfterEvent>(OnDoAfter);
|
||||||
SubscribeLocalEvent<InventoryComponent, IngestionAttemptEvent>(OnInventoryIngestAttempt);
|
SubscribeLocalEvent<InventoryComponent, IngestionAttemptEvent>(OnInventoryIngestAttempt);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,7 +66,8 @@ namespace Content.Server.Nutrition.EntitySystems
|
|||||||
if (ev.Handled)
|
if (ev.Handled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ev.Handled = TryFeed(ev.User, ev.User, uid, foodComponent);
|
ev.Handled = true;
|
||||||
|
TryFeed(ev.User, ev.User, uid, foodComponent);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -77,7 +78,8 @@ namespace Content.Server.Nutrition.EntitySystems
|
|||||||
if (args.Handled || args.Target == null || !args.CanReach)
|
if (args.Handled || args.Target == null || !args.CanReach)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
args.Handled = TryFeed(args.User, args.Target.Value, uid, foodComponent);
|
args.Handled = true;
|
||||||
|
TryFeed(args.User, args.Target.Value, uid, foodComponent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryFeed(EntityUid user, EntityUid target, EntityUid food, FoodComponent foodComp)
|
public bool TryFeed(EntityUid user, EntityUid target, EntityUid food, FoodComponent foodComp)
|
||||||
@@ -87,10 +89,10 @@ namespace Content.Server.Nutrition.EntitySystems
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Target can't be fed or they're already eating
|
// Target can't be fed or they're already eating
|
||||||
if (!EntityManager.HasComponent<BodyComponent>(target) || foodComp.Eating)
|
if (!EntityManager.HasComponent<BodyComponent>(target))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!_solutionContainerSystem.TryGetSolution(food, foodComp.SolutionName, out var foodSolution))
|
if (!_solutionContainerSystem.TryGetSolution(food, foodComp.SolutionName, out var foodSolution) || foodSolution.Name == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var flavors = _flavorProfileSystem.GetLocalizedFlavorsMessage(food, user, foodSolution);
|
var flavors = _flavorProfileSystem.GetLocalizedFlavorsMessage(food, user, foodSolution);
|
||||||
@@ -105,16 +107,15 @@ namespace Content.Server.Nutrition.EntitySystems
|
|||||||
if (IsMouthBlocked(target, user))
|
if (IsMouthBlocked(target, user))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!TryGetRequiredUtensils(user, foodComp, out var utensils))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!_interactionSystem.InRangeUnobstructed(user, food, popup: true))
|
if (!_interactionSystem.InRangeUnobstructed(user, food, popup: true))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
foodComp.Eating = true;
|
if (!TryGetRequiredUtensils(user, foodComp, out _))
|
||||||
foodComp.ForceFeed = user != target;
|
return true;
|
||||||
|
|
||||||
if (foodComp.ForceFeed)
|
var forceFeed = user != target;
|
||||||
|
|
||||||
|
if (forceFeed)
|
||||||
{
|
{
|
||||||
var userName = Identity.Entity(user, EntityManager);
|
var userName = Identity.Entity(user, EntityManager);
|
||||||
_popupSystem.PopupEntity(Loc.GetString("food-system-force-feed", ("user", userName)),
|
_popupSystem.PopupEntity(Loc.GetString("food-system-force-feed", ("user", userName)),
|
||||||
@@ -129,38 +130,31 @@ namespace Content.Server.Nutrition.EntitySystems
|
|||||||
_adminLogger.Add(LogType.Ingestion, LogImpact.Low, $"{ToPrettyString(target):target} is eating {ToPrettyString(food):food} {SolutionContainerSystem.ToPrettyString(foodSolution)}");
|
_adminLogger.Add(LogType.Ingestion, LogImpact.Low, $"{ToPrettyString(target):target} is eating {ToPrettyString(food):food} {SolutionContainerSystem.ToPrettyString(foodSolution)}");
|
||||||
}
|
}
|
||||||
|
|
||||||
var foodData = new FoodData(foodSolution, flavors, utensils);
|
var doAfterEventArgs = new DoAfterArgs(
|
||||||
|
user,
|
||||||
var doAfterEventArgs = new DoAfterEventArgs(user, foodComp.ForceFeed ? foodComp.ForceFeedDelay : foodComp.Delay, target: target, used: food)
|
forceFeed ? foodComp.ForceFeedDelay : foodComp.Delay,
|
||||||
|
new ConsumeDoAfterEvent(foodSolution.Name, flavors),
|
||||||
|
eventTarget: food,
|
||||||
|
target: target,
|
||||||
|
used: food)
|
||||||
{
|
{
|
||||||
RaiseOnTarget = foodComp.ForceFeed,
|
BreakOnUserMove = forceFeed,
|
||||||
RaiseOnUser = false, //causes a crash if mice eat if true
|
|
||||||
BreakOnUserMove = foodComp.ForceFeed,
|
|
||||||
BreakOnDamage = true,
|
BreakOnDamage = true,
|
||||||
BreakOnStun = true,
|
BreakOnTargetMove = forceFeed,
|
||||||
BreakOnTargetMove = foodComp.ForceFeed,
|
|
||||||
MovementThreshold = 0.01f,
|
MovementThreshold = 0.01f,
|
||||||
DistanceThreshold = 1.0f,
|
DistanceThreshold = 1.0f,
|
||||||
NeedHand = true
|
// Mice and the like can eat without hands.
|
||||||
|
// TODO maybe set this based on some CanEatWithoutHands event or component?
|
||||||
|
NeedHand = forceFeed,
|
||||||
};
|
};
|
||||||
|
|
||||||
_doAfterSystem.DoAfter(doAfterEventArgs, foodData);
|
_doAfterSystem.TryStartDoAfter(doAfterEventArgs);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDoAfter(EntityUid uid, FoodComponent component, DoAfterEvent<FoodData> args)
|
private void OnDoAfter(EntityUid uid, FoodComponent component, ConsumeDoAfterEvent args)
|
||||||
{
|
{
|
||||||
//Prevents the target from being force fed food but allows the user to chow down
|
if (args.Cancelled || args.Handled || component.Deleted || args.Args.Target == null)
|
||||||
if (args.Cancelled)
|
|
||||||
{
|
|
||||||
component.Eating = false;
|
|
||||||
component.ForceFeed = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args.Handled || component.Deleted || args.Args.Target == null)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!TryComp<BodyComponent>(args.Args.Target.Value, out var body))
|
if (!TryComp<BodyComponent>(args.Args.Target.Value, out var body))
|
||||||
@@ -169,29 +163,36 @@ namespace Content.Server.Nutrition.EntitySystems
|
|||||||
if (!_bodySystem.TryGetBodyOrganComponents<StomachComponent>(args.Args.Target.Value, out var stomachs, body))
|
if (!_bodySystem.TryGetBodyOrganComponents<StomachComponent>(args.Args.Target.Value, out var stomachs, body))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
component.Eating = false;
|
if (!_solutionContainerSystem.TryGetSolution(args.Used, args.Solution, out var solution))
|
||||||
|
return;
|
||||||
|
|
||||||
var transferAmount = component.TransferAmount != null ? FixedPoint2.Min((FixedPoint2) component.TransferAmount, args.AdditionalData.FoodSolution.Volume) : args.AdditionalData.FoodSolution.Volume;
|
if (!TryGetRequiredUtensils(args.User, component, out var utensils))
|
||||||
|
return;
|
||||||
|
|
||||||
var split = _solutionContainerSystem.SplitSolution(uid, args.AdditionalData.FoodSolution, transferAmount);
|
args.Handled = true;
|
||||||
|
|
||||||
|
var transferAmount = component.TransferAmount != null ? FixedPoint2.Min((FixedPoint2) component.TransferAmount, solution.Volume) : solution.Volume;
|
||||||
|
|
||||||
|
var split = _solutionContainerSystem.SplitSolution(uid, solution, transferAmount);
|
||||||
//TODO: Get the stomach UID somehow without nabbing owner
|
//TODO: Get the stomach UID somehow without nabbing owner
|
||||||
var firstStomach = stomachs.FirstOrNull(stomach => _stomachSystem.CanTransferSolution(stomach.Comp.Owner, split));
|
var firstStomach = stomachs.FirstOrNull(stomach => _stomachSystem.CanTransferSolution(stomach.Comp.Owner, split));
|
||||||
|
|
||||||
|
var forceFeed = args.User != args.Target;
|
||||||
|
|
||||||
// No stomach so just popup a message that they can't eat.
|
// No stomach so just popup a message that they can't eat.
|
||||||
if (firstStomach == null)
|
if (firstStomach == null)
|
||||||
{
|
{
|
||||||
_solutionContainerSystem.TryAddSolution(uid, args.AdditionalData.FoodSolution, split);
|
_solutionContainerSystem.TryAddSolution(uid, solution, split);
|
||||||
_popupSystem.PopupEntity(component.ForceFeed ? Loc.GetString("food-system-you-cannot-eat-any-more-other") : Loc.GetString("food-system-you-cannot-eat-any-more"), args.Args.Target.Value, args.Args.User);
|
_popupSystem.PopupEntity(forceFeed ? Loc.GetString("food-system-you-cannot-eat-any-more-other") : Loc.GetString("food-system-you-cannot-eat-any-more"), args.Args.Target.Value, args.Args.User);
|
||||||
args.Handled = true;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_reaction.DoEntityReaction(args.Args.Target.Value, args.AdditionalData.FoodSolution, ReactionMethod.Ingestion);
|
_reaction.DoEntityReaction(args.Args.Target.Value, solution, ReactionMethod.Ingestion);
|
||||||
_stomachSystem.TryTransferSolution(firstStomach.Value.Comp.Owner, split, firstStomach.Value.Comp);
|
_stomachSystem.TryTransferSolution(firstStomach.Value.Comp.Owner, split, firstStomach.Value.Comp);
|
||||||
|
|
||||||
var flavors = args.AdditionalData.FlavorMessage;
|
var flavors = args.FlavorMessage;
|
||||||
|
|
||||||
if (component.ForceFeed)
|
if (forceFeed)
|
||||||
{
|
{
|
||||||
var targetName = Identity.Entity(args.Args.Target.Value, EntityManager);
|
var targetName = Identity.Entity(args.Args.Target.Value, EntityManager);
|
||||||
var userName = Identity.Entity(args.Args.User, EntityManager);
|
var userName = Identity.Entity(args.Args.User, EntityManager);
|
||||||
@@ -202,7 +203,6 @@ namespace Content.Server.Nutrition.EntitySystems
|
|||||||
|
|
||||||
// log successful force feed
|
// log successful force feed
|
||||||
_adminLogger.Add(LogType.ForceFeed, LogImpact.Medium, $"{ToPrettyString(uid):user} forced {ToPrettyString(args.Args.User):target} to eat {ToPrettyString(uid):food}");
|
_adminLogger.Add(LogType.ForceFeed, LogImpact.Medium, $"{ToPrettyString(uid):user} forced {ToPrettyString(args.Args.User):target} to eat {ToPrettyString(uid):food}");
|
||||||
component.ForceFeed = false;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -215,26 +215,19 @@ namespace Content.Server.Nutrition.EntitySystems
|
|||||||
_audio.Play(component.UseSound, Filter.Pvs(args.Args.Target.Value), args.Args.Target.Value, true, AudioParams.Default.WithVolume(-1f));
|
_audio.Play(component.UseSound, Filter.Pvs(args.Args.Target.Value), args.Args.Target.Value, true, AudioParams.Default.WithVolume(-1f));
|
||||||
|
|
||||||
// Try to break all used utensils
|
// Try to break all used utensils
|
||||||
//TODO: Replace utensil owner with actual UID
|
foreach (var utensil in utensils)
|
||||||
foreach (var utensil in args.AdditionalData.Utensils)
|
|
||||||
{
|
{
|
||||||
_utensilSystem.TryBreak(utensil.Owner, args.Args.User);
|
_utensilSystem.TryBreak(utensil, args.Args.User);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (component.UsesRemaining > 0)
|
if (component.UsesRemaining > 0)
|
||||||
{
|
|
||||||
args.Handled = true;
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(component.TrashPrototype))
|
if (string.IsNullOrEmpty(component.TrashPrototype))
|
||||||
EntityManager.QueueDeleteEntity(uid);
|
EntityManager.QueueDeleteEntity(uid);
|
||||||
|
|
||||||
else
|
else
|
||||||
DeleteAndSpawnTrash(component, uid, args.Args.User);
|
DeleteAndSpawnTrash(component, uid, args.Args.User);
|
||||||
|
|
||||||
args.Handled = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DeleteAndSpawnTrash(FoodComponent component, EntityUid food, EntityUid? user = null)
|
private void DeleteAndSpawnTrash(FoodComponent component, EntityUid food, EntityUid? user = null)
|
||||||
@@ -329,9 +322,9 @@ namespace Content.Server.Nutrition.EntitySystems
|
|||||||
}
|
}
|
||||||
|
|
||||||
private bool TryGetRequiredUtensils(EntityUid user, FoodComponent component,
|
private bool TryGetRequiredUtensils(EntityUid user, FoodComponent component,
|
||||||
out List<UtensilComponent> utensils, HandsComponent? hands = null)
|
out List<EntityUid> utensils, HandsComponent? hands = null)
|
||||||
{
|
{
|
||||||
utensils = new List<UtensilComponent>();
|
utensils = new List<EntityUid>();
|
||||||
|
|
||||||
if (component.Utensil != UtensilType.None)
|
if (component.Utensil != UtensilType.None)
|
||||||
return true;
|
return true;
|
||||||
@@ -352,7 +345,7 @@ namespace Content.Server.Nutrition.EntitySystems
|
|||||||
{
|
{
|
||||||
// Add to used list
|
// Add to used list
|
||||||
usedTypes |= utensil.Types;
|
usedTypes |= utensil.Types;
|
||||||
utensils.Add(utensil);
|
utensils.Add(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -415,12 +408,5 @@ namespace Content.Server.Nutrition.EntitySystems
|
|||||||
|
|
||||||
return attempt.Cancelled;
|
return attempt.Cancelled;
|
||||||
}
|
}
|
||||||
|
|
||||||
private record struct FoodData(Solution FoodSolution, string FlavorMessage, List<UtensilComponent> Utensils)
|
|
||||||
{
|
|
||||||
public readonly Solution FoodSolution = FoodSolution;
|
|
||||||
public readonly string FlavorMessage = FlavorMessage;
|
|
||||||
public readonly List<UtensilComponent> Utensils = Utensils;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,11 +4,13 @@ using Content.Server.Power.Components;
|
|||||||
using Content.Shared.Access.Components;
|
using Content.Shared.Access.Components;
|
||||||
using Content.Shared.Access.Systems;
|
using Content.Shared.Access.Systems;
|
||||||
using Content.Shared.APC;
|
using Content.Shared.APC;
|
||||||
|
using Content.Shared.DoAfter;
|
||||||
using Content.Shared.Emag.Components;
|
using Content.Shared.Emag.Components;
|
||||||
using Content.Shared.Emag.Systems;
|
using Content.Shared.Emag.Systems;
|
||||||
using Content.Shared.Examine;
|
using Content.Shared.Examine;
|
||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
using Content.Shared.Popups;
|
using Content.Shared.Popups;
|
||||||
|
using Content.Shared.Power;
|
||||||
using Content.Shared.Tools;
|
using Content.Shared.Tools;
|
||||||
using Content.Shared.Tools.Components;
|
using Content.Shared.Tools.Components;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
@@ -28,6 +30,7 @@ namespace Content.Server.Power.EntitySystems
|
|||||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||||
[Dependency] private readonly SharedToolSystem _toolSystem = default!;
|
[Dependency] private readonly SharedToolSystem _toolSystem = default!;
|
||||||
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
||||||
|
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||||
|
|
||||||
private const float ScrewTime = 2f;
|
private const float ScrewTime = 2f;
|
||||||
|
|
||||||
@@ -43,7 +46,7 @@ namespace Content.Server.Power.EntitySystems
|
|||||||
SubscribeLocalEvent<ApcComponent, ApcToggleMainBreakerMessage>(OnToggleMainBreaker);
|
SubscribeLocalEvent<ApcComponent, ApcToggleMainBreakerMessage>(OnToggleMainBreaker);
|
||||||
SubscribeLocalEvent<ApcComponent, GotEmaggedEvent>(OnEmagged);
|
SubscribeLocalEvent<ApcComponent, GotEmaggedEvent>(OnEmagged);
|
||||||
|
|
||||||
SubscribeLocalEvent<ApcToolFinishedEvent>(OnToolFinished);
|
SubscribeLocalEvent<ApcComponent, ApcToolFinishedEvent>(OnToolFinished);
|
||||||
SubscribeLocalEvent<ApcComponent, InteractUsingEvent>(OnInteractUsing);
|
SubscribeLocalEvent<ApcComponent, InteractUsingEvent>(OnInteractUsing);
|
||||||
SubscribeLocalEvent<ApcComponent, ExaminedEvent>(OnExamine);
|
SubscribeLocalEvent<ApcComponent, ExaminedEvent>(OnExamine);
|
||||||
|
|
||||||
@@ -220,27 +223,21 @@ namespace Content.Server.Power.EntitySystems
|
|||||||
if (!EntityManager.TryGetComponent(args.Used, out ToolComponent? tool))
|
if (!EntityManager.TryGetComponent(args.Used, out ToolComponent? tool))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var toolEvData = new ToolEventData(new ApcToolFinishedEvent(uid), fuel: 0f);
|
if (_toolSystem.UseTool(args.Used, args.User, uid, ScrewTime, "Screwing", new ApcToolFinishedEvent(), toolComponent:tool))
|
||||||
|
|
||||||
if (_toolSystem.UseTool(args.Used, args.User, uid, ScrewTime, new [] { "Screwing" }, toolEvData, toolComponent:tool))
|
|
||||||
args.Handled = true;
|
args.Handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnToolFinished(ApcToolFinishedEvent args)
|
private void OnToolFinished(EntityUid uid, ApcComponent component, ApcToolFinishedEvent args)
|
||||||
{
|
{
|
||||||
if (!EntityManager.TryGetComponent(args.Target, out ApcComponent? component))
|
if (!args.Cancelled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
component.IsApcOpen = !component.IsApcOpen;
|
component.IsApcOpen = !component.IsApcOpen;
|
||||||
|
UpdatePanelAppearance(uid, apc: component);
|
||||||
|
|
||||||
if (TryComp(args.Target, out AppearanceComponent? appearance))
|
// this will play on top of the normal screw driver tool sound.
|
||||||
{
|
var sound = component.IsApcOpen ? component.ScrewdriverOpenSound : component.ScrewdriverCloseSound;
|
||||||
UpdatePanelAppearance(args.Target, appearance);
|
_audio.PlayPvs(sound, uid);
|
||||||
}
|
|
||||||
|
|
||||||
if (component.IsApcOpen)
|
|
||||||
SoundSystem.Play(component.ScrewdriverOpenSound.GetSound(), Filter.Pvs(args.Target), args.Target);
|
|
||||||
else
|
|
||||||
SoundSystem.Play(component.ScrewdriverCloseSound.GetSound(), Filter.Pvs(args.Target), args.Target);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdatePanelAppearance(EntityUid uid, AppearanceComponent? appearance = null, ApcComponent? apc = null)
|
private void UpdatePanelAppearance(EntityUid uid, AppearanceComponent? appearance = null, ApcComponent? apc = null)
|
||||||
@@ -251,16 +248,6 @@ namespace Content.Server.Power.EntitySystems
|
|||||||
_appearance.SetData(uid, ApcVisuals.PanelState, GetPanelState(apc), appearance);
|
_appearance.SetData(uid, ApcVisuals.PanelState, GetPanelState(apc), appearance);
|
||||||
}
|
}
|
||||||
|
|
||||||
private sealed class ApcToolFinishedEvent : EntityEventArgs
|
|
||||||
{
|
|
||||||
public EntityUid Target { get; }
|
|
||||||
|
|
||||||
public ApcToolFinishedEvent(EntityUid target)
|
|
||||||
{
|
|
||||||
Target = target;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnExamine(EntityUid uid, ApcComponent component, ExaminedEvent args)
|
private void OnExamine(EntityUid uid, ApcComponent component, ExaminedEvent args)
|
||||||
{
|
{
|
||||||
args.PushMarkup(Loc.GetString(component.IsApcOpen
|
args.PushMarkup(Loc.GetString(component.IsApcOpen
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using Content.Server.Electrocution;
|
|||||||
using Content.Server.Power.Components;
|
using Content.Server.Power.Components;
|
||||||
using Content.Server.Stack;
|
using Content.Server.Stack;
|
||||||
using Content.Shared.Database;
|
using Content.Shared.Database;
|
||||||
|
using Content.Shared.DoAfter;
|
||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
using Content.Shared.Tools;
|
using Content.Shared.Tools;
|
||||||
using Content.Shared.Tools.Components;
|
using Content.Shared.Tools.Components;
|
||||||
@@ -26,7 +27,7 @@ public sealed partial class CableSystem : EntitySystem
|
|||||||
InitializeCablePlacer();
|
InitializeCablePlacer();
|
||||||
|
|
||||||
SubscribeLocalEvent<CableComponent, InteractUsingEvent>(OnInteractUsing);
|
SubscribeLocalEvent<CableComponent, InteractUsingEvent>(OnInteractUsing);
|
||||||
SubscribeLocalEvent<CableComponent, CuttingFinishedEvent>(OnCableCut);
|
SubscribeLocalEvent<CableComponent, CableCuttingFinishedEvent>(OnCableCut);
|
||||||
// Shouldn't need re-anchoring.
|
// Shouldn't need re-anchoring.
|
||||||
SubscribeLocalEvent<CableComponent, AnchorStateChangedEvent>(OnAnchorChanged);
|
SubscribeLocalEvent<CableComponent, AnchorStateChangedEvent>(OnAnchorChanged);
|
||||||
}
|
}
|
||||||
@@ -36,12 +37,14 @@ public sealed partial class CableSystem : EntitySystem
|
|||||||
if (args.Handled)
|
if (args.Handled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var toolEvData = new ToolEventData(new CuttingFinishedEvent(args.User), targetEntity: uid);
|
args.Handled = _toolSystem.UseTool(args.Used, args.User, uid, cable.CuttingDelay, cable.CuttingQuality, new CableCuttingFinishedEvent());
|
||||||
args.Handled = _toolSystem.UseTool(args.Used, args.User, uid, cable.CuttingDelay, new[] { cable.CuttingQuality }, toolEvData);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnCableCut(EntityUid uid, CableComponent cable, CuttingFinishedEvent args)
|
private void OnCableCut(EntityUid uid, CableComponent cable, DoAfterEvent args)
|
||||||
{
|
{
|
||||||
|
if (args.Cancelled)
|
||||||
|
return;
|
||||||
|
|
||||||
if (_electrocutionSystem.TryDoElectrifiedAct(uid, args.User))
|
if (_electrocutionSystem.TryDoElectrifiedAct(uid, args.User))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -67,13 +70,3 @@ public sealed partial class CableSystem : EntitySystem
|
|||||||
QueueDel(uid);
|
QueueDel(uid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class CuttingFinishedEvent : EntityEventArgs
|
|
||||||
{
|
|
||||||
public EntityUid User;
|
|
||||||
|
|
||||||
public CuttingFinishedEvent(EntityUid user)
|
|
||||||
{
|
|
||||||
User = user;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -39,7 +39,5 @@ namespace Content.Server.RCD.Components
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[ViewVariables(VVAccess.ReadWrite)] [DataField("ammo")]
|
[ViewVariables(VVAccess.ReadWrite)] [DataField("ammo")]
|
||||||
public int CurrentAmmo = DefaultAmmoCount;
|
public int CurrentAmmo = DefaultAmmoCount;
|
||||||
|
|
||||||
public CancellationTokenSource? CancelToken = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
using System.Threading;
|
|
||||||
using Content.Server.Administration.Logs;
|
using Content.Server.Administration.Logs;
|
||||||
using Content.Server.DoAfter;
|
|
||||||
using Content.Server.Popups;
|
using Content.Server.Popups;
|
||||||
using Content.Server.RCD.Components;
|
using Content.Server.RCD.Components;
|
||||||
using Content.Shared.Database;
|
using Content.Shared.Database;
|
||||||
@@ -23,7 +21,7 @@ namespace Content.Server.RCD.Systems
|
|||||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||||
|
|
||||||
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
|
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
|
||||||
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
|
||||||
[Dependency] private readonly SharedInteractionSystem _interactionSystem = default!;
|
[Dependency] private readonly SharedInteractionSystem _interactionSystem = default!;
|
||||||
[Dependency] private readonly PopupSystem _popup = default!;
|
[Dependency] private readonly PopupSystem _popup = default!;
|
||||||
[Dependency] private readonly TagSystem _tagSystem = default!;
|
[Dependency] private readonly TagSystem _tagSystem = default!;
|
||||||
@@ -59,14 +57,6 @@ namespace Content.Server.RCD.Systems
|
|||||||
if (args.Handled || !args.CanReach)
|
if (args.Handled || !args.CanReach)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (rcd.CancelToken != null)
|
|
||||||
{
|
|
||||||
rcd.CancelToken?.Cancel();
|
|
||||||
rcd.CancelToken = null;
|
|
||||||
args.Handled = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!args.ClickLocation.IsValid(EntityManager)) return;
|
if (!args.ClickLocation.IsValid(EntityManager)) return;
|
||||||
|
|
||||||
var clickLocationMod = args.ClickLocation;
|
var clickLocationMod = args.ClickLocation;
|
||||||
@@ -96,19 +86,15 @@ namespace Content.Server.RCD.Systems
|
|||||||
var user = args.User;
|
var user = args.User;
|
||||||
|
|
||||||
//Using an RCD isn't instantaneous
|
//Using an RCD isn't instantaneous
|
||||||
rcd.CancelToken = new CancellationTokenSource();
|
var doAfterEventArgs = new DoAfterArgs(user, rcd.Delay, new AwaitedDoAfterEvent(), null, target: args.Target)
|
||||||
var doAfterEventArgs = new DoAfterEventArgs(user, rcd.Delay, rcd.CancelToken.Token, args.Target)
|
|
||||||
{
|
{
|
||||||
BreakOnDamage = true,
|
BreakOnDamage = true,
|
||||||
BreakOnStun = true,
|
|
||||||
NeedHand = true,
|
NeedHand = true,
|
||||||
ExtraCheck = () => IsRCDStillValid(rcd, args, mapGrid, tile, startingMode) //All of the sanity checks are here
|
ExtraCheck = () => IsRCDStillValid(rcd, args, mapGrid, tile, startingMode) //All of the sanity checks are here
|
||||||
};
|
};
|
||||||
|
|
||||||
var result = await _doAfterSystem.WaitDoAfter(doAfterEventArgs);
|
var result = await _doAfterSystem.WaitDoAfter(doAfterEventArgs);
|
||||||
|
|
||||||
rcd.CancelToken = null;
|
|
||||||
|
|
||||||
if (result == DoAfterStatus.Cancelled)
|
if (result == DoAfterStatus.Cancelled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
using Content.Server.Administration.Logs;
|
using Content.Server.Administration.Logs;
|
||||||
using Content.Shared.Damage;
|
using Content.Shared.Damage;
|
||||||
using Content.Shared.Database;
|
using Content.Shared.Database;
|
||||||
|
using Content.Shared.DoAfter;
|
||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
using Content.Shared.Popups;
|
using Content.Shared.Popups;
|
||||||
|
using Content.Shared.Repairable;
|
||||||
using Content.Shared.Tools;
|
using Content.Shared.Tools;
|
||||||
using Content.Shared.Tools.Components;
|
using Content.Shared.Tools.Components;
|
||||||
|
|
||||||
namespace Content.Server.Repairable
|
namespace Content.Server.Repairable
|
||||||
{
|
{
|
||||||
public sealed class RepairableSystem : EntitySystem
|
public sealed class RepairableSystem : SharedRepairableSystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly SharedToolSystem _toolSystem = default!;
|
[Dependency] private readonly SharedToolSystem _toolSystem = default!;
|
||||||
[Dependency] private readonly DamageableSystem _damageableSystem = default!;
|
[Dependency] private readonly DamageableSystem _damageableSystem = default!;
|
||||||
@@ -22,6 +24,9 @@ namespace Content.Server.Repairable
|
|||||||
|
|
||||||
private void OnRepairFinished(EntityUid uid, RepairableComponent component, RepairFinishedEvent args)
|
private void OnRepairFinished(EntityUid uid, RepairableComponent component, RepairFinishedEvent args)
|
||||||
{
|
{
|
||||||
|
if (args.Cancelled)
|
||||||
|
return;
|
||||||
|
|
||||||
if (!EntityManager.TryGetComponent(uid, out DamageableComponent? damageable) || damageable.TotalDamage == 0)
|
if (!EntityManager.TryGetComponent(uid, out DamageableComponent? damageable) || damageable.TotalDamage == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -38,15 +43,17 @@ namespace Content.Server.Repairable
|
|||||||
_adminLogger.Add(LogType.Healed, $"{ToPrettyString(args.User):user} repaired {ToPrettyString(uid):target} back to full health");
|
_adminLogger.Add(LogType.Healed, $"{ToPrettyString(args.User):user} repaired {ToPrettyString(uid):target} back to full health");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uid.PopupMessage(args.User,
|
uid.PopupMessage(args.User,
|
||||||
Loc.GetString("comp-repairable-repair",
|
Loc.GetString("comp-repairable-repair",
|
||||||
("target", uid),
|
("target", uid),
|
||||||
("tool", args.Used)));
|
("tool", args.Used!)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public async void Repair(EntityUid uid, RepairableComponent component, InteractUsingEvent args)
|
public async void Repair(EntityUid uid, RepairableComponent component, InteractUsingEvent args)
|
||||||
{
|
{
|
||||||
|
if (args.Handled)
|
||||||
|
return;
|
||||||
|
|
||||||
// Only try repair the target if it is damaged
|
// Only try repair the target if it is damaged
|
||||||
if (!EntityManager.TryGetComponent(uid, out DamageableComponent? damageable) || damageable.TotalDamage == 0)
|
if (!EntityManager.TryGetComponent(uid, out DamageableComponent? damageable) || damageable.TotalDamage == 0)
|
||||||
return;
|
return;
|
||||||
@@ -57,25 +64,8 @@ namespace Content.Server.Repairable
|
|||||||
if (args.User == args.Target)
|
if (args.User == args.Target)
|
||||||
delay *= component.SelfRepairPenalty;
|
delay *= component.SelfRepairPenalty;
|
||||||
|
|
||||||
var toolEvData = new ToolEventData(new RepairFinishedEvent(args.User, args.Used), component.FuelCost, targetEntity:uid);
|
|
||||||
|
|
||||||
// Can the tool actually repair this, does it have enough fuel?
|
// Can the tool actually repair this, does it have enough fuel?
|
||||||
if (!_toolSystem.UseTool(args.Used, args.User, uid, delay, component.QualityNeeded, toolEvData, component.FuelCost))
|
args.Handled = !_toolSystem.UseTool(args.Used, args.User, uid, delay, component.QualityNeeded, new RepairFinishedEvent(), component.FuelCost);
|
||||||
return;
|
|
||||||
|
|
||||||
args.Handled = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public sealed class RepairFinishedEvent : EntityEventArgs
|
|
||||||
{
|
|
||||||
public EntityUid User;
|
|
||||||
public EntityUid Used;
|
|
||||||
|
|
||||||
public RepairFinishedEvent(EntityUid user, EntityUid used)
|
|
||||||
{
|
|
||||||
User = user;
|
|
||||||
Used = used;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System.Threading;
|
using Content.Shared.DoAfter;
|
||||||
|
|
||||||
namespace Content.Server.Resist;
|
namespace Content.Server.Resist;
|
||||||
|
|
||||||
@@ -11,8 +11,8 @@ public sealed class CanEscapeInventoryComponent : Component
|
|||||||
[DataField("baseResistTime")]
|
[DataField("baseResistTime")]
|
||||||
public float BaseResistTime = 5f;
|
public float BaseResistTime = 5f;
|
||||||
|
|
||||||
[DataField("isEscaping")]
|
public bool IsEscaping => DoAfter != null;
|
||||||
public bool IsEscaping;
|
|
||||||
|
|
||||||
public CancellationTokenSource? CancelToken;
|
[DataField("doAfter")]
|
||||||
|
public DoAfterId? DoAfter;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
using System.Threading;
|
|
||||||
using Content.Server.DoAfter;
|
|
||||||
using Content.Server.Contests;
|
using Content.Server.Contests;
|
||||||
using Robust.Shared.Containers;
|
using Robust.Shared.Containers;
|
||||||
using Content.Server.Popups;
|
using Content.Server.Popups;
|
||||||
@@ -10,12 +8,13 @@ using Content.Shared.ActionBlocker;
|
|||||||
using Content.Shared.DoAfter;
|
using Content.Shared.DoAfter;
|
||||||
using Content.Shared.Movement.Events;
|
using Content.Shared.Movement.Events;
|
||||||
using Content.Shared.Interaction.Events;
|
using Content.Shared.Interaction.Events;
|
||||||
|
using Content.Shared.Resist;
|
||||||
|
|
||||||
namespace Content.Server.Resist;
|
namespace Content.Server.Resist;
|
||||||
|
|
||||||
public sealed class EscapeInventorySystem : EntitySystem
|
public sealed class EscapeInventorySystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
|
||||||
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
||||||
[Dependency] private readonly SharedContainerSystem _containerSystem = default!;
|
[Dependency] private readonly SharedContainerSystem _containerSystem = default!;
|
||||||
[Dependency] private readonly ActionBlockerSystem _actionBlockerSystem = default!;
|
[Dependency] private readonly ActionBlockerSystem _actionBlockerSystem = default!;
|
||||||
@@ -32,7 +31,7 @@ public sealed class EscapeInventorySystem : EntitySystem
|
|||||||
base.Initialize();
|
base.Initialize();
|
||||||
|
|
||||||
SubscribeLocalEvent<CanEscapeInventoryComponent, MoveInputEvent>(OnRelayMovement);
|
SubscribeLocalEvent<CanEscapeInventoryComponent, MoveInputEvent>(OnRelayMovement);
|
||||||
SubscribeLocalEvent<CanEscapeInventoryComponent, DoAfterEvent<EscapeInventoryEvent>>(OnEscape);
|
SubscribeLocalEvent<CanEscapeInventoryComponent, EscapeInventoryEvent>(OnEscape);
|
||||||
SubscribeLocalEvent<CanEscapeInventoryComponent, DroppedEvent>(OnDropped);
|
SubscribeLocalEvent<CanEscapeInventoryComponent, DroppedEvent>(OnDropped);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,50 +68,37 @@ public sealed class EscapeInventorySystem : EntitySystem
|
|||||||
if (component.IsEscaping)
|
if (component.IsEscaping)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
component.CancelToken = new CancellationTokenSource();
|
var doAfterEventArgs = new DoAfterArgs(user, component.BaseResistTime * multiplier, new EscapeInventoryEvent(), user, target: container)
|
||||||
component.IsEscaping = true;
|
|
||||||
var escapeEvent = new EscapeInventoryEvent();
|
|
||||||
var doAfterEventArgs = new DoAfterEventArgs(user, component.BaseResistTime * multiplier, cancelToken: component.CancelToken.Token, target:container)
|
|
||||||
{
|
{
|
||||||
BreakOnTargetMove = false,
|
BreakOnTargetMove = false,
|
||||||
BreakOnUserMove = true,
|
BreakOnUserMove = true,
|
||||||
BreakOnDamage = true,
|
BreakOnDamage = true,
|
||||||
BreakOnStun = true,
|
|
||||||
NeedHand = false
|
NeedHand = false
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (!_doAfterSystem.TryStartDoAfter(doAfterEventArgs, out component.DoAfter))
|
||||||
|
return;
|
||||||
|
|
||||||
|
Dirty(component);
|
||||||
_popupSystem.PopupEntity(Loc.GetString("escape-inventory-component-start-resisting"), user, user);
|
_popupSystem.PopupEntity(Loc.GetString("escape-inventory-component-start-resisting"), user, user);
|
||||||
_popupSystem.PopupEntity(Loc.GetString("escape-inventory-component-start-resisting-target"), container, container);
|
_popupSystem.PopupEntity(Loc.GetString("escape-inventory-component-start-resisting-target"), container, container);
|
||||||
_doAfterSystem.DoAfter(doAfterEventArgs, escapeEvent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnEscape(EntityUid uid, CanEscapeInventoryComponent component, DoAfterEvent<EscapeInventoryEvent> args)
|
private void OnEscape(EntityUid uid, CanEscapeInventoryComponent component, EscapeInventoryEvent args)
|
||||||
{
|
{
|
||||||
if (args.Cancelled)
|
component.DoAfter = null;
|
||||||
{
|
Dirty(component);
|
||||||
component.CancelToken = null;
|
|
||||||
component.IsEscaping = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args.Handled)
|
if (args.Handled || args.Cancelled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Transform(uid).AttachParentToContainerOrGrid(EntityManager);
|
Transform(uid).AttachParentToContainerOrGrid(EntityManager);
|
||||||
|
|
||||||
component.CancelToken = null;
|
|
||||||
component.IsEscaping = false;
|
|
||||||
args.Handled = true;
|
args.Handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDropped(EntityUid uid, CanEscapeInventoryComponent component, DroppedEvent args)
|
private void OnDropped(EntityUid uid, CanEscapeInventoryComponent component, DroppedEvent args)
|
||||||
{
|
{
|
||||||
component.CancelToken?.Cancel();
|
if (component.DoAfter != null)
|
||||||
component.CancelToken = null;
|
_doAfterSystem.Cancel(component.DoAfter);
|
||||||
}
|
|
||||||
|
|
||||||
private sealed class EscapeInventoryEvent : EntityEventArgs
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,4 @@ public sealed class ResistLockerComponent : Component
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public bool IsResisting = false;
|
public bool IsResisting = false;
|
||||||
|
|
||||||
public CancellationTokenSource? CancelToken;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
using System.Threading;
|
|
||||||
using Content.Server.DoAfter;
|
|
||||||
using Content.Server.Popups;
|
using Content.Server.Popups;
|
||||||
using Content.Server.Storage.Components;
|
using Content.Server.Storage.Components;
|
||||||
using Content.Server.Storage.EntitySystems;
|
using Content.Server.Storage.EntitySystems;
|
||||||
@@ -7,13 +5,13 @@ using Content.Shared.DoAfter;
|
|||||||
using Content.Shared.Lock;
|
using Content.Shared.Lock;
|
||||||
using Content.Shared.Movement.Events;
|
using Content.Shared.Movement.Events;
|
||||||
using Content.Shared.Popups;
|
using Content.Shared.Popups;
|
||||||
using Robust.Shared.Containers;
|
using Content.Shared.Resist;
|
||||||
|
|
||||||
namespace Content.Server.Resist;
|
namespace Content.Server.Resist;
|
||||||
|
|
||||||
public sealed class ResistLockerSystem : EntitySystem
|
public sealed class ResistLockerSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
|
||||||
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
||||||
[Dependency] private readonly LockSystem _lockSystem = default!;
|
[Dependency] private readonly LockSystem _lockSystem = default!;
|
||||||
[Dependency] private readonly EntityStorageSystem _entityStorage = default!;
|
[Dependency] private readonly EntityStorageSystem _entityStorage = default!;
|
||||||
@@ -22,8 +20,7 @@ public sealed class ResistLockerSystem : EntitySystem
|
|||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
SubscribeLocalEvent<ResistLockerComponent, ContainerRelayMovementEntityEvent>(OnRelayMovement);
|
SubscribeLocalEvent<ResistLockerComponent, ContainerRelayMovementEntityEvent>(OnRelayMovement);
|
||||||
SubscribeLocalEvent<ResistLockerComponent, DoAfterEvent<LockerDoAfterData>>(OnDoAfter);
|
SubscribeLocalEvent<ResistLockerComponent, ResistLockerDoAfterEvent>(OnDoAfter);
|
||||||
SubscribeLocalEvent<ResistLockerComponent, EntRemovedFromContainerMessage>(OnRemoved);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnRelayMovement(EntityUid uid, ResistLockerComponent component, ref ContainerRelayMovementEntityEvent args)
|
private void OnRelayMovement(EntityUid uid, ResistLockerComponent component, ref ContainerRelayMovementEntityEvent args)
|
||||||
@@ -45,34 +42,24 @@ public sealed class ResistLockerSystem : EntitySystem
|
|||||||
if (!Resolve(target, ref storageComponent, ref resistLockerComponent))
|
if (!Resolve(target, ref storageComponent, ref resistLockerComponent))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
resistLockerComponent.CancelToken = new CancellationTokenSource();
|
var doAfterEventArgs = new DoAfterArgs(user, resistLockerComponent.ResistTime, new ResistLockerDoAfterEvent(), target, target: target)
|
||||||
|
|
||||||
var doAfterEventArgs = new DoAfterEventArgs(user, resistLockerComponent.ResistTime, cancelToken:resistLockerComponent.CancelToken.Token, target:target)
|
|
||||||
{
|
{
|
||||||
BreakOnTargetMove = false,
|
BreakOnTargetMove = false,
|
||||||
BreakOnUserMove = true,
|
BreakOnUserMove = true,
|
||||||
BreakOnDamage = true,
|
BreakOnDamage = true,
|
||||||
BreakOnStun = true,
|
|
||||||
NeedHand = false //No hands 'cause we be kickin'
|
NeedHand = false //No hands 'cause we be kickin'
|
||||||
};
|
};
|
||||||
|
|
||||||
resistLockerComponent.IsResisting = true;
|
resistLockerComponent.IsResisting = true;
|
||||||
_popupSystem.PopupEntity(Loc.GetString("resist-locker-component-start-resisting"), user, user, PopupType.Large);
|
_popupSystem.PopupEntity(Loc.GetString("resist-locker-component-start-resisting"), user, user, PopupType.Large);
|
||||||
_doAfterSystem.DoAfter(doAfterEventArgs, new LockerDoAfterData());
|
_doAfterSystem.TryStartDoAfter(doAfterEventArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnRemoved(EntityUid uid, ResistLockerComponent component, EntRemovedFromContainerMessage args)
|
private void OnDoAfter(EntityUid uid, ResistLockerComponent component, DoAfterEvent args)
|
||||||
{
|
|
||||||
component.CancelToken?.Cancel();
|
|
||||||
component.CancelToken = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnDoAfter(EntityUid uid, ResistLockerComponent component, DoAfterEvent<LockerDoAfterData> args)
|
|
||||||
{
|
{
|
||||||
if (args.Cancelled)
|
if (args.Cancelled)
|
||||||
{
|
{
|
||||||
component.IsResisting = false;
|
component.IsResisting = false;
|
||||||
component.CancelToken = null;
|
|
||||||
_popupSystem.PopupEntity(Loc.GetString("resist-locker-component-resist-interrupted"), args.Args.User, args.Args.User, PopupType.Medium);
|
_popupSystem.PopupEntity(Loc.GetString("resist-locker-component-resist-interrupted"), args.Args.User, args.Args.User, PopupType.Medium);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -93,11 +80,6 @@ public sealed class ResistLockerSystem : EntitySystem
|
|||||||
_entityStorage.TryOpenStorage(args.Args.User, uid);
|
_entityStorage.TryOpenStorage(args.Args.User, uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
component.CancelToken = null;
|
|
||||||
args.Handled = true;
|
args.Handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private struct LockerDoAfterData
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ using Content.Shared.Mobs;
|
|||||||
using Content.Shared.Mobs.Components;
|
using Content.Shared.Mobs.Components;
|
||||||
using Content.Shared.Mobs.Systems;
|
using Content.Shared.Mobs.Systems;
|
||||||
using Content.Shared.Revenant.Components;
|
using Content.Shared.Revenant.Components;
|
||||||
|
using Content.Shared.Revenant.EntitySystems;
|
||||||
using Robust.Shared.Physics.Components;
|
using Robust.Shared.Physics.Components;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
@@ -46,8 +47,8 @@ public sealed partial class RevenantSystem
|
|||||||
private void InitializeAbilities()
|
private void InitializeAbilities()
|
||||||
{
|
{
|
||||||
SubscribeLocalEvent<RevenantComponent, InteractNoHandEvent>(OnInteract);
|
SubscribeLocalEvent<RevenantComponent, InteractNoHandEvent>(OnInteract);
|
||||||
SubscribeLocalEvent<RevenantComponent, DoAfterEvent<SoulEvent>>(OnSoulSearch);
|
SubscribeLocalEvent<RevenantComponent, SoulEvent>(OnSoulSearch);
|
||||||
SubscribeLocalEvent<RevenantComponent, DoAfterEvent<HarvestEvent>>(OnHarvest);
|
SubscribeLocalEvent<RevenantComponent, HarvestEvent>(OnHarvest);
|
||||||
|
|
||||||
SubscribeLocalEvent<RevenantComponent, RevenantDefileActionEvent>(OnDefileAction);
|
SubscribeLocalEvent<RevenantComponent, RevenantDefileActionEvent>(OnDefileAction);
|
||||||
SubscribeLocalEvent<RevenantComponent, RevenantOverloadLightsActionEvent>(OnOverloadLightsAction);
|
SubscribeLocalEvent<RevenantComponent, RevenantOverloadLightsActionEvent>(OnOverloadLightsAction);
|
||||||
@@ -84,17 +85,19 @@ public sealed partial class RevenantSystem
|
|||||||
|
|
||||||
private void BeginSoulSearchDoAfter(EntityUid uid, EntityUid target, RevenantComponent revenant)
|
private void BeginSoulSearchDoAfter(EntityUid uid, EntityUid target, RevenantComponent revenant)
|
||||||
{
|
{
|
||||||
_popup.PopupEntity(Loc.GetString("revenant-soul-searching", ("target", target)), uid, uid, PopupType.Medium);
|
var searchDoAfter = new DoAfterArgs(uid, revenant.SoulSearchDuration, new SoulEvent(), uid, target: target)
|
||||||
var soulSearchEvent = new SoulEvent();
|
|
||||||
var searchDoAfter = new DoAfterEventArgs(uid, revenant.SoulSearchDuration, target:target)
|
|
||||||
{
|
{
|
||||||
BreakOnUserMove = true,
|
BreakOnUserMove = true,
|
||||||
DistanceThreshold = 2
|
DistanceThreshold = 2
|
||||||
};
|
};
|
||||||
_doAfter.DoAfter(searchDoAfter, soulSearchEvent);
|
|
||||||
|
if (!_doAfter.TryStartDoAfter(searchDoAfter))
|
||||||
|
return;
|
||||||
|
|
||||||
|
_popup.PopupEntity(Loc.GetString("revenant-soul-searching", ("target", target)), uid, uid, PopupType.Medium);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnSoulSearch(EntityUid uid, RevenantComponent component, DoAfterEvent<SoulEvent> args)
|
private void OnSoulSearch(EntityUid uid, RevenantComponent component, SoulEvent args)
|
||||||
{
|
{
|
||||||
if (args.Handled || args.Cancelled)
|
if (args.Handled || args.Cancelled)
|
||||||
return;
|
return;
|
||||||
@@ -135,25 +138,25 @@ public sealed partial class RevenantSystem
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var harvestEvent = new HarvestEvent();
|
var doAfter = new DoAfterArgs(uid, revenant.HarvestDebuffs.X, new HarvestEvent(), uid, target: target)
|
||||||
|
|
||||||
var doAfter = new DoAfterEventArgs(uid, revenant.HarvestDebuffs.X, target:target)
|
|
||||||
{
|
{
|
||||||
DistanceThreshold = 2,
|
DistanceThreshold = 2,
|
||||||
BreakOnUserMove = true,
|
BreakOnUserMove = true,
|
||||||
NeedHand = false
|
RequireCanInteract = false, // stuns itself
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (!_doAfter.TryStartDoAfter(doAfter))
|
||||||
|
return;
|
||||||
|
|
||||||
_appearance.SetData(uid, RevenantVisuals.Harvesting, true);
|
_appearance.SetData(uid, RevenantVisuals.Harvesting, true);
|
||||||
|
|
||||||
_popup.PopupEntity(Loc.GetString("revenant-soul-begin-harvest", ("target", target)),
|
_popup.PopupEntity(Loc.GetString("revenant-soul-begin-harvest", ("target", target)),
|
||||||
target, PopupType.Large);
|
target, PopupType.Large);
|
||||||
|
|
||||||
TryUseAbility(uid, revenant, 0, revenant.HarvestDebuffs);
|
TryUseAbility(uid, revenant, 0, revenant.HarvestDebuffs);
|
||||||
_doAfter.DoAfter(doAfter, harvestEvent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnHarvest(EntityUid uid, RevenantComponent component, DoAfterEvent<HarvestEvent> args)
|
private void OnHarvest(EntityUid uid, RevenantComponent component, HarvestEvent args)
|
||||||
{
|
{
|
||||||
if (args.Cancelled)
|
if (args.Cancelled)
|
||||||
{
|
{
|
||||||
@@ -327,14 +330,4 @@ public sealed partial class RevenantSystem
|
|||||||
_emag.DoEmagEffect(ent, ent); //it emags itself. spooky.
|
_emag.DoEmagEffect(ent, ent); //it emags itself. spooky.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private sealed class SoulEvent : EntityEventArgs
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private sealed class HarvestEvent : EntityEventArgs
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ using Content.Shared.Popups;
|
|||||||
using Content.Shared.Alert;
|
using Content.Shared.Alert;
|
||||||
using Content.Shared.Damage;
|
using Content.Shared.Damage;
|
||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
using Content.Server.DoAfter;
|
|
||||||
using Content.Server.GameTicking;
|
using Content.Server.GameTicking;
|
||||||
using Content.Shared.Stunnable;
|
using Content.Shared.Stunnable;
|
||||||
using Content.Shared.Revenant;
|
using Content.Shared.Revenant;
|
||||||
@@ -17,6 +16,7 @@ using Content.Shared.Actions.ActionTypes;
|
|||||||
using Content.Shared.Tag;
|
using Content.Shared.Tag;
|
||||||
using Content.Server.Store.Components;
|
using Content.Server.Store.Components;
|
||||||
using Content.Server.Store.Systems;
|
using Content.Server.Store.Systems;
|
||||||
|
using Content.Shared.DoAfter;
|
||||||
using Content.Shared.FixedPoint;
|
using Content.Shared.FixedPoint;
|
||||||
using Content.Shared.Maps;
|
using Content.Shared.Maps;
|
||||||
using Content.Shared.Mobs.Systems;
|
using Content.Shared.Mobs.Systems;
|
||||||
@@ -32,7 +32,7 @@ public sealed partial class RevenantSystem : EntitySystem
|
|||||||
[Dependency] private readonly ActionsSystem _action = default!;
|
[Dependency] private readonly ActionsSystem _action = default!;
|
||||||
[Dependency] private readonly AlertsSystem _alerts = default!;
|
[Dependency] private readonly AlertsSystem _alerts = default!;
|
||||||
[Dependency] private readonly DamageableSystem _damage = default!;
|
[Dependency] private readonly DamageableSystem _damage = default!;
|
||||||
[Dependency] private readonly DoAfterSystem _doAfter = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
|
||||||
[Dependency] private readonly EntityLookupSystem _lookup = default!;
|
[Dependency] private readonly EntityLookupSystem _lookup = default!;
|
||||||
[Dependency] private readonly MobStateSystem _mobState = default!;
|
[Dependency] private readonly MobStateSystem _mobState = default!;
|
||||||
[Dependency] private readonly PhysicsSystem _physics = default!;
|
[Dependency] private readonly PhysicsSystem _physics = default!;
|
||||||
|
|||||||
@@ -1,22 +1,20 @@
|
|||||||
using Content.Server.DoAfter;
|
|
||||||
using Content.Server.Popups;
|
using Content.Server.Popups;
|
||||||
using Content.Server.Sticky.Components;
|
using Content.Server.Sticky.Components;
|
||||||
using Content.Server.Sticky.Events;
|
using Content.Server.Sticky.Events;
|
||||||
using Content.Shared.DoAfter;
|
using Content.Shared.DoAfter;
|
||||||
using Content.Shared.Hands.EntitySystems;
|
using Content.Shared.Hands.EntitySystems;
|
||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
|
using Content.Shared.Sticky;
|
||||||
using Content.Shared.Sticky.Components;
|
using Content.Shared.Sticky.Components;
|
||||||
using Content.Shared.Verbs;
|
using Content.Shared.Verbs;
|
||||||
using Robust.Server.GameObjects;
|
|
||||||
using Robust.Shared.Containers;
|
using Robust.Shared.Containers;
|
||||||
using Robust.Shared.Player;
|
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
namespace Content.Server.Sticky.Systems;
|
namespace Content.Server.Sticky.Systems;
|
||||||
|
|
||||||
public sealed class StickySystem : EntitySystem
|
public sealed class StickySystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
|
||||||
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
||||||
[Dependency] private readonly SharedContainerSystem _containerSystem = default!;
|
[Dependency] private readonly SharedContainerSystem _containerSystem = default!;
|
||||||
[Dependency] private readonly SharedHandsSystem _handsSystem = default!;
|
[Dependency] private readonly SharedHandsSystem _handsSystem = default!;
|
||||||
@@ -28,7 +26,7 @@ public sealed class StickySystem : EntitySystem
|
|||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
SubscribeLocalEvent<StickyComponent, DoAfterEvent>(OnStickSuccessful);
|
SubscribeLocalEvent<StickyComponent, StickyDoAfterEvent>(OnStickFinished);
|
||||||
SubscribeLocalEvent<StickyComponent, AfterInteractEvent>(OnAfterInteract);
|
SubscribeLocalEvent<StickyComponent, AfterInteractEvent>(OnAfterInteract);
|
||||||
SubscribeLocalEvent<StickyComponent, GetVerbsEvent<Verb>>(AddUnstickVerb);
|
SubscribeLocalEvent<StickyComponent, GetVerbsEvent<Verb>>(AddUnstickVerb);
|
||||||
}
|
}
|
||||||
@@ -88,9 +86,8 @@ public sealed class StickySystem : EntitySystem
|
|||||||
component.Stick = true;
|
component.Stick = true;
|
||||||
|
|
||||||
// start sticking object to target
|
// start sticking object to target
|
||||||
_doAfterSystem.DoAfter(new DoAfterEventArgs(user, delay, target: target, used: uid)
|
_doAfterSystem.TryStartDoAfter(new DoAfterArgs(user, delay, new StickyDoAfterEvent(), uid, target: target, used: uid)
|
||||||
{
|
{
|
||||||
BreakOnStun = true,
|
|
||||||
BreakOnTargetMove = true,
|
BreakOnTargetMove = true,
|
||||||
BreakOnUserMove = true,
|
BreakOnUserMove = true,
|
||||||
NeedHand = true
|
NeedHand = true
|
||||||
@@ -105,14 +102,13 @@ public sealed class StickySystem : EntitySystem
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnStickSuccessful(EntityUid uid, StickyComponent component, DoAfterEvent args)
|
private void OnStickFinished(EntityUid uid, StickyComponent component, DoAfterEvent args)
|
||||||
{
|
{
|
||||||
if (args.Handled || args.Cancelled || args.Args.Target == null)
|
if (args.Handled || args.Cancelled || args.Args.Target == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (component.Stick)
|
if (component.Stick)
|
||||||
StickToEntity(uid, args.Args.Target.Value, args.Args.User, component);
|
StickToEntity(uid, args.Args.Target.Value, args.Args.User, component);
|
||||||
|
|
||||||
else
|
else
|
||||||
UnstickFromEntity(uid, args.Args.User, component);
|
UnstickFromEntity(uid, args.Args.User, component);
|
||||||
|
|
||||||
@@ -137,9 +133,8 @@ public sealed class StickySystem : EntitySystem
|
|||||||
component.Stick = false;
|
component.Stick = false;
|
||||||
|
|
||||||
// start unsticking object
|
// start unsticking object
|
||||||
_doAfterSystem.DoAfter(new DoAfterEventArgs(user, delay, target: uid)
|
_doAfterSystem.TryStartDoAfter(new DoAfterArgs(user, delay, new StickyDoAfterEvent(), uid, target: uid)
|
||||||
{
|
{
|
||||||
BreakOnStun = true,
|
|
||||||
BreakOnTargetMove = true,
|
BreakOnTargetMove = true,
|
||||||
BreakOnUserMove = true,
|
BreakOnUserMove = true,
|
||||||
NeedHand = true
|
NeedHand = true
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Server.DoAfter;
|
|
||||||
using Content.Server.Explosion.EntitySystems;
|
using Content.Server.Explosion.EntitySystems;
|
||||||
using Content.Server.Mind.Components;
|
using Content.Server.Mind.Components;
|
||||||
using Content.Server.Resist;
|
using Content.Server.Resist;
|
||||||
@@ -11,6 +10,7 @@ using Content.Shared.Coordinates;
|
|||||||
using Content.Shared.DoAfter;
|
using Content.Shared.DoAfter;
|
||||||
using Content.Shared.Lock;
|
using Content.Shared.Lock;
|
||||||
using Content.Shared.Storage.Components;
|
using Content.Shared.Storage.Components;
|
||||||
|
using Content.Shared.Storage.EntitySystems;
|
||||||
using Robust.Shared.Random;
|
using Robust.Shared.Random;
|
||||||
using Robust.Shared.Timing;
|
using Robust.Shared.Timing;
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@ public sealed class BluespaceLockerSystem : EntitySystem
|
|||||||
[Dependency] private readonly EntityStorageSystem _entityStorage = default!;
|
[Dependency] private readonly EntityStorageSystem _entityStorage = default!;
|
||||||
[Dependency] private readonly WeldableSystem _weldableSystem = default!;
|
[Dependency] private readonly WeldableSystem _weldableSystem = default!;
|
||||||
[Dependency] private readonly LockSystem _lockSystem = default!;
|
[Dependency] private readonly LockSystem _lockSystem = default!;
|
||||||
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
|
||||||
[Dependency] private readonly ExplosionSystem _explosionSystem = default!;
|
[Dependency] private readonly ExplosionSystem _explosionSystem = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
@@ -33,7 +33,7 @@ public sealed class BluespaceLockerSystem : EntitySystem
|
|||||||
SubscribeLocalEvent<BluespaceLockerComponent, ComponentStartup>(OnStartup);
|
SubscribeLocalEvent<BluespaceLockerComponent, ComponentStartup>(OnStartup);
|
||||||
SubscribeLocalEvent<BluespaceLockerComponent, StorageBeforeOpenEvent>(PreOpen);
|
SubscribeLocalEvent<BluespaceLockerComponent, StorageBeforeOpenEvent>(PreOpen);
|
||||||
SubscribeLocalEvent<BluespaceLockerComponent, StorageAfterCloseEvent>(PostClose);
|
SubscribeLocalEvent<BluespaceLockerComponent, StorageAfterCloseEvent>(PostClose);
|
||||||
SubscribeLocalEvent<BluespaceLockerComponent, DoAfterEvent>(OnDoAfter);
|
SubscribeLocalEvent<BluespaceLockerComponent, BluespaceLockerDoAfterEvent>(OnDoAfter);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnStartup(EntityUid uid, BluespaceLockerComponent component, ComponentStartup args)
|
private void OnStartup(EntityUid uid, BluespaceLockerComponent component, ComponentStartup args)
|
||||||
@@ -284,7 +284,7 @@ public sealed class BluespaceLockerSystem : EntitySystem
|
|||||||
{
|
{
|
||||||
EnsureComp<DoAfterComponent>(uid);
|
EnsureComp<DoAfterComponent>(uid);
|
||||||
|
|
||||||
_doAfterSystem.DoAfter(new DoAfterEventArgs(uid, component.BehaviorProperties.Delay));
|
_doAfterSystem.TryStartDoAfter(new DoAfterArgs(uid, component.BehaviorProperties.Delay, new BluespaceLockerDoAfterEvent(), uid));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
using System.Threading;
|
|
||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
using Content.Server.Storage.Components;
|
using Content.Server.Storage.Components;
|
||||||
using Content.Shared.Storage.Components;
|
using Content.Shared.Storage.Components;
|
||||||
using Content.Shared.Verbs;
|
using Content.Shared.Verbs;
|
||||||
using Content.Server.Disposal.Unit.Components;
|
using Content.Server.Disposal.Unit.Components;
|
||||||
using Content.Server.Disposal.Unit.EntitySystems;
|
using Content.Server.Disposal.Unit.EntitySystems;
|
||||||
using Content.Server.DoAfter;
|
using Content.Server.Xenoarchaeology.XenoArtifacts.Triggers.Systems;
|
||||||
using Content.Shared.DoAfter;
|
using Content.Shared.DoAfter;
|
||||||
using Content.Shared.Placeable;
|
using Content.Shared.Placeable;
|
||||||
using Content.Shared.Storage;
|
using Content.Shared.Storage;
|
||||||
@@ -17,7 +16,7 @@ namespace Content.Server.Storage.EntitySystems
|
|||||||
{
|
{
|
||||||
public sealed class DumpableSystem : EntitySystem
|
public sealed class DumpableSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
|
||||||
[Dependency] private readonly DisposalUnitSystem _disposalUnitSystem = default!;
|
[Dependency] private readonly DisposalUnitSystem _disposalUnitSystem = default!;
|
||||||
[Dependency] private readonly IRobustRandom _random = default!;
|
[Dependency] private readonly IRobustRandom _random = default!;
|
||||||
[Dependency] private readonly SharedContainerSystem _container = default!;
|
[Dependency] private readonly SharedContainerSystem _container = default!;
|
||||||
@@ -28,16 +27,19 @@ namespace Content.Server.Storage.EntitySystems
|
|||||||
SubscribeLocalEvent<DumpableComponent, AfterInteractEvent>(OnAfterInteract, after: new[]{ typeof(StorageSystem) });
|
SubscribeLocalEvent<DumpableComponent, AfterInteractEvent>(OnAfterInteract, after: new[]{ typeof(StorageSystem) });
|
||||||
SubscribeLocalEvent<DumpableComponent, GetVerbsEvent<AlternativeVerb>>(AddDumpVerb);
|
SubscribeLocalEvent<DumpableComponent, GetVerbsEvent<AlternativeVerb>>(AddDumpVerb);
|
||||||
SubscribeLocalEvent<DumpableComponent, GetVerbsEvent<UtilityVerb>>(AddUtilityVerbs);
|
SubscribeLocalEvent<DumpableComponent, GetVerbsEvent<UtilityVerb>>(AddUtilityVerbs);
|
||||||
SubscribeLocalEvent<DumpableComponent, DoAfterEvent>(OnDoAfter);
|
SubscribeLocalEvent<DumpableComponent, DumpableDoAfterEvent>(OnDoAfter);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnAfterInteract(EntityUid uid, DumpableComponent component, AfterInteractEvent args)
|
private void OnAfterInteract(EntityUid uid, DumpableComponent component, AfterInteractEvent args)
|
||||||
{
|
{
|
||||||
if (!args.CanReach)
|
if (!args.CanReach || args.Handled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!HasComp<DisposalUnitComponent>(args.Target) && !HasComp<PlaceableSurfaceComponent>(args.Target))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (HasComp<DisposalUnitComponent>(args.Target) || HasComp<PlaceableSurfaceComponent>(args.Target))
|
|
||||||
StartDoAfter(uid, args.Target.Value, args.User, component);
|
StartDoAfter(uid, args.Target.Value, args.User, component);
|
||||||
|
args.Handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddDumpVerb(EntityUid uid, DumpableComponent dumpable, GetVerbsEvent<AlternativeVerb> args)
|
private void AddDumpVerb(EntityUid uid, DumpableComponent dumpable, GetVerbsEvent<AlternativeVerb> args)
|
||||||
@@ -52,7 +54,7 @@ namespace Content.Server.Storage.EntitySystems
|
|||||||
{
|
{
|
||||||
Act = () =>
|
Act = () =>
|
||||||
{
|
{
|
||||||
StartDoAfter(uid, null, args.User, dumpable);//Had multiplier of 0.6f
|
StartDoAfter(uid, args.Target, args.User, dumpable);//Had multiplier of 0.6f
|
||||||
},
|
},
|
||||||
Text = Loc.GetString("dump-verb-name"),
|
Text = Loc.GetString("dump-verb-name"),
|
||||||
Icon = new SpriteSpecifier.Texture(new ResourcePath("/Textures/Interface/VerbIcons/drop.svg.192dpi.png")),
|
Icon = new SpriteSpecifier.Texture(new ResourcePath("/Textures/Interface/VerbIcons/drop.svg.192dpi.png")),
|
||||||
@@ -104,12 +106,10 @@ namespace Content.Server.Storage.EntitySystems
|
|||||||
|
|
||||||
float delay = storage.StoredEntities.Count * (float) dumpable.DelayPerItem.TotalSeconds * dumpable.Multiplier;
|
float delay = storage.StoredEntities.Count * (float) dumpable.DelayPerItem.TotalSeconds * dumpable.Multiplier;
|
||||||
|
|
||||||
_doAfterSystem.DoAfter(new DoAfterEventArgs(userUid, delay, target: targetUid, used: storageUid)
|
_doAfterSystem.TryStartDoAfter(new DoAfterArgs(userUid, delay, new DumpableDoAfterEvent(), storageUid, target: targetUid, used: storageUid)
|
||||||
{
|
{
|
||||||
RaiseOnTarget = false,
|
|
||||||
BreakOnTargetMove = true,
|
BreakOnTargetMove = true,
|
||||||
BreakOnUserMove = true,
|
BreakOnUserMove = true,
|
||||||
BreakOnStun = true,
|
|
||||||
NeedHand = true
|
NeedHand = true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,8 +12,6 @@ using Robust.Shared.Containers;
|
|||||||
using Robust.Shared.Random;
|
using Robust.Shared.Random;
|
||||||
using Robust.Shared.Timing;
|
using Robust.Shared.Timing;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
using System.Threading;
|
|
||||||
using Content.Server.DoAfter;
|
|
||||||
using Content.Server.Interaction;
|
using Content.Server.Interaction;
|
||||||
using Content.Shared.Hands.EntitySystems;
|
using Content.Shared.Hands.EntitySystems;
|
||||||
using Content.Shared.Item;
|
using Content.Shared.Item;
|
||||||
@@ -33,7 +31,6 @@ using Content.Shared.Containers.ItemSlots;
|
|||||||
using Content.Shared.DoAfter;
|
using Content.Shared.DoAfter;
|
||||||
using Content.Shared.Implants.Components;
|
using Content.Shared.Implants.Components;
|
||||||
using Content.Shared.Lock;
|
using Content.Shared.Lock;
|
||||||
using Content.Shared.Movement.Events;
|
|
||||||
using Content.Server.Ghost.Components;
|
using Content.Server.Ghost.Components;
|
||||||
using Content.Server.Administration.Managers;
|
using Content.Server.Administration.Managers;
|
||||||
using Content.Shared.Administration;
|
using Content.Shared.Administration;
|
||||||
@@ -47,7 +44,7 @@ namespace Content.Server.Storage.EntitySystems
|
|||||||
[Dependency] private readonly IRobustRandom _random = default!;
|
[Dependency] private readonly IRobustRandom _random = default!;
|
||||||
[Dependency] private readonly IAdminManager _admin = default!;
|
[Dependency] private readonly IAdminManager _admin = default!;
|
||||||
[Dependency] private readonly ContainerSystem _containerSystem = default!;
|
[Dependency] private readonly ContainerSystem _containerSystem = default!;
|
||||||
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
|
||||||
[Dependency] private readonly EntityLookupSystem _entityLookupSystem = default!;
|
[Dependency] private readonly EntityLookupSystem _entityLookupSystem = default!;
|
||||||
[Dependency] private readonly EntityStorageSystem _entityStorage = default!;
|
[Dependency] private readonly EntityStorageSystem _entityStorage = default!;
|
||||||
[Dependency] private readonly InteractionSystem _interactionSystem = default!;
|
[Dependency] private readonly InteractionSystem _interactionSystem = default!;
|
||||||
@@ -81,7 +78,7 @@ namespace Content.Server.Storage.EntitySystems
|
|||||||
SubscribeLocalEvent<ServerStorageComponent, BoundUIClosedEvent>(OnBoundUIClosed);
|
SubscribeLocalEvent<ServerStorageComponent, BoundUIClosedEvent>(OnBoundUIClosed);
|
||||||
SubscribeLocalEvent<ServerStorageComponent, EntRemovedFromContainerMessage>(OnStorageItemRemoved);
|
SubscribeLocalEvent<ServerStorageComponent, EntRemovedFromContainerMessage>(OnStorageItemRemoved);
|
||||||
|
|
||||||
SubscribeLocalEvent<ServerStorageComponent, DoAfterEvent<StorageData>>(OnDoAfter);
|
SubscribeLocalEvent<ServerStorageComponent, AreaPickupDoAfterEvent>(OnDoAfter);
|
||||||
|
|
||||||
SubscribeLocalEvent<StorageFillComponent, MapInitEvent>(OnStorageFillMapInit);
|
SubscribeLocalEvent<StorageFillComponent, MapInitEvent>(OnStorageFillMapInit);
|
||||||
}
|
}
|
||||||
@@ -234,16 +231,14 @@ namespace Content.Server.Storage.EntitySystems
|
|||||||
//If there's only one then let's be generous
|
//If there's only one then let's be generous
|
||||||
if (validStorables.Count > 1)
|
if (validStorables.Count > 1)
|
||||||
{
|
{
|
||||||
var storageData = new StorageData(validStorables);
|
var doAfterArgs = new DoAfterArgs(args.User, 0.2f * validStorables.Count, new AreaPickupDoAfterEvent(validStorables), uid, target: uid)
|
||||||
var doAfterArgs = new DoAfterEventArgs(args.User, 0.2f * validStorables.Count, target: uid)
|
|
||||||
{
|
{
|
||||||
BreakOnStun = true,
|
|
||||||
BreakOnDamage = true,
|
BreakOnDamage = true,
|
||||||
BreakOnUserMove = true,
|
BreakOnUserMove = true,
|
||||||
NeedHand = true
|
NeedHand = true
|
||||||
};
|
};
|
||||||
|
|
||||||
_doAfterSystem.DoAfter(doAfterArgs, storageData);
|
_doAfterSystem.TryStartDoAfter(doAfterArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -278,7 +273,7 @@ namespace Content.Server.Storage.EntitySystems
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDoAfter(EntityUid uid, ServerStorageComponent component, DoAfterEvent<StorageData> args)
|
private void OnDoAfter(EntityUid uid, ServerStorageComponent component, AreaPickupDoAfterEvent args)
|
||||||
{
|
{
|
||||||
if (args.Handled || args.Cancelled)
|
if (args.Handled || args.Cancelled)
|
||||||
return;
|
return;
|
||||||
@@ -289,7 +284,7 @@ namespace Content.Server.Storage.EntitySystems
|
|||||||
var xformQuery = GetEntityQuery<TransformComponent>();
|
var xformQuery = GetEntityQuery<TransformComponent>();
|
||||||
xformQuery.TryGetComponent(uid, out var xform);
|
xformQuery.TryGetComponent(uid, out var xform);
|
||||||
|
|
||||||
foreach (var entity in args.AdditionalData.ValidStorables)
|
foreach (var entity in args.Entities)
|
||||||
{
|
{
|
||||||
// Check again, situation may have changed for some entities, but we'll still pick up any that are valid
|
// Check again, situation may have changed for some entities, but we'll still pick up any that are valid
|
||||||
if (_containerSystem.IsEntityInContainer(entity)
|
if (_containerSystem.IsEntityInContainer(entity)
|
||||||
@@ -667,10 +662,5 @@ namespace Content.Server.Storage.EntitySystems
|
|||||||
|
|
||||||
_popupSystem.PopupEntity(Loc.GetString(message), player, player);
|
_popupSystem.PopupEntity(Loc.GetString(message), player, player);
|
||||||
}
|
}
|
||||||
|
|
||||||
private record struct StorageData(List<EntityUid> validStorables)
|
|
||||||
{
|
|
||||||
public List<EntityUid> ValidStorables = validStorables;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Server.DoAfter;
|
|
||||||
using Content.Server.Ensnaring;
|
using Content.Server.Ensnaring;
|
||||||
using Content.Server.Hands.Components;
|
using Content.Server.Hands.Components;
|
||||||
using Content.Shared.CombatMode;
|
using Content.Shared.CombatMode;
|
||||||
@@ -12,7 +11,6 @@ using Content.Shared.Popups;
|
|||||||
using Content.Shared.Strip.Components;
|
using Content.Shared.Strip.Components;
|
||||||
using Content.Shared.Verbs;
|
using Content.Shared.Verbs;
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
using System.Threading;
|
|
||||||
using Content.Server.Administration.Logs;
|
using Content.Server.Administration.Logs;
|
||||||
using Content.Shared.Cuffs;
|
using Content.Shared.Cuffs;
|
||||||
using Content.Shared.Cuffs.Components;
|
using Content.Shared.Cuffs.Components;
|
||||||
@@ -30,8 +28,8 @@ namespace Content.Server.Strip
|
|||||||
[Dependency] private readonly SharedCuffableSystem _cuffable = default!;
|
[Dependency] private readonly SharedCuffableSystem _cuffable = default!;
|
||||||
[Dependency] private readonly SharedHandsSystem _handsSystem = default!;
|
[Dependency] private readonly SharedHandsSystem _handsSystem = default!;
|
||||||
[Dependency] private readonly InventorySystem _inventorySystem = default!;
|
[Dependency] private readonly InventorySystem _inventorySystem = default!;
|
||||||
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
|
||||||
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
|
[Dependency] private readonly SharedPopupSystem _popup = default!;
|
||||||
[Dependency] private readonly EnsnareableSystem _ensnaring = default!;
|
[Dependency] private readonly EnsnareableSystem _ensnaring = default!;
|
||||||
[Dependency] private readonly UserInterfaceSystem _userInterfaceSystem = default!;
|
[Dependency] private readonly UserInterfaceSystem _userInterfaceSystem = default!;
|
||||||
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
|
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
|
||||||
@@ -61,12 +59,12 @@ namespace Content.Server.Strip
|
|||||||
if (!TryComp<EnsnaringComponent>(entity, out var ensnaring))
|
if (!TryComp<EnsnaringComponent>(entity, out var ensnaring))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
_ensnaring.TryFree(uid, entity, ensnaring, user);
|
_ensnaring.TryFree(uid, user, entity, ensnaring);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnStripButtonPressed(EntityUid uid, StrippableComponent component, StrippingSlotButtonPressed args)
|
private void OnStripButtonPressed(EntityUid target, StrippableComponent component, StrippingSlotButtonPressed args)
|
||||||
{
|
{
|
||||||
if (args.Session.AttachedEntity is not {Valid: true} user ||
|
if (args.Session.AttachedEntity is not {Valid: true} user ||
|
||||||
!TryComp<HandsComponent>(user, out var userHands))
|
!TryComp<HandsComponent>(user, out var userHands))
|
||||||
@@ -74,19 +72,19 @@ namespace Content.Server.Strip
|
|||||||
|
|
||||||
if (args.IsHand)
|
if (args.IsHand)
|
||||||
{
|
{
|
||||||
StripHand(uid, user, args.Slot, component, userHands);
|
StripHand(target, user, args.Slot, component, userHands);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!TryComp<InventoryComponent>(component.Owner, out var inventory))
|
if (!TryComp<InventoryComponent>(target, out var inventory))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var hasEnt = _inventorySystem.TryGetSlotEntity(component.Owner, args.Slot, out _, inventory);
|
var hasEnt = _inventorySystem.TryGetSlotEntity(target, args.Slot, out var held, inventory);
|
||||||
|
|
||||||
if (userHands.ActiveHandEntity != null && !hasEnt)
|
if (userHands.ActiveHandEntity != null && !hasEnt)
|
||||||
PlaceActiveHandItemInInventory(user, args.Slot, component);
|
PlaceActiveHandItemInInventory(user, target, userHands.ActiveHandEntity.Value, args.Slot, component);
|
||||||
else if (userHands.ActiveHandEntity == null && hasEnt)
|
else if (userHands.ActiveHandEntity == null && hasEnt)
|
||||||
TakeItemFromInventory(user, args.Slot, component);
|
TakeItemFromInventory(user, target, held!.Value, args.Slot, component);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void StripHand(EntityUid target, EntityUid user, string handId, StrippableComponent component, HandsComponent userHands)
|
private void StripHand(EntityUid target, EntityUid user, string handId, StrippableComponent component, HandsComponent userHands)
|
||||||
@@ -104,10 +102,10 @@ namespace Content.Server.Strip
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hand.IsEmpty && userHands.ActiveHandEntity != null)
|
if (userHands.ActiveHandEntity != null && hand.HeldEntity == null)
|
||||||
PlaceActiveHandItemInHands(user, handId, component);
|
PlaceActiveHandItemInHands(user, target, userHands.ActiveHandEntity.Value, handId, component);
|
||||||
else if (!hand.IsEmpty && userHands.ActiveHandEntity == null)
|
else if (userHands.ActiveHandEntity == null && hand.HeldEntity != null)
|
||||||
TakeItemFromHands(user, handId, component);
|
TakeItemFromHands(user,target, hand.HeldEntity.Value, handId, component);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void StartOpeningStripper(EntityUid user, StrippableComponent component, bool openInCombat = false)
|
public override void StartOpeningStripper(EntityUid user, StrippableComponent component, bool openInCombat = false)
|
||||||
@@ -166,287 +164,291 @@ namespace Content.Server.Strip
|
|||||||
if (args.Target == args.User)
|
if (args.Target == args.User)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!HasComp<ActorComponent>(args.User))
|
if (!TryComp<ActorComponent>(args.User, out var actor))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
args.Handled = true;
|
|
||||||
StartOpeningStripper(args.User, component);
|
StartOpeningStripper(args.User, component);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Places item in user's active hand to an inventory slot.
|
/// Places item in user's active hand to an inventory slot.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private async void PlaceActiveHandItemInInventory(EntityUid user, string slot, StrippableComponent component)
|
private async void PlaceActiveHandItemInInventory(
|
||||||
|
EntityUid user,
|
||||||
|
EntityUid target,
|
||||||
|
EntityUid held,
|
||||||
|
string slot,
|
||||||
|
StrippableComponent component)
|
||||||
{
|
{
|
||||||
var userHands = Comp<HandsComponent>(user);
|
var userHands = Comp<HandsComponent>(user);
|
||||||
|
|
||||||
bool Check()
|
bool Check()
|
||||||
{
|
{
|
||||||
if (userHands.ActiveHand?.HeldEntity is not { } held)
|
if (userHands.ActiveHandEntity != held)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!_handsSystem.CanDropHeld(user, userHands.ActiveHand!))
|
||||||
{
|
{
|
||||||
user.PopupMessageCursor(Loc.GetString("strippable-component-not-holding-anything"));
|
_popup.PopupCursor(Loc.GetString("strippable-component-cannot-drop"), user);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_handsSystem.CanDropHeld(user, userHands.ActiveHand))
|
if (_inventorySystem.TryGetSlotEntity(target, slot, out _))
|
||||||
{
|
{
|
||||||
user.PopupMessageCursor(Loc.GetString("strippable-component-cannot-drop"));
|
_popup.PopupCursor(Loc.GetString("strippable-component-item-slot-occupied",("owner", target)), user);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_inventorySystem.HasSlot(component.Owner, slot))
|
if (!_inventorySystem.CanEquip(user, target, held, slot, out _))
|
||||||
return false;
|
|
||||||
|
|
||||||
if (_inventorySystem.TryGetSlotEntity(component.Owner, slot, out _))
|
|
||||||
{
|
{
|
||||||
user.PopupMessageCursor(Loc.GetString("strippable-component-item-slot-occupied",("owner", component.Owner)));
|
_popup.PopupCursor(Loc.GetString("strippable-component-cannot-equip-message",("owner", target)), user);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_inventorySystem.CanEquip(user, component.Owner, held, slot, out _))
|
|
||||||
{
|
|
||||||
user.PopupMessageCursor(Loc.GetString("strippable-component-cannot-equip-message",("owner", component.Owner)));
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_inventorySystem.TryGetSlot(component.Owner, slot, out var slotDef))
|
if (!_inventorySystem.TryGetSlot(target, slot, out var slotDef))
|
||||||
{
|
{
|
||||||
Logger.Error($"{ToPrettyString(user)} attempted to place an item in a non-existent inventory slot ({slot}) on {ToPrettyString(component.Owner)}");
|
Logger.Error($"{ToPrettyString(user)} attempted to place an item in a non-existent inventory slot ({slot}) on {ToPrettyString(target)}");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var (time, stealth) = GetStripTimeModifiers(user, component.Owner, slotDef.StripTime);
|
var userEv = new BeforeStripEvent(slotDef.StripTime);
|
||||||
|
RaiseLocalEvent(user, userEv);
|
||||||
|
var ev = new BeforeGettingStrippedEvent(userEv.Time, userEv.Stealth);
|
||||||
|
RaiseLocalEvent(target, ev);
|
||||||
|
|
||||||
var doAfterArgs = new DoAfterEventArgs(user, time, CancellationToken.None, component.Owner)
|
var doAfterArgs = new DoAfterArgs(user, ev.Time, new AwaitedDoAfterEvent(), null, target: target, used: held)
|
||||||
{
|
{
|
||||||
ExtraCheck = Check,
|
ExtraCheck = Check,
|
||||||
BreakOnStun = true,
|
AttemptFrequency = AttemptFrequency.EveryTick,
|
||||||
BreakOnDamage = true,
|
BreakOnDamage = true,
|
||||||
BreakOnTargetMove = true,
|
BreakOnTargetMove = true,
|
||||||
BreakOnUserMove = true,
|
BreakOnUserMove = true,
|
||||||
NeedHand = true,
|
NeedHand = true,
|
||||||
|
DuplicateCondition = DuplicateConditions.SameTool // Block any other DoAfters featuring this same entity.
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!stealth && Check() && userHands.ActiveHandEntity != null)
|
if (!ev.Stealth && Check() && userHands.ActiveHandEntity != null)
|
||||||
{
|
{
|
||||||
var message = Loc.GetString("strippable-component-alert-owner-insert",
|
var message = Loc.GetString("strippable-component-alert-owner-insert",
|
||||||
("user", Identity.Entity(user, EntityManager)), ("item", userHands.ActiveHandEntity));
|
("user", Identity.Entity(user, EntityManager)), ("item", userHands.ActiveHandEntity));
|
||||||
_popupSystem.PopupEntity(message, component.Owner, component.Owner, PopupType.Large);
|
_popup.PopupEntity(message, target, target, PopupType.Large);
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = await _doAfterSystem.WaitDoAfter(doAfterArgs);
|
var result = await _doAfter.WaitDoAfter(doAfterArgs);
|
||||||
if (result != DoAfterStatus.Finished) return;
|
if (result != DoAfterStatus.Finished) return;
|
||||||
|
|
||||||
if (userHands.ActiveHand?.HeldEntity is { } held
|
DebugTools.Assert(userHands.ActiveHand?.HeldEntity == held);
|
||||||
&& _handsSystem.TryDrop(user, userHands.ActiveHand, handsComp: userHands))
|
|
||||||
{
|
|
||||||
_inventorySystem.TryEquip(user, component.Owner, held, slot);
|
|
||||||
|
|
||||||
_adminLogger.Add(LogType.Stripping, LogImpact.Medium, $"{ToPrettyString(user):user} has placed the item {ToPrettyString(held):item} in {ToPrettyString(component.Owner):target}'s {slot} slot");
|
if (_handsSystem.TryDrop(user, handsComp: userHands))
|
||||||
|
{
|
||||||
|
_inventorySystem.TryEquip(user, target, held, slot);
|
||||||
|
|
||||||
|
_adminLogger.Add(LogType.Stripping, LogImpact.Medium, $"{ToPrettyString(user):user} has placed the item {ToPrettyString(held):item} in {ToPrettyString(target):target}'s {slot} slot");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Places item in user's active hand in one of the entity's hands.
|
/// Places item in user's active hand in one of the entity's hands.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private async void PlaceActiveHandItemInHands(EntityUid user, string handName, StrippableComponent component)
|
private async void PlaceActiveHandItemInHands(
|
||||||
|
EntityUid user,
|
||||||
|
EntityUid target,
|
||||||
|
EntityUid held,
|
||||||
|
string handName,
|
||||||
|
StrippableComponent component)
|
||||||
{
|
{
|
||||||
var hands = Comp<HandsComponent>(component.Owner);
|
var hands = Comp<HandsComponent>(target);
|
||||||
var userHands = Comp<HandsComponent>(user);
|
var userHands = Comp<HandsComponent>(user);
|
||||||
|
|
||||||
bool Check()
|
bool Check()
|
||||||
{
|
{
|
||||||
if (userHands.ActiveHandEntity == null)
|
if (userHands.ActiveHandEntity != held)
|
||||||
{
|
|
||||||
user.PopupMessageCursor(Loc.GetString("strippable-component-not-holding-anything"));
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
if (!_handsSystem.CanDropHeld(user, userHands.ActiveHand!))
|
if (!_handsSystem.CanDropHeld(user, userHands.ActiveHand!))
|
||||||
{
|
{
|
||||||
user.PopupMessageCursor(Loc.GetString("strippable-component-cannot-drop"));
|
_popup.PopupCursor(Loc.GetString("strippable-component-cannot-drop"), user);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hands.Hands.TryGetValue(handName, out var hand)
|
if (!hands.Hands.TryGetValue(handName, out var hand)
|
||||||
|| !_handsSystem.CanPickupToHand(component.Owner, userHands.ActiveHandEntity.Value, hand, checkActionBlocker: false, hands))
|
|| !_handsSystem.CanPickupToHand(target, userHands.ActiveHandEntity.Value, hand, checkActionBlocker: false, hands))
|
||||||
{
|
{
|
||||||
user.PopupMessageCursor(Loc.GetString("strippable-component-cannot-put-message",("owner", component.Owner)));
|
_popup.PopupCursor(Loc.GetString("strippable-component-cannot-put-message",("owner", target)), user);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
var (time, stealth) = GetStripTimeModifiers(user, component.Owner, component.HandStripDelay);
|
var userEv = new BeforeStripEvent(component.HandStripDelay);
|
||||||
|
RaiseLocalEvent(user, userEv);
|
||||||
|
var ev = new BeforeGettingStrippedEvent(userEv.Time, userEv.Stealth);
|
||||||
|
RaiseLocalEvent(target, ev);
|
||||||
|
|
||||||
var doAfterArgs = new DoAfterEventArgs(user, time, CancellationToken.None, component.Owner)
|
var doAfterArgs = new DoAfterArgs(user, ev.Time, new AwaitedDoAfterEvent(), null, target: target, used: held)
|
||||||
{
|
{
|
||||||
ExtraCheck = Check,
|
ExtraCheck = Check,
|
||||||
BreakOnStun = true,
|
AttemptFrequency = AttemptFrequency.EveryTick,
|
||||||
BreakOnDamage = true,
|
BreakOnDamage = true,
|
||||||
BreakOnTargetMove = true,
|
BreakOnTargetMove = true,
|
||||||
BreakOnUserMove = true,
|
BreakOnUserMove = true,
|
||||||
NeedHand = true,
|
NeedHand = true,
|
||||||
|
DuplicateCondition = DuplicateConditions.SameTool
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!stealth
|
var result = await _doAfter.WaitDoAfter(doAfterArgs);
|
||||||
&& Check()
|
|
||||||
&& userHands.Hands.TryGetValue(handName, out var handSlot)
|
|
||||||
&& handSlot.HeldEntity != null)
|
|
||||||
{
|
|
||||||
_popupSystem.PopupEntity(
|
|
||||||
Loc.GetString("strippable-component-alert-owner-insert",
|
|
||||||
("user", Identity.Entity(user, EntityManager)),
|
|
||||||
("item", handSlot.HeldEntity)),
|
|
||||||
component.Owner, component.Owner, PopupType.Large);
|
|
||||||
}
|
|
||||||
|
|
||||||
var result = await _doAfterSystem.WaitDoAfter(doAfterArgs);
|
|
||||||
if (result != DoAfterStatus.Finished) return;
|
if (result != DoAfterStatus.Finished) return;
|
||||||
|
|
||||||
if (userHands.ActiveHandEntity is not { } held)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_handsSystem.TryDrop(user, checkActionBlocker: false, handsComp: userHands);
|
_handsSystem.TryDrop(user, checkActionBlocker: false, handsComp: userHands);
|
||||||
_handsSystem.TryPickup(component.Owner, held, handName, checkActionBlocker: false, animateUser: true, animate: !stealth, handsComp: hands);
|
_handsSystem.TryPickup(target, held, handName, checkActionBlocker: false, animateUser: true, handsComp: hands);
|
||||||
_adminLogger.Add(LogType.Stripping, LogImpact.Medium, $"{ToPrettyString(user):user} has placed the item {ToPrettyString(held):item} in {ToPrettyString(component.Owner):target}'s hands");
|
_adminLogger.Add(LogType.Stripping, LogImpact.Medium, $"{ToPrettyString(user):user} has placed the item {ToPrettyString(held):item} in {ToPrettyString(target):target}'s hands");
|
||||||
// hand update will trigger strippable update
|
// hand update will trigger strippable update
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Takes an item from the inventory and places it in the user's active hand.
|
/// Takes an item from the inventory and places it in the user's active hand.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private async void TakeItemFromInventory(EntityUid user, string slot, StrippableComponent component)
|
private async void TakeItemFromInventory(
|
||||||
|
EntityUid user,
|
||||||
|
EntityUid target,
|
||||||
|
EntityUid item,
|
||||||
|
string slot,
|
||||||
|
StrippableComponent component)
|
||||||
{
|
{
|
||||||
bool Check()
|
bool Check()
|
||||||
{
|
{
|
||||||
if (!_inventorySystem.HasSlot(component.Owner, slot))
|
if (!_inventorySystem.TryGetSlotEntity(target, slot, out var ent) && ent == item)
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!_inventorySystem.TryGetSlotEntity(component.Owner, slot, out _))
|
|
||||||
{
|
{
|
||||||
user.PopupMessageCursor(Loc.GetString("strippable-component-item-slot-free-message", ("owner", component.Owner)));
|
_popup.PopupCursor(Loc.GetString("strippable-component-item-slot-free-message", ("owner", target)), user);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_inventorySystem.CanUnequip(user, component.Owner, slot, out var reason))
|
if (!_inventorySystem.CanUnequip(user, target, slot, out var reason))
|
||||||
{
|
{
|
||||||
user.PopupMessageCursor(reason);
|
_popup.PopupCursor(reason, user);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_inventorySystem.TryGetSlot(component.Owner, slot, out var slotDef))
|
if (!_inventorySystem.TryGetSlot(target, slot, out var slotDef))
|
||||||
{
|
{
|
||||||
Logger.Error($"{ToPrettyString(user)} attempted to take an item from a non-existent inventory slot ({slot}) on {ToPrettyString(component.Owner)}");
|
Logger.Error($"{ToPrettyString(user)} attempted to take an item from a non-existent inventory slot ({slot}) on {ToPrettyString(target)}");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var (time, stealth) = GetStripTimeModifiers(user, component.Owner, slotDef.StripTime);
|
var userEv = new BeforeStripEvent(slotDef.StripTime);
|
||||||
|
RaiseLocalEvent(user, userEv);
|
||||||
|
var ev = new BeforeGettingStrippedEvent(userEv.Time, userEv.Stealth);
|
||||||
|
RaiseLocalEvent(target, ev);
|
||||||
|
|
||||||
var doAfterArgs = new DoAfterEventArgs(user, time, CancellationToken.None, component.Owner)
|
var doAfterArgs = new DoAfterArgs(user, ev.Time, new AwaitedDoAfterEvent(), null, target: target, used: item)
|
||||||
{
|
{
|
||||||
ExtraCheck = Check,
|
ExtraCheck = Check,
|
||||||
BreakOnStun = true,
|
AttemptFrequency = AttemptFrequency.EveryTick,
|
||||||
BreakOnDamage = true,
|
BreakOnDamage = true,
|
||||||
BreakOnTargetMove = true,
|
BreakOnTargetMove = true,
|
||||||
BreakOnUserMove = true,
|
BreakOnUserMove = true,
|
||||||
|
NeedHand = true,
|
||||||
|
BreakOnHandChange = false, // allow simultaneously removing multiple items.
|
||||||
|
DuplicateCondition = DuplicateConditions.SameTool
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!stealth && Check())
|
if (!ev.Stealth && Check())
|
||||||
{
|
{
|
||||||
if (slotDef.StripHidden)
|
if (slotDef.StripHidden)
|
||||||
{
|
{
|
||||||
_popupSystem.PopupEntity(Loc.GetString("strippable-component-alert-owner-hidden", ("slot", slot)), component.Owner,
|
_popup.PopupEntity(Loc.GetString("strippable-component-alert-owner-hidden", ("slot", slot)), target,
|
||||||
component.Owner, PopupType.Large);
|
target, PopupType.Large);
|
||||||
}
|
}
|
||||||
else if (_inventorySystem.TryGetSlotEntity(component.Owner, slot, out var slotItem))
|
else if (_inventorySystem.TryGetSlotEntity(component.Owner, slot, out var slotItem))
|
||||||
{
|
{
|
||||||
_popupSystem.PopupEntity(Loc.GetString("strippable-component-alert-owner", ("user", Identity.Entity(user, EntityManager)), ("item", slotItem)), component.Owner,
|
_popup.PopupEntity(Loc.GetString("strippable-component-alert-owner", ("user", Identity.Entity(user, EntityManager)), ("item", slotItem)), target,
|
||||||
component.Owner, PopupType.Large);
|
target, PopupType.Large);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = await _doAfterSystem.WaitDoAfter(doAfterArgs);
|
var result = await _doAfter.WaitDoAfter(doAfterArgs);
|
||||||
if (result != DoAfterStatus.Finished) return;
|
if (result != DoAfterStatus.Finished) return;
|
||||||
|
|
||||||
if (_inventorySystem.TryGetSlotEntity(component.Owner, slot, out var item) && _inventorySystem.TryUnequip(user, component.Owner, slot))
|
if (!_inventorySystem.TryUnequip(user, component.Owner, slot))
|
||||||
{
|
return;
|
||||||
// Raise a dropped event, so that things like gas tank internals properly deactivate when stripping
|
|
||||||
RaiseLocalEvent(item.Value, new DroppedEvent(user), true);
|
// Raise a dropped event, so that things like gas tank internals properly deactivate when stripping
|
||||||
|
RaiseLocalEvent(item, new DroppedEvent(user), true);
|
||||||
|
|
||||||
|
_handsSystem.PickupOrDrop(user, item);
|
||||||
|
_adminLogger.Add(LogType.Stripping, LogImpact.Medium, $"{ToPrettyString(user):user} has stripped the item {ToPrettyString(item):item} from {ToPrettyString(target):target}");
|
||||||
|
|
||||||
_handsSystem.PickupOrDrop(user, item.Value, animate: !stealth);
|
|
||||||
_adminLogger.Add(LogType.Stripping, LogImpact.Medium, $"{ToPrettyString(user):user} has stripped the item {ToPrettyString(item.Value):item} from {ToPrettyString(component.Owner):target}");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Takes an item from a hand and places it in the user's active hand.
|
/// Takes an item from a hand and places it in the user's active hand.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private async void TakeItemFromHands(EntityUid user, string handName, StrippableComponent component)
|
private async void TakeItemFromHands(EntityUid user, EntityUid target, EntityUid item, string handName, StrippableComponent component)
|
||||||
{
|
{
|
||||||
var hands = Comp<HandsComponent>(component.Owner);
|
var hands = Comp<HandsComponent>(target);
|
||||||
var userHands = Comp<HandsComponent>(user);
|
var userHands = Comp<HandsComponent>(user);
|
||||||
|
|
||||||
bool Check()
|
bool Check()
|
||||||
{
|
{
|
||||||
if (!hands.Hands.TryGetValue(handName, out var hand) || hand.HeldEntity == null)
|
if (!hands.Hands.TryGetValue(handName, out var hand) || hand.HeldEntity != item)
|
||||||
{
|
{
|
||||||
user.PopupMessageCursor(Loc.GetString("strippable-component-item-slot-free-message",("owner", component.Owner)));
|
_popup.PopupCursor(Loc.GetString("strippable-component-item-slot-free-message",("owner", target)), user);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (HasComp<HandVirtualItemComponent>(hand.HeldEntity))
|
if (HasComp<HandVirtualItemComponent>(hand.HeldEntity))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!_handsSystem.CanDropHeld(component.Owner, hand, false))
|
if (!_handsSystem.CanDropHeld(target, hand, false))
|
||||||
{
|
{
|
||||||
user.PopupMessageCursor(Loc.GetString("strippable-component-cannot-drop-message",("owner", component.Owner)));
|
_popup.PopupCursor(Loc.GetString("strippable-component-cannot-drop-message",("owner", target)), user);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
var (time, stealth) = GetStripTimeModifiers(user, component.Owner, component.HandStripDelay);
|
var userEv = new BeforeStripEvent(component.HandStripDelay);
|
||||||
|
RaiseLocalEvent(user, userEv);
|
||||||
|
var ev = new BeforeGettingStrippedEvent(userEv.Time, userEv.Stealth);
|
||||||
|
RaiseLocalEvent(target, ev);
|
||||||
|
|
||||||
var doAfterArgs = new DoAfterEventArgs(user, time, CancellationToken.None, component.Owner)
|
var doAfterArgs = new DoAfterArgs(user, ev.Time, new AwaitedDoAfterEvent(), null, target: target, used: item)
|
||||||
{
|
{
|
||||||
ExtraCheck = Check,
|
ExtraCheck = Check,
|
||||||
BreakOnStun = true,
|
AttemptFrequency = AttemptFrequency.EveryTick,
|
||||||
BreakOnDamage = true,
|
BreakOnDamage = true,
|
||||||
BreakOnTargetMove = true,
|
BreakOnTargetMove = true,
|
||||||
BreakOnUserMove = true,
|
BreakOnUserMove = true,
|
||||||
|
NeedHand = true,
|
||||||
|
BreakOnHandChange = false, // allow simultaneously removing multiple items.
|
||||||
|
DuplicateCondition = DuplicateConditions.SameTool
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!stealth
|
if (Check() && hands.Hands.TryGetValue(handName, out var handSlot) && handSlot.HeldEntity != null)
|
||||||
&& Check()
|
|
||||||
&& hands.Hands.TryGetValue(handName, out var handSlot)
|
|
||||||
&& handSlot.HeldEntity != null)
|
|
||||||
{
|
{
|
||||||
_popupSystem.PopupEntity(
|
_popup.PopupEntity(
|
||||||
Loc.GetString("strippable-component-alert-owner",
|
Loc.GetString("strippable-component-alert-owner",
|
||||||
("user", Identity.Entity(user, EntityManager)),
|
("user", Identity.Entity(user, EntityManager)), ("item", item)),
|
||||||
("item", handSlot.HeldEntity)),
|
component.Owner,
|
||||||
component.Owner, component.Owner);
|
component.Owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = await _doAfterSystem.WaitDoAfter(doAfterArgs);
|
var result = await _doAfter.WaitDoAfter(doAfterArgs);
|
||||||
if (result != DoAfterStatus.Finished) return;
|
if (result != DoAfterStatus.Finished) return;
|
||||||
|
|
||||||
if (!hands.Hands.TryGetValue(handName, out var hand) || hand.HeldEntity is not { } held)
|
_handsSystem.TryDrop(target, item, checkActionBlocker: false, handsComp: hands);
|
||||||
return;
|
_handsSystem.PickupOrDrop(user, item, handsComp: userHands);
|
||||||
|
|
||||||
_handsSystem.TryDrop(component.Owner, hand, checkActionBlocker: false, handsComp: hands);
|
|
||||||
_handsSystem.PickupOrDrop(user, held, handsComp: userHands, animate: !stealth);
|
|
||||||
// hand update will trigger strippable update
|
// hand update will trigger strippable update
|
||||||
_adminLogger.Add(LogType.Stripping, LogImpact.Medium, $"{ToPrettyString(user):user} has stripped the item {ToPrettyString(held):item} from {ToPrettyString(component.Owner):target}");
|
_adminLogger.Add(LogType.Stripping, LogImpact.Medium,
|
||||||
|
$"{ToPrettyString(user):user} has stripped the item {ToPrettyString(item):item} from {ToPrettyString(target):target}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using Content.Server.Administration.Logs;
|
using Content.Server.Administration.Logs;
|
||||||
using Content.Server.DoAfter;
|
|
||||||
using Content.Shared.DoAfter;
|
using Content.Shared.DoAfter;
|
||||||
using Content.Shared.Database;
|
using Content.Shared.Database;
|
||||||
using Content.Shared.Interaction.Events;
|
using Content.Shared.Interaction.Events;
|
||||||
@@ -17,14 +16,14 @@ public sealed class HandTeleporterSystem : EntitySystem
|
|||||||
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
|
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
|
||||||
[Dependency] private readonly LinkedEntitySystem _link = default!;
|
[Dependency] private readonly LinkedEntitySystem _link = default!;
|
||||||
[Dependency] private readonly AudioSystem _audio = default!;
|
[Dependency] private readonly AudioSystem _audio = default!;
|
||||||
[Dependency] private readonly DoAfterSystem _doafter = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doafter = default!;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
SubscribeLocalEvent<HandTeleporterComponent, UseInHandEvent>(OnUseInHand);
|
SubscribeLocalEvent<HandTeleporterComponent, UseInHandEvent>(OnUseInHand);
|
||||||
|
|
||||||
SubscribeLocalEvent<HandTeleporterComponent, DoAfterEvent>(OnDoAfter);
|
SubscribeLocalEvent<HandTeleporterComponent, TeleporterDoAfterEvent>(OnDoAfter);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDoAfter(EntityUid uid, HandTeleporterComponent component, DoAfterEvent args)
|
private void OnDoAfter(EntityUid uid, HandTeleporterComponent component, DoAfterEvent args)
|
||||||
@@ -56,15 +55,14 @@ public sealed class HandTeleporterSystem : EntitySystem
|
|||||||
if (xform.ParentUid != xform.GridUid)
|
if (xform.ParentUid != xform.GridUid)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var doafterArgs = new DoAfterEventArgs(args.User, component.PortalCreationDelay, used: uid)
|
var doafterArgs = new DoAfterArgs(args.User, component.PortalCreationDelay, new TeleporterDoAfterEvent(), uid, used: uid)
|
||||||
{
|
{
|
||||||
BreakOnDamage = true,
|
BreakOnDamage = true,
|
||||||
BreakOnStun = true,
|
|
||||||
BreakOnUserMove = true,
|
BreakOnUserMove = true,
|
||||||
MovementThreshold = 0.5f,
|
MovementThreshold = 0.5f,
|
||||||
};
|
};
|
||||||
|
|
||||||
_doafter.DoAfter(doafterArgs);
|
_doafter.TryStartDoAfter(doafterArgs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ using Content.Server.Storage.EntitySystems;
|
|||||||
using Content.Shared.Body.Components;
|
using Content.Shared.Body.Components;
|
||||||
using Content.Shared.Body.Part;
|
using Content.Shared.Body.Part;
|
||||||
using Content.Shared.Buckle.Components;
|
using Content.Shared.Buckle.Components;
|
||||||
|
using Content.Shared.DoAfter;
|
||||||
using Content.Shared.Examine;
|
using Content.Shared.Examine;
|
||||||
using Content.Shared.IdentityManagement;
|
using Content.Shared.IdentityManagement;
|
||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
@@ -39,8 +40,7 @@ namespace Content.Server.Toilet
|
|||||||
SubscribeLocalEvent<ToiletComponent, InteractHandEvent>(OnInteractHand, new []{typeof(BuckleSystem)});
|
SubscribeLocalEvent<ToiletComponent, InteractHandEvent>(OnInteractHand, new []{typeof(BuckleSystem)});
|
||||||
SubscribeLocalEvent<ToiletComponent, ExaminedEvent>(OnExamine);
|
SubscribeLocalEvent<ToiletComponent, ExaminedEvent>(OnExamine);
|
||||||
SubscribeLocalEvent<ToiletComponent, SuicideEvent>(OnSuicide);
|
SubscribeLocalEvent<ToiletComponent, SuicideEvent>(OnSuicide);
|
||||||
SubscribeLocalEvent<ToiletPryFinished>(OnToiletPried);
|
SubscribeLocalEvent<ToiletComponent, ToiletPryDoAfterEvent>(OnToiletPried);
|
||||||
SubscribeLocalEvent<ToiletPryInterrupted>(OnToiletInterrupt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnSuicide(EntityUid uid, ToiletComponent component, SuicideEvent args)
|
private void OnSuicide(EntityUid uid, ToiletComponent component, SuicideEvent args)
|
||||||
@@ -94,29 +94,15 @@ namespace Content.Server.Toilet
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// are player trying place or lift of cistern lid?
|
// are player trying place or lift of cistern lid?
|
||||||
if (EntityManager.TryGetComponent(args.Used, out ToolComponent? tool)
|
if (_toolSystem.UseTool(args.Used, args.User, uid, component.PryLidTime, component.PryingQuality, new ToiletPryDoAfterEvent()))
|
||||||
&& tool.Qualities.Contains(component.PryingQuality))
|
|
||||||
{
|
{
|
||||||
// check if someone is already prying this toilet
|
|
||||||
if (component.IsPrying)
|
|
||||||
return;
|
|
||||||
component.IsPrying = true;
|
|
||||||
|
|
||||||
var toolEvData = new ToolEventData(new ToiletPryFinished(uid));
|
|
||||||
|
|
||||||
// try to pry toilet cistern
|
|
||||||
if (!_toolSystem.UseTool(args.Used, args.User, uid, component.PryLidTime, new [] {component.PryingQuality}, toolEvData))
|
|
||||||
{
|
|
||||||
component.IsPrying = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
args.Handled = true;
|
args.Handled = true;
|
||||||
}
|
}
|
||||||
// maybe player trying to hide something inside cistern?
|
// maybe player trying to hide something inside cistern?
|
||||||
else if (component.LidOpen)
|
else if (component.LidOpen)
|
||||||
{
|
{
|
||||||
args.Handled = _secretStash.TryHideItem(uid, args.User, args.Used);
|
args.Handled = true;
|
||||||
|
_secretStash.TryHideItem(uid, args.User, args.Used);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,22 +146,13 @@ namespace Content.Server.Toilet
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnToiletInterrupt(ToiletPryInterrupted ev)
|
private void OnToiletPried(EntityUid uid, ToiletComponent toilet, ToiletPryDoAfterEvent args)
|
||||||
{
|
{
|
||||||
if (!EntityManager.TryGetComponent(ev.Uid, out ToiletComponent? toilet))
|
if (args.Cancelled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
toilet.IsPrying = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnToiletPried(ToiletPryFinished ev)
|
|
||||||
{
|
|
||||||
if (!EntityManager.TryGetComponent(ev.Uid, out ToiletComponent? toilet))
|
|
||||||
return;
|
|
||||||
|
|
||||||
toilet.IsPrying = false;
|
|
||||||
toilet.LidOpen = !toilet.LidOpen;
|
toilet.LidOpen = !toilet.LidOpen;
|
||||||
UpdateSprite(ev.Uid, toilet);
|
UpdateSprite(uid, toilet);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ToggleToiletSeat(EntityUid uid, ToiletComponent? component = null)
|
public void ToggleToiletSeat(EntityUid uid, ToiletComponent? component = null)
|
||||||
@@ -197,24 +174,4 @@ namespace Content.Server.Toilet
|
|||||||
_appearance.SetData(uid, ToiletVisuals.SeatUp, component.IsSeatUp, appearance);
|
_appearance.SetData(uid, ToiletVisuals.SeatUp, component.IsSeatUp, appearance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class ToiletPryFinished : EntityEventArgs
|
|
||||||
{
|
|
||||||
public EntityUid Uid;
|
|
||||||
|
|
||||||
public ToiletPryFinished(EntityUid uid)
|
|
||||||
{
|
|
||||||
Uid = uid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public sealed class ToiletPryInterrupted : EntityEventArgs
|
|
||||||
{
|
|
||||||
public EntityUid Uid;
|
|
||||||
|
|
||||||
public ToiletPryInterrupted(EntityUid uid)
|
|
||||||
{
|
|
||||||
Uid = uid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,9 +6,6 @@ namespace Content.Server.Tools.Components;
|
|||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
public sealed class LatticeCuttingComponent : Component
|
public sealed class LatticeCuttingComponent : Component
|
||||||
{
|
{
|
||||||
[DataField("toolComponentNeeded")]
|
|
||||||
public bool ToolComponentNeeded = true;
|
|
||||||
|
|
||||||
[DataField("qualityNeeded", customTypeSerializer:typeof(PrototypeIdSerializer<ToolQualityPrototype>))]
|
[DataField("qualityNeeded", customTypeSerializer:typeof(PrototypeIdSerializer<ToolQualityPrototype>))]
|
||||||
public string QualityNeeded = "Cutting";
|
public string QualityNeeded = "Cutting";
|
||||||
|
|
||||||
|
|||||||
@@ -15,8 +15,5 @@ namespace Content.Server.Tools.Components
|
|||||||
|
|
||||||
[DataField("delay")]
|
[DataField("delay")]
|
||||||
public float Delay = 1f;
|
public float Delay = 1f;
|
||||||
|
|
||||||
[DataField("cancelToken")]
|
|
||||||
public CancellationTokenSource? CancelToken;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,15 +47,9 @@ public sealed class WeldableComponent : SharedWeldableComponent
|
|||||||
[ViewVariables(VVAccess.ReadWrite)]
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
public string? WeldedExamineMessage = "weldable-component-examine-is-welded";
|
public string? WeldedExamineMessage = "weldable-component-examine-is-welded";
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Whether something is currently using a welder on this so DoAfter isn't spammed.
|
|
||||||
/// </summary>
|
|
||||||
[ViewVariables(VVAccess.ReadOnly)]
|
|
||||||
public bool BeingWelded;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Is this entity currently welded shut?
|
/// Is this entity currently welded shut?
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ViewVariables(VVAccess.ReadOnly)]
|
[DataField("isWelded")]
|
||||||
public bool IsWelded;
|
public bool IsWelded;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
using Content.Server.Administration.Logs;
|
using Content.Server.Administration.Logs;
|
||||||
using Content.Server.Tools.Components;
|
using Content.Server.Tools.Components;
|
||||||
using Content.Shared.Database;
|
using Content.Shared.Database;
|
||||||
|
using Content.Shared.DoAfter;
|
||||||
using Content.Shared.Examine;
|
using Content.Shared.Examine;
|
||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
using Content.Shared.Tools;
|
using Content.Shared.Tools;
|
||||||
using Content.Shared.Tools.Components;
|
using Content.Shared.Tools.Components;
|
||||||
|
using Content.Shared.Tools.Systems;
|
||||||
using Robust.Shared.Physics;
|
using Robust.Shared.Physics;
|
||||||
using Robust.Shared.Physics.Systems;
|
using Robust.Shared.Physics.Systems;
|
||||||
|
|
||||||
@@ -22,7 +24,6 @@ public sealed class WeldableSystem : EntitySystem
|
|||||||
base.Initialize();
|
base.Initialize();
|
||||||
SubscribeLocalEvent<WeldableComponent, InteractUsingEvent>(OnInteractUsing);
|
SubscribeLocalEvent<WeldableComponent, InteractUsingEvent>(OnInteractUsing);
|
||||||
SubscribeLocalEvent<WeldableComponent, WeldFinishedEvent>(OnWeldFinished);
|
SubscribeLocalEvent<WeldableComponent, WeldFinishedEvent>(OnWeldFinished);
|
||||||
SubscribeLocalEvent<WeldableComponent, WeldCancelledEvent>(OnWeldCanceled);
|
|
||||||
SubscribeLocalEvent<LayerChangeOnWeldComponent, WeldableChangedEvent>(OnWeldChanged);
|
SubscribeLocalEvent<LayerChangeOnWeldComponent, WeldableChangedEvent>(OnWeldChanged);
|
||||||
SubscribeLocalEvent<WeldableComponent, ExaminedEvent>(OnExamine);
|
SubscribeLocalEvent<WeldableComponent, ExaminedEvent>(OnExamine);
|
||||||
}
|
}
|
||||||
@@ -47,9 +48,7 @@ public sealed class WeldableSystem : EntitySystem
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Basic checks
|
// Basic checks
|
||||||
if (!component.Weldable || component.BeingWelded)
|
if (!component.Weldable)
|
||||||
return false;
|
|
||||||
if (!_toolSystem.HasQuality(tool, component.WeldingQuality))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Other component systems
|
// Other component systems
|
||||||
@@ -69,8 +68,8 @@ public sealed class WeldableSystem : EntitySystem
|
|||||||
if (!CanWeld(uid, tool, user, component))
|
if (!CanWeld(uid, tool, user, component))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var toolEvData = new ToolEventData(new WeldFinishedEvent(user, tool), cancelledEv: new WeldCancelledEvent(),targetEntity: uid);
|
if (!_toolSystem.UseTool(tool, user, uid, component.WeldingTime.Seconds, component.WeldingQuality, new WeldFinishedEvent(), fuel: component.FuelConsumption))
|
||||||
component.BeingWelded = _toolSystem.UseTool(tool, user, uid, component.WeldingTime.Seconds, new[] { component.WeldingQuality }, toolEvData, fuel: component.FuelConsumption);
|
return false;
|
||||||
|
|
||||||
// Log attempt
|
// Log attempt
|
||||||
_adminLogger.Add(LogType.Action, LogImpact.Low, $"{ToPrettyString(user):user} is {(component.IsWelded ? "un" : "")}welding {ToPrettyString(uid):target} at {Transform(uid).Coordinates:targetlocation}");
|
_adminLogger.Add(LogType.Action, LogImpact.Low, $"{ToPrettyString(user):user} is {(component.IsWelded ? "un" : "")}welding {ToPrettyString(uid):target} at {Transform(uid).Coordinates:targetlocation}");
|
||||||
@@ -80,10 +79,11 @@ public sealed class WeldableSystem : EntitySystem
|
|||||||
|
|
||||||
private void OnWeldFinished(EntityUid uid, WeldableComponent component, WeldFinishedEvent args)
|
private void OnWeldFinished(EntityUid uid, WeldableComponent component, WeldFinishedEvent args)
|
||||||
{
|
{
|
||||||
component.BeingWelded = false;
|
if (args.Cancelled || args.Used == null)
|
||||||
|
return;
|
||||||
|
|
||||||
// Check if target is still valid
|
// Check if target is still valid
|
||||||
if (!CanWeld(uid, args.Tool, args.User, component))
|
if (!CanWeld(uid, args.Used.Value, args.User, component))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
component.IsWelded = !component.IsWelded;
|
component.IsWelded = !component.IsWelded;
|
||||||
@@ -95,11 +95,6 @@ public sealed class WeldableSystem : EntitySystem
|
|||||||
_adminLogger.Add(LogType.Action, LogImpact.Low, $"{ToPrettyString(args.User):user} {(!component.IsWelded ? "un" : "")}welded {ToPrettyString(uid):target}");
|
_adminLogger.Add(LogType.Action, LogImpact.Low, $"{ToPrettyString(args.User):user} {(!component.IsWelded ? "un" : "")}welded {ToPrettyString(uid):target}");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnWeldCanceled(EntityUid uid, WeldableComponent component, WeldCancelledEvent args)
|
|
||||||
{
|
|
||||||
component.BeingWelded = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnWeldChanged(EntityUid uid, LayerChangeOnWeldComponent component, WeldableChangedEvent args)
|
private void OnWeldChanged(EntityUid uid, LayerChangeOnWeldComponent component, WeldableChangedEvent args)
|
||||||
{
|
{
|
||||||
if (!TryComp<FixturesComponent>(uid, out var fixtures))
|
if (!TryComp<FixturesComponent>(uid, out var fixtures))
|
||||||
@@ -148,30 +143,6 @@ public sealed class WeldableSystem : EntitySystem
|
|||||||
return;
|
return;
|
||||||
component.WeldingTime = time;
|
component.WeldingTime = time;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Raised after welding do_after has finished. It doesn't guarantee success,
|
|
||||||
/// use <see cref="WeldableChangedEvent"/> to get updated status.
|
|
||||||
/// </summary>
|
|
||||||
private sealed class WeldFinishedEvent : EntityEventArgs
|
|
||||||
{
|
|
||||||
public readonly EntityUid User;
|
|
||||||
public readonly EntityUid Tool;
|
|
||||||
|
|
||||||
public WeldFinishedEvent(EntityUid user, EntityUid tool)
|
|
||||||
{
|
|
||||||
User = user;
|
|
||||||
Tool = tool;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Raised when entity welding has failed.
|
|
||||||
/// </summary>
|
|
||||||
private sealed class WeldCancelledEvent : EntityEventArgs
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using Content.Server.Maps;
|
using Content.Server.Maps;
|
||||||
using Content.Server.Tools.Components;
|
using Content.Server.Tools.Components;
|
||||||
using Content.Shared.Database;
|
using Content.Shared.Database;
|
||||||
|
using Content.Shared.DoAfter;
|
||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
using Content.Shared.Maps;
|
using Content.Shared.Maps;
|
||||||
using Content.Shared.Tools.Components;
|
using Content.Shared.Tools.Components;
|
||||||
@@ -22,6 +23,9 @@ public sealed partial class ToolSystem
|
|||||||
|
|
||||||
private void OnLatticeCutComplete(EntityUid uid, LatticeCuttingComponent component, LatticeCuttingCompleteEvent args)
|
private void OnLatticeCutComplete(EntityUid uid, LatticeCuttingComponent component, LatticeCuttingCompleteEvent args)
|
||||||
{
|
{
|
||||||
|
if (args.Cancelled)
|
||||||
|
return;
|
||||||
|
|
||||||
var gridUid = args.Coordinates.GetGridUid(EntityManager);
|
var gridUid = args.Coordinates.GetGridUid(EntityManager);
|
||||||
if (gridUid == null)
|
if (gridUid == null)
|
||||||
return;
|
return;
|
||||||
@@ -50,10 +54,6 @@ public sealed partial class ToolSystem
|
|||||||
|
|
||||||
private bool TryCut(EntityUid toolEntity, EntityUid user, LatticeCuttingComponent component, EntityCoordinates clickLocation)
|
private bool TryCut(EntityUid toolEntity, EntityUid user, LatticeCuttingComponent component, EntityCoordinates clickLocation)
|
||||||
{
|
{
|
||||||
ToolComponent? tool = null;
|
|
||||||
if (component.ToolComponentNeeded && !TryComp<ToolComponent?>(toolEntity, out tool))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!_mapManager.TryGetGrid(clickLocation.GetGridUid(EntityManager), out var mapGrid))
|
if (!_mapManager.TryGetGrid(clickLocation.GetGridUid(EntityManager), out var mapGrid))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -71,24 +71,8 @@ public sealed partial class ToolSystem
|
|||||||
|| tile.IsBlockedTurf(true))
|
|| tile.IsBlockedTurf(true))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var toolEvData = new ToolEventData(new LatticeCuttingCompleteEvent(clickLocation, user), targetEntity: toolEntity);
|
var ev = new LatticeCuttingCompleteEvent(clickLocation);
|
||||||
|
return UseTool(toolEntity, user, toolEntity, component.Delay, component.QualityNeeded, ev);
|
||||||
if (!UseTool(toolEntity, user, null, component.Delay, new[] {component.QualityNeeded}, toolEvData, toolComponent: tool))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private sealed class LatticeCuttingCompleteEvent : EntityEventArgs
|
|
||||||
{
|
|
||||||
public EntityCoordinates Coordinates;
|
|
||||||
public EntityUid User;
|
|
||||||
|
|
||||||
public LatticeCuttingCompleteEvent(EntityCoordinates coordinates, EntityUid user)
|
|
||||||
{
|
|
||||||
Coordinates = coordinates;
|
|
||||||
User = user;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using Content.Server.Fluids.Components;
|
using Content.Server.Fluids.Components;
|
||||||
using Content.Server.Tools.Components;
|
using Content.Server.Tools.Components;
|
||||||
|
using Content.Shared.DoAfter;
|
||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
using Content.Shared.Maps;
|
using Content.Shared.Maps;
|
||||||
using Content.Shared.Tools.Components;
|
using Content.Shared.Tools.Components;
|
||||||
@@ -18,8 +19,7 @@ public sealed partial class ToolSystem
|
|||||||
private void InitializeTilePrying()
|
private void InitializeTilePrying()
|
||||||
{
|
{
|
||||||
SubscribeLocalEvent<TilePryingComponent, AfterInteractEvent>(OnTilePryingAfterInteract);
|
SubscribeLocalEvent<TilePryingComponent, AfterInteractEvent>(OnTilePryingAfterInteract);
|
||||||
SubscribeLocalEvent<TilePryingComponent, TilePryingCompleteEvent>(OnTilePryComplete);
|
SubscribeLocalEvent<TilePryingComponent, TilePryingDoAfterEvent>(OnTilePryComplete);
|
||||||
SubscribeLocalEvent<TilePryingComponent, TilePryingCancelledEvent>(OnTilePryCancelled);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnTilePryingAfterInteract(EntityUid uid, TilePryingComponent component, AfterInteractEvent args)
|
private void OnTilePryingAfterInteract(EntityUid uid, TilePryingComponent component, AfterInteractEvent args)
|
||||||
@@ -30,9 +30,11 @@ public sealed partial class ToolSystem
|
|||||||
args.Handled = true;
|
args.Handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnTilePryComplete(EntityUid uid, TilePryingComponent component, TilePryingCompleteEvent args)
|
private void OnTilePryComplete(EntityUid uid, TilePryingComponent component, TilePryingDoAfterEvent args)
|
||||||
{
|
{
|
||||||
component.CancelToken = null;
|
if (args.Cancelled)
|
||||||
|
return;
|
||||||
|
|
||||||
var gridUid = args.Coordinates.GetGridUid(EntityManager);
|
var gridUid = args.Coordinates.GetGridUid(EntityManager);
|
||||||
if (!_mapManager.TryGetGrid(gridUid, out var grid))
|
if (!_mapManager.TryGetGrid(gridUid, out var grid))
|
||||||
{
|
{
|
||||||
@@ -44,14 +46,9 @@ public sealed partial class ToolSystem
|
|||||||
_tile.PryTile(tile);
|
_tile.PryTile(tile);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnTilePryCancelled(EntityUid uid, TilePryingComponent component, TilePryingCancelledEvent args)
|
|
||||||
{
|
|
||||||
component.CancelToken = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool TryPryTile(EntityUid toolEntity, EntityUid user, TilePryingComponent component, EntityCoordinates clickLocation)
|
private bool TryPryTile(EntityUid toolEntity, EntityUid user, TilePryingComponent component, EntityCoordinates clickLocation)
|
||||||
{
|
{
|
||||||
if (!TryComp<ToolComponent?>(toolEntity, out var tool) && component.ToolComponentNeeded || component.CancelToken != null)
|
if (!TryComp<ToolComponent?>(toolEntity, out var tool) && component.ToolComponentNeeded)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!_mapManager.TryGetGrid(clickLocation.GetGridUid(EntityManager), out var mapGrid))
|
if (!_mapManager.TryGetGrid(clickLocation.GetGridUid(EntityManager), out var mapGrid))
|
||||||
@@ -69,28 +66,8 @@ public sealed partial class ToolSystem
|
|||||||
if (!tileDef.CanCrowbar)
|
if (!tileDef.CanCrowbar)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
component.CancelToken = new CancellationTokenSource();
|
var ev = new TilePryingDoAfterEvent(clickLocation);
|
||||||
|
|
||||||
var toolEvData = new ToolEventData(new TilePryingCompleteEvent(clickLocation), cancelledEv:new TilePryingCancelledEvent() ,targetEntity:toolEntity);
|
|
||||||
|
|
||||||
if (!UseTool(toolEntity, user, null, component.Delay, new[] { component.QualityNeeded }, toolEvData, toolComponent: tool, cancelToken: component.CancelToken))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private sealed class TilePryingCompleteEvent : EntityEventArgs
|
|
||||||
{
|
|
||||||
public readonly EntityCoordinates Coordinates;
|
|
||||||
|
|
||||||
public TilePryingCompleteEvent(EntityCoordinates coordinates)
|
|
||||||
{
|
|
||||||
Coordinates = coordinates;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private sealed class TilePryingCancelledEvent : EntityEventArgs
|
|
||||||
{
|
|
||||||
|
|
||||||
|
return UseTool(toolEntity, user, toolEntity, component.Delay, component.QualityNeeded, ev, toolComponent: tool);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using Content.Server.Chemistry.Components.SolutionManager;
|
|||||||
using Content.Server.Chemistry.EntitySystems;
|
using Content.Server.Chemistry.EntitySystems;
|
||||||
using Content.Server.Tools.Components;
|
using Content.Server.Tools.Components;
|
||||||
using Content.Shared.Database;
|
using Content.Shared.Database;
|
||||||
|
using Content.Shared.DoAfter;
|
||||||
using Content.Shared.Examine;
|
using Content.Shared.Examine;
|
||||||
using Content.Shared.FixedPoint;
|
using Content.Shared.FixedPoint;
|
||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
@@ -15,6 +16,7 @@ using Content.Shared.Weapons.Melee.Events;
|
|||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
using Robust.Shared.GameStates;
|
using Robust.Shared.GameStates;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
namespace Content.Server.Tools
|
namespace Content.Server.Tools
|
||||||
{
|
{
|
||||||
@@ -38,8 +40,8 @@ namespace Content.Server.Tools
|
|||||||
SubscribeLocalEvent<WelderComponent, SolutionChangedEvent>(OnWelderSolutionChange);
|
SubscribeLocalEvent<WelderComponent, SolutionChangedEvent>(OnWelderSolutionChange);
|
||||||
SubscribeLocalEvent<WelderComponent, ActivateInWorldEvent>(OnWelderActivate);
|
SubscribeLocalEvent<WelderComponent, ActivateInWorldEvent>(OnWelderActivate);
|
||||||
SubscribeLocalEvent<WelderComponent, AfterInteractEvent>(OnWelderAfterInteract);
|
SubscribeLocalEvent<WelderComponent, AfterInteractEvent>(OnWelderAfterInteract);
|
||||||
SubscribeLocalEvent<WelderComponent, ToolUseAttemptEvent>(OnWelderToolUseAttempt);
|
SubscribeLocalEvent<WelderComponent, DoAfterAttemptEvent<ToolDoAfterEvent>>(OnWelderToolUseAttempt);
|
||||||
SubscribeLocalEvent<WelderComponent, ToolUseFinishAttemptEvent>(OnWelderToolUseFinishAttempt);
|
SubscribeLocalEvent<WelderComponent, ToolDoAfterEvent>(OnWelderDoAfter);
|
||||||
SubscribeLocalEvent<WelderComponent, ComponentShutdown>(OnWelderShutdown);
|
SubscribeLocalEvent<WelderComponent, ComponentShutdown>(OnWelderShutdown);
|
||||||
SubscribeLocalEvent<WelderComponent, ComponentGetState>(OnWelderGetState);
|
SubscribeLocalEvent<WelderComponent, ComponentGetState>(OnWelderGetState);
|
||||||
SubscribeLocalEvent<WelderComponent, MeleeHitEvent>(OnMeleeHit);
|
SubscribeLocalEvent<WelderComponent, MeleeHitEvent>(OnMeleeHit);
|
||||||
@@ -262,56 +264,36 @@ namespace Content.Server.Tools
|
|||||||
args.Handled = true;
|
args.Handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnWelderToolUseAttempt(EntityUid uid, WelderComponent welder, ToolUseAttemptEvent args)
|
private void OnWelderToolUseAttempt(EntityUid uid, WelderComponent welder, DoAfterAttemptEvent<ToolDoAfterEvent> args)
|
||||||
{
|
{
|
||||||
if (args.Cancelled)
|
DebugTools.Assert(args.Event.Fuel > 0);
|
||||||
return;
|
var user = args.DoAfter.Args.User;
|
||||||
|
|
||||||
if (!welder.Lit)
|
if (!welder.Lit)
|
||||||
{
|
{
|
||||||
_popupSystem.PopupEntity(Loc.GetString("welder-component-welder-not-lit-message"), uid, args.User);
|
_popupSystem.PopupEntity(Loc.GetString("welder-component-welder-not-lit-message"), uid, user);
|
||||||
args.Cancel();
|
args.Cancel();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var (fuel, _) = GetWelderFuelAndCapacity(uid, welder);
|
var (fuel, _) = GetWelderFuelAndCapacity(uid, welder);
|
||||||
|
|
||||||
if (FixedPoint2.New(args.Fuel) > fuel)
|
if (FixedPoint2.New(args.Event.Fuel) > fuel)
|
||||||
{
|
{
|
||||||
_popupSystem.PopupEntity(Loc.GetString("welder-component-cannot-weld-message"), uid, args.User);
|
_popupSystem.PopupEntity(Loc.GetString("welder-component-cannot-weld-message"), uid, user);
|
||||||
args.Cancel();
|
args.Cancel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnWelderToolUseFinishAttempt(EntityUid uid, WelderComponent welder, ToolUseFinishAttemptEvent args)
|
private void OnWelderDoAfter(EntityUid uid, WelderComponent welder, ToolDoAfterEvent args)
|
||||||
{
|
{
|
||||||
if (args.Cancelled)
|
if (args.Cancelled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!welder.Lit)
|
|
||||||
{
|
|
||||||
_popupSystem.PopupEntity(Loc.GetString("welder-component-welder-not-lit-message"), uid, args.User);
|
|
||||||
args.Cancel();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var (fuel, _) = GetWelderFuelAndCapacity(uid, welder);
|
|
||||||
|
|
||||||
var neededFuel = FixedPoint2.New(args.Fuel);
|
|
||||||
|
|
||||||
if (neededFuel > fuel)
|
|
||||||
{
|
|
||||||
_popupSystem.PopupEntity(Loc.GetString("welder-component-cannot-weld-message"), uid, args.User);
|
|
||||||
args.Cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_solutionContainerSystem.TryGetSolution(uid, welder.FuelSolution, out var solution))
|
if (!_solutionContainerSystem.TryGetSolution(uid, welder.FuelSolution, out var solution))
|
||||||
{
|
|
||||||
args.Cancel();
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
solution.RemoveReagent(welder.FuelReagent, neededFuel);
|
solution.RemoveReagent(welder.FuelReagent, FixedPoint2.New(args.Fuel));
|
||||||
_entityManager.Dirty(welder);
|
_entityManager.Dirty(welder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Server.Cargo.Systems;
|
using Content.Server.Cargo.Systems;
|
||||||
using Content.Server.DoAfter;
|
|
||||||
using Content.Shared.DoAfter;
|
using Content.Shared.DoAfter;
|
||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
using Content.Shared.Popups;
|
using Content.Shared.Popups;
|
||||||
@@ -16,7 +15,7 @@ namespace Content.Server.VendingMachines.Restock
|
|||||||
{
|
{
|
||||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||||
|
|
||||||
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
|
||||||
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
|
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
|
||||||
[Dependency] private readonly AudioSystem _audioSystem = default!;
|
[Dependency] private readonly AudioSystem _audioSystem = default!;
|
||||||
[Dependency] private readonly PricingSystem _pricingSystem = default!;
|
[Dependency] private readonly PricingSystem _pricingSystem = default!;
|
||||||
@@ -65,7 +64,7 @@ namespace Content.Server.VendingMachines.Restock
|
|||||||
|
|
||||||
private void OnAfterInteract(EntityUid uid, VendingMachineRestockComponent component, AfterInteractEvent args)
|
private void OnAfterInteract(EntityUid uid, VendingMachineRestockComponent component, AfterInteractEvent args)
|
||||||
{
|
{
|
||||||
if (args.Target == null || !args.CanReach)
|
if (args.Target == null || !args.CanReach || args.Handled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!TryComp<VendingMachineComponent>(args.Target, out var machineComponent))
|
if (!TryComp<VendingMachineComponent>(args.Target, out var machineComponent))
|
||||||
@@ -77,14 +76,19 @@ namespace Content.Server.VendingMachines.Restock
|
|||||||
if (!TryAccessMachine(uid, component, machineComponent, args.User, args.Target.Value))
|
if (!TryAccessMachine(uid, component, machineComponent, args.User, args.Target.Value))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_doAfterSystem.DoAfter(new DoAfterEventArgs(args.User, (float) component.RestockDelay.TotalSeconds, target:args.Target, used:uid)
|
args.Handled = true;
|
||||||
|
|
||||||
|
var doAfterArgs = new DoAfterArgs(args.User, (float) component.RestockDelay.TotalSeconds, new RestockDoAfterEvent(), args.Target,
|
||||||
|
target: args.Target, used: uid)
|
||||||
{
|
{
|
||||||
BreakOnTargetMove = true,
|
BreakOnTargetMove = true,
|
||||||
BreakOnUserMove = true,
|
BreakOnUserMove = true,
|
||||||
BreakOnStun = true,
|
|
||||||
BreakOnDamage = true,
|
BreakOnDamage = true,
|
||||||
NeedHand = true
|
NeedHand = true
|
||||||
});
|
};
|
||||||
|
|
||||||
|
if (!_doAfterSystem.TryStartDoAfter(doAfterArgs))
|
||||||
|
return;
|
||||||
|
|
||||||
_popupSystem.PopupEntity(Loc.GetString("vending-machine-restock-start", ("this", uid), ("user", args.User), ("target", args.Target)),
|
_popupSystem.PopupEntity(Loc.GetString("vending-machine-restock-start", ("this", uid), ("user", args.User), ("target", args.Target)),
|
||||||
args.User,
|
args.User,
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ namespace Content.Server.VendingMachines
|
|||||||
|
|
||||||
SubscribeLocalEvent<VendingMachineComponent, VendingMachineSelfDispenseEvent>(OnSelfDispense);
|
SubscribeLocalEvent<VendingMachineComponent, VendingMachineSelfDispenseEvent>(OnSelfDispense);
|
||||||
|
|
||||||
SubscribeLocalEvent<VendingMachineComponent, DoAfterEvent>(OnDoAfter);
|
SubscribeLocalEvent<VendingMachineComponent, RestockDoAfterEvent>(OnDoAfter);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnVendingPrice(EntityUid uid, VendingMachineComponent component, ref PriceCalculationEvent args)
|
private void OnVendingPrice(EntityUid uid, VendingMachineComponent component, ref PriceCalculationEvent args)
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
using Content.Server.DoAfter;
|
|
||||||
using Content.Server.Hands.Components;
|
using Content.Server.Hands.Components;
|
||||||
using Content.Server.Hands.Systems;
|
using Content.Server.Hands.Systems;
|
||||||
using Content.Server.Wieldable.Components;
|
using Content.Server.Wieldable.Components;
|
||||||
@@ -13,13 +12,14 @@ using Robust.Shared.Player;
|
|||||||
using Content.Server.Actions.Events;
|
using Content.Server.Actions.Events;
|
||||||
using Content.Shared.DoAfter;
|
using Content.Shared.DoAfter;
|
||||||
using Content.Shared.Weapons.Melee.Events;
|
using Content.Shared.Weapons.Melee.Events;
|
||||||
|
using Content.Shared.Wieldable;
|
||||||
|
|
||||||
|
|
||||||
namespace Content.Server.Wieldable
|
namespace Content.Server.Wieldable
|
||||||
{
|
{
|
||||||
public sealed class WieldableSystem : EntitySystem
|
public sealed class WieldableSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly DoAfterSystem _doAfter = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
|
||||||
[Dependency] private readonly HandVirtualItemSystem _virtualItemSystem = default!;
|
[Dependency] private readonly HandVirtualItemSystem _virtualItemSystem = default!;
|
||||||
[Dependency] private readonly SharedHandsSystem _handsSystem = default!;
|
[Dependency] private readonly SharedHandsSystem _handsSystem = default!;
|
||||||
[Dependency] private readonly SharedItemSystem _itemSystem = default!;
|
[Dependency] private readonly SharedItemSystem _itemSystem = default!;
|
||||||
@@ -31,7 +31,7 @@ namespace Content.Server.Wieldable
|
|||||||
base.Initialize();
|
base.Initialize();
|
||||||
|
|
||||||
SubscribeLocalEvent<WieldableComponent, UseInHandEvent>(OnUseInHand);
|
SubscribeLocalEvent<WieldableComponent, UseInHandEvent>(OnUseInHand);
|
||||||
SubscribeLocalEvent<WieldableComponent, DoAfterEvent>(OnDoAfter);
|
SubscribeLocalEvent<WieldableComponent, WieldableDoAfterEvent>(OnDoAfter);
|
||||||
SubscribeLocalEvent<WieldableComponent, ItemUnwieldedEvent>(OnItemUnwielded);
|
SubscribeLocalEvent<WieldableComponent, ItemUnwieldedEvent>(OnItemUnwielded);
|
||||||
SubscribeLocalEvent<WieldableComponent, GotUnequippedHandEvent>(OnItemLeaveHand);
|
SubscribeLocalEvent<WieldableComponent, GotUnequippedHandEvent>(OnItemLeaveHand);
|
||||||
SubscribeLocalEvent<WieldableComponent, VirtualItemDeletedEvent>(OnVirtualItemDeleted);
|
SubscribeLocalEvent<WieldableComponent, VirtualItemDeletedEvent>(OnVirtualItemDeleted);
|
||||||
@@ -126,15 +126,13 @@ namespace Content.Server.Wieldable
|
|||||||
if (ev.Cancelled)
|
if (ev.Cancelled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var doargs = new DoAfterEventArgs(user, component.WieldTime, used:used)
|
var doargs = new DoAfterArgs(user, component.WieldTime, new WieldableDoAfterEvent(), used, used: used)
|
||||||
{
|
{
|
||||||
BreakOnUserMove = false,
|
BreakOnUserMove = false,
|
||||||
BreakOnDamage = true,
|
BreakOnDamage = true
|
||||||
BreakOnStun = true,
|
|
||||||
BreakOnTargetMove = true
|
|
||||||
};
|
};
|
||||||
|
|
||||||
_doAfter.DoAfter(doargs);
|
_doAfter.TryStartDoAfter(doargs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ using System.Diagnostics.CodeAnalysis;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using Content.Server.Administration.Logs;
|
using Content.Server.Administration.Logs;
|
||||||
using Content.Server.DoAfter;
|
|
||||||
using Content.Server.Hands.Components;
|
using Content.Server.Hands.Components;
|
||||||
using Content.Server.Power.Components;
|
using Content.Server.Power.Components;
|
||||||
using Content.Shared.DoAfter;
|
using Content.Shared.DoAfter;
|
||||||
@@ -24,15 +23,14 @@ public sealed class WiresSystem : SharedWiresSystem
|
|||||||
{
|
{
|
||||||
[Dependency] private readonly IPrototypeManager _protoMan = default!;
|
[Dependency] private readonly IPrototypeManager _protoMan = default!;
|
||||||
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
|
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
|
||||||
[Dependency] private readonly DoAfterSystem _doAfter = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
|
||||||
[Dependency] private readonly SharedToolSystem _toolSystem = default!;
|
[Dependency] private readonly SharedToolSystem _toolSystem = default!;
|
||||||
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
|
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
|
||||||
[Dependency] private readonly SharedInteractionSystem _interactionSystem = default!;
|
[Dependency] private readonly SharedInteractionSystem _interactionSystem = default!;
|
||||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||||
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
|
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
|
||||||
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
||||||
|
[Dependency] private readonly IRobustRandom _random = default!;
|
||||||
private IRobustRandom _random = new RobustRandom();
|
|
||||||
|
|
||||||
// This is where all the wire layouts are stored.
|
// This is where all the wire layouts are stored.
|
||||||
[ViewVariables] private readonly Dictionary<string, WireLayout> _layouts = new();
|
[ViewVariables] private readonly Dictionary<string, WireLayout> _layouts = new();
|
||||||
@@ -48,15 +46,14 @@ public sealed class WiresSystem : SharedWiresSystem
|
|||||||
SubscribeLocalEvent<RoundRestartCleanupEvent>(Reset);
|
SubscribeLocalEvent<RoundRestartCleanupEvent>(Reset);
|
||||||
|
|
||||||
// this is a broadcast event
|
// this is a broadcast event
|
||||||
SubscribeLocalEvent<WireToolFinishedEvent>(OnToolFinished);
|
SubscribeLocalEvent<WiresPanelComponent, WirePanelDoAfterEvent>(OnPanelDoAfter);
|
||||||
SubscribeLocalEvent<WireToolCanceledEvent>(OnToolCanceled);
|
|
||||||
SubscribeLocalEvent<WiresComponent, ComponentStartup>(OnWiresStartup);
|
SubscribeLocalEvent<WiresComponent, ComponentStartup>(OnWiresStartup);
|
||||||
SubscribeLocalEvent<WiresComponent, WiresActionMessage>(OnWiresActionMessage);
|
SubscribeLocalEvent<WiresComponent, WiresActionMessage>(OnWiresActionMessage);
|
||||||
SubscribeLocalEvent<WiresComponent, InteractUsingEvent>(OnInteractUsing);
|
SubscribeLocalEvent<WiresComponent, InteractUsingEvent>(OnInteractUsing);
|
||||||
SubscribeLocalEvent<WiresComponent, MapInitEvent>(OnMapInit);
|
SubscribeLocalEvent<WiresComponent, MapInitEvent>(OnMapInit);
|
||||||
SubscribeLocalEvent<WiresComponent, TimedWireEvent>(OnTimedWire);
|
SubscribeLocalEvent<WiresComponent, TimedWireEvent>(OnTimedWire);
|
||||||
SubscribeLocalEvent<WiresComponent, PowerChangedEvent>(OnWiresPowered);
|
SubscribeLocalEvent<WiresComponent, PowerChangedEvent>(OnWiresPowered);
|
||||||
SubscribeLocalEvent<WiresComponent, DoAfterEvent<WireExtraData>>(OnDoAfter);
|
SubscribeLocalEvent<WiresComponent, WireDoAfterEvent>(OnDoAfter);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetOrCreateWireLayout(EntityUid uid, WiresComponent? wires = null)
|
private void SetOrCreateWireLayout(EntityUid uid, WiresComponent? wires = null)
|
||||||
@@ -437,86 +434,64 @@ public sealed class WiresSystem : SharedWiresSystem
|
|||||||
TryDoWireAction(uid, player, activeHandEntity, args.Id, args.Action, component, tool);
|
TryDoWireAction(uid, player, activeHandEntity, args.Id, args.Action, component, tool);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDoAfter(EntityUid uid, WiresComponent component, DoAfterEvent<WireExtraData> args)
|
private void OnDoAfter(EntityUid uid, WiresComponent component, WireDoAfterEvent args)
|
||||||
{
|
{
|
||||||
if (args.Cancelled)
|
if (args.Cancelled)
|
||||||
{
|
{
|
||||||
component.WiresQueue.Remove(args.AdditionalData.Id);
|
component.WiresQueue.Remove(args.Id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args.Handled || args.Args.Target == null || args.Args.Used == null)
|
if (args.Handled || args.Args.Target == null || args.Args.Used == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
UpdateWires(args.Args.Target.Value, args.Args.User, args.Args.Used.Value, args.AdditionalData.Id, args.AdditionalData.Action, component);
|
UpdateWires(args.Args.Target.Value, args.Args.User, args.Args.Used.Value, args.Id, args.Action, component);
|
||||||
|
|
||||||
args.Handled = true;
|
args.Handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnInteractUsing(EntityUid uid, WiresComponent component, InteractUsingEvent args)
|
private void OnInteractUsing(EntityUid uid, WiresComponent component, InteractUsingEvent args)
|
||||||
{
|
{
|
||||||
|
if (args.Handled)
|
||||||
|
return;
|
||||||
|
|
||||||
if (!TryComp<ToolComponent>(args.Used, out var tool) || !TryComp<WiresPanelComponent>(uid, out var panel))
|
if (!TryComp<ToolComponent>(args.Used, out var tool) || !TryComp<WiresPanelComponent>(uid, out var panel))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (panel.Open &&
|
if (panel.Open &&
|
||||||
(_toolSystem.HasQuality(args.Used, "Cutting", tool) ||
|
(_toolSystem.HasQuality(args.Used, "Cutting", tool) ||
|
||||||
_toolSystem.HasQuality(args.Used, "Pulsing", tool)))
|
_toolSystem.HasQuality(args.Used, "Pulsing", tool)))
|
||||||
{
|
{
|
||||||
if (EntityManager.TryGetComponent(args.User, out ActorComponent? actor))
|
if (TryComp(args.User, out ActorComponent? actor))
|
||||||
{
|
_uiSystem.TryOpen(uid, WiresUiKey.Key, actor.PlayerSession);
|
||||||
var ui = _uiSystem.GetUiOrNull(uid, WiresUiKey.Key);
|
|
||||||
if (ui != null)
|
|
||||||
_uiSystem.OpenUi(ui, actor.PlayerSession);
|
|
||||||
args.Handled = true;
|
|
||||||
}
|
}
|
||||||
}
|
else if (_toolSystem.UseTool(args.Used, args.User, uid, ScrewTime, "Screwing", new WirePanelDoAfterEvent(), toolComponent: tool))
|
||||||
else if (!panel.IsScrewing && _toolSystem.HasQuality(args.Used, "Screwing", tool))
|
|
||||||
{
|
{
|
||||||
var toolEvData = new ToolEventData(new WireToolFinishedEvent(uid, args.User), cancelledEv: new WireToolCanceledEvent(uid));
|
_adminLogger.Add(LogType.Action, LogImpact.Low,
|
||||||
|
$"{ToPrettyString(args.User):user} is screwing {ToPrettyString(uid):target}'s {(panel.Open ? "open" : "closed")} maintenance panel at {Transform(uid).Coordinates:targetlocation}");
|
||||||
panel.IsScrewing = _toolSystem.UseTool(args.Used, args.User, uid, ScrewTime, new[] { "Screwing" }, toolEvData, toolComponent: tool);
|
|
||||||
args.Handled = panel.IsScrewing;
|
|
||||||
|
|
||||||
// Log attempt
|
|
||||||
_adminLogger.Add(LogType.Action, LogImpact.Low, $"{ToPrettyString(args.User):user} is screwing {ToPrettyString(uid):target}'s {(panel.Open ? "open" : "closed")} maintenance panel at {Transform(uid).Coordinates:targetlocation}");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnToolFinished(WireToolFinishedEvent args)
|
private void OnPanelDoAfter(EntityUid uid, WiresPanelComponent panel, WirePanelDoAfterEvent args)
|
||||||
{
|
{
|
||||||
if (!TryComp<WiresPanelComponent>((args.Target), out var panel))
|
if (args.Cancelled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
panel.IsScrewing = false;
|
TogglePanel(uid, panel, !panel.Open);
|
||||||
TogglePanel(args.Target, panel, !panel.Open);
|
UpdateAppearance(uid, panel);
|
||||||
|
_adminLogger.Add(LogType.Action, LogImpact.Low, $"{ToPrettyString(args.User):user} screwed {ToPrettyString(uid):target}'s maintenance panel {(panel.Open ? "open" : "closed")}");
|
||||||
// Log success
|
|
||||||
_adminLogger.Add(LogType.Action, LogImpact.Low, $"{ToPrettyString(args.User):user} screwed {ToPrettyString(args.Target):target}'s maintenance panel {(panel.Open ? "open" : "closed")}");
|
|
||||||
|
|
||||||
if (panel.Open)
|
if (panel.Open)
|
||||||
{
|
{
|
||||||
_audio.PlayPvs(panel.ScrewdriverOpenSound, args.Target);
|
_audio.PlayPvs(panel.ScrewdriverOpenSound, uid);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_audio.PlayPvs(panel.ScrewdriverCloseSound, args.Target);
|
_audio.PlayPvs(panel.ScrewdriverCloseSound, uid);
|
||||||
var ui = _uiSystem.GetUiOrNull(args.Target, WiresUiKey.Key);
|
_uiSystem.TryCloseAll(uid, WiresUiKey.Key);
|
||||||
if (ui != null)
|
|
||||||
{
|
|
||||||
_uiSystem.CloseAll(ui);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Dirty(panel);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnToolCanceled(WireToolCanceledEvent ev)
|
|
||||||
{
|
|
||||||
if (!TryComp<WiresPanelComponent>(ev.Target, out var component))
|
|
||||||
return;
|
|
||||||
|
|
||||||
component.IsScrewing = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnMapInit(EntityUid uid, WiresComponent component, MapInitEvent args)
|
private void OnMapInit(EntityUid uid, WiresComponent component, MapInitEvent args)
|
||||||
{
|
{
|
||||||
EnsureComp<WiresPanelComponent>(uid);
|
EnsureComp<WiresPanelComponent>(uid);
|
||||||
@@ -662,16 +637,16 @@ public sealed class WiresSystem : SharedWiresSystem
|
|||||||
_appearance.SetData(uid, WiresVisuals.MaintenancePanelState, panel.Open && panel.Visible, appearance);
|
_appearance.SetData(uid, WiresVisuals.MaintenancePanelState, panel.Open && panel.Visible, appearance);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void TryDoWireAction(EntityUid used, EntityUid user, EntityUid toolEntity, int id, WiresAction action, WiresComponent? wires = null, ToolComponent? tool = null)
|
private void TryDoWireAction(EntityUid target, EntityUid user, EntityUid toolEntity, int id, WiresAction action, WiresComponent? wires = null, ToolComponent? tool = null)
|
||||||
{
|
{
|
||||||
if (!Resolve(used, ref wires)
|
if (!Resolve(target, ref wires)
|
||||||
|| !Resolve(toolEntity, ref tool))
|
|| !Resolve(toolEntity, ref tool))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (wires.WiresQueue.Contains(id))
|
if (wires.WiresQueue.Contains(id))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var wire = TryGetWire(used, id, wires);
|
var wire = TryGetWire(target, id, wires);
|
||||||
|
|
||||||
if (wire == null)
|
if (wire == null)
|
||||||
return;
|
return;
|
||||||
@@ -726,29 +701,21 @@ public sealed class WiresSystem : SharedWiresSystem
|
|||||||
|
|
||||||
if (_toolTime > 0f)
|
if (_toolTime > 0f)
|
||||||
{
|
{
|
||||||
var data = new WireExtraData(action, id);
|
var args = new DoAfterArgs(user, _toolTime, new WireDoAfterEvent(action, id), target, target: target, used: toolEntity)
|
||||||
var args = new DoAfterEventArgs(user, _toolTime, target: used, used: toolEntity)
|
|
||||||
{
|
{
|
||||||
NeedHand = true,
|
NeedHand = true,
|
||||||
BreakOnStun = true,
|
|
||||||
BreakOnDamage = true,
|
BreakOnDamage = true,
|
||||||
BreakOnUserMove = true
|
BreakOnUserMove = true
|
||||||
};
|
};
|
||||||
|
|
||||||
_doAfter.DoAfter(args, data);
|
_doAfter.TryStartDoAfter(args);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
UpdateWires(used, user, toolEntity, id, action, wires);
|
UpdateWires(target, user, toolEntity, id, action, wires);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private record struct WireExtraData(WiresAction Action, int Id)
|
|
||||||
{
|
|
||||||
public WiresAction Action = Action;
|
|
||||||
public int Id = Id;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdateWires(EntityUid used, EntityUid user, EntityUid toolEntity, int id, WiresAction action, WiresComponent? wires = null, ToolComponent? tool = null)
|
private void UpdateWires(EntityUid used, EntityUid user, EntityUid toolEntity, int id, WiresAction action, WiresComponent? wires = null, ToolComponent? tool = null)
|
||||||
{
|
{
|
||||||
if (!Resolve(used, ref wires))
|
if (!Resolve(used, ref wires))
|
||||||
@@ -786,7 +753,7 @@ public sealed class WiresSystem : SharedWiresSystem
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
_toolSystem.PlayToolSound(toolEntity, tool);
|
_toolSystem.PlayToolSound(toolEntity, tool, user);
|
||||||
if (wire.Action == null || wire.Action.Cut(user, wire))
|
if (wire.Action == null || wire.Action.Cut(user, wire))
|
||||||
{
|
{
|
||||||
wire.IsCut = true;
|
wire.IsCut = true;
|
||||||
@@ -807,7 +774,7 @@ public sealed class WiresSystem : SharedWiresSystem
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
_toolSystem.PlayToolSound(toolEntity, tool);
|
_toolSystem.PlayToolSound(toolEntity, tool, user);
|
||||||
if (wire.Action == null || wire.Action.Mend(user, wire))
|
if (wire.Action == null || wire.Action.Mend(user, wire))
|
||||||
{
|
{
|
||||||
wire.IsCut = false;
|
wire.IsCut = false;
|
||||||
@@ -921,25 +888,8 @@ public sealed class WiresSystem : SharedWiresSystem
|
|||||||
private void Reset(RoundRestartCleanupEvent args)
|
private void Reset(RoundRestartCleanupEvent args)
|
||||||
{
|
{
|
||||||
_layouts.Clear();
|
_layouts.Clear();
|
||||||
_random = new RobustRandom();
|
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Events
|
|
||||||
private sealed class WireToolFinishedEvent : EntityEventArgs
|
|
||||||
{
|
|
||||||
public EntityUid User { get; }
|
|
||||||
public EntityUid Target { get; }
|
|
||||||
|
|
||||||
public WireToolFinishedEvent(EntityUid target, EntityUid user)
|
|
||||||
{
|
|
||||||
Target = target;
|
|
||||||
User = user;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public record struct WireToolCanceledEvent(EntityUid Target);
|
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class Wire
|
public sealed class Wire
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ namespace Content.Shared.ActionBlocker
|
|||||||
if (ev.Cancelled)
|
if (ev.Cancelled)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (target == null)
|
if (target == null || target == user)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
var targetEv = new GettingInteractedWithAttemptEvent(user, target);
|
var targetEv = new GettingInteractedWithAttemptEvent(user, target);
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using Content.Shared.DoAfter;
|
||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
namespace Content.Shared.AirlockPainter
|
namespace Content.Shared.AirlockPainter
|
||||||
@@ -29,4 +30,22 @@ namespace Content.Shared.AirlockPainter
|
|||||||
SelectedStyle = selectedStyle;
|
SelectedStyle = selectedStyle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public sealed class AirlockPainterDoAfterEvent : DoAfterEvent
|
||||||
|
{
|
||||||
|
[DataField("sprite", required: true)]
|
||||||
|
public readonly string Sprite = default!;
|
||||||
|
|
||||||
|
private AirlockPainterDoAfterEvent()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public AirlockPainterDoAfterEvent(string sprite)
|
||||||
|
{
|
||||||
|
Sprite = sprite;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override DoAfterEvent Clone() => this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
9
Content.Shared/Anomaly/ScannerDoAfterEvent.cs
Normal file
9
Content.Shared/Anomaly/ScannerDoAfterEvent.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
using Content.Shared.DoAfter;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
|
namespace Content.Shared.Anomaly;
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public sealed class ScannerDoAfterEvent : SimpleDoAfterEvent
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -1,21 +1,21 @@
|
|||||||
|
using Content.Shared.DoAfter;
|
||||||
using Content.Shared.FixedPoint;
|
using Content.Shared.FixedPoint;
|
||||||
using Robust.Shared.GameStates;
|
using Robust.Shared.GameStates;
|
||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
namespace Content.Shared.Chemistry.Components
|
namespace Content.Shared.Chemistry.Components
|
||||||
{
|
{
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public sealed class InjectorDoAfterEvent : SimpleDoAfterEvent
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Shared class for injectors & syringes
|
/// Shared class for injectors & syringes
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[NetworkedComponent, ComponentProtoName("Injector")]
|
[NetworkedComponent, ComponentProtoName("Injector")]
|
||||||
public abstract class SharedInjectorComponent : Component
|
public abstract class SharedInjectorComponent : Component
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Checks to see if the entity being injected
|
|
||||||
/// </summary>
|
|
||||||
[DataField("isInjecting")]
|
|
||||||
public bool IsInjecting;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Component data used for net updates. Used by client for item status ui
|
/// Component data used for net updates. Used by client for item status ui
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -26,7 +26,8 @@ namespace Content.Shared.Chemistry.Components
|
|||||||
public FixedPoint2 TotalVolume { get; }
|
public FixedPoint2 TotalVolume { get; }
|
||||||
public InjectorToggleMode CurrentMode { get; }
|
public InjectorToggleMode CurrentMode { get; }
|
||||||
|
|
||||||
public InjectorComponentState(FixedPoint2 currentVolume, FixedPoint2 totalVolume, InjectorToggleMode currentMode)
|
public InjectorComponentState(FixedPoint2 currentVolume, FixedPoint2 totalVolume,
|
||||||
|
InjectorToggleMode currentMode)
|
||||||
{
|
{
|
||||||
CurrentVolume = currentVolume;
|
CurrentVolume = currentVolume;
|
||||||
TotalVolume = totalVolume;
|
TotalVolume = totalVolume;
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
|
using Content.Shared.DoAfter;
|
||||||
using Content.Shared.DragDrop;
|
using Content.Shared.DragDrop;
|
||||||
using Content.Shared.Movement.Events;
|
using Content.Shared.Movement.Events;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
namespace Content.Shared.Climbing;
|
namespace Content.Shared.Climbing;
|
||||||
|
|
||||||
@@ -24,4 +26,9 @@ public abstract class SharedClimbSystem : EntitySystem
|
|||||||
{
|
{
|
||||||
args.CanDrop = HasComp<ClimbingComponent>(args.Dragged);
|
args.CanDrop = HasComp<ClimbingComponent>(args.Dragged);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
protected sealed class ClimbDoAfterEvent : SimpleDoAfterEvent
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user