Revert "Physics (#3452)"

This reverts commit 3e64fd56a1.
This commit is contained in:
Pieter-Jan Briers
2021-02-28 18:49:48 +01:00
parent eddec5fcce
commit 1eb0fbd8d0
211 changed files with 2560 additions and 2600 deletions

View File

@@ -0,0 +1,17 @@
#nullable enable
using Robust.Shared.GameObjects;
using Robust.Shared.Maths;
using Robust.Shared.Physics;
namespace Content.Shared.Physics
{
public class BulletController : VirtualController
{
public override IPhysicsComponent? ControlledComponent { protected get; set; }
public void Push(Vector2 velocityDirection, float speed)
{
LinearVelocity = velocityDirection * speed;
}
}
}

View File

@@ -0,0 +1,89 @@
#nullable enable
using Robust.Shared.Maths;
using Robust.Shared.Physics;
namespace Content.Shared.Physics
{
/// <summary>
/// Movement controller used by the climb system. Lerps the player from A to B.
/// Also does checks to make sure the player isn't blocked.
/// </summary>
public class ClimbController : VirtualController
{
private Vector2? _movingTo = null;
private Vector2 _lastKnownPosition = default;
private int _numTicksBlocked = 0;
/// <summary>
/// If 5 ticks have passed and our position has not changed then something is blocking us.
/// </summary>
public bool IsBlocked => _numTicksBlocked > 5 || _isMovingWrongDirection;
/// <summary>
/// If the controller is currently moving the player somewhere, it is considered active.
/// </summary>
public bool IsActive => _movingTo.HasValue;
private float _initialDist = default;
private bool _isMovingWrongDirection = false;
public void TryMoveTo(Vector2 from, Vector2 to)
{
if (ControlledComponent == null)
{
return;
}
_initialDist = (from - to).Length;
_numTicksBlocked = 0;
_lastKnownPosition = from;
_movingTo = to;
_isMovingWrongDirection = false;
}
public override void UpdateAfterProcessing()
{
base.UpdateAfterProcessing();
if (ControlledComponent == null || _movingTo == null)
{
return;
}
ControlledComponent.WakeBody();
if ((ControlledComponent.Owner.Transform.WorldPosition - _lastKnownPosition).Length <= 0.05f)
{
_numTicksBlocked++;
}
else
{
_numTicksBlocked = 0;
}
_lastKnownPosition = ControlledComponent.Owner.Transform.WorldPosition;
if ((ControlledComponent.Owner.Transform.WorldPosition - _movingTo.Value).Length <= 0.1f)
{
_movingTo = null;
}
if (_movingTo.HasValue)
{
var dist = (_lastKnownPosition - _movingTo.Value).Length;
if (dist > _initialDist)
{
_isMovingWrongDirection = true;
}
var diff = _movingTo.Value - ControlledComponent.Owner.Transform.WorldPosition;
LinearVelocity = diff.Normalized * 5;
}
else
{
LinearVelocity = Vector2.Zero;
}
}
}
}

View File

@@ -2,7 +2,6 @@
using System;
using JetBrains.Annotations;
using Robust.Shared.Map;
using Robust.Shared.Physics.Dynamics;
using Robust.Shared.Serialization;
using RobustPhysics = Robust.Shared.Physics;
@@ -12,7 +11,7 @@ namespace Content.Shared.Physics
/// Defined collision groups for the physics system.
/// </summary>
[Flags, PublicAPI]
[FlagsFor(typeof(CollisionLayer)), FlagsFor(typeof(CollisionMask))]
[FlagsFor(typeof(RobustPhysics.CollisionLayer)), FlagsFor(typeof(RobustPhysics.CollisionMask))]
public enum CollisionGroup
{
None = 0,

View File

@@ -0,0 +1,10 @@
#nullable enable
using Robust.Shared.Physics;
namespace Content.Shared.Physics
{
public class ContainmentFieldCollisionController : VirtualController
{
}
}

View File

@@ -0,0 +1,13 @@
#nullable enable
using Robust.Shared.Maths;
namespace Content.Shared.Physics
{
public class ContainmentFieldRepellController : FrictionController
{
public void Repell(Direction dir, float speed)
{
LinearVelocity = dir.ToVec() * speed;
}
}
}

View File

@@ -1,142 +0,0 @@
#nullable enable
using Content.Shared.GameObjects.Components.Mobs.State;
using Content.Shared.GameObjects.Components.Movement;
using Content.Shared.GameObjects.Components.Pulling;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Maths;
using Robust.Shared.Physics;
using Robust.Shared.Physics.Broadphase;
using Robust.Shared.Physics.Controllers;
namespace Content.Shared.Physics.Controllers
{
/// <summary>
/// Handles player and NPC mob movement.
/// NPCs are handled server-side only.
/// </summary>
public abstract class SharedMoverController : VirtualController
{
[Dependency] private readonly IPhysicsManager _physicsManager = default!;
private SharedBroadPhaseSystem _broadPhaseSystem = default!;
public override void Initialize()
{
base.Initialize();
_broadPhaseSystem = EntitySystem.Get<SharedBroadPhaseSystem>();
}
/// <summary>
/// A generic kinematic mover for entities.
/// </summary>
protected void HandleKinematicMovement(IMoverComponent mover, PhysicsComponent physicsComponent)
{
var (walkDir, sprintDir) = mover.VelocityDir;
// Regular movement.
// Target velocity.
var total = (walkDir * mover.CurrentWalkSpeed + sprintDir * mover.CurrentSprintSpeed);
if (total != Vector2.Zero)
{
mover.Owner.Transform.LocalRotation = total.GetDir().ToAngle();
}
physicsComponent.LinearVelocity = total;
}
/// <summary>
/// Movement while considering actionblockers, weightlessness, etc.
/// </summary>
/// <param name="mover"></param>
/// <param name="physicsComponent"></param>
/// <param name="mobMover"></param>
protected void HandleMobMovement(IMoverComponent mover, PhysicsComponent physicsComponent, IMobMoverComponent mobMover)
{
// TODO: Look at https://gameworksdocs.nvidia.com/PhysX/4.1/documentation/physxguide/Manual/CharacterControllers.html?highlight=controller as it has some adviceo n kinematic controllersx
if (!UseMobMovement(_broadPhaseSystem, physicsComponent, _physicsManager))
{
return;
}
var transform = mover.Owner.Transform;
var (walkDir, sprintDir) = mover.VelocityDir;
var weightless = transform.Owner.IsWeightless(_physicsManager);
// Handle wall-pushes.
if (weightless)
{
// No gravity: is our entity touching anything?
var touching = IsAroundCollider(_broadPhaseSystem, transform, mobMover, physicsComponent);
if (!touching)
{
transform.LocalRotation = physicsComponent.LinearVelocity.GetDir().ToAngle();
return;
}
}
// Regular movement.
// Target velocity.
var total = (walkDir * mover.CurrentWalkSpeed + sprintDir * mover.CurrentSprintSpeed);
if (total != Vector2.Zero)
{
// This should have its event run during island solver soooo
transform.DeferUpdates = true;
transform.LocalRotation = total.GetDir().ToAngle();
HandleFootsteps(mover, mobMover);
}
physicsComponent.LinearVelocity = total;
}
public static bool UseMobMovement(SharedBroadPhaseSystem broadPhaseSystem, PhysicsComponent body, IPhysicsManager? physicsManager = null)
{
return (body.BodyStatus == BodyStatus.OnGround) &
body.Owner.HasComponent<IMobStateComponent>() &&
ActionBlockerSystem.CanMove(body.Owner) &&
(!body.Owner.IsWeightless(physicsManager) ||
body.Owner.TryGetComponent(out SharedPlayerMobMoverComponent? mover) &&
IsAroundCollider(broadPhaseSystem, body.Owner.Transform, mover, body));
}
/// <summary>
/// Used for weightlessness to determine if we are near a wall.
/// </summary>
/// <param name="broadPhaseSystem"></param>
/// <param name="transform"></param>
/// <param name="mover"></param>
/// <param name="collider"></param>
/// <returns></returns>
public static bool IsAroundCollider(SharedBroadPhaseSystem broadPhaseSystem, ITransformComponent transform, IMobMoverComponent mover, IPhysBody collider)
{
var enlargedAABB = collider.GetWorldAABB().Enlarged(mover.GrabRange);
foreach (var otherCollider in broadPhaseSystem.GetCollidingEntities(transform.MapID, enlargedAABB))
{
if (otherCollider == collider) continue; // Don't try to push off of yourself!
// Only allow pushing off of anchored things that have collision.
if (otherCollider.BodyType != BodyType.Static ||
!otherCollider.CanCollide ||
((collider.CollisionMask & otherCollider.CollisionLayer) == 0 &&
(otherCollider.CollisionMask & collider.CollisionLayer) == 0) ||
(otherCollider.Entity.TryGetComponent(out SharedPullableComponent? pullable) && pullable.BeingPulled))
{
continue;
}
return true;
}
return false;
}
// TODO: Need a predicted client version that only plays for our own entity and then have server-side ignore our session (for that entity only)
protected virtual void HandleFootsteps(IMoverComponent mover, IMobMoverComponent mobMover) {}
}
}

View File

@@ -1,103 +0,0 @@
using System;
using Content.Shared.GameObjects.Components.Mobs.State;
using Content.Shared.GameObjects.Components.Movement;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using JetBrains.Annotations;
using Robust.Shared;
using Robust.Shared.Configuration;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Map;
using Robust.Shared.Physics;
using Robust.Shared.Physics.Broadphase;
using Robust.Shared.Physics.Controllers;
using Robust.Shared.Physics.Dynamics;
#nullable enable
namespace Content.Shared.Physics.Controllers
{
public sealed class SharedTileFrictionController : VirtualController
{
[Dependency] private readonly IConfigurationManager _configManager = default!;
[Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly IPhysicsManager _physicsManager = default!;
[Dependency] private readonly ITileDefinitionManager _tileDefinitionManager = default!;
private SharedBroadPhaseSystem _broadPhaseSystem = default!;
private float _stopSpeed;
private float _frictionModifier;
public override void Initialize()
{
base.Initialize();
_broadPhaseSystem = EntitySystem.Get<SharedBroadPhaseSystem>();
_frictionModifier = _configManager.GetCVar(CCVars.TileFrictionModifier);
_configManager.OnValueChanged(CCVars.TileFrictionModifier, value => _frictionModifier = value);
_stopSpeed = _configManager.GetCVar(CCVars.StopSpeed);
_configManager.OnValueChanged(CCVars.StopSpeed, value => _stopSpeed = value);
}
public override void UpdateBeforeMapSolve(bool prediction, PhysicsMap map, float frameTime)
{
base.UpdateBeforeMapSolve(prediction, map, frameTime);
foreach (var body in map.AwakeBodies)
{
var speed = body.LinearVelocity.Length;
if (speed <= 0.0f || body.BodyStatus == BodyStatus.InAir) continue;
// This is the *actual* amount that speed will drop by, we just do some multiplication around it to be easier.
var drop = 0.0f;
float control;
// Only apply friction when it's not a mob (or the mob doesn't have control).
if (SharedMoverController.UseMobMovement(_broadPhaseSystem, body, _physicsManager)) continue;
var surfaceFriction = GetTileFriction(body);
var bodyModifier = body.Owner.GetComponentOrNull<SharedTileFrictionModifier>()?.Modifier ?? 1.0f;
var friction = _frictionModifier * surfaceFriction * bodyModifier;
if (friction > 0.0f)
{
// TBH I can't really tell if this makes a difference, player movement is fucking hard.
if (!prediction)
{
control = speed < _stopSpeed ? _stopSpeed : speed;
}
else
{
control = speed;
}
drop += control * friction * frameTime;
}
var newSpeed = MathF.Max(0.0f, speed - drop);
newSpeed /= speed;
body.LinearVelocity *= newSpeed;
}
}
[Pure]
private float GetTileFriction(IPhysBody body)
{
if (body.BodyStatus == BodyStatus.InAir || body.Entity.Transform.GridID == GridId.Invalid)
return 0.0f;
var transform = body.Owner.Transform;
var coords = transform.Coordinates;
var grid = _mapManager.GetGrid(coords.GetGridId(body.Owner.EntityManager));
var tile = grid.GetTileRef(coords);
var tileDef = _tileDefinitionManager[tile.Tile.TypeId];
return tileDef.Friction;
}
}
}

View File

@@ -0,0 +1,62 @@
#nullable enable
using Content.Shared.GameObjects.Components.Movement;
using Robust.Shared.GameObjects;
using Robust.Shared.Maths;
using Robust.Shared.Physics;
namespace Content.Shared.Physics
{
public class ConveyedController : VirtualController
{
public override IPhysicsComponent? ControlledComponent { protected get; set; }
public void Move(Vector2 velocityDirection, float speed, Vector2 itemRelativeToConveyor)
{
if (ControlledComponent?.Owner.IsWeightless() ?? false)
{
return;
}
if (ControlledComponent?.Status == BodyStatus.InAir)
{
return;
}
LinearVelocity = velocityDirection * speed;
//gravitating item towards center
//http://csharphelper.com/blog/2016/09/find-the-shortest-distance-between-a-point-and-a-line-segment-in-c/
Vector2 centerPoint;
var t = 0f;
if (velocityDirection.Length > 0) //if velocitydirection is 0, this calculation will divide by 0
{
t = Vector2.Dot(itemRelativeToConveyor, velocityDirection) /
Vector2.Dot(velocityDirection, velocityDirection);
}
if (t < 0)
{
centerPoint = new Vector2();
}
else if(t > 1)
{
centerPoint = velocityDirection;
}
else
{
centerPoint = velocityDirection * t;
}
var delta = centerPoint - itemRelativeToConveyor;
LinearVelocity += delta * (4 * delta.Length);
}
public override void UpdateAfterProcessing()
{
base.UpdateAfterProcessing();
LinearVelocity = Vector2.Zero;
}
}
}

View File

@@ -0,0 +1,24 @@
#nullable enable
using System;
using Robust.Shared.IoC;
using Robust.Shared.Physics;
namespace Content.Shared.Physics
{
public abstract class FrictionController : VirtualController
{
[Dependency] private readonly IPhysicsManager _physicsManager = default!;
public override void UpdateAfterProcessing()
{
base.UpdateAfterProcessing();
if (ControlledComponent != null && !_physicsManager.IsWeightless(ControlledComponent.Owner.Transform.Coordinates))
{
LinearVelocity *= 0.85f;
if (MathF.Abs(LinearVelocity.Length) < 1f)
Stop();
}
}
}
}

View File

@@ -0,0 +1,33 @@
#nullable enable
using Content.Shared.GameObjects.Components.Movement;
using Robust.Shared.GameObjects;
using Robust.Shared.Maths;
using Robust.Shared.Physics;
namespace Content.Shared.Physics
{
public class MoverController : VirtualController
{
public override IPhysicsComponent? ControlledComponent { protected get; set; }
public void Move(Vector2 velocityDirection, float speed)
{
if (ControlledComponent?.Owner.IsWeightless() ?? false)
{
return;
}
Push(velocityDirection, speed);
}
public void Push(Vector2 velocityDirection, float speed)
{
LinearVelocity = velocityDirection * speed;
}
public void StopMoving()
{
LinearVelocity = Vector2.Zero;
}
}
}

View File

@@ -1,11 +1,11 @@
#nullable enable
using Robust.Shared.Physics;
using Robust.Shared.GameObjects;
namespace Content.Shared.Physics.Pull
{
public class PullAttemptMessage : PullMessage
{
public PullAttemptMessage(IPhysBody puller, IPhysBody pulled) : base(puller, pulled) { }
public PullAttemptMessage(IPhysicsComponent puller, IPhysicsComponent pulled) : base(puller, pulled) { }
public bool Cancelled { get; set; }
}

View File

@@ -0,0 +1,190 @@
#nullable enable
using System;
using System.Linq;
using Robust.Shared.Containers;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.Physics;
using Content.Shared.GameObjects.Components.Pulling;
using static Content.Shared.GameObjects.EntitySystems.SharedInteractionSystem;
namespace Content.Shared.Physics.Pull
{
/// <summary>
/// This is applied upon a Pullable object when that object is being pulled.
/// It lives only to serve that Pullable object.
/// </summary>
public class PullController : VirtualController
{
[Dependency] private readonly IEntityManager _entityManager = default!;
[Dependency] private readonly IPhysicsManager _physicsManager = default!;
private const float DistBeforeStopPull = InteractionRange;
private const float StopMoveThreshold = 0.25f;
/// <summary>
/// The managing SharedPullableComponent of this PullController.
/// MUST BE SET! If you go attaching PullControllers yourself, YOU ARE DOING IT WRONG.
/// If you get a crash based on such, then, well, see previous note.
/// This is set by the SharedPullableComponent attaching the PullController.
/// </summary>
public SharedPullableComponent Manager = default!;
private EntityCoordinates? _movingTo;
public EntityCoordinates? MovingTo
{
get => _movingTo;
set
{
if (_movingTo == value || ControlledComponent == null)
{
return;
}
_movingTo = value;
ControlledComponent.WakeBody();
}
}
private bool PullerMovingTowardsPulled()
{
var _puller = Manager.PullerPhysics;
if (_puller == null)
{
return false;
}
if (ControlledComponent == null)
{
return false;
}
if (_puller.LinearVelocity.EqualsApprox(Vector2.Zero))
{
return false;
}
var pullerTransform = _puller.Owner.Transform;
var origin = pullerTransform.Coordinates.Position;
var velocity = _puller.LinearVelocity.Normalized;
var mapId = pullerTransform.MapPosition.MapId;
var ray = new CollisionRay(origin, velocity, (int) CollisionGroup.AllMask);
bool Predicate(IEntity e) => e != ControlledComponent.Owner;
var rayResults =
_physicsManager.IntersectRayWithPredicate(mapId, ray, DistBeforeStopPull, Predicate);
return rayResults.Any();
}
public bool TryMoveTo(EntityCoordinates from, EntityCoordinates to)
{
var _puller = Manager.PullerPhysics;
if (_puller == null || ControlledComponent == null)
{
return false;
}
if (!_puller.Owner.Transform.Coordinates.InRange(_entityManager, from, InteractionRange))
{
return false;
}
if (!_puller.Owner.Transform.Coordinates.InRange(_entityManager, to, InteractionRange))
{
return false;
}
if (!from.InRange(_entityManager, to, InteractionRange))
{
return false;
}
if (from.Position.EqualsApprox(to.Position))
{
return false;
}
if (!_puller.Owner.Transform.Coordinates.TryDistance(_entityManager, to, out var distance) ||
Math.Sqrt(distance) > DistBeforeStopPull ||
Math.Sqrt(distance) < StopMoveThreshold)
{
return false;
}
MovingTo = to;
return true;
}
public override void UpdateBeforeProcessing()
{
var _puller = Manager.PullerPhysics;
if (_puller == null || ControlledComponent == null)
{
return;
}
if (!_puller.Owner.IsInSameOrNoContainer(ControlledComponent.Owner))
{
Manager.Puller = null;
return;
}
var distance = _puller.Owner.Transform.WorldPosition - ControlledComponent.Owner.Transform.WorldPosition;
if (distance.Length > DistBeforeStopPull)
{
Manager.Puller = null;
}
else if (MovingTo.HasValue)
{
var diff = MovingTo.Value.Position - ControlledComponent.Owner.Transform.Coordinates.Position;
LinearVelocity = diff.Normalized * 5;
}
else
{
if (PullerMovingTowardsPulled())
{
LinearVelocity = Vector2.Zero;
return;
}
var distanceAbs = Vector2.Abs(distance);
var totalAabb = _puller.AABB.Size + ControlledComponent.AABB.Size / 2;
if (distanceAbs.X < totalAabb.X && distanceAbs.Y < totalAabb.Y)
{
LinearVelocity = Vector2.Zero;
return;
}
LinearVelocity = distance.Normalized * _puller.LinearVelocity.Length * 1.5f;
}
}
public override void UpdateAfterProcessing()
{
base.UpdateAfterProcessing();
if (ControlledComponent == null)
{
MovingTo = null;
return;
}
if (MovingTo != null &&
ControlledComponent.Owner.Transform.Coordinates.Position.EqualsApprox(MovingTo.Value.Position, 0.01))
{
MovingTo = null;
}
if (LinearVelocity != Vector2.Zero)
{
var angle = LinearVelocity.ToAngle();
ControlledComponent.Owner.Transform.LocalRotation = angle;
}
}
}
}

View File

@@ -1,15 +1,14 @@
#nullable enable
using Robust.Shared.GameObjects;
using Robust.Shared.Physics;
namespace Content.Shared.Physics.Pull
{
public class PullMessage : ComponentMessage
{
public readonly IPhysBody Puller;
public readonly IPhysBody Pulled;
public readonly IPhysicsComponent Puller;
public readonly IPhysicsComponent Pulled;
protected PullMessage(IPhysBody puller, IPhysBody pulled)
protected PullMessage(IPhysicsComponent puller, IPhysicsComponent pulled)
{
Puller = puller;
Pulled = pulled;

View File

@@ -1,11 +1,11 @@
#nullable enable
using Robust.Shared.Physics;
using Robust.Shared.GameObjects;
namespace Content.Shared.Physics.Pull
{
public class PullStartedMessage : PullMessage
{
public PullStartedMessage(IPhysBody puller, IPhysBody pulled) :
public PullStartedMessage(IPhysicsComponent puller, IPhysicsComponent pulled) :
base(puller, pulled)
{
}

View File

@@ -1,11 +1,11 @@
#nullable enable
using Robust.Shared.Physics;
using Robust.Shared.GameObjects;
namespace Content.Shared.Physics.Pull
{
public class PullStoppedMessage : PullMessage
{
public PullStoppedMessage(IPhysBody puller, IPhysBody pulled) : base(puller, pulled)
public PullStoppedMessage(IPhysicsComponent puller, IPhysicsComponent pulled) : base(puller, pulled)
{
}
}

View File

@@ -0,0 +1,17 @@
#nullable enable
using Robust.Shared.GameObjects;
using Robust.Shared.Maths;
using Robust.Shared.Physics;
namespace Content.Shared.Physics
{
public class ShuttleController : VirtualController
{
public override IPhysicsComponent? ControlledComponent { protected get; set; }
public void Push(Vector2 velocityDirection, float speed)
{
LinearVelocity = velocityDirection * speed;
}
}
}

View File

@@ -0,0 +1,18 @@
#nullable enable
using Robust.Shared.GameObjects;
using Robust.Shared.Maths;
using Robust.Shared.Physics;
namespace Content.Shared.Physics
{
public class SingularityController : VirtualController
{
public override IPhysicsComponent? ControlledComponent { protected get; set; }
public void Push(Vector2 velocityDirection, float speed)
{
LinearVelocity = velocityDirection * speed;
}
}
}

View File

@@ -0,0 +1,22 @@
#nullable enable
using Robust.Shared.GameObjects;
using Robust.Shared.Maths;
using Robust.Shared.Physics;
namespace Content.Server.GameObjects.Components.Singularity
{
public class SingularityPullController : VirtualController
{
public override IPhysicsComponent? ControlledComponent { protected get; set; }
public void StopPull()
{
LinearVelocity = Vector2.Zero;
}
public void Pull(Vector2 velocityDirection, float speed)
{
LinearVelocity = velocityDirection * speed;
}
}
}

View File

@@ -0,0 +1,44 @@
#nullable enable
using Robust.Shared.IoC;
using Robust.Shared.Maths;
using Robust.Shared.Physics;
namespace Content.Shared.Physics
{
public class SlipController : VirtualController
{
[Dependency] private readonly IPhysicsManager _physicsManager = default!;
public SlipController()
{
IoCManager.InjectDependencies(this);
}
private float Decay { get; set; } = 0.95f;
public override void UpdateAfterProcessing()
{
if (ControlledComponent == null)
{
return;
}
if (_physicsManager.IsWeightless(ControlledComponent.Owner.Transform.Coordinates))
{
if (ControlledComponent.IsColliding(Vector2.Zero, false))
{
Stop();
}
return;
}
LinearVelocity *= Decay;
if (LinearVelocity.Length < 0.001)
{
Stop();
}
}
}
}

View File

@@ -0,0 +1,50 @@
#nullable enable
using Content.Shared.GameObjects.Components.Movement;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Robust.Shared.IoC;
using Robust.Shared.Maths;
using Robust.Shared.Physics;
namespace Content.Shared.Physics
{
public class ThrowKnockbackController : VirtualController
{
public ThrowKnockbackController()
{
IoCManager.InjectDependencies(this);
}
public void Push(Vector2 velocityDirection, float speed)
{
LinearVelocity = velocityDirection * speed;
}
private float Decay { get; set; } = 0.95f;
public override void UpdateAfterProcessing()
{
if (ControlledComponent == null)
{
return;
}
if (ControlledComponent.Owner.IsWeightless())
{
if (ActionBlockerSystem.CanMove(ControlledComponent.Owner)
&& ControlledComponent.IsColliding(Vector2.Zero, false))
{
Stop();
}
return;
}
LinearVelocity *= Decay;
if (LinearVelocity.Length < 0.001)
{
Stop();
}
}
}
}

View File

@@ -0,0 +1,17 @@
#nullable enable
using Robust.Shared.GameObjects;
using Robust.Shared.Maths;
using Robust.Shared.Physics;
namespace Content.Shared.Physics
{
public class ThrownController : VirtualController
{
public override IPhysicsComponent? ControlledComponent { protected get; set; }
public void Push(Vector2 velocityDirection, float speed)
{
LinearVelocity = velocityDirection * speed;
}
}
}

View File

@@ -0,0 +1,14 @@
#nullable enable
using Robust.Shared.Maths;
using Robust.Shared.Physics;
namespace Content.Shared.Physics
{
public class VaporController : VirtualController
{
public void Move(Vector2 velocityDirection, float speed)
{
LinearVelocity = velocityDirection * speed;
}
}
}