+using Content.Shared.Follower.Components;
using Content.Shared.Movement.Components;
using Content.Shared.Movement.Systems;
using Robust.Client.GameObjects;
SubscribeLocalEvent<EyeComponent, ComponentStartup>(OnEyeStartup);
SubscribeLocalEvent<EyeComponent, ComponentShutdown>(OnEyeShutdown);
- SubscribeLocalEvent<LerpingEyeComponent, EntParentChangedMessage>(HandleMapChange);
SubscribeLocalEvent<EyeComponent, PlayerAttachedEvent>(OnAttached);
+
+ SubscribeLocalEvent<LerpingEyeComponent, EntParentChangedMessage>(HandleMapChange);
SubscribeLocalEvent<LerpingEyeComponent, PlayerDetachedEvent>(OnDetached);
UpdatesAfter.Add(typeof(TransformSystem));
/// Attached to entities that are currently being followed by a ghost.
/// </summary>
[RegisterComponent, Access(typeof(FollowerSystem))]
-[NetworkedComponent]
-public sealed class FollowedComponent : Component
+[NetworkedComponent, AutoGenerateComponentState]
+public sealed partial class FollowedComponent : Component
{
+ [AutoNetworkedField(true), DataField("following")]
public HashSet<EntityUid> Following = new();
}
[RegisterComponent]
[Access(typeof(FollowerSystem))]
-[NetworkedComponent]
-public sealed class FollowerComponent : Component
+[NetworkedComponent, AutoGenerateComponentState]
+public sealed partial class FollowerComponent : Component
{
+ [AutoNetworkedField, DataField("following")]
public EntityUid Following;
}
using Content.Shared.Follower.Components;
using Content.Shared.Ghost;
using Content.Shared.Movement.Events;
+using Content.Shared.Movement.Systems;
using Content.Shared.Verbs;
using Robust.Shared.Map;
using Robust.Shared.Utility;
followerComp.Following = entity;
var followedComp = EnsureComp<FollowedComponent>(entity);
- followedComp.Following.Add(follower);
+
+ if (!followedComp.Following.Add(follower))
+ return;
var xform = Transform(follower);
- _transform.SetParent(follower, xform, entity);
- xform.LocalPosition = Vector2.Zero;
- xform.LocalRotation = Angle.Zero;
+ _transform.SetCoordinates(follower, xform, new EntityCoordinates(entity, Vector2.Zero), Angle.Zero);
EnsureComp<OrbitVisualsComponent>(follower);
RaiseLocalEvent(follower, followerEv, true);
RaiseLocalEvent(entity, entityEv, false);
+ Dirty(followedComp);
}
/// <summary>
RemComp<FollowerComponent>(uid);
var xform = Transform(uid);
- xform.AttachToGridOrMap();
+ _transform.AttachToGridOrMap(uid, xform);
if (xform.MapID == MapId.Nullspace)
{
- Del(uid);
+ QueueDel(uid);
return;
}
RaiseLocalEvent(uid, uidEv, true);
RaiseLocalEvent(target, targetEv, false);
+ Dirty(followed);
}
/// <summary>
using Content.Shared.CCVar;
+using Content.Shared.Follower.Components;
using Content.Shared.Input;
using Content.Shared.Movement.Components;
using Content.Shared.Movement.Events;
SubscribeLocalEvent<InputMoverComponent, ComponentHandleState>(OnInputHandleState);
SubscribeLocalEvent<InputMoverComponent, EntParentChangedMessage>(OnInputParentChange);
+ SubscribeLocalEvent<FollowedComponent, EntParentChangedMessage>(OnFollowedParentChange);
+
_configManager.OnValueChanged(CCVars.CameraRotationLocked, SetCameraRotationLocked, true);
_configManager.OnValueChanged(CCVars.GameDiagonalMovement, SetDiagonalMovement, true);
}
return rotation;
}
+ private void OnFollowedParentChange(EntityUid uid, FollowedComponent component, ref EntParentChangedMessage args)
+ {
+ var moverQuery = GetEntityQuery<InputMoverComponent>();
+ var xformQuery = GetEntityQuery<TransformComponent>();
+
+ foreach (var foll in component.Following)
+ {
+ if (!moverQuery.TryGetComponent(foll, out var mover))
+ continue;
+
+ var ev = new EntParentChangedMessage(foll, null, args.OldMapId, xformQuery.GetComponent(foll));
+ OnInputParentChange(foll, mover, ref ev);
+ }
+ }
+
private void OnInputParentChange(EntityUid uid, InputMoverComponent component, ref EntParentChangedMessage args)
{
// If we change our grid / map then delay updating our LastGridAngle.