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(OnGetAlternativeVerbs); SubscribeLocalEvent(OnFollowerMove); SubscribeLocalEvent(OnFollowedTerminating); } private void OnGetAlternativeVerbs(GetAlternativeVerbsEvent ev) { if (!HasComp(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); } /// /// Makes an entity follow another entity, by parenting to it. /// /// The entity that should follow /// The entity to be followed public void StartFollowingEntity(EntityUid follower, EntityUid entity) { var followerComp = EnsureComp(follower); followerComp.Following = entity; var followedComp = EnsureComp(entity); followedComp.Following.Add(follower); var xform = Transform(follower); xform.AttachParent(entity); xform.LocalPosition = Vector2.Zero; } /// /// Forces an entity to stop following another entity, if it is doing so. /// public void StopFollowingEntity(EntityUid uid, EntityUid target, FollowedComponent? followed=null) { if (!Resolve(target, ref followed)) return; if (!HasComp(uid)) return; followed.Following.Remove(uid); if (followed.Following.Count == 0) RemComp(target); RemComp(uid); Transform(uid).AttachToGridOrMap(); } /// /// Forces all of an entity's followers to stop following it. /// public void StopAllFollowers(EntityUid uid, FollowedComponent? followed=null) { if (!Resolve(uid, ref followed)) return; foreach (var player in followed.Following) { StopFollowingEntity(player, uid, followed); } } }