Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Psionic Power Feedback Messages #776

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 41 additions & 40 deletions Content.Server/Abilities/Psionics/PsionicAbilitiesSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,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
{
Expand All @@ -24,6 +26,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<WeightedRandomPrototype> _pool = "RandomPsionicPowerPool";
private const string GenericInitializationMessage = "generic-power-initialization-feedback";
Expand All @@ -38,9 +42,6 @@ public override void Initialize()
/// <summary>
/// Special use-case for a InnatePsionicPowers, which allows an entity to start with any number of Psionic Powers.
/// </summary>
/// <param name="uid"></param>
/// <param name="comp"></param>
/// <param name="args"></param>
private void InnatePowerStartup(EntityUid uid, InnatePsionicPowersComponent comp, ComponentStartup args)
{
// Any entity with InnatePowers should also be psionic, but in case they aren't already...
Expand All @@ -64,7 +65,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.
/// </summary>
/// <param name="uid"></param>
public void AddPsionics(EntityUid uid)
{
if (Deleted(uid))
Expand All @@ -77,7 +77,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.
/// </summary>
/// <param name="uid"></param>
public void AddRandomPsionicPower(EntityUid uid)
{
// We need to EnsureComp here to make sure that we aren't iterating over a component that:
Expand All @@ -95,7 +94,7 @@ public void AddRandomPsionicPower(EntityUid uid)
_prototypeManager.TryIndex<PsionicPowerPrototype>(s, out var p) &&
psionic.ActivePowers.Contains(p));

if (newPool is null)
if (newPool.Count == 0)
return;

var newProto = _random.Pick(newPool);
Expand All @@ -110,11 +109,7 @@ public void AddRandomPsionicPower(EntityUid uid)
/// <summary>
/// Initializes a new Psionic Power on a given entity, assuming the entity does not already have said power initialized.
/// </summary>
/// <param name="uid"></param>
/// <param name="proto"></param>
/// <param name="psionic"></param>
/// <param name="playPopup"></param>
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<PsionicPowerPrototype>(proto.ID)
|| psionic.ActivePowers.Contains(proto))
Expand All @@ -126,31 +121,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!
}

/// <summary>
/// Initializes a new Psionic Power on a given entity, assuming the entity does not already have said power initialized.
/// </summary>
/// <param name="uid"></param>
/// <param name="proto"></param>
/// <param name="psionic"></param>
/// <param name="playPopup"></param>
public void InitializePsionicPower(EntityUid uid, PsionicPowerPrototype proto, bool playPopup = true)
public void InitializePsionicPower(EntityUid uid, PsionicPowerPrototype proto, bool playFeedback = true)
{
EnsureComp<PsionicComponent>(uid, out var psionic);

InitializePsionicPower(uid, proto, psionic, playPopup);
InitializePsionicPower(uid, proto, psionic, playFeedback);
}

/// <summary>
/// Updates a Psion's casting stats, call this anytime a system adds a new source of Amp or Damp.
/// </summary>
/// <param name="uid"></param>
/// <param name="comp"></param>
public void RefreshPsionicModifiers(EntityUid uid, PsionicComponent comp)
{
var ampModifier = 0f;
Expand All @@ -173,7 +160,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.
/// </summary>
/// <param name="uid"></param>
public void RefreshPsionicModifiers(EntityUid uid)
{
if (!TryComp<PsionicComponent>(uid, out var comp))
Expand All @@ -186,7 +172,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.
/// </summary>
/// <param name="uid"></param>
public void MindBreak(EntityUid uid)
{
RemoveAllPsionicPowers(uid, true);
Expand All @@ -196,8 +181,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.
/// </summary>
/// <param name="uid"></param>
/// <param name="mindbreak"></param>
public void RemoveAllPsionicPowers(EntityUid uid, bool mindbreak = false)
{
if (!TryComp<PsionicComponent>(uid, out var psionic)
Expand Down Expand Up @@ -239,9 +222,6 @@ public void RemoveAllPsionicPowers(EntityUid uid, bool mindbreak = false)
/// <summary>
/// Add all actions associated with a specific Psionic Power
/// </summary>
/// <param name="uid"></param>
/// <param name="proto"></param>
/// <param name="psionic"></param>
private void AddPsionicActions(EntityUid uid, PsionicPowerPrototype proto, PsionicComponent psionic)
{
foreach (var id in proto.Actions)
Expand All @@ -258,8 +238,6 @@ private void AddPsionicActions(EntityUid uid, PsionicPowerPrototype proto, Psion
/// <summary>
/// Add all components associated with a specific Psionic power.
/// </summary>
/// <param name="uid"></param>
/// <param name="proto"></param>
private void AddPsionicPowerComponents(EntityUid uid, PsionicPowerPrototype proto)
{
if (proto.Components is null)
Expand All @@ -279,8 +257,6 @@ private void AddPsionicPowerComponents(EntityUid uid, PsionicPowerPrototype prot
/// <summary>
/// Update the Amplification and Dampening sources of a Psion to include a new Power.
/// </summary>
/// <param name="proto"></param>
/// <param name="psionic"></param>
private void AddPsionicStatSources(PsionicPowerPrototype proto, PsionicComponent psionic)
{
if (proto.AmplificationModifier != 0)
Expand All @@ -290,11 +266,40 @@ private void AddPsionicStatSources(PsionicPowerPrototype proto, PsionicComponent
psionic.DampeningSources.Add(proto.Name, proto.DampeningModifier);
}

/// <summary>
/// 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.
/// </summary>
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;

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,
feedbackMessage,
EntityUid.Invalid,
false,
session.Channel);
}

/// <summary>
/// Remove all Psychic Actions listed in an entity's Psionic Component. Unfortunately, removing actions associated with a specific Power Prototype is not supported.
/// </summary>
/// <param name="uid"></param>
/// <param name="psionic"></param>
private void RemovePsionicActions(EntityUid uid, PsionicComponent psionic)
{
if (psionic.Actions is null)
Expand All @@ -307,8 +312,6 @@ private void RemovePsionicActions(EntityUid uid, PsionicComponent psionic)
/// <summary>
/// Remove all Components associated with a specific Psionic Power.
/// </summary>
/// <param name="uid"></param>
/// <param name="proto"></param>
private void RemovePsionicPowerComponents(EntityUid uid, PsionicPowerPrototype proto)
{
if (proto.Components is null)
Expand All @@ -327,8 +330,6 @@ private void RemovePsionicPowerComponents(EntityUid uid, PsionicPowerPrototype p
/// <summary>
/// Remove all stat sources associated with a specific Psionic Power.
/// </summary>
/// <param name="proto"></param>
/// <param name="psionic"></param>
private void RemovePsionicStatSources(EntityUid uid, PsionicPowerPrototype proto, PsionicComponent psionic)
{
if (proto.AmplificationModifier != 0)
Expand Down
34 changes: 31 additions & 3 deletions Content.Shared/Psionics/PsionicPowerPrototype.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using Content.Shared.Chat;
using Robust.Shared.Prototypes;

namespace Content.Shared.Psionics;
Expand Down Expand Up @@ -36,10 +37,37 @@ public sealed partial class PsionicPowerPrototype : IPrototype
public ComponentRegistry Components = new();

/// <summary>
/// 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"
/// </summary>
[DataField(required: true)]
public string InitializationFeedback = "psionic-power-initialization-default";
[DataField]
public string? InitializationPopup;

/// <summary>
/// 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.
/// </summary>
[DataField]
public string? InitializationFeedback;

/// <summary>
/// What color will the initialization feedback display in the chat window with.
/// </summary>
[DataField]
public string InitializationFeedbackColor = "#8A00C2";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make this something that contrasts better with chat

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

I'll take it one more step up the chain. That should be good. :)


/// <summary>
/// What font size will the initialization message use in chat.
/// </summary>
[DataField]
public int InitializationFeedbackFontSize = 12;

/// <summary>
/// Which chat channel will the initialization message use.
/// </summary>
[DataField]
public ChatChannel InitializationFeedbackChannel = ChatChannel.Emotes;

/// <summary>
/// What message will this power generate when scanned by a Metempsionic Focused Pulse.
Expand Down
2 changes: 1 addition & 1 deletion Resources/Prototypes/Psionics/psionics.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading