Follow verb for ghosts (#6016)
* Follow verb for ghosts * oop * Use parenting instead * Update Content.Shared/Follower/FollowerSystem.cs Co-authored-by: ShadowCommander <10494922+ShadowCommander@users.noreply.github.com> * mfw * parent fixes * figs * oop * porbis Co-authored-by: ShadowCommander <10494922+ShadowCommander@users.noreply.github.com>
This commit is contained in:
14
Content.Shared/Follower/Components/FollowedComponent.cs
Normal file
14
Content.Shared/Follower/Components/FollowedComponent.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using Robust.Shared.Analyzers;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
|
||||||
|
namespace Content.Shared.Follower.Components;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Attached to entities that are currently being followed by a ghost.
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent, ComponentProtoName("Followed"), Friend(typeof(FollowerSystem))]
|
||||||
|
public class FollowedComponent : Component
|
||||||
|
{
|
||||||
|
public HashSet<EntityUid> Following = new();
|
||||||
|
}
|
||||||
11
Content.Shared/Follower/Components/FollowerComponent.cs
Normal file
11
Content.Shared/Follower/Components/FollowerComponent.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
using Robust.Shared.Analyzers;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
|
||||||
|
namespace Content.Shared.Follower.Components;
|
||||||
|
|
||||||
|
[RegisterComponent, ComponentProtoName("Follower")]
|
||||||
|
[Friend(typeof(FollowerSystem))]
|
||||||
|
public class FollowerComponent : Component
|
||||||
|
{
|
||||||
|
public EntityUid Following;
|
||||||
|
}
|
||||||
106
Content.Shared/Follower/FollowerSystem.cs
Normal file
106
Content.Shared/Follower/FollowerSystem.cs
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
using Content.Shared.Database;
|
||||||
|
using Content.Shared.Ghost;
|
||||||
|
using Content.Shared.Movement.EntitySystems;
|
||||||
|
using Content.Shared.Verbs;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.Localization;
|
||||||
|
using Content.Shared.Follower.Components;
|
||||||
|
using Robust.Shared.Maths;
|
||||||
|
|
||||||
|
namespace Content.Shared.Follower;
|
||||||
|
|
||||||
|
public class FollowerSystem : EntitySystem
|
||||||
|
{
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
|
||||||
|
SubscribeLocalEvent<GetAlternativeVerbsEvent>(OnGetAlternativeVerbs);
|
||||||
|
SubscribeLocalEvent<FollowerComponent, RelayMoveInputEvent>(OnFollowerMove);
|
||||||
|
SubscribeLocalEvent<FollowedComponent, EntityTerminatingEvent>(OnFollowedTerminating);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnGetAlternativeVerbs(GetAlternativeVerbsEvent ev)
|
||||||
|
{
|
||||||
|
if (!HasComp<SharedGhostComponent>(ev.User))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var verb = new Verb
|
||||||
|
{
|
||||||
|
Priority = 10,
|
||||||
|
Act = (() =>
|
||||||
|
{
|
||||||
|
StartFollowingEntity(ev.User, ev.Target);
|
||||||
|
}),
|
||||||
|
Impact = LogImpact.Low,
|
||||||
|
Text = Loc.GetString("verb-follow-text"),
|
||||||
|
IconTexture = "/Textures/Interface/VerbIcons/open.svg.192dpi.png",
|
||||||
|
};
|
||||||
|
|
||||||
|
ev.Verbs.Add(verb);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnFollowerMove(EntityUid uid, FollowerComponent component, RelayMoveInputEvent args)
|
||||||
|
{
|
||||||
|
StopFollowingEntity(uid, component.Following);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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, EntityTerminatingEvent args)
|
||||||
|
{
|
||||||
|
StopAllFollowers(uid, component);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Makes an entity follow another entity, by parenting to it.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="follower">The entity that should follow</param>
|
||||||
|
/// <param name="entity">The entity to be followed</param>
|
||||||
|
public void StartFollowingEntity(EntityUid follower, EntityUid entity)
|
||||||
|
{
|
||||||
|
var followerComp = EnsureComp<FollowerComponent>(follower);
|
||||||
|
followerComp.Following = entity;
|
||||||
|
|
||||||
|
var followedComp = EnsureComp<FollowedComponent>(entity);
|
||||||
|
followedComp.Following.Add(follower);
|
||||||
|
|
||||||
|
var xform = Transform(follower);
|
||||||
|
xform.AttachParent(entity);
|
||||||
|
xform.LocalPosition = Vector2.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <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)
|
||||||
|
{
|
||||||
|
if (!Resolve(target, ref followed))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!HasComp<FollowerComponent>(uid))
|
||||||
|
return;
|
||||||
|
|
||||||
|
followed.Following.Remove(uid);
|
||||||
|
if (followed.Following.Count == 0)
|
||||||
|
RemComp<FollowedComponent>(target);
|
||||||
|
RemComp<FollowerComponent>(uid);
|
||||||
|
Transform(uid).AttachToGridOrMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Forces all of an entity's followers to stop following it.
|
||||||
|
/// </summary>
|
||||||
|
public void StopAllFollowers(EntityUid uid,
|
||||||
|
FollowedComponent? followed=null)
|
||||||
|
{
|
||||||
|
if (!Resolve(uid, ref followed))
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (var player in followed.Following)
|
||||||
|
{
|
||||||
|
StopFollowingEntity(player, uid, followed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1
Resources/Locale/en-US/follower/follow-verb.ftl
Normal file
1
Resources/Locale/en-US/follower/follow-verb.ftl
Normal file
@@ -0,0 +1 @@
|
|||||||
|
verb-follow-text = Follow
|
||||||
Reference in New Issue
Block a user