using System.Linq; using Content.Server.Buckle.Components; using Content.Server.Storage.Components; using Content.Shared.Interaction; using Content.Shared.Item; using Content.Shared.Verbs; using JetBrains.Annotations; using Robust.Shared.Containers; using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Localization; namespace Content.Server.Foldable { [UsedImplicitly] public sealed class FoldableSystem : EntitySystem { [Dependency] private SharedContainerSystem _container = default!; private const string FoldKey = "FoldedState"; public override void Initialize() { base.Initialize(); SubscribeLocalEvent(OnFoldableInit); SubscribeLocalEvent(OnFoldableOpenAttempt); SubscribeLocalEvent(OnPickedUpAttempt); SubscribeLocalEvent(AddFoldVerb); } private void OnFoldableOpenAttempt(EntityUid uid, FoldableComponent component, StorageOpenAttemptEvent args) { if (component.IsFolded) args.Cancel(); } private void OnFoldableInit(EntityUid uid, FoldableComponent component, ComponentInit args) { SetFolded(component, component.IsFolded); } private bool TryToggleFold(FoldableComponent comp) { return TrySetFolded(comp, !comp.IsFolded); } /// /// Try to fold/unfold /// /// /// Folded state we want /// True if successful private bool TrySetFolded(FoldableComponent comp, bool state) { if (state == comp.IsFolded) return false; if (_container.IsEntityInContainer(comp.Owner)) return false; // First we check if the foldable object has a strap component if (EntityManager.TryGetComponent(comp.Owner, out StrapComponent? strap)) { // If an entity is buckled to the object we can't pick it up or fold it if (strap.BuckledEntities.Any()) return false; } SetFolded(comp, state); return true; } /// /// Set the folded state of the given /// /// /// If true, the component will become folded, else unfolded private void SetFolded(FoldableComponent component, bool folded) { component.IsFolded = folded; component.CanBeFolded = !_container.IsEntityInContainer(component.Owner); // You can't buckle an entity to a folded object if (EntityManager.TryGetComponent(component.Owner, out StrapComponent? strap)) strap.Enabled = !component.IsFolded; // Update visuals only if the value has changed if (EntityManager.TryGetComponent(component.Owner, out AppearanceComponent? appearance)) appearance.SetData(FoldKey, folded); } #region Event handlers /// /// Prevents foldable objects to be picked up when unfolded /// /// /// /// private void OnPickedUpAttempt(EntityUid uid, FoldableComponent component, AttemptItemPickupEvent args) { if (!component.IsFolded) args.Cancel(); } #endregion #region Verb private void AddFoldVerb(EntityUid uid, FoldableComponent component, GetAlternativeVerbsEvent args) { if (!args.CanAccess || !args.CanInteract) return; Verb verb = new() { Act = () => TryToggleFold(component), Text = component.IsFolded ? Loc.GetString("unfold-verb") : Loc.GetString("fold-verb"), IconTexture = "/Textures/Interface/VerbIcons/fold.svg.192dpi.png", // If the object is unfolded and they click it, they want to fold it, if it's folded, they want to pick it up Priority = component.IsFolded ? 0 : 2, }; args.Verbs.Add(verb); } #endregion } }