Crawling Part 1: The Knockdownening (#36881)
Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com> Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Co-authored-by: Princess Cheeseballs <66055347+Pronana@users.noreply.github.com> Co-authored-by: ScarKy0 <scarky0@onet.eu>
This commit is contained in:
committed by
GitHub
parent
cfb0a95035
commit
dec2d42a1d
@@ -1,19 +1,53 @@
|
||||
using Content.Shared.Movement.Events;
|
||||
using Content.Shared.Movement.Systems;
|
||||
using Content.Shared.Standing;
|
||||
using Content.Shared.Stunnable;
|
||||
using Content.Shared.Throwing;
|
||||
using Content.Shared.Weapons.Ranged.Systems;
|
||||
using Robust.Shared.Physics.Components;
|
||||
using Robust.Shared.Physics.Events;
|
||||
using Robust.Shared.Physics.Systems;
|
||||
|
||||
namespace Content.Shared.Slippery;
|
||||
|
||||
public sealed class SlidingSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly SharedPhysicsSystem _physics = default!;
|
||||
[Dependency] private readonly MovementSpeedModifierSystem _speedModifierSystem = default!;
|
||||
|
||||
private EntityQuery<SlipperyComponent> _slipperyQuery;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
_slipperyQuery = GetEntityQuery<SlipperyComponent>();
|
||||
|
||||
SubscribeLocalEvent<SlidingComponent, ComponentInit>(OnComponentInit);
|
||||
SubscribeLocalEvent<SlidingComponent, ComponentShutdown>(OnComponentShutdown);
|
||||
SubscribeLocalEvent<SlidingComponent, StoodEvent>(OnStand);
|
||||
SubscribeLocalEvent<SlidingComponent, StartCollideEvent>(OnStartCollide);
|
||||
SubscribeLocalEvent<SlidingComponent, EndCollideEvent>(OnEndCollide);
|
||||
SubscribeLocalEvent<SlidingComponent, RefreshFrictionModifiersEvent>(OnRefreshFrictionModifiers);
|
||||
SubscribeLocalEvent<SlidingComponent, ThrowerImpulseEvent>(OnThrowerImpulse);
|
||||
SubscribeLocalEvent<SlidingComponent, ShooterImpulseEvent>(ShooterImpulseEvent);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When the component is first added, calculate the friction modifier we need.
|
||||
/// Don't do this more than once to avoid mispredicts.
|
||||
/// </summary>
|
||||
private void OnComponentInit(Entity<SlidingComponent> entity, ref ComponentInit args)
|
||||
{
|
||||
if (CalculateSlidingModifier(entity))
|
||||
_speedModifierSystem.RefreshFrictionModifiers(entity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When the component is removed, refresh friction modifiers and set ours to 1 to avoid causing issues.
|
||||
/// </summary>
|
||||
private void OnComponentShutdown(Entity<SlidingComponent> entity, ref ComponentShutdown args)
|
||||
{
|
||||
entity.Comp.FrictionModifier = 1;
|
||||
_speedModifierSystem.RefreshFrictionModifiers(entity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -25,28 +59,81 @@ public sealed class SlidingSystem : EntitySystem
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets friction to 0 if colliding with a SuperSlippery Entity.
|
||||
/// Updates friction when we collide with a slippery entity
|
||||
/// </summary>
|
||||
private void OnStartCollide(EntityUid uid, SlidingComponent component, ref StartCollideEvent args)
|
||||
private void OnStartCollide(Entity<SlidingComponent> entity, ref StartCollideEvent args)
|
||||
{
|
||||
if (!TryComp<SlipperyComponent>(args.OtherEntity, out var slippery) || !slippery.SlipData.SuperSlippery)
|
||||
if (!_slipperyQuery.TryComp(args.OtherEntity, out var slippery) || !slippery.AffectsSliding)
|
||||
return;
|
||||
|
||||
component.CollidingEntities.Add(args.OtherEntity);
|
||||
Dirty(uid, component);
|
||||
CalculateSlidingModifier(entity);
|
||||
_speedModifierSystem.RefreshFrictionModifiers(entity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set friction to normal when ending collision with a SuperSlippery entity.
|
||||
/// Update friction when we stop colliding with a slippery entity
|
||||
/// </summary>
|
||||
private void OnEndCollide(EntityUid uid, SlidingComponent component, ref EndCollideEvent args)
|
||||
private void OnEndCollide(Entity<SlidingComponent> entity, ref EndCollideEvent args)
|
||||
{
|
||||
if (!component.CollidingEntities.Remove(args.OtherEntity))
|
||||
if (!_slipperyQuery.TryComp(args.OtherEntity, out var slippery) || !slippery.AffectsSliding)
|
||||
return;
|
||||
|
||||
if (component.CollidingEntities.Count == 0)
|
||||
RemComp<SlidingComponent>(uid);
|
||||
if (!CalculateSlidingModifier(entity, args.OtherEntity))
|
||||
{
|
||||
RemComp<SlidingComponent>(entity);
|
||||
return;
|
||||
}
|
||||
|
||||
Dirty(uid, component);
|
||||
_speedModifierSystem.RefreshFrictionModifiers(entity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets contacting slippery entities and averages their friction modifiers.
|
||||
/// </summary>
|
||||
private bool CalculateSlidingModifier(Entity<SlidingComponent, PhysicsComponent?> entity, EntityUid? ignore = null)
|
||||
{
|
||||
if (!Resolve(entity, ref entity.Comp2, false))
|
||||
return false;
|
||||
|
||||
var friction = 0.0f;
|
||||
var count = 0;
|
||||
entity.Comp1.Contacting.Clear();
|
||||
|
||||
_physics.GetContactingEntities((entity, entity.Comp2), entity.Comp1.Contacting);
|
||||
|
||||
foreach (var ent in entity.Comp1.Contacting)
|
||||
{
|
||||
if (ent == ignore || !_slipperyQuery.TryComp(ent, out var slippery) || !slippery.AffectsSliding)
|
||||
continue;
|
||||
|
||||
friction += slippery.SlipData.SlipFriction;
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
if (count > 0)
|
||||
{
|
||||
entity.Comp1.FrictionModifier = friction / count;
|
||||
Dirty(entity.Owner, entity.Comp1);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void OnRefreshFrictionModifiers(Entity<SlidingComponent> entity, ref RefreshFrictionModifiersEvent args)
|
||||
{
|
||||
args.ModifyFriction(entity.Comp.FrictionModifier);
|
||||
args.ModifyAcceleration(entity.Comp.FrictionModifier);
|
||||
}
|
||||
|
||||
private void OnThrowerImpulse(Entity<SlidingComponent> entity, ref ThrowerImpulseEvent args)
|
||||
{
|
||||
args.Push = true;
|
||||
}
|
||||
|
||||
private void ShooterImpulseEvent(Entity<SlidingComponent> entity, ref ShooterImpulseEvent args)
|
||||
{
|
||||
args.Push = true;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user