6
StarHorizon_Public/Content.Server/_NF/PacifiedZone/PacifiedZoneGeneratorSystem.cs
2026-01-18 12:53:36 +03:00

131 lines
4.9 KiB
C#

using Robust.Shared.Timing;
using Content.Server.Administration.Systems;
using Content.Shared.Alert;
using Content.Shared.CombatMode.Pacification;
using Content.Shared.Humanoid;
using Content.Shared.Mind;
using Content.Shared.Roles.Jobs;
using Robust.Shared.Prototypes;
namespace Content.Server._NF.PacifiedZone;
public sealed class PacifiedZoneGeneratorSystem : EntitySystem
{
[Dependency] private readonly EntityLookupSystem _lookup = default!;
[Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly SharedMindSystem _mindSystem = default!;
[Dependency] private readonly SharedJobSystem _jobSystem = default!;
[Dependency] private readonly AlertsSystem _alerts = default!;
[Dependency] private readonly AdminSystem _admin = default!;
private static readonly ProtoId<AlertPrototype> AlertProto = "PacifiedZone";
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<PacifiedZoneGeneratorComponent, ComponentInit>(OnComponentInit);
SubscribeLocalEvent<PacifiedZoneGeneratorComponent, ComponentShutdown>(OnComponentShutdown);
}
private void OnComponentInit(EntityUid uid, PacifiedZoneGeneratorComponent component, ComponentInit args)
{
UpdatePacifiedState(uid, component);
}
private void OnComponentShutdown(EntityUid uid, PacifiedZoneGeneratorComponent component, ComponentShutdown args)
{
foreach (var entity in component.TrackedEntities)
{
RemComp<PacifiedComponent>(entity);
RemComp<PacifiedByZoneComponent>(entity);
DisableAlert(entity);
}
}
public override void Update(float frameTime)
{
base.Update(frameTime);
var genQuery = AllEntityQuery<PacifiedZoneGeneratorComponent>();
while (genQuery.MoveNext(out var genUid, out var component))
{
// Not yet update time, skip this
if (_gameTiming.CurTime < component.NextUpdate)
continue;
UpdatePacifiedState(genUid, component);
}
}
private void UpdatePacifiedState(EntityUid genUid, PacifiedZoneGeneratorComponent component)
{
List<EntityUid> newEntities = new List<EntityUid>();
var query = _lookup.GetEntitiesInRange<HumanoidAppearanceComponent>(Transform(genUid).Coordinates, component.Radius);
foreach (var humanoidUid in query)
{
// Check preconditions for an entity to be pacified at all.
// If player matches an immune role, or has playtime above a zone's threshold, it should not be pacified.
if (!_mindSystem.TryGetMind(humanoidUid, out var mindId, out var mind))
continue;
_jobSystem.MindTryGetJobId(mindId, out var jobId);
if (jobId != null && component.ImmuneRoles.Contains(jobId.Value))
continue;
if (component.ImmunePlaytime != null)
{
var playerInfo = _admin.GetCachedPlayerInfo(mind?.UserId);
if (playerInfo != null && playerInfo.OverallPlaytime >= component.ImmunePlaytime)
{
continue;
}
}
// Existing entity, note it still exists.
if (component.TrackedEntities.Contains(humanoidUid))
{
// Entity still in zone.
newEntities.Add(humanoidUid);
component.TrackedEntities.Remove(humanoidUid);
}
else
{
// Player is pacified (either naturally or by another zone), skip them.
if (HasComp<PacifiedComponent>(humanoidUid))
continue;
// New entity in zone, needs the Pacified comp.
var pacifiedComponent = AddComp<PacifiedComponent>(humanoidUid);
EnableAlert(humanoidUid, pacifiedComponent);
AddComp<PacifiedByZoneComponent>(humanoidUid);
newEntities.Add(humanoidUid);
}
}
// Anything left in our old set has left the zone, remove their pacified status.
foreach (var humanoid_net_uid in component.TrackedEntities)
{
RemComp<PacifiedComponent>(humanoid_net_uid);
RemComp<PacifiedByZoneComponent>(humanoid_net_uid);
DisableAlert(humanoid_net_uid);
}
// Update state for next run.
component.TrackedEntities = newEntities;
component.NextUpdate = _gameTiming.CurTime + component.UpdateInterval;
}
// Overrides the default Pacified alert with one for the pacified zone.
private void EnableAlert(EntityUid entity, PacifiedComponent pacified)
{
_alerts.ClearAlert(entity, pacified.PacifiedAlert);
_alerts.ShowAlert(entity, AlertProto);
}
// Hides our pacified zone alert.
private void DisableAlert(EntityUid entity)
{
_alerts.ClearAlert(entity, AlertProto);
}
}