Cleanup TipsSystem, add TippyOnTrigger (#41477)
* tippy on trigger and refactor * optional parameter for command
This commit is contained in:
5
Content.Client/Tips/TipsSystem.cs
Normal file
5
Content.Client/Tips/TipsSystem.cs
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
using Content.Shared.Tips;
|
||||||
|
|
||||||
|
namespace Content.Client.Tips;
|
||||||
|
|
||||||
|
public sealed class TipsSystem : SharedTipsSystem;
|
||||||
103
Content.Server/Administration/Commands/TippyCommand.cs
Normal file
103
Content.Server/Administration/Commands/TippyCommand.cs
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
using Content.Shared.Administration;
|
||||||
|
using Content.Shared.Tips;
|
||||||
|
using Robust.Server.Player;
|
||||||
|
using Robust.Shared.Console;
|
||||||
|
using Robust.Shared.Player;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
|
namespace Content.Server.Administration.Commands;
|
||||||
|
|
||||||
|
[AdminCommand(AdminFlags.Fun)]
|
||||||
|
public sealed class TippyCommand : LocalizedEntityCommands
|
||||||
|
{
|
||||||
|
[Dependency] private readonly SharedTipsSystem _tips = default!;
|
||||||
|
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
||||||
|
[Dependency] private readonly IPlayerManager _player = default!;
|
||||||
|
|
||||||
|
public override string Command => "tippy";
|
||||||
|
|
||||||
|
public override void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||||
|
{
|
||||||
|
if (args.Length < 2)
|
||||||
|
{
|
||||||
|
shell.WriteLine(Loc.GetString("cmd-tippy-help"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ICommonSession? targetSession = null;
|
||||||
|
if (args[0] != "all")
|
||||||
|
{
|
||||||
|
if (!_player.TryGetSessionByUsername(args[0], out targetSession))
|
||||||
|
{
|
||||||
|
shell.WriteLine(Loc.GetString("cmd-tippy-error-no-user"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var msg = args[1];
|
||||||
|
|
||||||
|
EntProtoId? prototype = null;
|
||||||
|
if (args.Length > 2)
|
||||||
|
{
|
||||||
|
if (args[2] == "null")
|
||||||
|
prototype = null;
|
||||||
|
else if (!_prototype.HasIndex<EntityPrototype>(args[2]))
|
||||||
|
{
|
||||||
|
shell.WriteError(Loc.GetString("cmd-tippy-error-no-prototype", ("proto", args[2])));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
prototype = args[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
var speakTime = _tips.GetSpeechTime(msg);
|
||||||
|
var slideTime = 3f;
|
||||||
|
var waddleInterval = 0.5f;
|
||||||
|
|
||||||
|
if (args.Length > 3 && float.TryParse(args[3], out var parsedSpeakTime))
|
||||||
|
speakTime = parsedSpeakTime;
|
||||||
|
|
||||||
|
if (args.Length > 4 && float.TryParse(args[4], out var parsedSlideTime))
|
||||||
|
slideTime = parsedSlideTime;
|
||||||
|
|
||||||
|
if (args.Length > 5 && float.TryParse(args[5], out var parsedWaddleInterval))
|
||||||
|
waddleInterval = parsedWaddleInterval;
|
||||||
|
|
||||||
|
if (targetSession != null) // send to specified player
|
||||||
|
_tips.SendTippy(targetSession, msg, prototype, speakTime, slideTime, waddleInterval);
|
||||||
|
else // send to everyone
|
||||||
|
_tips.SendTippy(msg, prototype, speakTime, slideTime, waddleInterval);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override CompletionResult GetCompletion(IConsoleShell shell, string[] args)
|
||||||
|
{
|
||||||
|
return args.Length switch
|
||||||
|
{
|
||||||
|
1 => CompletionResult.FromHintOptions(
|
||||||
|
CompletionHelper.SessionNames(players: _player),
|
||||||
|
Loc.GetString("cmd-tippy-auto-1")),
|
||||||
|
2 => CompletionResult.FromHint(Loc.GetString("cmd-tippy-auto-2")),
|
||||||
|
3 => CompletionResult.FromHintOptions(
|
||||||
|
CompletionHelper.PrototypeIdsLimited<EntityPrototype>(args[2], _prototype),
|
||||||
|
Loc.GetString("cmd-tippy-auto-3")),
|
||||||
|
4 => CompletionResult.FromHint(Loc.GetString("cmd-tippy-auto-4")),
|
||||||
|
5 => CompletionResult.FromHint(Loc.GetString("cmd-tippy-auto-5")),
|
||||||
|
6 => CompletionResult.FromHint(Loc.GetString("cmd-tippy-auto-6")),
|
||||||
|
_ => CompletionResult.Empty
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[AdminCommand(AdminFlags.Fun)]
|
||||||
|
public sealed class TipCommand : LocalizedEntityCommands
|
||||||
|
{
|
||||||
|
[Dependency] private readonly SharedTipsSystem _tips = default!;
|
||||||
|
|
||||||
|
public override string Command => "tip";
|
||||||
|
|
||||||
|
public override void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||||
|
{
|
||||||
|
_tips.AnnounceRandomTip();
|
||||||
|
_tips.RecalculateNextTipTime();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,10 +4,7 @@ using Content.Shared.CCVar;
|
|||||||
using Content.Shared.Chat;
|
using Content.Shared.Chat;
|
||||||
using Content.Shared.Dataset;
|
using Content.Shared.Dataset;
|
||||||
using Content.Shared.Tips;
|
using Content.Shared.Tips;
|
||||||
using Robust.Server.GameObjects;
|
|
||||||
using Robust.Server.Player;
|
|
||||||
using Robust.Shared.Configuration;
|
using Robust.Shared.Configuration;
|
||||||
using Robust.Shared.Console;
|
|
||||||
using Robust.Shared.Player;
|
using Robust.Shared.Player;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Random;
|
using Robust.Shared.Random;
|
||||||
@@ -15,10 +12,7 @@ using Robust.Shared.Timing;
|
|||||||
|
|
||||||
namespace Content.Server.Tips;
|
namespace Content.Server.Tips;
|
||||||
|
|
||||||
/// <summary>
|
public sealed class TipsSystem : SharedTipsSystem
|
||||||
/// Handles periodically displaying gameplay tips to all players ingame.
|
|
||||||
/// </summary>
|
|
||||||
public sealed class TipsSystem : EntitySystem
|
|
||||||
{
|
{
|
||||||
[Dependency] private readonly IChatManager _chat = default!;
|
[Dependency] private readonly IChatManager _chat = default!;
|
||||||
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
||||||
@@ -26,8 +20,6 @@ public sealed class TipsSystem : EntitySystem
|
|||||||
[Dependency] private readonly IGameTiming _timing = default!;
|
[Dependency] private readonly IGameTiming _timing = default!;
|
||||||
[Dependency] private readonly IRobustRandom _random = default!;
|
[Dependency] private readonly IRobustRandom _random = default!;
|
||||||
[Dependency] private readonly GameTicker _ticker = default!;
|
[Dependency] private readonly GameTicker _ticker = default!;
|
||||||
[Dependency] private readonly IConsoleHost _conHost = default!;
|
|
||||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
|
||||||
|
|
||||||
private bool _tipsEnabled;
|
private bool _tipsEnabled;
|
||||||
private float _tipTimeOutOfRound;
|
private float _tipTimeOutOfRound;
|
||||||
@@ -35,16 +27,6 @@ public sealed class TipsSystem : EntitySystem
|
|||||||
private string _tipsDataset = "";
|
private string _tipsDataset = "";
|
||||||
private float _tipTippyChance;
|
private float _tipTippyChance;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Always adds this time to a speech message. This is so really short message stay around for a bit.
|
|
||||||
/// </summary>
|
|
||||||
private const float SpeechBuffer = 3f;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Expected reading speed.
|
|
||||||
/// </summary>
|
|
||||||
private const float Wpm = 180f;
|
|
||||||
|
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
private TimeSpan _nextTipTime = TimeSpan.Zero;
|
private TimeSpan _nextTipTime = TimeSpan.Zero;
|
||||||
|
|
||||||
@@ -53,110 +35,45 @@ public sealed class TipsSystem : EntitySystem
|
|||||||
base.Initialize();
|
base.Initialize();
|
||||||
|
|
||||||
SubscribeLocalEvent<GameRunLevelChangedEvent>(OnGameRunLevelChanged);
|
SubscribeLocalEvent<GameRunLevelChangedEvent>(OnGameRunLevelChanged);
|
||||||
Subs.CVar(_cfg, CCVars.TipFrequencyOutOfRound, SetOutOfRound, true);
|
|
||||||
Subs.CVar(_cfg, CCVars.TipFrequencyInRound, SetInRound, true);
|
|
||||||
Subs.CVar(_cfg, CCVars.TipsEnabled, SetEnabled, true);
|
Subs.CVar(_cfg, CCVars.TipsEnabled, SetEnabled, true);
|
||||||
Subs.CVar(_cfg, CCVars.TipsDataset, SetDataset, true);
|
Subs.CVar(_cfg, CCVars.TipFrequencyOutOfRound, value => _tipTimeOutOfRound = value, true);
|
||||||
Subs.CVar(_cfg, CCVars.TipsTippyChance, SetTippyChance, true);
|
Subs.CVar(_cfg, CCVars.TipFrequencyInRound, value => _tipTimeInRound = value, true);
|
||||||
|
Subs.CVar(_cfg, CCVars.TipsDataset, value => _tipsDataset = value, true);
|
||||||
|
Subs.CVar(_cfg, CCVars.TipsTippyChance, value => _tipTippyChance = value, true);
|
||||||
|
|
||||||
RecalculateNextTipTime();
|
RecalculateNextTipTime();
|
||||||
_conHost.RegisterCommand("tippy", Loc.GetString("cmd-tippy-desc"), Loc.GetString("cmd-tippy-help"), SendTippy, SendTippyHelper);
|
|
||||||
_conHost.RegisterCommand("tip", Loc.GetString("cmd-tip-desc"), "tip", SendTip);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private CompletionResult SendTippyHelper(IConsoleShell shell, string[] args)
|
private void OnGameRunLevelChanged(GameRunLevelChangedEvent ev)
|
||||||
{
|
{
|
||||||
return args.Length switch
|
// reset for lobby -> inround
|
||||||
|
// reset for inround -> post but not post -> lobby
|
||||||
|
if (ev.New == GameRunLevel.InRound || ev.Old == GameRunLevel.InRound)
|
||||||
{
|
{
|
||||||
1 => CompletionResult.FromHintOptions(
|
RecalculateNextTipTime();
|
||||||
CompletionHelper.SessionNames(players: _playerManager),
|
}
|
||||||
Loc.GetString("cmd-tippy-auto-1")),
|
|
||||||
2 => CompletionResult.FromHint(Loc.GetString("cmd-tippy-auto-2")),
|
|
||||||
3 => CompletionResult.FromHintOptions(
|
|
||||||
CompletionHelper.PrototypeIdsLimited<EntityPrototype>(args[2], _prototype),
|
|
||||||
Loc.GetString("cmd-tippy-auto-3")),
|
|
||||||
4 => CompletionResult.FromHint(Loc.GetString("cmd-tippy-auto-4")),
|
|
||||||
5 => CompletionResult.FromHint(Loc.GetString("cmd-tippy-auto-5")),
|
|
||||||
6 => CompletionResult.FromHint(Loc.GetString("cmd-tippy-auto-6")),
|
|
||||||
_ => CompletionResult.Empty
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SendTip(IConsoleShell shell, string argstr, string[] args)
|
private void SetEnabled(bool value)
|
||||||
{
|
{
|
||||||
AnnounceRandomTip();
|
_tipsEnabled = value;
|
||||||
|
|
||||||
|
if (_nextTipTime != TimeSpan.Zero)
|
||||||
RecalculateNextTipTime();
|
RecalculateNextTipTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SendTippy(IConsoleShell shell, string argstr, string[] args)
|
public override void RecalculateNextTipTime()
|
||||||
{
|
{
|
||||||
if (args.Length < 2)
|
if (_ticker.RunLevel == GameRunLevel.InRound)
|
||||||
{
|
{
|
||||||
shell.WriteLine(Loc.GetString("cmd-tippy-help"));
|
_nextTipTime = _timing.CurTime + TimeSpan.FromSeconds(_tipTimeInRound);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ActorComponent? actor = null;
|
|
||||||
if (args[0] != "all")
|
|
||||||
{
|
|
||||||
ICommonSession? session;
|
|
||||||
if (args.Length > 0)
|
|
||||||
{
|
|
||||||
// Get player entity
|
|
||||||
if (!_playerManager.TryGetSessionByUsername(args[0], out session))
|
|
||||||
{
|
|
||||||
shell.WriteLine(Loc.GetString("cmd-tippy-error-no-user"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
session = shell.Player;
|
_nextTipTime = _timing.CurTime + TimeSpan.FromSeconds(_tipTimeOutOfRound);
|
||||||
}
|
|
||||||
|
|
||||||
if (session?.AttachedEntity is not { } user)
|
|
||||||
{
|
|
||||||
shell.WriteLine(Loc.GetString("cmd-tippy-error-no-user"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!TryComp(user, out actor))
|
|
||||||
{
|
|
||||||
shell.WriteError(Loc.GetString("cmd-tippy-error-no-user"));
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var ev = new TippyEvent(args[1]);
|
|
||||||
|
|
||||||
if (args.Length > 2)
|
|
||||||
{
|
|
||||||
ev.Proto = args[2];
|
|
||||||
if (!_prototype.HasIndex<EntityPrototype>(args[2]))
|
|
||||||
{
|
|
||||||
shell.WriteError(Loc.GetString("cmd-tippy-error-no-prototype", ("proto", args[2])));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args.Length > 3)
|
|
||||||
ev.SpeakTime = float.Parse(args[3]);
|
|
||||||
else
|
|
||||||
ev.SpeakTime = GetSpeechTime(ev.Msg);
|
|
||||||
|
|
||||||
if (args.Length > 4)
|
|
||||||
ev.SlideTime = float.Parse(args[4]);
|
|
||||||
|
|
||||||
if (args.Length > 5)
|
|
||||||
ev.WaddleInterval = float.Parse(args[5]);
|
|
||||||
|
|
||||||
if (actor != null)
|
|
||||||
RaiseNetworkEvent(ev, actor.PlayerSession);
|
|
||||||
else
|
|
||||||
RaiseNetworkEvent(ev);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public override void Update(float frameTime)
|
public override void Update(float frameTime)
|
||||||
{
|
{
|
||||||
base.Update(frameTime);
|
base.Update(frameTime);
|
||||||
@@ -171,41 +88,30 @@ public sealed class TipsSystem : EntitySystem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetOutOfRound(float value)
|
public override void SendTippy(
|
||||||
|
string message,
|
||||||
|
EntProtoId? prototype = null,
|
||||||
|
float speakTime = 5f,
|
||||||
|
float slideTime = 3f,
|
||||||
|
float waddleInterval = 0.5f)
|
||||||
{
|
{
|
||||||
_tipTimeOutOfRound = value;
|
var ev = new TippyEvent(message, prototype, speakTime, slideTime, waddleInterval);
|
||||||
|
RaiseNetworkEvent(ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetInRound(float value)
|
public override void SendTippy(
|
||||||
|
ICommonSession session,
|
||||||
|
string message,
|
||||||
|
EntProtoId? prototype = null,
|
||||||
|
float speakTime = 5f,
|
||||||
|
float slideTime = 3f,
|
||||||
|
float waddleInterval = 0.5f)
|
||||||
{
|
{
|
||||||
_tipTimeInRound = value;
|
var ev = new TippyEvent(message, prototype, speakTime, slideTime, waddleInterval);
|
||||||
|
RaiseNetworkEvent(ev, session);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetEnabled(bool value)
|
public override void AnnounceRandomTip()
|
||||||
{
|
|
||||||
_tipsEnabled = value;
|
|
||||||
|
|
||||||
if (_nextTipTime != TimeSpan.Zero)
|
|
||||||
RecalculateNextTipTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetDataset(string value)
|
|
||||||
{
|
|
||||||
_tipsDataset = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetTippyChance(float value)
|
|
||||||
{
|
|
||||||
_tipTippyChance = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static float GetSpeechTime(string text)
|
|
||||||
{
|
|
||||||
var wordCount = (float)text.Split().Length;
|
|
||||||
return SpeechBuffer + wordCount * (60f / Wpm);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AnnounceRandomTip()
|
|
||||||
{
|
{
|
||||||
if (!_prototype.TryIndex<LocalizedDatasetPrototype>(_tipsDataset, out var tips))
|
if (!_prototype.TryIndex<LocalizedDatasetPrototype>(_tipsDataset, out var tips))
|
||||||
return;
|
return;
|
||||||
@@ -215,35 +121,20 @@ public sealed class TipsSystem : EntitySystem
|
|||||||
|
|
||||||
if (_random.Prob(_tipTippyChance))
|
if (_random.Prob(_tipTippyChance))
|
||||||
{
|
{
|
||||||
var ev = new TippyEvent(msg);
|
var speakTime = GetSpeechTime(msg);
|
||||||
ev.SpeakTime = GetSpeechTime(msg);
|
SendTippy(msg, speakTime: speakTime);
|
||||||
RaiseNetworkEvent(ev);
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
_chat.ChatMessageToManyFiltered(Filter.Broadcast(), ChatChannel.OOC, tip, msg,
|
|
||||||
EntityUid.Invalid, false, false, Color.MediumPurple);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void RecalculateNextTipTime()
|
|
||||||
{
|
|
||||||
if (_ticker.RunLevel == GameRunLevel.InRound)
|
|
||||||
{
|
|
||||||
_nextTipTime = _timing.CurTime + TimeSpan.FromSeconds(_tipTimeInRound);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_nextTipTime = _timing.CurTime + TimeSpan.FromSeconds(_tipTimeOutOfRound);
|
_chat.ChatMessageToManyFiltered(
|
||||||
}
|
Filter.Broadcast(),
|
||||||
}
|
ChatChannel.OOC,
|
||||||
|
tip,
|
||||||
private void OnGameRunLevelChanged(GameRunLevelChangedEvent ev)
|
msg,
|
||||||
{
|
EntityUid.Invalid,
|
||||||
// reset for lobby -> inround
|
false,
|
||||||
// reset for inround -> post but not post -> lobby
|
false,
|
||||||
if (ev.New == GameRunLevel.InRound || ev.Old == GameRunLevel.InRound)
|
Color.MediumPurple);
|
||||||
{
|
|
||||||
RecalculateNextTipTime();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
74
Content.Shared/Tips/SharedTipsSystem.cs
Normal file
74
Content.Shared/Tips/SharedTipsSystem.cs
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
using Content.Shared.CCVar;
|
||||||
|
using Robust.Shared.Player;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
|
namespace Content.Shared.Tips;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handles periodically displaying gameplay tips to all players ingame.
|
||||||
|
/// </summary>
|
||||||
|
public abstract class SharedTipsSystem : EntitySystem
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Always adds this time to a speech message. This is so really short message stay around for a bit.
|
||||||
|
/// </summary>
|
||||||
|
private const float SpeechBuffer = 3f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Expected reading speed.
|
||||||
|
/// </summary>
|
||||||
|
private const float Wpm = 180f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Send a tippy message to all clients.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="message">The text to show in the speech bubble.</param>
|
||||||
|
/// <param name="prototype">The entity to show. Defaults to tippy.</param>
|
||||||
|
/// <param name="speakTime">The time the speech bubble is shown, in seconds.</param>
|
||||||
|
/// <param name="slideTime">The time the entity takes to walk onto the screen, in seconds.</param>
|
||||||
|
/// <param name="waddleInterval">The time between waddle animation steps, in seconds.</param>
|
||||||
|
public virtual void SendTippy(
|
||||||
|
string message,
|
||||||
|
EntProtoId? prototype = null,
|
||||||
|
float speakTime = 5f,
|
||||||
|
float slideTime = 3f,
|
||||||
|
float waddleInterval = 0.5f)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Send a tippy message to the given player session.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="session">The player session to send the message to.</param>
|
||||||
|
/// <param name="message">The text to show in the speech bubble.</param>
|
||||||
|
/// <param name="prototype">The entity to show. Defaults to tippy.</param>
|
||||||
|
/// <param name="speakTime">The time the speech bubble is shown, in seconds.</param>
|
||||||
|
/// <param name="slideTime">The time the entity takes to walk onto the screen, in seconds.</param>
|
||||||
|
/// <param name="waddleInterval">The time between waddle animation steps, in seconds.</param>
|
||||||
|
public virtual void SendTippy(
|
||||||
|
ICommonSession session,
|
||||||
|
string message,
|
||||||
|
EntProtoId? prototype = null,
|
||||||
|
float speakTime = 5f,
|
||||||
|
float slideTime = 3f,
|
||||||
|
float waddleInterval = 0.5f)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Send a random tippy message from the dataset given in <see cref="CCVars.TipsDataset"/>.
|
||||||
|
/// </summary>
|
||||||
|
public virtual void AnnounceRandomTip() { }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set a random time stamp for the next automatic game tip.
|
||||||
|
/// </summary>
|
||||||
|
public virtual void RecalculateNextTipTime() { }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Calculate the recommended speak time for a given message.
|
||||||
|
/// </summary>
|
||||||
|
public float GetSpeechTime(string text)
|
||||||
|
{
|
||||||
|
var wordCount = (float)text.Split().Length;
|
||||||
|
return SpeechBuffer + wordCount * (60f / Wpm);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,21 +1,37 @@
|
|||||||
|
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
namespace Content.Shared.Tips;
|
namespace Content.Shared.Tips;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Networked event that makes a client show a message on their screen using tippy or another protoype.
|
||||||
|
/// </summary>
|
||||||
[Serializable, NetSerializable]
|
[Serializable, NetSerializable]
|
||||||
public sealed class TippyEvent : EntityEventArgs
|
public sealed class TippyEvent(string msg, EntProtoId? proto, float speakTime, float slideTime, float waddleInterval) : EntityEventArgs
|
||||||
{
|
{
|
||||||
public TippyEvent(string msg)
|
/// <summary>
|
||||||
{
|
/// The text to show in the speech bubble.
|
||||||
Msg = msg;
|
/// </summary>
|
||||||
}
|
public string Msg = msg;
|
||||||
|
|
||||||
public string Msg;
|
/// <summary>
|
||||||
public string? Proto;
|
/// The entity to show. Defaults to tippy.
|
||||||
|
/// </summary>
|
||||||
|
public EntProtoId? Proto = proto;
|
||||||
|
|
||||||
// TODO: Why are these defaults even here, have the caller specify. This get overriden only most of the time.
|
/// <summary>
|
||||||
public float SpeakTime = 5;
|
/// The time the speech bubble is shown, in seconds.
|
||||||
public float SlideTime = 3;
|
/// </summary>
|
||||||
public float WaddleInterval = 0.5f;
|
public float SpeakTime = speakTime;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The time the entity takes to walk onto the screen, in seconds.
|
||||||
|
/// </summary>
|
||||||
|
public float SlideTime = slideTime;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The time between waddle animation steps, in seconds.
|
||||||
|
/// </summary>
|
||||||
|
public float WaddleInterval = waddleInterval;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
using Robust.Shared.GameStates;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
|
namespace Content.Shared.Trigger.Components.Effects;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sends a tippy message to either the entity or all players when triggered.
|
||||||
|
/// If TargetUser is true the user will receive the message.
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
|
||||||
|
public sealed partial class TippyOnTriggerComponent : BaseXOnTriggerComponent
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Unlocalized message text to send to the player(s).
|
||||||
|
/// Intended only for admeme purposes. For anything else you should use <see cref="LocMessage"/> instead.
|
||||||
|
/// </summary>
|
||||||
|
[DataField, AutoNetworkedField]
|
||||||
|
public string Message = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Localized message text to send to the player(s).
|
||||||
|
/// This has priority over <see cref="Message"/>.
|
||||||
|
/// </summary>
|
||||||
|
[DataField, AutoNetworkedField]
|
||||||
|
public LocId? LocMessage;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If true the message will be send to all players.
|
||||||
|
/// If false it will be send to the user or owning entity, depending on <see cref="BaseXOnTriggerComponent.TargetUser"/>.
|
||||||
|
/// </summary>
|
||||||
|
[DataField, AutoNetworkedField]
|
||||||
|
public bool SendToAll;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The entity prototype to show to the client.
|
||||||
|
/// Will default to tippy if null.
|
||||||
|
/// </summary>
|
||||||
|
[DataField, AutoNetworkedField]
|
||||||
|
public EntProtoId? Prototype;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use the prototype of the entity owning this component?
|
||||||
|
/// Will take priority over <see cref="Prototype"/>.
|
||||||
|
/// </summary>
|
||||||
|
[DataField, AutoNetworkedField]
|
||||||
|
public bool UseOwnerPrototype;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The time the speech bubble is shown, in seconds.
|
||||||
|
/// Will be calculated automatically from the message length if null.
|
||||||
|
/// </summary>
|
||||||
|
[DataField, AutoNetworkedField]
|
||||||
|
public float? SpeakTime;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The time the entity takes to walk onto the screen, in seconds.
|
||||||
|
/// </summary>
|
||||||
|
[DataField, AutoNetworkedField]
|
||||||
|
public float SlideTime = 3f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The time between waddle animation steps, in seconds.
|
||||||
|
/// </summary>
|
||||||
|
[DataField, AutoNetworkedField]
|
||||||
|
public float WaddleInterval = 0.5f;
|
||||||
|
}
|
||||||
49
Content.Shared/Trigger/Systems/TippyOnTriggerSystem.cs
Normal file
49
Content.Shared/Trigger/Systems/TippyOnTriggerSystem.cs
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
using Content.Shared.Tips;
|
||||||
|
using Content.Shared.Trigger.Components.Effects;
|
||||||
|
using Robust.Shared.Player;
|
||||||
|
|
||||||
|
namespace Content.Shared.Trigger.Systems;
|
||||||
|
|
||||||
|
public sealed class TippyOnTriggerSystem : EntitySystem
|
||||||
|
{
|
||||||
|
[Dependency] private readonly SharedTipsSystem _tips = default!;
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
|
||||||
|
SubscribeLocalEvent<TippyOnTriggerComponent, TriggerEvent>(OnTrigger);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnTrigger(Entity<TippyOnTriggerComponent> ent, ref TriggerEvent args)
|
||||||
|
{
|
||||||
|
if (args.Key != null && !ent.Comp.KeysIn.Contains(args.Key))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var msg = ent.Comp.Message;
|
||||||
|
var prototype = ent.Comp.Prototype;
|
||||||
|
|
||||||
|
if (ent.Comp.LocMessage != null)
|
||||||
|
msg = Loc.GetString(ent.Comp.LocMessage.Value);
|
||||||
|
|
||||||
|
if (ent.Comp.UseOwnerPrototype)
|
||||||
|
prototype = Prototype(ent)?.ID;
|
||||||
|
|
||||||
|
var speakTime = ent.Comp.SpeakTime ?? _tips.GetSpeechTime(msg);
|
||||||
|
|
||||||
|
if (ent.Comp.SendToAll)
|
||||||
|
{
|
||||||
|
_tips.SendTippy(msg, prototype, speakTime, ent.Comp.SlideTime, ent.Comp.WaddleInterval);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var target = ent.Comp.TargetUser ? args.User : ent.Owner;
|
||||||
|
if (!TryComp<ActorComponent>(target, out var actor))
|
||||||
|
return;
|
||||||
|
|
||||||
|
_tips.SendTippy(actor.PlayerSession, msg, prototype, speakTime, ent.Comp.SlideTime, ent.Comp.WaddleInterval);
|
||||||
|
}
|
||||||
|
|
||||||
|
args.Handled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
cmd-tippy-desc = Broadcast a message as Tippy the clown.
|
cmd-tippy-desc = Broadcast a message as Tippy the clown.
|
||||||
cmd-tippy-help = tippy <user | all> <message> [entity prototype] [speak time] [slide time] [waddle interval]
|
cmd-tippy-help = tippy <user | all> <message> [entity prototype | null] [speak time] [slide time] [waddle interval]
|
||||||
cmd-tippy-auto-1 = <user | all>
|
cmd-tippy-auto-1 = <user | all>
|
||||||
cmd-tippy-auto-2 = message
|
cmd-tippy-auto-2 = message
|
||||||
cmd-tippy-auto-3 = entity prototype
|
cmd-tippy-auto-3 = entity prototype
|
||||||
|
|||||||
@@ -96,11 +96,6 @@
|
|||||||
Commands:
|
Commands:
|
||||||
- listplayers
|
- listplayers
|
||||||
|
|
||||||
- Flags: FUN
|
|
||||||
Commands:
|
|
||||||
- tippy
|
|
||||||
- tip
|
|
||||||
|
|
||||||
- Flags: SERVER
|
- Flags: SERVER
|
||||||
Commands:
|
Commands:
|
||||||
- delete
|
- delete
|
||||||
|
|||||||
Reference in New Issue
Block a user