Separate "thank you" messages from general ads (#25867)

* Separated "thank you" messages from general ads

* Moved MessagePackPrototype to shared, cleaned up AdvertiseComponent, and actually killed AdvertisementsPackPrototype.
+More suggests changes.

* Rename PackPrototypeID to Pack in both components.
This commit is contained in:
Tayrtahn
2024-03-28 02:46:26 -04:00
committed by GitHub
parent 29f34d8423
commit 794a447bb7
72 changed files with 603 additions and 470 deletions

View File

@@ -0,0 +1,137 @@
using Content.Server.Advertise.Components;
using Content.Server.Chat.Systems;
using Content.Server.Power.Components;
using Content.Shared.VendingMachines;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using Robust.Shared.Timing;
namespace Content.Server.Advertise.EntitySystems;
public sealed class AdvertiseSystem : EntitySystem
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly ChatSystem _chat = default!;
/// <summary>
/// The maximum amount of time between checking if advertisements should be displayed
/// </summary>
private readonly TimeSpan _maximumNextCheckDuration = TimeSpan.FromSeconds(15);
/// <summary>
/// The next time the game will check if advertisements should be displayed
/// </summary>
private TimeSpan _nextCheckTime = TimeSpan.MaxValue;
public override void Initialize()
{
SubscribeLocalEvent<AdvertiseComponent, MapInitEvent>(OnMapInit);
SubscribeLocalEvent<AdvertiseComponent, PowerChangedEvent>(OnPowerChanged);
SubscribeLocalEvent<ApcPowerReceiverComponent, AdvertiseEnableChangeAttemptEvent>(OnPowerReceiverEnableChangeAttempt);
SubscribeLocalEvent<VendingMachineComponent, AdvertiseEnableChangeAttemptEvent>(OnVendingEnableChangeAttempt);
// The component inits will lower this.
_nextCheckTime = TimeSpan.MaxValue;
}
private void OnMapInit(EntityUid uid, AdvertiseComponent advertise, MapInitEvent args)
{
RefreshTimer(uid, advertise);
}
private void OnPowerChanged(EntityUid uid, AdvertiseComponent advertise, ref PowerChangedEvent args)
{
SetEnabled(uid, args.Powered, advertise);
}
public void RefreshTimer(EntityUid uid, AdvertiseComponent? advertise = null)
{
if (!Resolve(uid, ref advertise))
return;
if (!advertise.Enabled)
return;
var minDuration = Math.Max(1, advertise.MinimumWait);
var maxDuration = Math.Max(minDuration, advertise.MaximumWait);
var waitDuration = TimeSpan.FromSeconds(_random.Next(minDuration, maxDuration));
var nextTime = _gameTiming.CurTime + waitDuration;
advertise.NextAdvertisementTime = nextTime;
_nextCheckTime = MathHelper.Min(nextTime, _nextCheckTime);
}
public void SayAdvertisement(EntityUid uid, AdvertiseComponent? advertise = null)
{
if (!Resolve(uid, ref advertise))
return;
if (_prototypeManager.TryIndex(advertise.Pack, out var advertisements))
_chat.TrySendInGameICMessage(uid, Loc.GetString(_random.Pick(advertisements.Messages)), InGameICChatType.Speak, hideChat: true);
}
public void SetEnabled(EntityUid uid, bool enable, AdvertiseComponent? advertise = null)
{
if (!Resolve(uid, ref advertise))
return;
if (advertise.Enabled == enable)
return;
var attemptEvent = new AdvertiseEnableChangeAttemptEvent(enable);
RaiseLocalEvent(uid, attemptEvent);
if (attemptEvent.Cancelled)
return;
advertise.Enabled = enable;
RefreshTimer(uid, advertise);
}
private static void OnPowerReceiverEnableChangeAttempt(EntityUid uid, ApcPowerReceiverComponent component, AdvertiseEnableChangeAttemptEvent args)
{
if (args.Enabling && !component.Powered)
args.Cancel();
}
private static void OnVendingEnableChangeAttempt(EntityUid uid, VendingMachineComponent component, AdvertiseEnableChangeAttemptEvent args)
{
if (args.Enabling && component.Broken)
args.Cancel();
}
public override void Update(float frameTime)
{
var curTime = _gameTiming.CurTime;
if (_nextCheckTime > curTime)
return;
_nextCheckTime = curTime + _maximumNextCheckDuration;
var query = EntityQueryEnumerator<AdvertiseComponent>();
while (query.MoveNext(out var uid, out var advert))
{
if (!advert.Enabled)
continue;
// If this isn't advertising yet
if (advert.NextAdvertisementTime > curTime)
{
_nextCheckTime = MathHelper.Min(advert.NextAdvertisementTime, _nextCheckTime);
continue;
}
SayAdvertisement(uid, advert);
RefreshTimer(uid, advert);
}
}
}
public sealed class AdvertiseEnableChangeAttemptEvent(bool enabling) : CancellableEntityEventArgs
{
public bool Enabling { get; } = enabling;
}

View File

@@ -0,0 +1,58 @@
using Content.Server.Advertise.Components;
using Content.Server.Chat.Systems;
using Content.Server.UserInterface;
using Content.Shared.Advertise;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
namespace Content.Server.Advertise;
public sealed partial class SpeakOnUIClosedSystem : EntitySystem
{
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly ChatSystem _chat = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<SpeakOnUIClosedComponent, BoundUIClosedEvent>(OnBoundUIClosed);
}
private void OnBoundUIClosed(Entity<SpeakOnUIClosedComponent> entity, ref BoundUIClosedEvent args)
{
if (!TryComp(entity, out ActivatableUIComponent? activatable) || !args.UiKey.Equals(activatable.Key))
return;
if (entity.Comp.RequireFlag && !entity.Comp.Flag)
return;
TrySpeak((entity, entity.Comp));
}
public bool TrySpeak(Entity<SpeakOnUIClosedComponent?> entity)
{
if (!Resolve(entity, ref entity.Comp))
return false;
if (!entity.Comp.Enabled)
return false;
if (!_prototypeManager.TryIndex(entity.Comp.Pack, out MessagePackPrototype? messagePack))
return false;
var message = Loc.GetString(_random.Pick(messagePack.Messages), ("name", Name(entity)));
_chat.TrySendInGameICMessage(entity, message, InGameICChatType.Speak, true);
entity.Comp.Flag = false;
return true;
}
public bool TrySetFlag(Entity<SpeakOnUIClosedComponent?> entity, bool value = true)
{
if (!Resolve(entity, ref entity.Comp))
return false;
entity.Comp.Flag = value;
return true;
}
}