diff --git a/Content.Client/GameObjects/Components/PDA/PDABoundUserInterface.cs b/Content.Client/GameObjects/Components/PDA/PDABoundUserInterface.cs index b5ad84b435..1ba1ce1eea 100644 --- a/Content.Client/GameObjects/Components/PDA/PDABoundUserInterface.cs +++ b/Content.Client/GameObjects/Components/PDA/PDABoundUserInterface.cs @@ -23,7 +23,7 @@ namespace Content.Client.GameObjects.Components.PDA [Dependency] private readonly IUserInterfaceManager _userInterfaceManager = default!; private PDAMenu _menu; - private PDAMenuPopup failPopup; + private PDAMenuPopup _failPopup; public PDABoundUserInterface(ClientUserInterfaceComponent owner, object uiKey) : base(owner, uiKey) { @@ -47,6 +47,11 @@ namespace Content.Client.GameObjects.Components.PDA SendMessage(new PDAEjectIDMessage()); }; + _menu.EjectPenButton.OnPressed += args => + { + SendMessage(new PDAEjectPenMessage()); + }; + _menu.MasterTabContainer.OnTabChanged += i => { var tab = _menu.MasterTabContainer.GetChild(i); @@ -60,12 +65,12 @@ namespace Content.Client.GameObjects.Components.PDA { if (_menu.CurrentLoggedInAccount.DataBalance < listing.Price) { - failPopup = new PDAMenuPopup(Loc.GetString("Insufficient funds!")); - _userInterfaceManager.ModalRoot.AddChild(failPopup); - failPopup.Open(UIBox2.FromDimensions(_menu.Position.X + 150, _menu.Position.Y + 60, 156, 24)); + _failPopup = new PDAMenuPopup(Loc.GetString("Insufficient funds!")); + _userInterfaceManager.ModalRoot.AddChild(_failPopup); + _failPopup.Open(UIBox2.FromDimensions(_menu.Position.X + 150, _menu.Position.Y + 60, 156, 24)); _menu.OnClose += () => { - failPopup.Dispose(); + _failPopup.Dispose(); }; } @@ -106,6 +111,7 @@ namespace Content.Client.GameObjects.Components.PDA } _menu.EjectIDButton.Visible = msg.PDAOwnerInfo.IdOwner != null; + _menu.EjectPenButton.Visible = msg.HasPen; if (msg.Account != null) { _menu.CurrentLoggedInAccount = msg.Account; @@ -220,6 +226,7 @@ namespace Content.Client.GameObjects.Components.PDA public Button FlashLightToggleButton { get; } public Button EjectIDButton { get; } + public Button EjectPenButton { get; } public TabContainer MasterTabContainer; @@ -288,13 +295,20 @@ namespace Content.Client.GameObjects.Components.PDA SizeFlagsHorizontal = SizeFlags.ShrinkCenter, SizeFlagsVertical = SizeFlags.ShrinkCenter }; + EjectPenButton = new Button + { + Text = Loc.GetString("Eject Pen"), + SizeFlagsHorizontal = SizeFlags.ShrinkCenter, + SizeFlagsVertical = SizeFlags.ShrinkCenter + }; var innerHBoxContainer = new HBoxContainer { Children = { IDInfoLabel, - EjectIDButton + EjectIDButton, + EjectPenButton } }; diff --git a/Content.Server/GameObjects/Components/PDA/PDAComponent.cs b/Content.Server/GameObjects/Components/PDA/PDAComponent.cs index 58bdc2a1b8..bfec94de05 100644 --- a/Content.Server/GameObjects/Components/PDA/PDAComponent.cs +++ b/Content.Server/GameObjects/Components/PDA/PDAComponent.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using Content.Server.GameObjects.Components.Access; using Content.Server.GameObjects.Components.GUI; using Content.Server.GameObjects.Components.Items.Storage; +using Content.Server.GameObjects.Components.Paper; using Content.Server.Interfaces; using Content.Server.Interfaces.GameObjects.Components.Items; using Content.Server.Interfaces.PDA; @@ -39,13 +40,19 @@ namespace Content.Server.GameObjects.Components.PDA [Dependency] private readonly IPDAUplinkManager _uplinkManager = default!; [Dependency] private readonly IEntityManager _entityManager = default!; - [ViewVariables] private Container _idSlot = default!; + [ViewVariables] private ContainerSlot _idSlot = default!; + [ViewVariables] private ContainerSlot _penSlot = default!; + [ViewVariables] private bool _lightOn; - [ViewVariables] private string _startingIdCard = default!; - [ViewVariables] public bool IdSlotEmpty => _idSlot.ContainedEntities.Count < 1; + + [ViewVariables] private string? _startingIdCard = default!; + [ViewVariables] private string? _startingPen = default!; + [ViewVariables] public string? OwnerName { get; private set; } [ViewVariables] public IdCardComponent? ContainedID { get; private set; } + [ViewVariables] public bool IdSlotEmpty => _idSlot.ContainedEntity == null; + [ViewVariables] public bool PenSlotEmpty => _penSlot.ContainedEntity == null; [ViewVariables] private UplinkAccount? _syndicateUplinkAccount; @@ -62,22 +69,34 @@ namespace Content.Server.GameObjects.Components.PDA { base.ExposeData(serializer); serializer.DataField(ref _startingIdCard, "idCard", "AssistantIDCard"); + serializer.DataField(ref _startingPen, "pen", "Pen"); } public override void Initialize() { base.Initialize(); - _idSlot = ContainerManagerComponent.Ensure("pda_entity_container", Owner, out var existed); + _idSlot = ContainerManagerComponent.Ensure("pda_entity_container", Owner); + _penSlot = ContainerManagerComponent.Ensure("pda_pen_slot", Owner); if (UserInterface != null) { UserInterface.OnReceiveMessage += UserInterfaceOnReceiveMessage; } - var idCard = _entityManager.SpawnEntity(_startingIdCard, Owner.Transform.Coordinates); - var idCardComponent = idCard.GetComponent(); - _idSlot.Insert(idCardComponent.Owner); - ContainedID = idCardComponent; + if (!string.IsNullOrEmpty(_startingIdCard)) + { + var idCard = _entityManager.SpawnEntity(_startingIdCard, Owner.Transform.Coordinates); + var idCardComponent = idCard.GetComponent(); + _idSlot.Insert(idCardComponent.Owner); + ContainedID = idCardComponent; + } + + if (!string.IsNullOrEmpty(_startingPen)) + { + var pen = _entityManager.SpawnEntity(_startingPen, Owner.Transform.Coordinates); + _penSlot.Insert(pen); + } + UpdatePDAAppearance(); } @@ -85,23 +104,29 @@ namespace Content.Server.GameObjects.Components.PDA { switch (message.Message) { - case PDARequestUpdateInterfaceMessage msg: + case PDARequestUpdateInterfaceMessage _: { UpdatePDAUserInterface(); break; } - case PDAToggleFlashlightMessage msg: + case PDAToggleFlashlightMessage _: { ToggleLight(); break; } - case PDAEjectIDMessage msg: + case PDAEjectIDMessage _: { HandleIDEjection(message.Session.AttachedEntity!); break; } + case PDAEjectPenMessage _: + { + HandlePenEjection(message.Session.AttachedEntity!); + break; + } + case PDAUplinkBuyListingMessage buyMsg: { if (!_uplinkManager.TryPurchaseItem(_syndicateUplinkAccount, buyMsg.ItemId)) @@ -131,11 +156,11 @@ namespace Content.Server.GameObjects.Components.PDA var accData = new UplinkAccountData(_syndicateUplinkAccount.AccountHolder, _syndicateUplinkAccount.Balance); var listings = _uplinkManager.FetchListings.Values.ToArray(); - UserInterface?.SetState(new PDAUpdateState(_lightOn, ownerInfo, accData, listings)); + UserInterface?.SetState(new PDAUpdateState(_lightOn, !PenSlotEmpty, ownerInfo, accData, listings)); } else { - UserInterface?.SetState(new PDAUpdateState(_lightOn, ownerInfo)); + UserInterface?.SetState(new PDAUpdateState(_lightOn, !PenSlotEmpty, ownerInfo)); } UpdatePDAAppearance(); @@ -150,14 +175,11 @@ namespace Content.Server.GameObjects.Components.PDA } } - public async Task InteractUsing(InteractUsingEventArgs eventArgs) + private bool TryInsertIdCard(InteractUsingEventArgs eventArgs, IdCardComponent idCardComponent) { var item = eventArgs.Using; - - if (!item.TryGetComponent(out var idCardComponent) || _idSlot.Contains(item)) - { + if (_idSlot.Contains(item)) return false; - } if (!eventArgs.User.TryGetComponent(out IHandsComponent? hands)) { @@ -177,17 +199,70 @@ namespace Content.Server.GameObjects.Components.PDA return true; } - InsertIdCard(idCardComponent); - if (swap != null) { - eventArgs.User.GetComponent().PutInHand(swap.GetComponent()); + hands.PutInHand(swap.GetComponent()); } + InsertIdCard(idCardComponent); + UpdatePDAUserInterface(); return true; } + private bool TryInsertPen(InteractUsingEventArgs eventArgs) + { + var item = eventArgs.Using; + if (_penSlot.Contains(item)) + return false; + + if (!eventArgs.User.TryGetComponent(out IHandsComponent? hands)) + { + Owner.PopupMessage(eventArgs.User, Loc.GetString("You have no hands!")); + return true; + } + + IEntity? swap = null; + if (!PenSlotEmpty) + { + // Swap + swap = _penSlot.ContainedEntities[0]; + } + + if (!hands.Drop(item)) + { + return true; + } + + if (swap != null) + { + hands.PutInHand(swap.GetComponent()); + } + + // Insert Pen + _penSlot.Insert(item); + + UpdatePDAUserInterface(); + return true; + } + + public async Task InteractUsing(InteractUsingEventArgs eventArgs) + { + var item = eventArgs.Using; + + if (item.TryGetComponent(out var idCardComponent)) + { + return TryInsertIdCard(eventArgs, idCardComponent); + } + + if (item.HasComponent()) + { + return TryInsertPen(eventArgs); + } + + return false; + } + void IActivate.Activate(ActivateEventArgs eventArgs) { if (!eventArgs.User.TryGetComponent(out IActorComponent? actor)) @@ -273,6 +348,21 @@ namespace Content.Server.GameObjects.Components.PDA UpdatePDAUserInterface(); } + private void HandlePenEjection(IEntity pdaUser) + { + if (PenSlotEmpty) + return; + + var pen = _penSlot.ContainedEntities[0]; + _penSlot.Remove(pen); + + var hands = pdaUser.GetComponent(); + var itemComponent = pen.GetComponent(); + hands.PutInHandOrDrop(itemComponent); + + UpdatePDAUserInterface(); + } + [Verb] public sealed class EjectIDVerb : Verb { @@ -294,6 +384,28 @@ namespace Content.Server.GameObjects.Components.PDA } } + [Verb] + public sealed class EjectPenVerb : Verb + { + protected override void GetData(IEntity user, PDAComponent component, VerbData data) + { + if (!ActionBlockerSystem.CanInteract(user)) + { + data.Visibility = VerbVisibility.Invisible; + return; + } + + data.Text = Loc.GetString("Eject Pen"); + data.Visibility = component.PenSlotEmpty ? VerbVisibility.Invisible : VerbVisibility.Visible; + } + + protected override void Activate(IEntity user, PDAComponent component) + { + component.HandlePenEjection(user); + } + } + + [Verb] public sealed class ToggleFlashlightVerb : Verb { protected override void GetData(IEntity user, PDAComponent component, VerbData data) diff --git a/Content.Shared/GameObjects/Components/PDA/SharedPDAComponent.cs b/Content.Shared/GameObjects/Components/PDA/SharedPDAComponent.cs index c34d57ca9b..ceaabec258 100644 --- a/Content.Shared/GameObjects/Components/PDA/SharedPDAComponent.cs +++ b/Content.Shared/GameObjects/Components/PDA/SharedPDAComponent.cs @@ -30,6 +30,15 @@ namespace Content.Shared.GameObjects.Components.PDA } } + [Serializable, NetSerializable] + public sealed class PDAEjectPenMessage : BoundUserInterfaceMessage + { + public PDAEjectPenMessage() + { + + } + } + [Serializable, NetSerializable] public class PDAUBoundUserInterfaceState : BoundUserInterfaceState { @@ -40,28 +49,27 @@ namespace Content.Shared.GameObjects.Components.PDA public sealed class PDAUpdateState : PDAUBoundUserInterfaceState { public bool FlashlightEnabled; + public bool HasPen; public PDAIdInfoText PDAOwnerInfo; public UplinkAccountData Account; public UplinkListingData[] Listings; - public PDAUpdateState(bool isFlashlightOn, PDAIdInfoText ownerInfo) + public PDAUpdateState(bool isFlashlightOn, bool hasPen, PDAIdInfoText ownerInfo) { FlashlightEnabled = isFlashlightOn; + HasPen = hasPen; PDAOwnerInfo = ownerInfo; } - public PDAUpdateState(bool isFlashlightOn, PDAIdInfoText ownerInfo, UplinkAccountData accountData) + public PDAUpdateState(bool isFlashlightOn, bool hasPen, PDAIdInfoText ownerInfo, UplinkAccountData accountData) + : this(isFlashlightOn, hasPen, ownerInfo) { - FlashlightEnabled = isFlashlightOn; - PDAOwnerInfo = ownerInfo; Account = accountData; } - public PDAUpdateState(bool isFlashlightOn, PDAIdInfoText ownerInfo, UplinkAccountData accountData, UplinkListingData[] listings) + public PDAUpdateState(bool isFlashlightOn, bool hasPen, PDAIdInfoText ownerInfo, UplinkAccountData accountData, UplinkListingData[] listings) + : this(isFlashlightOn, hasPen, ownerInfo, accountData) { - FlashlightEnabled = isFlashlightOn; - PDAOwnerInfo = ownerInfo; - Account = accountData; Listings = listings; } }