157 lines
4.2 KiB
C#
157 lines
4.2 KiB
C#
#nullable enable
|
|
using System;
|
|
using Content.Shared.GameObjects.EntitySystems;
|
|
using Robust.Shared.Containers;
|
|
using Robust.Shared.GameObjects.Components;
|
|
using Robust.Shared.Interfaces.Map;
|
|
using Robust.Shared.IoC;
|
|
using Robust.Shared.Map;
|
|
using Robust.Shared.Maths;
|
|
using Robust.Shared.Physics;
|
|
using Robust.Shared.Utility;
|
|
|
|
namespace Content.Shared.Physics.Pull
|
|
{
|
|
public class PullController : VirtualController
|
|
{
|
|
private const float DistBeforePull = 1.0f;
|
|
|
|
private const float DistBeforeStopPull = SharedInteractionSystem.InteractionRange;
|
|
|
|
private ICollidableComponent? _puller;
|
|
|
|
public bool GettingPulled => _puller != null;
|
|
|
|
private GridCoordinates? _movingTo;
|
|
|
|
public ICollidableComponent? Puller => _puller;
|
|
|
|
public void StartPull(ICollidableComponent puller)
|
|
{
|
|
DebugTools.AssertNotNull(puller);
|
|
|
|
if (_puller == puller)
|
|
{
|
|
return;
|
|
}
|
|
|
|
_puller = puller;
|
|
|
|
if (ControlledComponent == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var message = new PullStartedMessage(this, _puller, ControlledComponent);
|
|
|
|
_puller.Owner.SendMessage(null, message);
|
|
ControlledComponent.Owner.SendMessage(null, message);
|
|
}
|
|
|
|
public void StopPull()
|
|
{
|
|
var oldPuller = _puller;
|
|
|
|
if (oldPuller == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
_puller = null;
|
|
|
|
if (ControlledComponent == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var message = new PullStoppedMessage(this, oldPuller, ControlledComponent);
|
|
|
|
oldPuller.Owner.SendMessage(null, message);
|
|
ControlledComponent.Owner.SendMessage(null, message);
|
|
|
|
ControlledComponent.TryRemoveController<PullController>();
|
|
}
|
|
|
|
public void TryMoveTo(GridCoordinates from, GridCoordinates to)
|
|
{
|
|
if (_puller == null || ControlledComponent == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var mapManager = IoCManager.Resolve<IMapManager>();
|
|
|
|
if (!from.InRange(mapManager, to, SharedInteractionSystem.InteractionRange))
|
|
{
|
|
return;
|
|
}
|
|
|
|
var dist = _puller.Owner.Transform.GridPosition.Position - to.Position;
|
|
|
|
if (Math.Sqrt(dist.LengthSquared) > DistBeforeStopPull ||
|
|
Math.Sqrt(dist.LengthSquared) < 0.25f)
|
|
{
|
|
return;
|
|
}
|
|
|
|
_movingTo = to;
|
|
}
|
|
|
|
public override void UpdateBeforeProcessing()
|
|
{
|
|
if (_puller == null || ControlledComponent == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (!_puller.Owner.IsInSameOrNoContainer(ControlledComponent.Owner))
|
|
{
|
|
StopPull();
|
|
return;
|
|
}
|
|
|
|
// Are we outside of pulling range?
|
|
var dist = _puller.Owner.Transform.WorldPosition - ControlledComponent.Owner.Transform.WorldPosition;
|
|
|
|
if (dist.Length > DistBeforeStopPull)
|
|
{
|
|
StopPull();
|
|
}
|
|
else if (_movingTo.HasValue)
|
|
{
|
|
var diff = _movingTo.Value.Position - ControlledComponent.Owner.Transform.GridPosition.Position;
|
|
LinearVelocity = diff.Normalized * 5;
|
|
}
|
|
else if (dist.Length > DistBeforePull)
|
|
{
|
|
LinearVelocity = dist.Normalized * _puller.LinearVelocity.Length * 1.1f;
|
|
}
|
|
else
|
|
{
|
|
LinearVelocity = Vector2.Zero;
|
|
}
|
|
}
|
|
|
|
public override void UpdateAfterProcessing()
|
|
{
|
|
base.UpdateAfterProcessing();
|
|
|
|
if (ControlledComponent == null)
|
|
{
|
|
_movingTo = null;
|
|
return;
|
|
}
|
|
|
|
if (_movingTo == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (ControlledComponent.Owner.Transform.GridPosition.Position.EqualsApprox(_movingTo.Value.Position, 0.01))
|
|
{
|
|
_movingTo = null;
|
|
}
|
|
}
|
|
}
|
|
}
|