diff --git a/Content.Client/SS220/Contractor/UI/ContractorBoundUserInterface.cs b/Content.Client/SS220/Contractor/UI/ContractorBoundUserInterface.cs index c87f06fb036640..90a2abdbbcb8cf 100644 --- a/Content.Client/SS220/Contractor/UI/ContractorBoundUserInterface.cs +++ b/Content.Client/SS220/Contractor/UI/ContractorBoundUserInterface.cs @@ -52,7 +52,7 @@ protected override void ReceiveMessage(BoundUserInterfaceMessage message) { case ContractorUpdateStatsMessage: UpdateStats(); - UpdateContracts(EntMan.GetEntity(_contractorPdaComponent.PdaOwner)!.Value, Owner); + UpdateContracts(EntMan.GetEntity(_contractorPdaComponent.PdaOwner)!.Value); break; case ContractorCompletedContractMessage: @@ -84,7 +84,7 @@ protected override void Open() UpdateStats(); - UpdateContracts(_playerManager.LocalSession.AttachedEntity.Value, Owner); + UpdateContracts(_playerManager.LocalSession.AttachedEntity.Value); UpdateHub(_contractorPdaComponent.AvailableItems); } @@ -123,16 +123,16 @@ private void UpdateStats() Loc.GetString("contractor-uplink-current-contracts-completed", ("amountContractsCompleted", _contractorComponent.ContractsCompleted)); } - private void UpdateContracts(EntityUid contractor, EntityUid pda) + private void UpdateContracts(EntityUid player) { if (_menu == null) return; _menu.ContractsListPanel.RemoveAllChildren(); - var contracts = _contractorSystem.GetContractsForPda(contractor, pda); + var contracts = _contractorComponent!.Contracts; - if (contracts is null) + if (_contractorPdaComponent.PdaOwner != EntMan.GetNetEntity(player)) return; foreach (var contract in contracts) @@ -223,8 +223,29 @@ private void AddContract(NetEntity key, ContractorContract contract) var isAlreadyAccepted = _contractorPdaComponent.CurrentContractEntity is not null && _contractorPdaComponent.CurrentContractData is not null; // todo only on server + var abortButton = new Button() + { + VerticalExpand = false, + HorizontalExpand = false, + Visible = false, + MaxSize = new Vector2(100, 30), + }; + + abortButton.OnPressed += _ => + { + SendMessage(new ContractorAbortContractMessage(key)); + topContainer.RemoveChild(abortButton); + }; + + topContainer.AddChild(abortButton); + foreach (var amountPosition in contract.AmountPositions) { + if (_contractorPdaComponent.CurrentContractEntity == key) + { + abortButton.Visible = true; + } + var positionButton = new Button { Text = $"{amountPosition.Location} ({amountPosition.TcReward} ТК) ({amountPosition.Difficulty})", @@ -242,6 +263,8 @@ private void AddContract(NetEntity key, ContractorContract contract) amountPosition.TcReward, amountPosition.Uid)); + abortButton.Visible = true; + foreach (var buttons in _allPositionButtons) { buttons.Disabled = true; diff --git a/Content.Server/SS220/Contractor/ContractorServerSystem.cs b/Content.Server/SS220/Contractor/ContractorServerSystem.cs index b81b1cd91b3aeb..08a0381172a8e8 100644 --- a/Content.Server/SS220/Contractor/ContractorServerSystem.cs +++ b/Content.Server/SS220/Contractor/ContractorServerSystem.cs @@ -47,6 +47,7 @@ public override void Initialize() SubscribeLocalEvent(OnNewContractAccepted); SubscribeLocalEvent(OnWithdrawTc); SubscribeLocalEvent(OnExecuteContract); + SubscribeLocalEvent(AbortContract); SubscribeLocalEvent(OnBuyContractorKit); } @@ -220,7 +221,7 @@ public void HandleContractAccepted(NetEntity acceptedPlayer, EntityUid contracto if (!contractorComp.Contracts.Remove(acceptedPlayer)) continue; - if (contractorComp.Contracts.Count >= 5) + if (contractorComp.Contracts.Count >= contractorComp.MaxAvailableContracts) continue; var newContract = GenerateContractForContractor((uid, contractorComp)); @@ -269,7 +270,7 @@ public void HandleContractAccepted(NetEntity acceptedPlayer, EntityUid contracto if (_roleSystem.MindHasRole(mindId)) continue; - _jobs.MindTryGetJobName(mindId, out var jobName); + _jobs.MindTryGetJobName(mindId, out var jobName); // && jobName == "JobCaptain" - disable for testing return (GetNetEntity(player), new ContractorContract @@ -310,9 +311,9 @@ public void GenerateContracts(Entity ent) if (ent.Comp.Contracts.ContainsKey(GetNetEntity(player))) continue; - _jobs.MindTryGetJobName(mindId, out var jobName); + _jobs.MindTryGetJobName(mindId, out var jobName); // && jobName == "JobCaptain" - disable for testing - if (ent.Comp.Contracts is { Count: >= 5 }) + if (ent.Comp.Contracts.Count == ent.Comp.MaxAvailableContracts) return; ent.Comp.Contracts.Add(GetNetEntity(player), @@ -383,4 +384,36 @@ private bool IsCloseWithPosition(NetEntity playerNet) return isPlayerCloseToPortal && isTargetCloseToPortal; } + + private void AbortContract(Entity ent, ref ContractorAbortContractMessage ev) + { + var pdaOwner = GetEntity(ent.Comp.PdaOwner); + + if (ev.Actor != pdaOwner) + return; + + if (!TryComp(pdaOwner, out var contractorComponent)) + return; + + if (!contractorComponent.Contracts.Remove(ev.ContractEntity)) + return; + + _adminLogger.Add( + LogType.Action, + LogImpact.High, + $"Contractor {ev.Actor} aborted unknown contract {ev.ContractEntity}"); + + contractorComponent.MaxAvailableContracts--; + contractorComponent.Reputation--; + contractorComponent.CurrentContractEntity = null; + contractorComponent.CurrentContractData = null; + + ent.Comp.CurrentContractEntity = null; + ent.Comp.CurrentContractData = null; + + _uiSystem.ServerSendUiMessage(ent.Owner, ContractorPdaKey.Key, new ContractorUpdateStatsMessage()); + + Dirty(ent); + Dirty(pdaOwner.Value, contractorComponent); + } } diff --git a/Content.Shared/SS220/Contractor/ContractorComponent.cs b/Content.Shared/SS220/Contractor/ContractorComponent.cs index 2ea9278139b349..7c0ba88bca8a1a 100644 --- a/Content.Shared/SS220/Contractor/ContractorComponent.cs +++ b/Content.Shared/SS220/Contractor/ContractorComponent.cs @@ -41,6 +41,8 @@ public sealed partial class ContractorComponent : Component public int ContractsCompleted = 0; public readonly int ReputationAward = 2; + + public int MaxAvailableContracts = 5; } [Serializable] diff --git a/Content.Shared/SS220/Contractor/ContractorMessagesUi.cs b/Content.Shared/SS220/Contractor/ContractorMessagesUi.cs index be8602cb49a673..5f7d77da373e75 100644 --- a/Content.Shared/SS220/Contractor/ContractorMessagesUi.cs +++ b/Content.Shared/SS220/Contractor/ContractorMessagesUi.cs @@ -56,6 +56,17 @@ public ContractorNewContractAcceptedMessage(NetEntity contractEntity, Contractor } } +[Serializable, NetSerializable] +public sealed class ContractorAbortContractMessage : BoundUserInterfaceMessage +{ + public NetEntity ContractEntity; + + public ContractorAbortContractMessage(NetEntity contractEntity) + { + ContractEntity = contractEntity; + } +} + [Serializable, NetSerializable] public sealed class ContractorHubBuyItemMessage : BoundUserInterfaceMessage { diff --git a/Content.Shared/SS220/Contractor/SharedContractorSystem.cs b/Content.Shared/SS220/Contractor/SharedContractorSystem.cs index 6c08de656a0ecf..17b54c6e32fb84 100644 --- a/Content.Shared/SS220/Contractor/SharedContractorSystem.cs +++ b/Content.Shared/SS220/Contractor/SharedContractorSystem.cs @@ -83,28 +83,6 @@ private void OnBuyItem(Entity ent, ref ContractorHubBuyI Dirty(ev.Actor, contractorComponent); } - - /// - /// Used in bound ui on client, to get contracts for pda - /// - /// Return dictionary of contracts - public Dictionary? GetContractsForPda(EntityUid contractor, EntityUid pdaEntity) - { - AddContractsToPda(contractor, pdaEntity); - - return !TryComp(pdaEntity, out var contractorPdaComponent) ? null : contractorPdaComponent.Contracts; - } - - private void AddContractsToPda(EntityUid contractor, EntityUid pdaEntity) - { - if (!TryComp(pdaEntity, out var contractorPdaComponent)) - return; - if (!TryComp(contractor, out var contractorComponent)) - return; - - contractorPdaComponent.Contracts = contractorComponent.Contracts; - } - } ///