using Content.Shared.Body.Events; using Content.Shared.DragDrop; using Content.Shared.Emoting; using Content.Shared.Interaction; using Content.Shared.Interaction.Events; using Content.Shared.Item; using Content.Shared.Movement; using Content.Shared.Movement.Components; using Content.Shared.Movement.Events; using Content.Shared.Speech; using Content.Shared.Throwing; using JetBrains.Annotations; namespace Content.Shared.ActionBlocker { /// /// Utility methods to check if a specific entity is allowed to perform an action. /// [UsedImplicitly] public sealed class ActionBlockerSystem : EntitySystem { public override void Initialize() { base.Initialize(); SubscribeLocalEvent(OnMoverStartup); } private void OnMoverStartup(EntityUid uid, InputMoverComponent component, ComponentStartup args) { UpdateCanMove(uid, component); } public bool CanMove(EntityUid uid, InputMoverComponent? component = null) { return Resolve(uid, ref component, false) && component.CanMove; } public bool UpdateCanMove(EntityUid uid, InputMoverComponent? component = null) { if (!Resolve(uid, ref component, false)) return false; var ev = new UpdateCanMoveEvent(uid); RaiseLocalEvent(uid, ev, true); if (component.CanMove == ev.Cancelled && component is Component comp) Dirty(comp); component.CanMove = !ev.Cancelled; return !ev.Cancelled; } /// /// Raises an event directed at both the user and the target entity to check whether a user is capable of /// interacting with this entity. /// /// /// If this is a generic interaction without a target (e.g., stop-drop-and-roll when burning), the target /// may be null. Note that this is checked by . In the majority of /// cases, systems that provide interactions will not need to check this themselves, though they may need to /// check other blockers like /// /// public bool CanInteract(EntityUid user, EntityUid? target) { var ev = new InteractionAttemptEvent(user, target); RaiseLocalEvent(user, ev, true); if (ev.Cancelled) return false; if (target == null) return true; var targetEv = new GettingInteractedWithAttemptEvent(user, target); RaiseLocalEvent(target.Value, targetEv, true); if (!targetEv.Cancelled) InteractWithItem(user, target.Value); return !targetEv.Cancelled; } /// /// Can a user utilize the entity that they are currently holding in their hands. /// > /// /// This event is automatically checked by for any interactions that /// involve using a held entity. In the majority of cases, systems that provide interactions will not need /// to check this themselves. /// public bool CanUseHeldEntity(EntityUid user) { var ev = new UseAttemptEvent(user); RaiseLocalEvent(user, ev, true); return !ev.Cancelled; } public bool CanThrow(EntityUid user, EntityUid itemUid) { var ev = new ThrowAttemptEvent(user, itemUid); RaiseLocalEvent(user, ev, true); return !ev.Cancelled; } public bool CanSpeak(EntityUid uid) { var ev = new SpeakAttemptEvent(uid); RaiseLocalEvent(uid, ev, true); return !ev.Cancelled; } public bool CanDrop(EntityUid uid) { var ev = new DropAttemptEvent(uid); RaiseLocalEvent(uid, ev, true); return !ev.Cancelled; } public bool CanPickup(EntityUid user, EntityUid item) { var userEv = new PickupAttemptEvent(user, item); RaiseLocalEvent(user, userEv, false); if (userEv.Cancelled) return false; var itemEv = new GettingPickedUpAttemptEvent(user, item); RaiseLocalEvent(item, itemEv, false); if (!itemEv.Cancelled) InteractWithItem(user, item); return !itemEv.Cancelled; } public bool CanEmote(EntityUid uid) { var ev = new EmoteAttemptEvent(uid); RaiseLocalEvent(uid, ev, true); return !ev.Cancelled; } public bool CanAttack(EntityUid uid, EntityUid? target = null) { var ev = new AttackAttemptEvent(uid, target); RaiseLocalEvent(uid, ev, true); return !ev.Cancelled; } public bool CanChangeDirection(EntityUid uid) { var ev = new ChangeDirectionAttemptEvent(uid); RaiseLocalEvent(uid, ev, true); return !ev.Cancelled; } public bool CanShiver(EntityUid uid) { var ev = new ShiverAttemptEvent(uid); RaiseLocalEvent(uid, ev, true); return !ev.Cancelled; } public bool CanSweat(EntityUid uid) { var ev = new SweatAttemptEvent(uid); RaiseLocalEvent(uid, ev, true); return !ev.Cancelled; } private void InteractWithItem(EntityUid user, EntityUid item) { var userEvent = new UserInteractedWithItemEvent(user, item); RaiseLocalEvent(user, userEvent); var itemEvent = new ItemInteractedWithEvent(user, item); RaiseLocalEvent(item, itemEvent); } } }