From a5d19876a8b3cec3c2a7cc1b6af12563cb16e009 Mon Sep 17 00:00:00 2001 From: VMSolidus Date: Wed, 21 Aug 2024 19:02:42 -0400 Subject: [PATCH 1/4] This is gradually becoming a very monolithic Prototype --- .../Psionics/PsionicAbilitiesSystem.cs | 78 +++++++++---------- .../Psionics/PsionicPowerPrototype.cs | 34 +++++++- 2 files changed, 70 insertions(+), 42 deletions(-) diff --git a/Content.Server/Abilities/Psionics/PsionicAbilitiesSystem.cs b/Content.Server/Abilities/Psionics/PsionicAbilitiesSystem.cs index 005078242b0..732b52eb33d 100644 --- a/Content.Server/Abilities/Psionics/PsionicAbilitiesSystem.cs +++ b/Content.Server/Abilities/Psionics/PsionicAbilitiesSystem.cs @@ -1,5 +1,6 @@ using Content.Shared.Abilities.Psionics; using Content.Shared.Actions; +using Content.Shared.Chat; using Content.Shared.Popups; using Content.Shared.Psionics.Glimmer; using Content.Shared.Random; @@ -10,6 +11,8 @@ using Robust.Shared.Serialization.Manager; using Content.Shared.Psionics; using System.Linq; +using Robust.Server.Player; +using Content.Server.Chat.Managers; namespace Content.Server.Abilities.Psionics { @@ -24,6 +27,8 @@ public sealed class PsionicAbilitiesSystem : EntitySystem [Dependency] private readonly SharedActionsSystem _actions = default!; [Dependency] private readonly SharedPopupSystem _popups = default!; [Dependency] private readonly ISerializationManager _serialization = default!; + [Dependency] private readonly IPlayerManager _playerManager = default!; + [Dependency] private readonly IChatManager _chatManager = default!; private ProtoId _pool = "RandomPsionicPowerPool"; private const string GenericInitializationMessage = "generic-power-initialization-feedback"; @@ -38,9 +43,6 @@ public override void Initialize() /// /// Special use-case for a InnatePsionicPowers, which allows an entity to start with any number of Psionic Powers. /// - /// - /// - /// private void InnatePowerStartup(EntityUid uid, InnatePsionicPowersComponent comp, ComponentStartup args) { // Any entity with InnatePowers should also be psionic, but in case they aren't already... @@ -64,7 +66,6 @@ private void OnPsionicShutdown(EntityUid uid, PsionicComponent component, Compon /// The most shorthand route to creating a Psion. If an entity is not already psionic, it becomes one. This also adds a random new PsionicPower. /// To create a "Latent Psychic"(Psion with no powers) just add or ensure the PsionicComponent normally. /// - /// public void AddPsionics(EntityUid uid) { if (Deleted(uid)) @@ -77,7 +78,6 @@ public void AddPsionics(EntityUid uid) /// Pretty straightforward, adds a random psionic power to a given Entity. If that Entity is not already Psychic, it will be made one. /// If an entity already has all possible powers, this will not add any new ones. /// - /// public void AddRandomPsionicPower(EntityUid uid) { // We need to EnsureComp here to make sure that we aren't iterating over a component that: @@ -110,11 +110,7 @@ public void AddRandomPsionicPower(EntityUid uid) /// /// Initializes a new Psionic Power on a given entity, assuming the entity does not already have said power initialized. /// - /// - /// - /// - /// - public void InitializePsionicPower(EntityUid uid, PsionicPowerPrototype proto, PsionicComponent psionic, bool playPopup = true) + public void InitializePsionicPower(EntityUid uid, PsionicPowerPrototype proto, PsionicComponent psionic, bool playFeedback = true) { if (!_prototypeManager.HasIndex(proto.ID) || psionic.ActivePowers.Contains(proto)) @@ -126,31 +122,23 @@ public void InitializePsionicPower(EntityUid uid, PsionicPowerPrototype proto, P AddPsionicPowerComponents(uid, proto); AddPsionicStatSources(proto, psionic); RefreshPsionicModifiers(uid, psionic); - - if (playPopup) - _popups.PopupEntity(Loc.GetString(GenericInitializationMessage), uid, uid, PopupType.MediumCaution); - // TODO: Replace this with chat message: _popups.PopupEntity(proto.InitializationFeedback, uid, uid, PopupType.MediumCaution); + SendFeedbackMessage(uid, proto, playFeedback); + //SendFeedbackAudio(uid, proto, playPopup); // TODO: This one is coming next! } /// /// Initializes a new Psionic Power on a given entity, assuming the entity does not already have said power initialized. /// - /// - /// - /// - /// - public void InitializePsionicPower(EntityUid uid, PsionicPowerPrototype proto, bool playPopup = true) + public void InitializePsionicPower(EntityUid uid, PsionicPowerPrototype proto, bool playFeedback = true) { EnsureComp(uid, out var psionic); - InitializePsionicPower(uid, proto, psionic, playPopup); + InitializePsionicPower(uid, proto, psionic, playFeedback); } /// /// Updates a Psion's casting stats, call this anytime a system adds a new source of Amp or Damp. /// - /// - /// public void RefreshPsionicModifiers(EntityUid uid, PsionicComponent comp) { var ampModifier = 0f; @@ -173,7 +161,6 @@ public void RefreshPsionicModifiers(EntityUid uid, PsionicComponent comp) /// Updates a Psion's casting stats, call this anytime a system adds a new source of Amp or Damp. /// Variant function for systems that didn't already have the PsionicComponent. /// - /// public void RefreshPsionicModifiers(EntityUid uid) { if (!TryComp(uid, out var comp)) @@ -186,7 +173,6 @@ public void RefreshPsionicModifiers(EntityUid uid) /// A more advanced form of removing powers. Mindbreaking not only removes all psionic powers, /// it also disables the possibility of obtaining new ones. /// - /// public void MindBreak(EntityUid uid) { RemoveAllPsionicPowers(uid, true); @@ -196,8 +182,6 @@ public void MindBreak(EntityUid uid) /// Remove all Psionic powers, with accompanying actions, components, and casting stat sources, from a given Psion. /// Optionally, the Psion can also be rendered permanently non-Psionic. /// - /// - /// public void RemoveAllPsionicPowers(EntityUid uid, bool mindbreak = false) { if (!TryComp(uid, out var psionic) @@ -239,9 +223,6 @@ public void RemoveAllPsionicPowers(EntityUid uid, bool mindbreak = false) /// /// Add all actions associated with a specific Psionic Power /// - /// - /// - /// private void AddPsionicActions(EntityUid uid, PsionicPowerPrototype proto, PsionicComponent psionic) { foreach (var id in proto.Actions) @@ -258,8 +239,6 @@ private void AddPsionicActions(EntityUid uid, PsionicPowerPrototype proto, Psion /// /// Add all components associated with a specific Psionic power. /// - /// - /// private void AddPsionicPowerComponents(EntityUid uid, PsionicPowerPrototype proto) { if (proto.Components is null) @@ -279,8 +258,6 @@ private void AddPsionicPowerComponents(EntityUid uid, PsionicPowerPrototype prot /// /// Update the Amplification and Dampening sources of a Psion to include a new Power. /// - /// - /// private void AddPsionicStatSources(PsionicPowerPrototype proto, PsionicComponent psionic) { if (proto.AmplificationModifier != 0) @@ -290,11 +267,38 @@ private void AddPsionicStatSources(PsionicPowerPrototype proto, PsionicComponent psionic.DampeningSources.Add(proto.Name, proto.DampeningModifier); } + /// + /// Displays a message to alert the player when they have obtained a new psionic power. These generally will not play for Innate powers. + /// Chat messages of this nature should be written in the first-person. + /// Popup feedback should be no more than a sentence, while the full Initialization Feedback can be as much as a paragraph of text. + /// + private void SendFeedbackMessage(EntityUid uid, PsionicPowerPrototype proto, bool playFeedback = true) + { + if (!playFeedback + || !_playerManager.TryGetSessionByEntity(uid, out var session) + || session is null) + return; + + if (proto.InitializationPopup is null) + _popups.PopupEntity(Loc.GetString(GenericInitializationMessage), uid, uid, PopupType.MediumCaution); + else _popups.PopupEntity(Loc.GetString(proto.InitializationPopup), uid, uid, PopupType.MediumCaution); + + if (proto.InitializationFeedback is null) + return; + + var feedbackMessage = $"[font size={proto.InitializationFeedbackFontSize}][color={proto.InitializationFeedbackColor}]{proto.InitializationFeedback}[/color][/font]"; + _chatManager.ChatMessageToOne( + proto.InitializationFeedbackChannel, + feedbackMessage, + feedbackMessage, + EntityUid.Invalid, + false, + session.Channel); + } + /// /// Remove all Psychic Actions listed in an entity's Psionic Component. Unfortunately, removing actions associated with a specific Power Prototype is not supported. /// - /// - /// private void RemovePsionicActions(EntityUid uid, PsionicComponent psionic) { if (psionic.Actions is null) @@ -307,8 +311,6 @@ private void RemovePsionicActions(EntityUid uid, PsionicComponent psionic) /// /// Remove all Components associated with a specific Psionic Power. /// - /// - /// private void RemovePsionicPowerComponents(EntityUid uid, PsionicPowerPrototype proto) { if (proto.Components is null) @@ -327,8 +329,6 @@ private void RemovePsionicPowerComponents(EntityUid uid, PsionicPowerPrototype p /// /// Remove all stat sources associated with a specific Psionic Power. /// - /// - /// private void RemovePsionicStatSources(EntityUid uid, PsionicPowerPrototype proto, PsionicComponent psionic) { if (proto.AmplificationModifier != 0) diff --git a/Content.Shared/Psionics/PsionicPowerPrototype.cs b/Content.Shared/Psionics/PsionicPowerPrototype.cs index 621a3ceb114..3d389f6cdbe 100644 --- a/Content.Shared/Psionics/PsionicPowerPrototype.cs +++ b/Content.Shared/Psionics/PsionicPowerPrototype.cs @@ -1,3 +1,4 @@ +using Content.Shared.Chat; using Robust.Shared.Prototypes; namespace Content.Shared.Psionics; @@ -36,10 +37,37 @@ public sealed partial class PsionicPowerPrototype : IPrototype public ComponentRegistry Components = new(); /// - /// What message will play as a popup when the power is initialized. + /// What message will be sent to the player as a Popup. + /// If left blank, it will default to the Const "generic-power-initialization-feedback" /// - [DataField(required: true)] - public string InitializationFeedback = "psionic-power-initialization-default"; + [DataField] + public string? InitializationPopup; + + /// + /// What message will be sent to the chat window when the power is initialized. Leave it blank to send no message. + /// Initialization messages won't play for powers that are Innate, only powers obtained during the round. + /// These should generally also be written in the first person, and can be far lengthier than popups. + /// + [DataField] + public string? InitializationFeedback; + + /// + /// What color will the initialization feedback display in the chat window with. + /// + [DataField] + public string InitializationFeedbackColor = "#8A00C2"; + + /// + /// What font size will the initialization message use in chat. + /// + [DataField] + public int InitializationFeedbackFontSize = 12; + + /// + /// Which chat channel will the initialization message use. + /// + [DataField] + public ChatChannel InitializationFeedbackChannel = ChatChannel.Emotes; /// /// What message will this power generate when scanned by a Metempsionic Focused Pulse. From 7f6a7dc570fe63fa6ce9e99d76afe7c8c822c17f Mon Sep 17 00:00:00 2001 From: VMSolidus Date: Wed, 21 Aug 2024 19:24:56 -0400 Subject: [PATCH 2/4] Update PsionicAbilitiesSystem.cs --- Content.Server/Abilities/Psionics/PsionicAbilitiesSystem.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Content.Server/Abilities/Psionics/PsionicAbilitiesSystem.cs b/Content.Server/Abilities/Psionics/PsionicAbilitiesSystem.cs index 732b52eb33d..ecf326cb292 100644 --- a/Content.Server/Abilities/Psionics/PsionicAbilitiesSystem.cs +++ b/Content.Server/Abilities/Psionics/PsionicAbilitiesSystem.cs @@ -1,6 +1,5 @@ using Content.Shared.Abilities.Psionics; using Content.Shared.Actions; -using Content.Shared.Chat; using Content.Shared.Popups; using Content.Shared.Psionics.Glimmer; using Content.Shared.Random; @@ -95,7 +94,7 @@ public void AddRandomPsionicPower(EntityUid uid) _prototypeManager.TryIndex(s, out var p) && psionic.ActivePowers.Contains(p)); - if (newPool is null) + if (newPool.Count == 0) return; var newProto = _random.Pick(newPool); @@ -286,7 +285,7 @@ private void SendFeedbackMessage(EntityUid uid, PsionicPowerPrototype proto, boo if (proto.InitializationFeedback is null) return; - var feedbackMessage = $"[font size={proto.InitializationFeedbackFontSize}][color={proto.InitializationFeedbackColor}]{proto.InitializationFeedback}[/color][/font]"; + var feedbackMessage = Loc.GetString($"[font size={proto.InitializationFeedbackFontSize}][color={proto.InitializationFeedbackColor}]{proto.InitializationFeedback}[/color][/font]"); _chatManager.ChatMessageToOne( proto.InitializationFeedbackChannel, feedbackMessage, From c23b87b0c0fe8a8e91742622b31c986dbb6b6514 Mon Sep 17 00:00:00 2001 From: VMSolidus Date: Wed, 21 Aug 2024 19:35:51 -0400 Subject: [PATCH 3/4] fix localizations --- Content.Server/Abilities/Psionics/PsionicAbilitiesSystem.cs | 2 +- Resources/Prototypes/Psionics/psionics.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Content.Server/Abilities/Psionics/PsionicAbilitiesSystem.cs b/Content.Server/Abilities/Psionics/PsionicAbilitiesSystem.cs index ecf326cb292..f2d5c3660ee 100644 --- a/Content.Server/Abilities/Psionics/PsionicAbilitiesSystem.cs +++ b/Content.Server/Abilities/Psionics/PsionicAbilitiesSystem.cs @@ -285,7 +285,7 @@ private void SendFeedbackMessage(EntityUid uid, PsionicPowerPrototype proto, boo if (proto.InitializationFeedback is null) return; - var feedbackMessage = Loc.GetString($"[font size={proto.InitializationFeedbackFontSize}][color={proto.InitializationFeedbackColor}]{proto.InitializationFeedback}[/color][/font]"); + var feedbackMessage = $"[font size={proto.InitializationFeedbackFontSize}][color={proto.InitializationFeedbackColor}]{Loc.GetString(proto.InitializationFeedback)}[/color][/font]"; _chatManager.ChatMessageToOne( proto.InitializationFeedbackChannel, feedbackMessage, diff --git a/Resources/Prototypes/Psionics/psionics.yml b/Resources/Prototypes/Psionics/psionics.yml index d4ae73669f9..dc43e6128e3 100644 --- a/Resources/Prototypes/Psionics/psionics.yml +++ b/Resources/Prototypes/Psionics/psionics.yml @@ -18,7 +18,7 @@ - ActionMassSleep components: - type: MassSleepPower - initializationFeedback: mass-sleep-power-initialization-feedback + # initializationFeedback: mass-sleep-power-initialization-feedback # I apologize, I don't feel like writing a paragraph of feedback for a power that's getting replaced with a new one. metapsionicFeedback: mass-sleep-power-metapsionic-feedback amplificationModifier: 0.5 dampeningModifier: 0.5 From 67c1443ca54b5e12176cf4869a5886f53cc23ef9 Mon Sep 17 00:00:00 2001 From: VMSolidus Date: Thu, 22 Aug 2024 12:34:23 -0400 Subject: [PATCH 4/4] Update Content.Server/Abilities/Psionics/PsionicAbilitiesSystem.cs Co-authored-by: Mnemotechnican <69920617+Mnemotechnician@users.noreply.github.com> Signed-off-by: VMSolidus --- Content.Server/Abilities/Psionics/PsionicAbilitiesSystem.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Content.Server/Abilities/Psionics/PsionicAbilitiesSystem.cs b/Content.Server/Abilities/Psionics/PsionicAbilitiesSystem.cs index f2d5c3660ee..1ac5db70151 100644 --- a/Content.Server/Abilities/Psionics/PsionicAbilitiesSystem.cs +++ b/Content.Server/Abilities/Psionics/PsionicAbilitiesSystem.cs @@ -285,7 +285,9 @@ private void SendFeedbackMessage(EntityUid uid, PsionicPowerPrototype proto, boo if (proto.InitializationFeedback is null) return; - var feedbackMessage = $"[font size={proto.InitializationFeedbackFontSize}][color={proto.InitializationFeedbackColor}]{Loc.GetString(proto.InitializationFeedback)}[/color][/font]"; + if (!Loc.TryGetString(proto.InitializationFeedback, out var feedback)) + return; + var feedbackMessage = $"[font size={proto.InitializationFeedbackFontSize}][color={proto.InitializationFeedbackColor}]{feedback}[/color][/font]"; _chatManager.ChatMessageToOne( proto.InitializationFeedbackChannel, feedbackMessage,