using Content.Shared.Interaction.Components; using Content.Shared.Movement.Components; using Content.Shared.Random.Helpers; using Robust.Shared.Physics; using Robust.Shared.Physics.Components; using Robust.Shared.Physics.Systems; using Robust.Shared.Timing; namespace Content.Shared.EntityEffects.Effects.Smite; /// /// Launches this entity as a spinning dynamic physics body. /// /// public sealed partial class FlingEntityEffectSystem : EntityEffectSystem { [Dependency] private FixtureSystem _fixtures = default!; [Dependency] private SharedPhysicsSystem _physics = default!; [Dependency] private IGameTiming _timing = default!; [Dependency] private SharedTransformSystem _transform = default!; protected override void Effect(Entity entity, ref EntityEffectEvent args) { if (!TryComp(entity, out var fixtures)) return; // Input movers must stop using mob movement, otherwise the mover controller asserts on dynamic bodies. if (HasComp(entity)) EnsureComp(entity); var fling = args.Effect; _transform.Unanchor(entity); _physics.SetBodyType(entity, BodyType.Dynamic, fixtures, entity.Comp); _physics.SetBodyStatus(entity, entity.Comp, BodyStatus.InAir); _physics.WakeBody(entity, manager: fixtures, body: entity.Comp); foreach (var fixture in fixtures.Fixtures.Values) { if (fling.NonSolid) _physics.SetHard(entity, fixture, false, fixtures); if (fling.Restitution.HasValue && fixture.Hard) _physics.SetRestitution(entity, fixture, fling.Restitution.Value, false, fixtures); } if (fling.Restitution.HasValue) _fixtures.FixtureUpdate(entity, manager: fixtures, body: entity.Comp); var random = SharedRandomExtensions.PredictedRandom(_timing, GetNetEntity(entity)); _physics.SetLinearVelocity(entity, random.NextVector2(fling.Speed, fling.Speed), manager: fixtures, body: entity.Comp); _physics.SetAngularVelocity(entity, fling.AngularVelocity, manager: fixtures, body: entity.Comp); _physics.SetLinearDamping(entity, entity.Comp, 0f); _physics.SetAngularDamping(entity, entity.Comp, 0f); } } /// public sealed partial class Fling : EntityEffectBase { /// /// Maximum magnitude of the random linear velocity applied on launch. /// [DataField] public float Speed = 1.5f; /// /// Angular velocity applied on launch in radians per second. /// [DataField] public float AngularVelocity = MathF.PI * 12f; /// /// Restitution applied to hard fixtures, making the entity bounce. /// [DataField] public float? Restitution = 1.1f; /// /// Make all fixtures non-solid so the entity passes through obstacles. /// [DataField] public bool NonSolid; }