diff --git a/Content.Server/Gatherable/Components/GatheringProjectileComponent.cs b/Content.Server/Gatherable/Components/GatheringProjectileComponent.cs new file mode 100644 index 0000000000..88388c7d06 --- /dev/null +++ b/Content.Server/Gatherable/Components/GatheringProjectileComponent.cs @@ -0,0 +1,10 @@ +namespace Content.Server.Gatherable.Components; + +/// +/// Destroys a gatherable entity when colliding with it. +/// +[RegisterComponent] +public sealed class GatheringProjectileComponent : Component +{ + +} diff --git a/Content.Server/Gatherable/GatherableSystem.Projectile.cs b/Content.Server/Gatherable/GatherableSystem.Projectile.cs new file mode 100644 index 0000000000..62417bc7b8 --- /dev/null +++ b/Content.Server/Gatherable/GatherableSystem.Projectile.cs @@ -0,0 +1,28 @@ +using Content.Server.Gatherable.Components; +using Content.Server.Projectiles; +using Content.Shared.Projectiles; +using Content.Shared.Weapons.Ranged.Systems; +using Robust.Shared.Physics.Events; + +namespace Content.Server.Gatherable; + +public sealed partial class GatherableSystem +{ + private void InitializeProjectile() + { + SubscribeLocalEvent(OnProjectileCollide); + } + + private void OnProjectileCollide(EntityUid uid, GatheringProjectileComponent component, ref StartCollideEvent args) + { + if (!args.OtherFixture.Hard || + args.OurFixture.ID != SharedProjectileSystem.ProjectileFixture || + !TryComp(args.OtherEntity, out var gatherable)) + { + return; + } + + Gather(args.OtherEntity, uid, gatherable); + QueueDel(uid); + } +} diff --git a/Content.Server/Gatherable/GatherableSystem.cs b/Content.Server/Gatherable/GatherableSystem.cs index 0aa8c256f8..b9a375d284 100644 --- a/Content.Server/Gatherable/GatherableSystem.cs +++ b/Content.Server/Gatherable/GatherableSystem.cs @@ -5,18 +5,20 @@ using Content.Shared.EntityList; using Content.Shared.Gatherable; using Content.Shared.Interaction; using Content.Shared.Tag; +using Robust.Shared.Audio; using Robust.Shared.Prototypes; using Robust.Shared.Random; namespace Content.Server.Gatherable; -public sealed class GatherableSystem : EntitySystem +public sealed partial class GatherableSystem : EntitySystem { [Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly DestructibleSystem _destructible = default!; [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!; [Dependency] private readonly SharedAudioSystem _audio = default!; + [Dependency] private readonly SharedTransformSystem _transform = default!; [Dependency] private readonly TagSystem _tagSystem = default!; public override void Initialize() @@ -25,6 +27,7 @@ public sealed class GatherableSystem : EntitySystem SubscribeLocalEvent(OnInteractUsing); SubscribeLocalEvent(OnDoAfter); + InitializeProjectile(); } private void OnInteractUsing(EntityUid uid, GatherableComponent component, InteractUsingEvent args) @@ -53,36 +56,44 @@ public sealed class GatherableSystem : EntitySystem private void OnDoAfter(EntityUid uid, GatherableComponent component, GatherableDoAfterEvent args) { - if(!TryComp(args.Args.Used, out var tool) || args.Args.Target == null) + if(!TryComp(args.Args.Used, out var tool)) return; - tool.GatheringEntities.Remove(args.Args.Target.Value); + tool.GatheringEntities.Remove(uid); if (args.Handled || args.Cancelled) return; + Gather(uid, args.Args.Used, component, tool.GatheringSound); + args.Handled = true; + } + + public void Gather(EntityUid gatheredUid, EntityUid? gatherer = null, GatherableComponent? component = null, SoundSpecifier? sound = null) + { + if (!Resolve(gatheredUid, ref component)) + return; + // Complete the gathering process - _destructible.DestroyEntity(args.Args.Target.Value); - _audio.PlayPvs(tool.GatheringSound, args.Args.Target.Value); + _destructible.DestroyEntity(gatheredUid); + _audio.PlayPvs(sound, gatheredUid); // Spawn the loot! if (component.MappedLoot == null) return; - var playerPos = Transform(args.Args.User).MapPosition; + var pos = Transform(gatheredUid).MapPosition; foreach (var (tag, table) in component.MappedLoot) { if (tag != "All") { - if (!_tagSystem.HasTag(tool.Owner, tag)) + if (gatherer != null && !_tagSystem.HasTag(gatherer.Value, tag)) continue; } var getLoot = _prototypeManager.Index(table); var spawnLoot = getLoot.GetSpawns(); - var spawnPos = playerPos.Offset(_random.NextVector2(0.3f)); + var spawnPos = pos.Offset(_random.NextVector2(0.3f)); Spawn(spawnLoot[0], spawnPos); } - args.Handled = true; } } diff --git a/Content.Shared/Destructible/SharedDestructibleSystem.cs b/Content.Shared/Destructible/SharedDestructibleSystem.cs index b16ededbe7..b16009e198 100644 --- a/Content.Shared/Destructible/SharedDestructibleSystem.cs +++ b/Content.Shared/Destructible/SharedDestructibleSystem.cs @@ -9,7 +9,7 @@ public abstract class SharedDestructibleSystem : EntitySystem { var eventArgs = new DestructionEventArgs(); - RaiseLocalEvent(owner, eventArgs, false); + RaiseLocalEvent(owner, eventArgs); QueueDel(owner); } @@ -19,7 +19,7 @@ public abstract class SharedDestructibleSystem : EntitySystem public void BreakEntity(EntityUid owner) { var eventArgs = new BreakageEventArgs(); - RaiseLocalEvent(owner, eventArgs, false); + RaiseLocalEvent(owner, eventArgs); } } diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/projectiles.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/projectiles.yml index 642b4f8d0b..796383f0fc 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/projectiles.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/projectiles.yml @@ -294,12 +294,12 @@ description: Not too bad, but you still don't want to get hit by it. components: - type: Sprite - netsync: false noRot: false sprite: Objects/Weapons/Guns/Projectiles/magic.rsi layers: - state: chronobolt shader: unshaded + - type: GatheringProjectile - type: Projectile impactEffect: BulletImpactEffectKinetic damage: