Fix embeddable projectiles dissapearing (reopening) (#35153)
This commit is contained in:
@@ -81,7 +81,7 @@ public abstract partial class SharedItemRecallSystem : EntitySystem
|
||||
return;
|
||||
|
||||
if (TryComp<EmbeddableProjectileComponent>(ent, out var projectile))
|
||||
_proj.UnEmbed(ent, projectile, actionOwner.Value);
|
||||
_proj.EmbedDetach(ent, projectile, actionOwner.Value);
|
||||
|
||||
_popups.PopupPredicted(Loc.GetString("item-recall-item-summon", ("item", ent)), actionOwner.Value, actionOwner.Value);
|
||||
|
||||
|
||||
13
Content.Shared/Projectiles/EmbeddedContainerComponent.cs
Normal file
13
Content.Shared/Projectiles/EmbeddedContainerComponent.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using Robust.Shared.GameStates;
|
||||
|
||||
namespace Content.Shared.Projectiles;
|
||||
|
||||
/// <summary>
|
||||
/// Stores a list of all stuck entities to release when this entity is deleted.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
|
||||
public sealed partial class EmbeddedContainerComponent : Component
|
||||
{
|
||||
[DataField, AutoNetworkedField]
|
||||
public HashSet<EntityUid> EmbeddedObjects = new();
|
||||
}
|
||||
@@ -15,6 +15,7 @@ using Robust.Shared.Physics.Dynamics;
|
||||
using Robust.Shared.Physics.Events;
|
||||
using Robust.Shared.Physics.Systems;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Shared.Projectiles;
|
||||
|
||||
@@ -22,7 +23,7 @@ public abstract partial class SharedProjectileSystem : EntitySystem
|
||||
{
|
||||
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!;
|
||||
@@ -38,62 +39,63 @@ public abstract partial class SharedProjectileSystem : EntitySystem
|
||||
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);
|
||||
@@ -106,8 +108,7 @@ public abstract partial class SharedProjectileSystem : EntitySystem
|
||||
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);
|
||||
@@ -115,13 +116,32 @@ public abstract partial class SharedProjectileSystem : EntitySystem
|
||||
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);
|
||||
@@ -149,6 +169,22 @@ public abstract partial class SharedProjectileSystem : EntitySystem
|
||||
_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))
|
||||
|
||||
Reference in New Issue
Block a user