Skip to content

Commit

Permalink
Merge pull request #170 from Evgencheg/master
Browse files Browse the repository at this point in the history
Revert "Physical Pulling (#883)"
  • Loading branch information
Evgencheg authored Sep 20, 2024
2 parents fe29a30 + 4094e9a commit 9901217
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 154 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,4 @@ public sealed partial class PullableComponent : Component
[Access(typeof(Systems.PullingSystem), Other = AccessPermissions.ReadExecute)]
[AutoNetworkedField, DataField]
public bool PrevFixedRotation;

/// <summary>
/// Whether the entity is currently being actively pushed by the puller.
/// If true, the entity will be able to enter disposals upon colliding with them, and the like.
/// </summary>
[DataField, AutoNetworkedField]
public bool BeingActivelyPushed = false;
}
38 changes: 6 additions & 32 deletions Content.Shared/Movement/Pulling/Components/PullerComponent.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using Content.Shared.Movement.Pulling.Systems;
using Robust.Shared.GameStates;
using Robust.Shared.Map;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;

namespace Content.Shared.Movement.Pulling.Components;
Expand All @@ -12,56 +11,31 @@ namespace Content.Shared.Movement.Pulling.Components;
[Access(typeof(PullingSystem))]
public sealed partial class PullerComponent : Component
{
// My raiding guild
/// <summary>
/// Next time the puller change where they are pulling the target towards.
/// Next time the puller can throw what is being pulled.
/// Used to avoid spamming it for infinite spin + velocity.
/// </summary>
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), AutoNetworkedField]
public TimeSpan NextPushTargetChange;

[DataField, AutoNetworkedField]
public TimeSpan NextPushStop;
public TimeSpan NextThrow;

[DataField]
public TimeSpan PushChangeCooldown = TimeSpan.FromSeconds(0.1f), PushDuration = TimeSpan.FromSeconds(2f);
public TimeSpan ThrowCooldown = TimeSpan.FromSeconds(1);

// Before changing how this is updated, please see SharedPullerSystem.RefreshMovementSpeed
public float WalkSpeedModifier => Pulling == default ? 1.0f : 0.95f;

public float SprintSpeedModifier => Pulling == default ? 1.0f : 0.95f;

/// <summary>
/// Entity currently being pulled/pushed if applicable.
/// Entity currently being pulled if applicable.
/// </summary>
[AutoNetworkedField, DataField]
public EntityUid? Pulling;

/// <summary>
/// The position the entity is currently being pulled towards.
/// </summary>
[AutoNetworkedField, DataField]
public EntityCoordinates? PushingTowards;

/// <summary>
/// Does this entity need hands to be able to pull something?
/// </summary>
[DataField]
public bool NeedsHands = true;

/// <summary>
/// The maximum acceleration of pushing, in meters per second squared.
/// </summary>
[DataField]
public float PushAcceleration = 0.3f;

/// <summary>
/// The maximum speed to which the pulled entity may be accelerated relative to the push direction, in meters per second.
/// </summary>
[DataField]
public float MaxPushSpeed = 1.2f;

/// <summary>
/// The maximum distance between the puller and the point towards which the puller may attempt to pull it, in meters.
/// </summary>
[DataField]
public float MaxPushRange = 2f;
}
137 changes: 24 additions & 113 deletions Content.Shared/Movement/Pulling/Systems/PullingSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,16 @@
using Content.Shared.Hands.EntitySystems;
using Content.Shared.Input;
using Content.Shared.Interaction;
using Content.Shared.Movement.Components;
using Content.Shared.Movement.Events;
using Content.Shared.Movement.Pulling.Components;
using Content.Shared.Movement.Pulling.Events;
using Content.Shared.Movement.Systems;
using Content.Shared.Projectiles;
using Content.Shared.Pulling.Events;
using Content.Shared.Throwing;
using Content.Shared.Verbs;
using Robust.Shared.Containers;
using Robust.Shared.Input.Binding;
using Robust.Shared.Map;
using Robust.Shared.Network;
using Robust.Shared.Physics;
using Robust.Shared.Physics.Components;
using Robust.Shared.Physics.Events;
Expand All @@ -37,7 +34,6 @@ public sealed class PullingSystem : EntitySystem
{
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
[Dependency] private readonly INetManager _net = default!;
[Dependency] private readonly ActionBlockerSystem _blocker = default!;
[Dependency] private readonly AlertsSystem _alertsSystem = default!;
[Dependency] private readonly MovementSpeedModifierSystem _modifierSystem = default!;
Expand All @@ -47,7 +43,7 @@ public sealed class PullingSystem : EntitySystem
[Dependency] private readonly SharedInteractionSystem _interaction = default!;
[Dependency] private readonly SharedPhysicsSystem _physics = default!;
[Dependency] private readonly SharedTransformSystem _xformSys = default!;
[Dependency] private readonly ThrownItemSystem _thrownItem = default!;
[Dependency] private readonly ThrowingSystem _throwing = default!;

public override void Initialize()
{
Expand All @@ -61,9 +57,7 @@ public override void Initialize()
SubscribeLocalEvent<PullableComponent, JointRemovedEvent>(OnJointRemoved);
SubscribeLocalEvent<PullableComponent, GetVerbsEvent<Verb>>(AddPullVerbs);
SubscribeLocalEvent<PullableComponent, EntGotInsertedIntoContainerMessage>(OnPullableContainerInsert);
SubscribeLocalEvent<PullableComponent, StartCollideEvent>(OnPullableCollide);

SubscribeLocalEvent<PullerComponent, MoveInputEvent>(OnPullerMoveInput);
SubscribeLocalEvent<PullerComponent, EntGotInsertedIntoContainerMessage>(OnPullerContainerInsert);
SubscribeLocalEvent<PullerComponent, EntityUnpausedEvent>(OnPullerUnpaused);
SubscribeLocalEvent<PullerComponent, VirtualItemDeletedEvent>(OnVirtualItemDeleted);
Expand All @@ -75,86 +69,6 @@ public override void Initialize()
.Register<PullingSystem>();
}

public override void Shutdown()
{
base.Shutdown();
CommandBinds.Unregister<PullingSystem>();
}

public override void Update(float frameTime)
{
if (_net.IsClient) // Client cannot predict this
return;

var query = EntityQueryEnumerator<PullerComponent, PhysicsComponent, TransformComponent>();
while (query.MoveNext(out var puller, out var pullerComp, out var pullerPhysics, out var pullerXForm))
{
// If not pulling, reset the pushing cooldowns and exit
if (pullerComp.Pulling is not { } pulled || !TryComp<PullableComponent>(pulled, out var pulledComp))
{
pullerComp.PushingTowards = null;
pullerComp.NextPushTargetChange = TimeSpan.Zero;
continue;
}

pulledComp.BeingActivelyPushed = false; // Temporarily set to false; if the checks below pass, it will be set to true again

// If pulling but the pullee is invalid or is on a different map, stop pulling
var pulledXForm = Transform(pulled);
if (!TryComp<PhysicsComponent>(pulled, out var pulledPhysics)
|| pulledPhysics.BodyType == BodyType.Static
|| pulledXForm.MapUid != pullerXForm.MapUid)
{
StopPulling(pulled, pulledComp);
continue;
}

if (pullerComp.PushingTowards is null)
continue;

// If pushing but the target position is invalid, or the push action has expired or finished, stop pushing
if (pullerComp.NextPushStop < _timing.CurTime
|| !(pullerComp.PushingTowards.Value.ToMap(EntityManager, _xformSys) is var pushCoordinates)
|| pushCoordinates.MapId != pulledXForm.MapID)
{
pullerComp.PushingTowards = null;
pullerComp.NextPushTargetChange = TimeSpan.Zero;
continue;
}

// Actual force calculation. All the Vector2's below are in map coordinates.
var desiredDeltaPos = pushCoordinates.Position - Transform(pulled).Coordinates.ToMapPos(EntityManager, _xformSys);
if (desiredDeltaPos.LengthSquared() < 0.1f)
{
pullerComp.PushingTowards = null;
continue;
}

var velocityAndDirectionAngle = new Angle(pulledPhysics.LinearVelocity) - new Angle(desiredDeltaPos);
var currentRelativeSpeed = pulledPhysics.LinearVelocity.Length() * (float) Math.Cos(velocityAndDirectionAngle.Theta);
var desiredAcceleration = MathF.Max(0f, pullerComp.MaxPushSpeed - currentRelativeSpeed);

var desiredImpulse = pulledPhysics.Mass * desiredDeltaPos;
var maxSourceImpulse = MathF.Min(pullerComp.PushAcceleration, desiredAcceleration) * pullerPhysics.Mass;
var actualImpulse = desiredImpulse.LengthSquared() > maxSourceImpulse * maxSourceImpulse ? desiredDeltaPos.Normalized() * maxSourceImpulse : desiredImpulse;

// Ideally we'd want to apply forces instead of impulses, however...
// We cannot use ApplyForce here because it will be cleared on the next physics substep which will render it ultimately useless
// The alternative is to run this function on every physics substep, but that is way too expensive for such a minor system
_physics.ApplyLinearImpulse(pulled, actualImpulse);
_physics.ApplyLinearImpulse(puller, -actualImpulse);
pulledComp.BeingActivelyPushed = true;
}
query.Dispose();
}

private void OnPullerMoveInput(EntityUid uid, PullerComponent component, ref MoveInputEvent args)
{
// Stop pushing
component.PushingTowards = null;
component.NextPushStop = TimeSpan.Zero;
}

private void OnPullerContainerInsert(Entity<PullerComponent> ent, ref EntGotInsertedIntoContainerMessage args)
{
if (ent.Comp.Pulling == null) return;
Expand All @@ -170,26 +84,15 @@ private void OnPullableContainerInsert(Entity<PullableComponent> ent, ref EntGot
TryStopPull(ent.Owner, ent.Comp);
}

private void OnPullableCollide(Entity<PullableComponent> ent, ref StartCollideEvent args)
public override void Shutdown()
{
if (!ent.Comp.BeingActivelyPushed || args.OtherEntity == ent.Comp.Puller)
return;

// This component isn't actually needed anywhere besides the thrownitemsyste`m itself, so we just fake it
var fakeThrown = new ThrownItemComponent()
{
Owner = ent.Owner,
Animate = false,
Landed = false,
PlayLandSound = false,
Thrower = ent.Comp.Puller
};
_thrownItem.ThrowCollideInteraction(fakeThrown, ent, args.OtherEntity);
base.Shutdown();
CommandBinds.Unregister<PullingSystem>();
}

private void OnPullerUnpaused(EntityUid uid, PullerComponent component, ref EntityUnpausedEvent args)
{
component.NextPushTargetChange += args.PausedTime;
component.NextThrow += args.PausedTime;
}

private void OnVirtualItemDeleted(EntityUid uid, PullerComponent component, VirtualItemDeletedEvent args)
Expand Down Expand Up @@ -331,22 +234,31 @@ public bool IsPulled(EntityUid uid, PullableComponent? component = null)

private bool OnRequestMovePulledObject(ICommonSession? session, EntityCoordinates coords, EntityUid uid)
{
if (session?.AttachedEntity is not { } player
|| !player.IsValid()
|| !TryComp<PullerComponent>(player, out var pullerComp))
if (session?.AttachedEntity is not { } player ||
!player.IsValid())
{
return false;
}

if (!TryComp<PullerComponent>(player, out var pullerComp))
return false;

var pulled = pullerComp.Pulling;
if (!HasComp<PullableComponent>(pulled)
|| _containerSystem.IsEntityInContainer(player)
|| _timing.CurTime < pullerComp.NextPushTargetChange)

if (!HasComp<PullableComponent>(pulled))
return false;

if (_containerSystem.IsEntityInContainer(player))
return false;

pullerComp.NextPushTargetChange = _timing.CurTime + pullerComp.PushChangeCooldown;
pullerComp.NextPushStop = _timing.CurTime + pullerComp.PushDuration;
// Cooldown buddy
if (_timing.CurTime < pullerComp.NextThrow)
return false;

pullerComp.NextThrow = _timing.CurTime + pullerComp.ThrowCooldown;

// Cap the distance
var range = pullerComp.MaxPushRange;
const float range = 2f;
var fromUserCoords = coords.WithEntityId(player, EntityManager);
var userCoords = new EntityCoordinates(player, Vector2.Zero);

Expand All @@ -356,9 +268,8 @@ private bool OnRequestMovePulledObject(ICommonSession? session, EntityCoordinate
fromUserCoords = userCoords.Offset(userDirection.Normalized() * range);
}

pullerComp.PushingTowards = fromUserCoords;
Dirty(player, pullerComp);

_throwing.TryThrow(pulled.Value, fromUserCoords, user: player, strength: 4f, animated: false, recoil: false, playSound: false, doSpin: false);
return false;
}

Expand Down
2 changes: 0 additions & 2 deletions Resources/Prototypes/Entities/Mobs/Player/admin_ghost.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@
- type: GhostHearing
- type: Hands
- type: Puller
pushAcceleration: 1000000 # Will still be capped in max speed
maxPushRange: 20
- type: CombatMode
- type: Physics
ignorePaused: true
Expand Down

0 comments on commit 9901217

Please sign in to comment.