Add GHOST GANG! (#13734)

Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com>
This commit is contained in:
Chief-Engineer
2023-05-28 04:21:06 -05:00
committed by GitHub
parent 707b9063f9
commit 485a2fd432
14 changed files with 230 additions and 30 deletions

View File

@@ -1,18 +1,27 @@
using Content.Shared.Database;
using Content.Shared.Follower.Components;
using Content.Shared.Ghost;
using Content.Shared.Hands;
using Content.Shared.Movement.Events;
using Content.Shared.Movement.Systems;
using Content.Shared.Physics.Pull;
using Content.Shared.Tag;
using Content.Shared.Verbs;
using Robust.Shared.Containers;
using Robust.Shared.Map;
using Robust.Shared.Map.Events;
using Robust.Shared.Utility;
using Robust.Shared.Physics;
using Robust.Shared.Physics.Systems;
namespace Content.Shared.Follower;
public sealed class FollowerSystem : EntitySystem
{
[Dependency] private readonly SharedTransformSystem _transform = default!;
[Dependency] private readonly TagSystem _tagSystem = default!;
[Dependency] private readonly SharedContainerSystem _containerSystem = default!;
[Dependency] private readonly SharedJointSystem _jointSystem = default!;
[Dependency] private readonly SharedPhysicsSystem _physicsSystem = default!;
public override void Initialize()
{
@@ -20,6 +29,8 @@ public sealed class FollowerSystem : EntitySystem
SubscribeLocalEvent<GetVerbsEvent<AlternativeVerb>>(OnGetAlternativeVerbs);
SubscribeLocalEvent<FollowerComponent, MoveInputEvent>(OnFollowerMove);
SubscribeLocalEvent<FollowerComponent, PullStartedMessage>(OnPullStarted);
SubscribeLocalEvent<FollowerComponent, GotEquippedHandEvent>(OnGotEquippedHand);
SubscribeLocalEvent<FollowedComponent, EntityTerminatingEvent>(OnFollowedTerminating);
SubscribeLocalEvent<BeforeSaveEvent>(OnBeforeSave);
}
@@ -44,25 +55,38 @@ public sealed class FollowerSystem : EntitySystem
private void OnGetAlternativeVerbs(GetVerbsEvent<AlternativeVerb> ev)
{
if (!HasComp<SharedGhostComponent>(ev.User))
return;
if (ev.User == ev.Target || ev.Target.IsClientSide())
return;
var verb = new AlternativeVerb
if (HasComp<SharedGhostComponent>(ev.User))
{
Priority = 10,
Act = (() =>
var verb = new AlternativeVerb()
{
StartFollowingEntity(ev.User, ev.Target);
}),
Impact = LogImpact.Low,
Text = Loc.GetString("verb-follow-text"),
Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/open.svg.192dpi.png")),
};
Priority = 10,
Act = () => StartFollowingEntity(ev.User, ev.Target),
Impact = LogImpact.Low,
Text = Loc.GetString("verb-follow-text"),
Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/open.svg.192dpi.png"))
};
ev.Verbs.Add(verb);
}
ev.Verbs.Add(verb);
if (_tagSystem.HasTag(ev.Target, "ForceableFollow"))
{
if (!ev.CanAccess || !ev.CanInteract)
return;
var verb = new AlternativeVerb
{
Priority = 10,
Act = () => StartFollowingEntity(ev.Target, ev.User),
Impact = LogImpact.Low,
Text = Loc.GetString("verb-follow-me-text"),
Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/VerbIcons/close.svg.192dpi.png")),
};
ev.Verbs.Add(verb);
}
}
private void OnFollowerMove(EntityUid uid, FollowerComponent component, ref MoveInputEvent args)
@@ -70,6 +94,16 @@ public sealed class FollowerSystem : EntitySystem
StopFollowingEntity(uid, component.Following);
}
private void OnPullStarted(EntityUid uid, FollowerComponent component, PullStartedMessage args)
{
StopFollowingEntity(uid, component.Following);
}
private void OnGotEquippedHand(EntityUid uid, FollowerComponent component, GotEquippedHandEvent args)
{
StopFollowingEntity(uid, component.Following, deparent:false);
}
// Since we parent our observer to the followed entity, we need to detach
// before they get deleted so that we don't get recursively deleted too.
private void OnFollowedTerminating(EntityUid uid, FollowedComponent component, ref EntityTerminatingEvent args)
@@ -102,24 +136,35 @@ public sealed class FollowerSystem : EntitySystem
if (!followedComp.Following.Add(follower))
return;
if (TryComp<JointComponent>(follower, out var joints))
_jointSystem.ClearJoints(follower, joints);
_physicsSystem.SetLinearVelocity(follower, Vector2.Zero);
var xform = Transform(follower);
_transform.SetCoordinates(follower, xform, new EntityCoordinates(entity, Vector2.Zero), Angle.Zero);
_containerSystem.AttachParentToContainerOrGrid(xform);
// If we didn't get to parent's container.
if (xform.ParentUid != Transform(xform.ParentUid).ParentUid)
{
_transform.SetCoordinates(follower, xform, new EntityCoordinates(entity, Vector2.Zero), rotation: Angle.Zero);
}
EnsureComp<OrbitVisualsComponent>(follower);
var followerEv = new StartedFollowingEntityEvent(entity, follower);
var entityEv = new EntityStartedFollowingEvent(entity, follower);
RaiseLocalEvent(follower, followerEv, true);
RaiseLocalEvent(entity, entityEv, false);
RaiseLocalEvent(follower, followerEv);
RaiseLocalEvent(entity, entityEv);
Dirty(followedComp);
}
/// <summary>
/// Forces an entity to stop following another entity, if it is doing so.
/// </summary>
public void StopFollowingEntity(EntityUid uid, EntityUid target,
FollowedComponent? followed=null)
/// <param name="deparent">Should the entity deparent itself</param>
public void StopFollowingEntity(EntityUid uid, EntityUid target, FollowedComponent? followed = null, bool deparent = true)
{
if (!Resolve(target, ref followed, false))
return;
@@ -130,24 +175,27 @@ public sealed class FollowerSystem : EntitySystem
followed.Following.Remove(uid);
if (followed.Following.Count == 0)
RemComp<FollowedComponent>(target);
RemComp<FollowerComponent>(uid);
var xform = Transform(uid);
_transform.AttachToGridOrMap(uid, xform);
if (xform.MapID == MapId.Nullspace)
{
QueueDel(uid);
return;
}
RemComp<OrbitVisualsComponent>(uid);
var uidEv = new StoppedFollowingEntityEvent(target, uid);
var targetEv = new EntityStoppedFollowingEvent(target, uid);
RaiseLocalEvent(uid, uidEv, true);
RaiseLocalEvent(target, targetEv, false);
Dirty(followed);
RaiseLocalEvent(uid, uidEv);
RaiseLocalEvent(target, targetEv);
if (!Deleted(uid) && deparent)
{
var xform = Transform(uid);
_transform.AttachToGridOrMap(uid, xform);
if (xform.MapUid == null)
{
QueueDel(uid);
}
}
}
/// <summary>