using Content.Shared._ES.Physics.PreventCollide; using Content.Shared._ES.Sparks.Components; // using Content.Shared._ES.TileFires; // DeltaV - we don't have tilefires using Content.Shared.Power.Components; using Content.Shared.Power.EntitySystems; using Content.Shared.Throwing; using JetBrains.Annotations; using Robust.Shared.Map; using Robust.Shared.Network; using Robust.Shared.Prototypes; using Robust.Shared.Random; using Robust.Shared.Timing; namespace Content.Shared._ES.Sparks; public sealed partial class ESSparksSystem : EntitySystem { [Dependency] private readonly IGameTiming _timing = default!; [Dependency] private readonly INetManager _net = default!; [Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly SharedPowerReceiverSystem _powerReceiver = default!; [Dependency] private readonly ESPreventCollideSystem _preventCollide = default!; // [Dependency] private readonly ESSharedTileFireSystem _tileFire = default!; // DeltaV - we don't have tilefires [Dependency] private readonly ThrowingSystem _throwing = default!; [Dependency] private readonly SharedTransformSystem _transform = default!; public static readonly EntProtoId DefaultSparks = "ESEffectSparks"; /// /// Variant of that takes /// the configuration from a base component rather than being passed in as args /// /// Entity that the sparks are originating from. Additionally, holds YAML configuration for spark effect /// A "user" who triggered the sparks /// If true, will check the cooldown on before spawning sparks public void DoSparks( Entity ent, EntityUid? user = null, bool cooldown = true) where T : ESBaseSparkConfigurationComponent { if (!_random.Prob(ent.Comp.Prob)) return; SharedApcPowerReceiverComponent? powerReceiver = null; if (_powerReceiver.ResolveApc(ent, ref powerReceiver) && (!_powerReceiver.IsPowered((ent, powerReceiver)) || powerReceiver.Load <= 0)) return; DoSparks(ent, number: ent.Comp.Count, ent.Comp.SparkPrototype, user: user, tileFireChance: ent.Comp.TileFireChance, cooldown: cooldown); } /// /// Spawns sparks originating from a target entity /// /// Entity that the sparks are originating from /// Number of sparks to spawn /// Spark prototype to use. Defaults to /// A "user" who triggered the sparks /// Chance that sparks will cause a fire to start /// If true, will check the cooldown on before spawning sparks [PublicAPI] public void DoSparks( EntityUid source, int number = 4, EntProtoId? sparksPrototype = null, EntityUid? user = null, float tileFireChance = 0f, bool cooldown = true) { // track last spark time var comp = EnsureComp(source); if (cooldown && _timing.CurTime - comp.LastSparkTime < comp.SparkDelay) return; comp.LastSparkTime = _timing.CurTime; var coords = Transform(source).Coordinates; DoSparks(coords, number, sparksPrototype, user, source, tileFireChance); } /// /// Spawns sparks at a given set of coordinates /// /// Where the sparks should spawn /// Number of sparks to spawn /// Spark prototype to use. Defaults to /// A "user" who triggered the sparks /// An entity whose collision will be ignored by the sparks /// Chance that sparks will cause a fire to start [PublicAPI] public void DoSparks( EntityCoordinates coordinates, int number = 4, EntProtoId? sparksPrototype = null, EntityUid? user = null, EntityUid? ignored = null, float tileFireChance = 0f) { if (_net.IsClient) return; sparksPrototype ??= DefaultSparks; var angleDelta = (Angle) (MathF.Tau / number); var angle = _random.NextAngle(); for (var i = 0; i < number; i++) { var sparks = Spawn(sparksPrototype, _transform.ToMapCoordinates(coordinates), rotation: angle); angle += angleDelta; _throwing.TryThrow(sparks, angle.ToVec(), 2f, animated: false); _preventCollide.PreventCollide(sparks, ignored); } // Begin DeltaV Removals - we don't have tilefires // if (_random.Prob(tileFireChance)) // _tileFire.TryDoTileFire(coordinates, user, _random.Next(1, 4)); // End DeltaV Removals - we don't have tilefires } }