17
Content.Shared/Physics/BulletController.cs
Normal file
17
Content.Shared/Physics/BulletController.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
89
Content.Shared/Physics/ClimbController.cs
Normal file
89
Content.Shared/Physics/ClimbController.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
#nullable enable
|
||||
using Robust.Shared.Physics;
|
||||
|
||||
namespace Content.Shared.Physics
|
||||
{
|
||||
public class ContainmentFieldCollisionController : VirtualController
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
13
Content.Shared/Physics/ContainmentFieldRepellController.cs
Normal file
13
Content.Shared/Physics/ContainmentFieldRepellController.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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) {}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
62
Content.Shared/Physics/ConveyedController.cs
Normal file
62
Content.Shared/Physics/ConveyedController.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
24
Content.Shared/Physics/FrictionController.cs
Normal file
24
Content.Shared/Physics/FrictionController.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
33
Content.Shared/Physics/MoverController.cs
Normal file
33
Content.Shared/Physics/MoverController.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
|
||||
190
Content.Shared/Physics/Pull/PullController.cs
Normal file
190
Content.Shared/Physics/Pull/PullController.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
17
Content.Shared/Physics/ShuttleController.cs
Normal file
17
Content.Shared/Physics/ShuttleController.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
18
Content.Shared/Physics/SingularityController.cs
Normal file
18
Content.Shared/Physics/SingularityController.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
22
Content.Shared/Physics/SingularityPullController.cs
Normal file
22
Content.Shared/Physics/SingularityPullController.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
44
Content.Shared/Physics/SlipController.cs
Normal file
44
Content.Shared/Physics/SlipController.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
50
Content.Shared/Physics/ThrowKnockbackController.cs
Normal file
50
Content.Shared/Physics/ThrowKnockbackController.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
17
Content.Shared/Physics/ThrownController.cs
Normal file
17
Content.Shared/Physics/ThrownController.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
14
Content.Shared/Physics/VaporController.cs
Normal file
14
Content.Shared/Physics/VaporController.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user