Slipping, now with 20% more ecs (#4310)

* Slipping, now with 20% more ecs

* vereview
This commit is contained in:
metalgearsloth
2021-07-21 22:13:58 +10:00
committed by GitHub
parent 321f65c1b3
commit 590a6ce969
5 changed files with 146 additions and 118 deletions

View File

@@ -0,0 +1,9 @@
using Content.Shared.Slippery;
namespace Content.Client.Slippery
{
internal sealed class SlipperySystem : SharedSlipperySystem
{
protected override void PlaySound(SlipperyComponent component) {}
}
}

View File

@@ -0,0 +1,18 @@
using Content.Shared.Audio;
using Content.Shared.Slippery;
using Robust.Shared.Audio;
using Robust.Shared.Player;
namespace Content.Server.Slippery
{
internal sealed class SlipperySystem : SharedSlipperySystem
{
protected override void PlaySound(SlipperyComponent component)
{
if (!string.IsNullOrEmpty(component.SlipSound))
{
SoundSystem.Play(Filter.Pvs(component.Owner), component.SlipSound, component.Owner, AudioHelpers.WithVariation(0.2f));
}
}
}
}

View File

@@ -0,0 +1,112 @@
using System.Linq;
using Content.Shared.EffectBlocker;
using Content.Shared.Stunnable;
using JetBrains.Annotations;
using Robust.Shared.Containers;
using Robust.Shared.GameObjects;
using Robust.Shared.Physics;
using Robust.Shared.Physics.Dynamics;
namespace Content.Shared.Slippery
{
[UsedImplicitly]
public abstract class SharedSlipperySystem : EntitySystem
{
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<SlipperyComponent, StartCollideEvent>(HandleCollide);
}
private void HandleCollide(EntityUid uid, SlipperyComponent component, StartCollideEvent args)
{
component.Colliding.Add(args.OtherFixture.Body.Owner.Uid);
}
/// <inheritdoc />
public override void Update(float frameTime)
{
foreach (var slipperyComp in ComponentManager.EntityQuery<SlipperyComponent>().ToArray())
{
Update(slipperyComp);
}
}
private bool TrySlip(SlipperyComponent component, IPhysBody ourBody, IPhysBody otherBody)
{
if (!component.Slippery
|| component.Owner.IsInContainer()
|| component.Slipped.Contains(otherBody.Owner.Uid)
|| !otherBody.Owner.TryGetComponent(out SharedStunnableComponent? stun))
{
return false;
}
if (otherBody.LinearVelocity.Length < component.RequiredSlipSpeed || stun.KnockedDown)
{
return false;
}
var percentage = otherBody.GetWorldAABB().IntersectPercentage(ourBody.GetWorldAABB());
if (percentage < component.IntersectPercentage)
{
return false;
}
if (!EffectBlockerSystem.CanSlip(otherBody.Owner))
{
return false;
}
otherBody.LinearVelocity *= component.LaunchForwardsMultiplier;
stun.Paralyze(5);
component.Slipped.Add(otherBody.Owner.Uid);
component.Dirty();
PlaySound(component);
return true;
}
// Until we get predicted slip sounds TM?
protected abstract void PlaySound(SlipperyComponent component);
// TODO: Now that we have StartCollide and EndCollide this should just use that to track bodies intersecting.
private void Update(SlipperyComponent component)
{
if (!component.Slippery)
return;
if (!ComponentManager.TryGetComponent(component.Owner.Uid, out PhysicsComponent? body))
{
component.Colliding.Clear();
return;
}
foreach (var uid in component.Colliding.ToArray())
{
if (!uid.IsValid() || !EntityManager.TryGetEntity(uid, out var entity))
{
component.Colliding.Remove(uid);
component.Slipped.Remove(uid);
component.Dirty();
continue;
}
if (!entity.TryGetComponent(out PhysicsComponent? otherPhysics) ||
!body.GetWorldAABB().Intersects(otherPhysics.GetWorldAABB()))
{
component.Colliding.Remove(uid);
component.Slipped.Remove(uid);
component.Dirty();
continue;
}
if (!component.Slipped.Contains(uid))
TrySlip(component, body, otherPhysics);
}
}
}
}

View File

@@ -1,20 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Content.Shared.Audio;
using Content.Shared.EffectBlocker;
using Content.Shared.Module;
using Content.Shared.Stunnable;
using Robust.Shared.Audio;
using Robust.Shared.Containers;
using Robust.Shared.GameObjects;
using Robust.Shared.GameStates;
using Robust.Shared.IoC;
using Robust.Shared.Maths;
using Robust.Shared.Physics;
using Robust.Shared.Physics.Collision;
using Robust.Shared.Physics.Dynamics;
using Robust.Shared.Player;
using Robust.Shared.Players;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
@@ -24,11 +13,9 @@ namespace Content.Shared.Slippery
{
[RegisterComponent]
[NetworkedComponent()]
public class SlipperyComponent : Component, IStartCollide
public sealed class SlipperyComponent : Component
{
[Dependency] private IModuleManager _moduleManager = default!;
public sealed override string Name => "Slippery";
public override string Name => "Slippery";
private float _paralyzeTime = 3f;
private float _intersectPercentage = 0.3f;
@@ -40,12 +27,12 @@ namespace Content.Shared.Slippery
/// <summary>
/// List of entities that are currently colliding with the entity.
/// </summary>
private readonly HashSet<EntityUid> _colliding = new();
public readonly HashSet<EntityUid> Colliding = new();
/// <summary>
/// The list of entities that have been slipped by this component, which shouldn't be slipped again.
/// </summary>
private readonly HashSet<EntityUid> _slipped = new();
public readonly HashSet<EntityUid> Slipped = new();
/// <summary>
/// Path to the sound to be played when a mob slips.
@@ -150,88 +137,9 @@ namespace Content.Shared.Slippery
}
}
private bool TrySlip(IPhysBody ourBody, IPhysBody otherBody)
{
if (!Slippery
|| Owner.IsInContainer()
|| _slipped.Contains(otherBody.Owner.Uid)
|| !otherBody.Owner.TryGetComponent(out SharedStunnableComponent? stun))
{
return false;
}
if (otherBody.LinearVelocity.Length < RequiredSlipSpeed || stun.KnockedDown)
{
return false;
}
var percentage = otherBody.GetWorldAABB().IntersectPercentage(ourBody.GetWorldAABB());
if (percentage < IntersectPercentage)
{
return false;
}
if (!EffectBlockerSystem.CanSlip(otherBody.Owner))
{
return false;
}
otherBody.LinearVelocity *= LaunchForwardsMultiplier;
stun.Paralyze(5);
_slipped.Add(otherBody.Owner.Uid);
Dirty();
if (!string.IsNullOrEmpty(SlipSound) && _moduleManager.IsServerModule)
{
SoundSystem.Play(Filter.Broadcast(), SlipSound, Owner, AudioHelpers.WithVariation(0.2f));
}
return true;
}
void IStartCollide.CollideWith(Fixture _, Fixture otherFixture, in Manifold manifold)
{
_colliding.Add(otherFixture.Body.Owner.Uid);
}
public void Update()
{
if (!Slippery)
return;
var physics = Owner.GetComponent<IPhysBody>();
foreach (var uid in _colliding.ToArray())
{
if (!uid.IsValid() || !Owner.EntityManager.EntityExists(uid))
{
_colliding.Remove(uid);
_slipped.Remove(uid);
Dirty();
continue;
}
var entity = Owner.EntityManager.GetEntity(uid);
var otherPhysics = entity.GetComponent<IPhysBody>();
if (!physics.GetWorldAABB().Intersects(otherPhysics.GetWorldAABB()))
{
_colliding.Remove(uid);
_slipped.Remove(uid);
Dirty();
continue;
}
if (!_slipped.Contains(uid))
TrySlip(physics, otherPhysics);
}
}
public override ComponentState GetComponentState(ICommonSession player)
{
return new SlipperyComponentState(ParalyzeTime, IntersectPercentage, RequiredSlipSpeed, LaunchForwardsMultiplier, Slippery, SlipSound, _slipped.ToArray());
return new SlipperyComponentState(ParalyzeTime, IntersectPercentage, RequiredSlipSpeed, LaunchForwardsMultiplier, Slippery, SlipSound, Slipped.ToArray());
}
public override void HandleComponentState(ComponentState? curState, ComponentState? nextState)
@@ -244,11 +152,11 @@ namespace Content.Shared.Slippery
_requiredSlipSpeed = state.RequiredSlipSpeed;
_launchForwardsMultiplier = state.LaunchForwardsMultiplier;
_slipSound = state.SlipSound;
_slipped.Clear();
Slipped.Clear();
foreach (var slipped in state.Slipped)
{
_slipped.Add(slipped);
Slipped.Add(slipped);
}
}
}

View File

@@ -1,19 +0,0 @@
using System.Linq;
using JetBrains.Annotations;
using Robust.Shared.GameObjects;
namespace Content.Shared.Slippery
{
[UsedImplicitly]
public class SlipperySystem : EntitySystem
{
/// <inheritdoc />
public override void Update(float frameTime)
{
foreach (var slipperyComp in ComponentManager.EntityQuery<SlipperyComponent>().ToArray())
{
slipperyComp.Update();
}
}
}
}