using Robust.Shared.Physics.Events;
using Robust.Shared.Physics.Systems;
using Robust.Shared.Serialization;
+using Robust.Shared.Utility;
namespace Content.Shared.Projectiles;
{
public const string ProjectileFixture = "projectile";
- [Dependency] private readonly INetManager _netManager = default!;
+ [Dependency] private readonly INetManager _net = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
[Dependency] private readonly SharedHandsSystem _hands = default!;
SubscribeLocalEvent<EmbeddableProjectileComponent, ThrowDoHitEvent>(OnEmbedThrowDoHit);
SubscribeLocalEvent<EmbeddableProjectileComponent, ActivateInWorldEvent>(OnEmbedActivate);
SubscribeLocalEvent<EmbeddableProjectileComponent, RemoveEmbeddedProjectileEvent>(OnEmbedRemove);
+
+ SubscribeLocalEvent<EmbeddedContainerComponent, EntityTerminatingEvent>(OnEmbeddableTermination);
}
- private void OnEmbedActivate(EntityUid uid, EmbeddableProjectileComponent component, ActivateInWorldEvent args)
+ private void OnEmbedActivate(Entity<EmbeddableProjectileComponent> embeddable, ref ActivateInWorldEvent args)
{
- // Nuh uh
- if (component.RemovalTime == null)
+ // Unremovable embeddables moment
+ if (embeddable.Comp.RemovalTime == null)
return;
- if (args.Handled || !args.Complex || !TryComp<PhysicsComponent>(uid, out var physics) || physics.BodyType != BodyType.Static)
+ if (args.Handled || !args.Complex || !TryComp<PhysicsComponent>(embeddable, out var physics) ||
+ physics.BodyType != BodyType.Static)
return;
args.Handled = true;
- _doAfter.TryStartDoAfter(new DoAfterArgs(EntityManager, args.User, component.RemovalTime.Value,
- new RemoveEmbeddedProjectileEvent(), eventTarget: uid, target: uid));
+ _doAfter.TryStartDoAfter(new DoAfterArgs(EntityManager,
+ args.User,
+ embeddable.Comp.RemovalTime.Value,
+ new RemoveEmbeddedProjectileEvent(),
+ eventTarget: embeddable,
+ target: embeddable));
}
- private void OnEmbedRemove(EntityUid uid, EmbeddableProjectileComponent component, RemoveEmbeddedProjectileEvent args)
+ private void OnEmbedRemove(Entity<EmbeddableProjectileComponent> embeddable, ref RemoveEmbeddedProjectileEvent args)
{
// Whacky prediction issues.
- if (args.Cancelled || _netManager.IsClient)
+ if (args.Cancelled || _net.IsClient)
return;
- if (component.DeleteOnRemove)
- {
- QueueDel(uid);
- return;
- }
-
- UnEmbed(uid, component, args.User);
+ EmbedDetach(embeddable, embeddable.Comp, args.User);
// try place it in the user's hand
- _hands.TryPickupAnyHand(args.User, uid);
+ _hands.TryPickupAnyHand(args.User, embeddable);
}
- private void OnEmbedThrowDoHit(EntityUid uid, EmbeddableProjectileComponent component, ThrowDoHitEvent args)
+ private void OnEmbedThrowDoHit(Entity<EmbeddableProjectileComponent> embeddable, ref ThrowDoHitEvent args)
{
- if (!component.EmbedOnThrow)
+ if (!embeddable.Comp.EmbedOnThrow)
return;
- Embed(uid, args.Target, null, component);
+ EmbedAttach(embeddable, args.Target, null, embeddable.Comp);
}
- private void OnEmbedProjectileHit(EntityUid uid, EmbeddableProjectileComponent component, ref ProjectileHitEvent args)
+ private void OnEmbedProjectileHit(Entity<EmbeddableProjectileComponent> embeddable, ref ProjectileHitEvent args)
{
- Embed(uid, args.Target, args.Shooter, component);
+ EmbedAttach(embeddable, args.Target, args.Shooter, embeddable.Comp);
// Raise a specific event for projectiles.
- if (TryComp(uid, out ProjectileComponent? projectile))
+ if (TryComp(embeddable, out ProjectileComponent? projectile))
{
var ev = new ProjectileEmbedEvent(projectile.Shooter!.Value, projectile.Weapon!.Value, args.Target);
- RaiseLocalEvent(uid, ref ev);
+ RaiseLocalEvent(embeddable, ref ev);
}
}
- private void Embed(EntityUid uid, EntityUid target, EntityUid? user, EmbeddableProjectileComponent component)
+ private void EmbedAttach(EntityUid uid, EntityUid target, EntityUid? user, EmbeddableProjectileComponent component)
{
TryComp<PhysicsComponent>(uid, out var physics);
_physics.SetLinearVelocity(uid, Vector2.Zero, body: physics);
var rotation = xform.LocalRotation;
if (TryComp<ThrowingAngleComponent>(uid, out var throwingAngleComp))
rotation += throwingAngleComp.Angle;
- _transform.SetLocalPosition(uid, xform.LocalPosition + rotation.RotateVec(component.Offset),
- xform);
+ _transform.SetLocalPosition(uid, xform.LocalPosition + rotation.RotateVec(component.Offset), xform);
}
_audio.PlayPredicted(component.Sound, uid, null);
var ev = new EmbedEvent(user, target);
RaiseLocalEvent(uid, ref ev);
Dirty(uid, component);
+
+ EnsureComp<EmbeddedContainerComponent>(target, out var embeddedContainer);
+
+ //Assert that this entity not embed
+ DebugTools.AssertEqual(embeddedContainer.EmbeddedObjects.Contains(uid), false);
+
+ embeddedContainer.EmbeddedObjects.Add(uid);
}
- public void UnEmbed(EntityUid uid, EmbeddableProjectileComponent? component, EntityUid? user = null)
+ public void EmbedDetach(EntityUid uid, EmbeddableProjectileComponent? component, EntityUid? user = null)
{
if (!Resolve(uid, ref component))
return;
+ if (component.DeleteOnRemove)
+ {
+ QueueDel(uid);
+ return;
+ }
+
+ if (component.EmbeddedIntoUid is not null)
+ {
+ if (TryComp<EmbeddedContainerComponent>(component.EmbeddedIntoUid.Value, out var embeddedContainer))
+ embeddedContainer.EmbeddedObjects.Remove(uid);
+ }
+
var xform = Transform(uid);
TryComp<PhysicsComponent>(uid, out var physics);
_physics.SetBodyType(uid, BodyType.Dynamic, body: physics, xform: xform);
_physics.WakeBody(uid, body: physics);
}
+ private void OnEmbeddableTermination(Entity<EmbeddedContainerComponent> container, ref EntityTerminatingEvent args)
+ {
+ DetachAllEmbedded(container);
+ }
+
+ public void DetachAllEmbedded(Entity<EmbeddedContainerComponent> container)
+ {
+ foreach (var embedded in container.Comp.EmbeddedObjects)
+ {
+ if (!TryComp<EmbeddableProjectileComponent>(embedded, out var embeddedComp))
+ continue;
+
+ EmbedDetach(embedded, embeddedComp);
+ }
+ }
+
private void PreventCollision(EntityUid uid, ProjectileComponent component, ref PreventCollideEvent args)
{
if (component.IgnoreShooter && (args.OtherEntity == component.Shooter || args.OtherEntity == component.Weapon))