Travelling pointing arrows, brains can no longer point (#24864)
* Decoupled from gravity, constant animation time, manual networking, cubic interpolation * Reduced overshoot * Implemented PointAttemptEvent, reacts with mobstate & sleeping * Brains can no longer point, PBs must be inside a chassis * Removed chassis check, made callback more obvious
This commit is contained in:
@@ -1,19 +1,12 @@
|
||||
using System.Numerics;
|
||||
using Content.Shared.Pointing.Components;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Content.Client.Pointing.Components;
|
||||
[RegisterComponent]
|
||||
public sealed partial class PointingArrowComponent : SharedPointingArrowComponent
|
||||
{
|
||||
/// <summary>
|
||||
/// How long it takes to go from the bottom of the animation to the top.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField("animationTime")]
|
||||
public float AnimationTime = 0.5f;
|
||||
|
||||
/// <summary>
|
||||
/// How far it goes in any direction.
|
||||
/// How far the arrow moves up and down during the floating phase.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField("offset")]
|
||||
|
||||
62
Content.Client/Pointing/PointingSystem.Visualizer.cs
Normal file
62
Content.Client/Pointing/PointingSystem.Visualizer.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
using Content.Client.Pointing.Components;
|
||||
using Content.Shared.Pointing;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.Animations;
|
||||
using Robust.Shared.Animations;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Content.Client.Pointing;
|
||||
|
||||
public sealed partial class PointingSystem : SharedPointingSystem
|
||||
{
|
||||
[Dependency] private readonly AnimationPlayerSystem _animationPlayer = default!;
|
||||
|
||||
public void InitializeVisualizer()
|
||||
{
|
||||
SubscribeLocalEvent<PointingArrowComponent, AnimationCompletedEvent>(OnAnimationCompleted);
|
||||
}
|
||||
|
||||
private void OnAnimationCompleted(EntityUid uid, PointingArrowComponent component, AnimationCompletedEvent args)
|
||||
{
|
||||
if (args.Key == component.AnimationKey)
|
||||
_animationPlayer.Stop(uid, component.AnimationKey);
|
||||
}
|
||||
|
||||
private void BeginPointAnimation(EntityUid uid, Vector2 startPosition, Vector2 offset, string animationKey)
|
||||
{
|
||||
if (_animationPlayer.HasRunningAnimation(uid, animationKey))
|
||||
return;
|
||||
|
||||
var animation = new Animation
|
||||
{
|
||||
Length = PointDuration,
|
||||
AnimationTracks =
|
||||
{
|
||||
new AnimationTrackComponentProperty
|
||||
{
|
||||
ComponentType = typeof(SpriteComponent),
|
||||
Property = nameof(SpriteComponent.Offset),
|
||||
InterpolationMode = AnimationInterpolationMode.Cubic,
|
||||
KeyFrames =
|
||||
{
|
||||
// We pad here to prevent improper looping and tighten the overshoot, just a touch
|
||||
new AnimationTrackProperty.KeyFrame(startPosition, 0f),
|
||||
new AnimationTrackProperty.KeyFrame(Vector2.Lerp(startPosition, offset, 0.9f), PointKeyTimeMove),
|
||||
new AnimationTrackProperty.KeyFrame(offset, PointKeyTimeMove),
|
||||
new AnimationTrackProperty.KeyFrame(Vector2.Zero, PointKeyTimeMove),
|
||||
new AnimationTrackProperty.KeyFrame(offset, PointKeyTimeHover),
|
||||
new AnimationTrackProperty.KeyFrame(Vector2.Zero, PointKeyTimeHover),
|
||||
new AnimationTrackProperty.KeyFrame(offset, PointKeyTimeHover),
|
||||
new AnimationTrackProperty.KeyFrame(Vector2.Zero, PointKeyTimeHover),
|
||||
new AnimationTrackProperty.KeyFrame(offset, PointKeyTimeHover),
|
||||
new AnimationTrackProperty.KeyFrame(Vector2.Zero, PointKeyTimeHover),
|
||||
new AnimationTrackProperty.KeyFrame(offset, PointKeyTimeHover),
|
||||
new AnimationTrackProperty.KeyFrame(Vector2.Zero, PointKeyTimeHover),
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
_animationPlayer.Play(uid, animation, animationKey);
|
||||
}
|
||||
}
|
||||
@@ -1,32 +1,25 @@
|
||||
using Content.Client.Pointing.Components;
|
||||
using Content.Client.Gravity;
|
||||
using Content.Shared.Mobs.Systems;
|
||||
using Content.Shared.Pointing;
|
||||
using Content.Shared.Verbs;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Utility;
|
||||
using DrawDepth = Content.Shared.DrawDepth.DrawDepth;
|
||||
|
||||
namespace Content.Client.Pointing;
|
||||
|
||||
public sealed class PointingSystem : SharedPointingSystem
|
||||
public sealed partial class PointingSystem : SharedPointingSystem
|
||||
{
|
||||
[Dependency] private readonly MobStateSystem _mobState = default!;
|
||||
[Dependency] private readonly FloatingVisualizerSystem _floatingSystem = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<GetVerbsEvent<Verb>>(AddPointingVerb);
|
||||
SubscribeLocalEvent<PointingArrowComponent, ComponentStartup>(OnArrowStartup);
|
||||
SubscribeLocalEvent<PointingArrowComponent, AnimationCompletedEvent>(OnArrowAnimation);
|
||||
SubscribeLocalEvent<RoguePointingArrowComponent, ComponentStartup>(OnRogueArrowStartup);
|
||||
}
|
||||
SubscribeLocalEvent<PointingArrowComponent, ComponentHandleState>(HandleCompState);
|
||||
|
||||
private void OnArrowAnimation(EntityUid uid, PointingArrowComponent component, AnimationCompletedEvent args)
|
||||
{
|
||||
_floatingSystem.FloatAnimation(uid, component.Offset, component.AnimationKey, component.AnimationTime);
|
||||
InitializeVisualizer();
|
||||
}
|
||||
|
||||
private void AddPointingVerb(GetVerbsEvent<Verb> args)
|
||||
@@ -38,15 +31,11 @@ public sealed class PointingSystem : SharedPointingSystem
|
||||
// I'm just adding this verb exclusively to clients so that the verb-loading pop-in on the verb menu isn't
|
||||
// as bad. Important for this verb seeing as its usually an option on just about any entity.
|
||||
|
||||
if (HasComp<PointingArrowComponent>(args.Target))
|
||||
{
|
||||
// this is a pointing arrow. no pointing here...
|
||||
if (HasComp<PointingArrowComponent>(args.Target))
|
||||
return;
|
||||
}
|
||||
|
||||
// Can the user point? Checking mob state directly instead of some action blocker, as many action blockers are blocked for
|
||||
// ghosts and there is no obvious choice for pointing (unless ghosts CanEmote?).
|
||||
if (_mobState.IsIncapacitated(args.User))
|
||||
if (!CanPoint(args.User))
|
||||
return;
|
||||
|
||||
// We won't check in range or visibility, as this verb is currently only executable via the context menu,
|
||||
@@ -66,11 +55,9 @@ public sealed class PointingSystem : SharedPointingSystem
|
||||
private void OnArrowStartup(EntityUid uid, PointingArrowComponent component, ComponentStartup args)
|
||||
{
|
||||
if (TryComp<SpriteComponent>(uid, out var sprite))
|
||||
{
|
||||
sprite.DrawDepth = (int) DrawDepth.Overlays;
|
||||
}
|
||||
|
||||
_floatingSystem.FloatAnimation(uid, component.Offset, component.AnimationKey, component.AnimationTime);
|
||||
BeginPointAnimation(uid, component.StartPosition, component.Offset, component.AnimationKey);
|
||||
}
|
||||
|
||||
private void OnRogueArrowStartup(EntityUid uid, RoguePointingArrowComponent arrow, ComponentStartup args)
|
||||
@@ -81,4 +68,13 @@ public sealed class PointingSystem : SharedPointingSystem
|
||||
sprite.NoRotation = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleCompState(Entity<PointingArrowComponent> entity, ref ComponentHandleState args)
|
||||
{
|
||||
if (args.Current is not SharedPointingArrowComponentState state)
|
||||
return;
|
||||
|
||||
entity.Comp.StartPosition = state.StartPosition;
|
||||
entity.Comp.EndTime = state.EndTime;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ using Content.Shared.Body.Components;
|
||||
using Content.Shared.Body.Events;
|
||||
using Content.Shared.Mind;
|
||||
using Content.Shared.Mind.Components;
|
||||
using Content.Shared.Pointing;
|
||||
|
||||
namespace Content.Server.Body.Systems
|
||||
{
|
||||
@@ -17,6 +18,7 @@ namespace Content.Server.Body.Systems
|
||||
|
||||
SubscribeLocalEvent<BrainComponent, AddedToPartInBodyEvent>((uid, _, args) => HandleMind(args.Body, uid));
|
||||
SubscribeLocalEvent<BrainComponent, RemovedFromPartInBodyEvent>((uid, _, args) => HandleMind(uid, args.OldBody));
|
||||
SubscribeLocalEvent<BrainComponent, PointAttemptEvent>(OnPointAttempt);
|
||||
}
|
||||
|
||||
private void HandleMind(EntityUid newEntity, EntityUid oldEntity)
|
||||
@@ -36,5 +38,10 @@ namespace Content.Server.Body.Systems
|
||||
|
||||
_mindSystem.TransferTo(mindId, newEntity, mind: mind);
|
||||
}
|
||||
|
||||
private void OnPointAttempt(EntityUid uid, BrainComponent component, PointAttemptEvent args)
|
||||
{
|
||||
args.Cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System.Linq;
|
||||
using Content.Server.Administration.Logs;
|
||||
using Content.Server.Pointing.Components;
|
||||
using Content.Shared.Bed.Sleep;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.Examine;
|
||||
using Content.Shared.Eye;
|
||||
@@ -10,13 +9,13 @@ using Content.Shared.IdentityManagement;
|
||||
using Content.Shared.Input;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Mind;
|
||||
using Content.Shared.Mobs.Systems;
|
||||
using Content.Shared.Pointing;
|
||||
using Content.Shared.Popups;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Shared.Enums;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Input.Binding;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Player;
|
||||
@@ -34,7 +33,6 @@ namespace Content.Server.Pointing.EntitySystems
|
||||
[Dependency] private readonly ITileDefinitionManager _tileDefinitionManager = default!;
|
||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||
[Dependency] private readonly RotateToFaceSystem _rotateToFaceSystem = default!;
|
||||
[Dependency] private readonly MobStateSystem _mobState = default!;
|
||||
[Dependency] private readonly SharedPopupSystem _popup = default!;
|
||||
[Dependency] private readonly VisibilitySystem _visibilitySystem = default!;
|
||||
[Dependency] private readonly SharedMindSystem _minds = default!;
|
||||
@@ -50,6 +48,15 @@ namespace Content.Server.Pointing.EntitySystems
|
||||
|
||||
private const float PointingRange = 15f;
|
||||
|
||||
private void GetCompState(Entity<PointingArrowComponent> entity, ref ComponentGetState args)
|
||||
{
|
||||
args.State = new SharedPointingArrowComponentState
|
||||
{
|
||||
StartPosition = entity.Comp.StartPosition,
|
||||
EndTime = entity.Comp.EndTime
|
||||
};
|
||||
}
|
||||
|
||||
private void OnPlayerStatusChanged(object? sender, SessionStatusEventArgs e)
|
||||
{
|
||||
if (e.NewStatus != SessionStatus.Disconnected)
|
||||
@@ -97,7 +104,7 @@ namespace Content.Server.Pointing.EntitySystems
|
||||
}
|
||||
}
|
||||
|
||||
public bool TryPoint(ICommonSession? session, EntityCoordinates coords, EntityUid pointed)
|
||||
public bool TryPoint(ICommonSession? session, EntityCoordinates coordsPointed, EntityUid pointed)
|
||||
{
|
||||
if (session?.AttachedEntity is not { } player)
|
||||
{
|
||||
@@ -105,9 +112,9 @@ namespace Content.Server.Pointing.EntitySystems
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!coords.IsValid(EntityManager))
|
||||
if (!coordsPointed.IsValid(EntityManager))
|
||||
{
|
||||
Log.Warning($"Player {ToPrettyString(player)} attempted to point at invalid coordinates: {coords}");
|
||||
Log.Warning($"Player {ToPrettyString(player)} attempted to point at invalid coordinates: {coordsPointed}");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -123,33 +130,30 @@ namespace Content.Server.Pointing.EntitySystems
|
||||
return false;
|
||||
}
|
||||
|
||||
// Checking mob state directly instead of some action blocker, as many action blockers are blocked for
|
||||
// ghosts and there is no obvious choice for pointing.
|
||||
if (_mobState.IsIncapacitated(player))
|
||||
if (!CanPoint(player))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (HasComp<SleepingComponent>(player))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!InRange(player, coords))
|
||||
if (!InRange(player, coordsPointed))
|
||||
{
|
||||
_popup.PopupEntity(Loc.GetString("pointing-system-try-point-cannot-reach"), player, player);
|
||||
return false;
|
||||
}
|
||||
|
||||
var mapCoordsPointed = coordsPointed.ToMap(EntityManager);
|
||||
_rotateToFaceSystem.TryFaceCoordinates(player, mapCoordsPointed.Position);
|
||||
|
||||
var mapCoords = coords.ToMap(EntityManager);
|
||||
_rotateToFaceSystem.TryFaceCoordinates(player, mapCoords.Position);
|
||||
|
||||
var arrow = EntityManager.SpawnEntity("PointingArrow", coords);
|
||||
var arrow = EntityManager.SpawnEntity("PointingArrow", coordsPointed);
|
||||
|
||||
if (TryComp<PointingArrowComponent>(arrow, out var pointing))
|
||||
{
|
||||
pointing.EndTime = _gameTiming.CurTime + TimeSpan.FromSeconds(4);
|
||||
if (TryComp(player, out TransformComponent? xformPlayer))
|
||||
pointing.StartPosition = EntityCoordinates.FromMap(arrow, xformPlayer.Coordinates.ToMap(EntityManager)).Position;
|
||||
|
||||
pointing.EndTime = _gameTiming.CurTime + PointDuration;
|
||||
|
||||
Dirty(arrow, pointing);
|
||||
}
|
||||
|
||||
if (EntityQuery<PointingArrowAngeringComponent>().FirstOrDefault() != null)
|
||||
@@ -215,10 +219,10 @@ namespace Content.Server.Pointing.EntitySystems
|
||||
TileRef? tileRef = null;
|
||||
string? position = null;
|
||||
|
||||
if (_mapManager.TryFindGridAt(mapCoords, out var gridUid, out var grid))
|
||||
if (_mapManager.TryFindGridAt(mapCoordsPointed, out var gridUid, out var grid))
|
||||
{
|
||||
position = $"EntId={gridUid} {grid.WorldToTile(mapCoords.Position)}";
|
||||
tileRef = grid.GetTileRef(grid.WorldToTile(mapCoords.Position));
|
||||
position = $"EntId={gridUid} {grid.WorldToTile(mapCoordsPointed.Position)}";
|
||||
tileRef = grid.GetTileRef(grid.WorldToTile(mapCoordsPointed.Position));
|
||||
}
|
||||
|
||||
var tileDef = _tileDefinitionManager[tileRef?.Tile.TypeId ?? 0];
|
||||
@@ -228,7 +232,7 @@ namespace Content.Server.Pointing.EntitySystems
|
||||
|
||||
viewerMessage = Loc.GetString("pointing-system-other-point-at-tile", ("otherName", playerName), ("tileName", name));
|
||||
|
||||
_adminLogger.Add(LogType.Action, LogImpact.Low, $"{ToPrettyString(player):user} pointed at {name} {(position == null ? mapCoords : position)}");
|
||||
_adminLogger.Add(LogType.Action, LogImpact.Low, $"{ToPrettyString(player):user} pointed at {name} {(position == null ? mapCoordsPointed : position)}");
|
||||
}
|
||||
|
||||
_pointers[session] = _gameTiming.CurTime;
|
||||
@@ -242,6 +246,8 @@ namespace Content.Server.Pointing.EntitySystems
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<PointingArrowComponent, ComponentGetState>(GetCompState);
|
||||
|
||||
SubscribeNetworkEvent<PointingAttemptEvent>(OnPointAttempt);
|
||||
|
||||
_playerManager.PlayerStatusChanged += OnPlayerStatusChanged;
|
||||
@@ -255,8 +261,8 @@ namespace Content.Server.Pointing.EntitySystems
|
||||
{
|
||||
var target = GetEntity(ev.Target);
|
||||
|
||||
if (TryComp(target, out TransformComponent? xform))
|
||||
TryPoint(args.SenderSession, xform.Coordinates, target);
|
||||
if (TryComp(target, out TransformComponent? xformTarget))
|
||||
TryPoint(args.SenderSession, xformTarget.Coordinates, target);
|
||||
else
|
||||
Log.Warning($"User {args.SenderSession} attempted to point at a non-existent entity uid: {ev.Target}");
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ using Content.Shared.Mind.Components;
|
||||
using Content.Shared.Mobs;
|
||||
using Content.Shared.Mobs.Systems;
|
||||
using Content.Shared.Movement.Systems;
|
||||
using Content.Shared.Pointing;
|
||||
using Content.Shared.PowerCell;
|
||||
using Content.Shared.PowerCell.Components;
|
||||
using Content.Shared.Roles;
|
||||
@@ -67,6 +68,7 @@ public sealed partial class BorgSystem : SharedBorgSystem
|
||||
SubscribeLocalEvent<BorgChassisComponent, GetCharactedDeadIcEvent>(OnGetDeadIC);
|
||||
|
||||
SubscribeLocalEvent<BorgBrainComponent, MindAddedMessage>(OnBrainMindAdded);
|
||||
SubscribeLocalEvent<BorgBrainComponent, PointAttemptEvent>(OnBrainPointAttempt);
|
||||
|
||||
InitializeModules();
|
||||
InitializeMMI();
|
||||
@@ -242,6 +244,11 @@ public sealed partial class BorgSystem : SharedBorgSystem
|
||||
_mind.TransferTo(mindId, containerEnt, mind: mind);
|
||||
}
|
||||
|
||||
private void OnBrainPointAttempt(EntityUid uid, BorgBrainComponent component, PointAttemptEvent args)
|
||||
{
|
||||
args.Cancel();
|
||||
}
|
||||
|
||||
private void UpdateBatteryAlert(EntityUid uid, PowerCellSlotComponent? slotComponent = null)
|
||||
{
|
||||
if (!_powerCell.TryGetBatteryFromSlot(uid, out var battery, slotComponent))
|
||||
|
||||
@@ -2,6 +2,7 @@ using Content.Shared.Actions;
|
||||
using Content.Shared.Bed.Sleep;
|
||||
using Content.Shared.Damage.ForceSay;
|
||||
using Content.Shared.Eye.Blinding.Systems;
|
||||
using Content.Shared.Pointing;
|
||||
using Content.Shared.Speech;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Prototypes;
|
||||
@@ -25,6 +26,7 @@ namespace Content.Server.Bed.Sleep
|
||||
SubscribeLocalEvent<SleepingComponent, ComponentShutdown>(OnShutdown);
|
||||
SubscribeLocalEvent<SleepingComponent, SpeakAttemptEvent>(OnSpeakAttempt);
|
||||
SubscribeLocalEvent<SleepingComponent, CanSeeAttemptEvent>(OnSeeAttempt);
|
||||
SubscribeLocalEvent<SleepingComponent, PointAttemptEvent>(OnPointAttempt);
|
||||
SubscribeLocalEvent<SleepingComponent, EntityUnpausedEvent>(OnSleepUnpaused);
|
||||
}
|
||||
|
||||
@@ -70,6 +72,11 @@ namespace Content.Server.Bed.Sleep
|
||||
if (component.LifeStage <= ComponentLifeStage.Running)
|
||||
args.Cancel();
|
||||
}
|
||||
|
||||
private void OnPointAttempt(EntityUid uid, SleepingComponent component, PointAttemptEvent args)
|
||||
{
|
||||
args.Cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ using Content.Shared.Inventory.Events;
|
||||
using Content.Shared.Item;
|
||||
using Content.Shared.Mobs.Components;
|
||||
using Content.Shared.Movement.Events;
|
||||
using Content.Shared.Pointing;
|
||||
using Content.Shared.Pulling.Events;
|
||||
using Content.Shared.Speech;
|
||||
using Content.Shared.Standing;
|
||||
@@ -38,6 +39,7 @@ public partial class MobStateSystem
|
||||
SubscribeLocalEvent<MobStateComponent, StartPullAttemptEvent>(CheckAct);
|
||||
SubscribeLocalEvent<MobStateComponent, UpdateCanMoveEvent>(CheckAct);
|
||||
SubscribeLocalEvent<MobStateComponent, StandAttemptEvent>(CheckAct);
|
||||
SubscribeLocalEvent<MobStateComponent, PointAttemptEvent>(CheckAct);
|
||||
SubscribeLocalEvent<MobStateComponent, TryingToSleepEvent>(OnSleepAttempt);
|
||||
SubscribeLocalEvent<MobStateComponent, CombatModeShouldHandInteractEvent>(OnCombatModeShouldHandInteract);
|
||||
SubscribeLocalEvent<MobStateComponent, AttemptPacifiedAttackEvent>(OnAttemptPacifiedAttack);
|
||||
|
||||
@@ -1,13 +1,22 @@
|
||||
using Robust.Shared.GameStates;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Content.Shared.Pointing.Components;
|
||||
|
||||
[NetworkedComponent]
|
||||
public abstract partial class SharedPointingArrowComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// The position of the sender when the point began.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public Vector2 StartPosition;
|
||||
|
||||
/// <summary>
|
||||
/// When the pointing arrow ends
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField("endTime")]
|
||||
[DataField]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public TimeSpan EndTime;
|
||||
}
|
||||
|
||||
@@ -1,17 +1,36 @@
|
||||
using Robust.Shared.Serialization;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Content.Shared.Pointing;
|
||||
|
||||
public abstract class SharedPointingSystem : EntitySystem
|
||||
{
|
||||
[Serializable, NetSerializable]
|
||||
protected sealed class PointingArrowComponentState : ComponentState
|
||||
{
|
||||
public TimeSpan EndTime;
|
||||
protected readonly TimeSpan PointDuration = TimeSpan.FromSeconds(4);
|
||||
protected readonly float PointKeyTimeMove = 0.1f;
|
||||
protected readonly float PointKeyTimeHover = 0.5f;
|
||||
|
||||
public PointingArrowComponentState(TimeSpan endTime)
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class SharedPointingArrowComponentState : ComponentState
|
||||
{
|
||||
EndTime = endTime;
|
||||
public Vector2 StartPosition { get; init; }
|
||||
public TimeSpan EndTime { get; init; }
|
||||
}
|
||||
|
||||
public bool CanPoint(EntityUid uid)
|
||||
{
|
||||
var ev = new PointAttemptEvent(uid);
|
||||
RaiseLocalEvent(uid, ev, true);
|
||||
|
||||
return !ev.Cancelled;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class PointAttemptEvent : CancellableEntityEventArgs
|
||||
{
|
||||
public PointAttemptEvent(EntityUid uid)
|
||||
{
|
||||
Uid = uid;
|
||||
}
|
||||
|
||||
public EntityUid Uid { get; }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user