| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227 |
- using Content.Server.Chat.Managers;
- using Content.Server.GameTicking;
- using Content.Shared.CCVar;
- using Content.Shared.Chat;
- using Content.Shared.Dataset;
- using Content.Shared.Tips;
- using Robust.Server.GameObjects;
- using Robust.Server.Player;
- using Robust.Shared.Configuration;
- using Robust.Shared.Console;
- using Robust.Shared.Player;
- using Robust.Shared.Prototypes;
- using Robust.Shared.Random;
- using Robust.Shared.Timing;
- namespace Content.Server.Tips;
- /// <summary>
- /// Handles periodically displaying gameplay tips to all players ingame.
- /// </summary>
- public sealed class TipsSystem : EntitySystem
- {
- [Dependency] private readonly IChatManager _chat = default!;
- [Dependency] private readonly IPrototypeManager _prototype = default!;
- [Dependency] private readonly IConfigurationManager _cfg = default!;
- [Dependency] private readonly IGameTiming _timing = default!;
- [Dependency] private readonly IRobustRandom _random = default!;
- [Dependency] private readonly GameTicker _ticker = default!;
- [Dependency] private readonly IConsoleHost _conHost = default!;
- [Dependency] private readonly IPlayerManager _playerManager = default!;
- private bool _tipsEnabled;
- private float _tipTimeOutOfRound;
- private float _tipTimeInRound;
- private string _tipsDataset = "";
- private float _tipTippyChance;
- [ViewVariables(VVAccess.ReadWrite)]
- private TimeSpan _nextTipTime = TimeSpan.Zero;
- public override void Initialize()
- {
- base.Initialize();
- 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.TipsDataset, SetDataset, true);
- Subs.CVar(_cfg, CCVars.TipsTippyChance, SetTippyChance, true);
- 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)
- {
- return args.Length switch
- {
- 1 => CompletionResult.FromHintOptions(CompletionHelper.SessionNames(), Loc.GetString("cmd-tippy-auto-1")),
- 2 => CompletionResult.FromHint(Loc.GetString("cmd-tippy-auto-2")),
- 3 => CompletionResult.FromHintOptions(CompletionHelper.PrototypeIDs<EntityPrototype>(), 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)
- {
- AnnounceRandomTip();
- RecalculateNextTipTime();
- }
- private void SendTippy(IConsoleShell shell, string argstr, string[] args)
- {
- if (args.Length < 2)
- {
- shell.WriteLine(Loc.GetString("cmd-tippy-help"));
- 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
- {
- session = shell.Player;
- }
- 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]);
- 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)
- {
- base.Update(frameTime);
- if (!_tipsEnabled)
- return;
- if (_nextTipTime != TimeSpan.Zero && _timing.CurTime > _nextTipTime)
- {
- AnnounceRandomTip();
- RecalculateNextTipTime();
- }
- }
- private void SetOutOfRound(float value)
- {
- _tipTimeOutOfRound = value;
- }
- private void SetInRound(float value)
- {
- _tipTimeInRound = value;
- }
- private void SetEnabled(bool value)
- {
- _tipsEnabled = value;
- if (_nextTipTime != TimeSpan.Zero)
- RecalculateNextTipTime();
- }
- private void SetDataset(string value)
- {
- _tipsDataset = value;
- }
- private void SetTippyChance(float value)
- {
- _tipTippyChance = value;
- }
- private void AnnounceRandomTip()
- {
- if (!_prototype.TryIndex<LocalizedDatasetPrototype>(_tipsDataset, out var tips))
- return;
- var tip = _random.Pick(tips.Values);
- var msg = Loc.GetString("tips-system-chat-message-wrap", ("tip", Loc.GetString(tip)));
- if (_random.Prob(_tipTippyChance))
- {
- var ev = new TippyEvent(msg);
- ev.SpeakTime = 1 + tip.Length * 0.05f;
- 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
- {
- _nextTipTime = _timing.CurTime + TimeSpan.FromSeconds(_tipTimeOutOfRound);
- }
- }
- private void OnGameRunLevelChanged(GameRunLevelChangedEvent ev)
- {
- // reset for lobby -> inround
- // reset for inround -> post but not post -> lobby
- if (ev.New == GameRunLevel.InRound || ev.Old == GameRunLevel.InRound)
- {
- RecalculateNextTipTime();
- }
- }
- }
|