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

Pacified Zone marker #1815

Merged
merged 17 commits into from
Aug 9, 2024
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
8 changes: 8 additions & 0 deletions Content.Server/Nyanotrasen/Abilities/Felinid/FelinidSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
using Robust.Shared.Prototypes;
using Content.Shared.Nutrition.EntitySystems;
using Content.Shared.Nyanotrasen.Abilities;
using Content.Shared.CombatMode.Pacification; // Frontier

namespace Content.Server.Abilities.Felinid
{
Expand All @@ -47,6 +48,8 @@ public override void Initialize()
SubscribeLocalEvent<FelinidComponent, DidUnequipHandEvent>(OnUnequipped);
SubscribeLocalEvent<HairballComponent, ThrowDoHitEvent>(OnHairballHit);
SubscribeLocalEvent<HairballComponent, GettingPickedUpAttemptEvent>(OnHairballPickupAttempt);

SubscribeLocalEvent<HairballComponent, AttemptPacifiedThrowEvent>(OnHairballAttemptPacifiedThrow); // Frontier - Block hairball abuse
}

private Queue<EntityUid> RemQueue = new();
Expand Down Expand Up @@ -190,6 +193,11 @@ private void OnHairballPickupAttempt(EntityUid uid, HairballComponent component,
args.Cancel();
}
}

private void OnHairballAttemptPacifiedThrow(Entity<HairballComponent> ent, ref AttemptPacifiedThrowEvent args) // Frontier - Block hairball abuse
{
args.Cancel("pacified-cannot-throw-hairball");
}
}

}
10 changes: 10 additions & 0 deletions Content.Server/_NF/PacifiedZone/PacifiedByZoneComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace Content.Server._NF.PacifiedZone
{
// Denotes an entity as being pacified by a zone.
// An entity with PacifiedComponent but not PacifiedByZoneComponent is naturally pacified
// (e.g. through Pax, or the Pious trait)
[RegisterComponent]
public sealed partial class PacifiedByZoneComponent : Component
{
}
}
27 changes: 27 additions & 0 deletions Content.Server/_NF/PacifiedZone/PacifiedZoneGeneratorComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using Robust.Shared.Prototypes;
using Content.Shared.Roles;

namespace Content.Server._NF.PacifiedZone
{
[RegisterComponent]
public sealed partial class PacifiedZoneGeneratorComponent : Component
{
[ViewVariables]
public List<EntityUid> TrackedEntities = new();

[ViewVariables]
public TimeSpan NextUpdate;

/// <summary>
/// The interval at which this component updates.
/// </summary>
[DataField]
public TimeSpan UpdateInterval = TimeSpan.FromSeconds(1);

[DataField]
public int Radius = 5;

[DataField]
public List<ProtoId<JobPrototype>> ImmuneRoles = new();
}
}
132 changes: 132 additions & 0 deletions Content.Server/_NF/PacifiedZone/PacifiedZoneGeneratorSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
using Robust.Shared.Timing;
using Content.Shared.Alert;
using Content.Shared.CombatMode.Pacification;
using Content.Shared.Humanoid;
using Content.Shared.Mind;
using Content.Shared.Roles.Jobs;

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!;

private const string Alert = "PacifiedZone";

public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<PacifiedZoneGeneratorComponent, ComponentInit>(OnComponentInit);
SubscribeLocalEvent<PacifiedZoneGeneratorComponent, ComponentShutdown>(OnComponentShutdown);
}

private void OnComponentInit(EntityUid uid, PacifiedZoneGeneratorComponent component, ComponentInit args)
{
foreach (var humanoidUid in _lookup.GetEntitiesInRange<HumanoidAppearanceComponent>(Transform(uid).Coordinates, component.Radius))
{
if (HasComp<PacifiedComponent>(humanoidUid))
continue;

if (!_mindSystem.TryGetMind(humanoidUid, out var mindId, out var _))
continue;

_jobSystem.MindTryGetJobId(mindId, out var jobId);

if (jobId != null && component.ImmuneRoles.Contains(jobId.Value))
continue;

var pacifiedComponent = AddComp<PacifiedComponent>(humanoidUid);
EnableAlert(humanoidUid, pacifiedComponent);
AddComp<PacifiedByZoneComponent>(humanoidUid);
component.TrackedEntities.Add(humanoidUid);
}

component.NextUpdate = _gameTiming.CurTime + component.UpdateInterval;
}

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))
{
List<EntityUid> newEntities = new List<EntityUid>();
// Not yet update time, skip this
if (_gameTiming.CurTime < component.NextUpdate)
continue;

var query = _lookup.GetEntitiesInRange<HumanoidAppearanceComponent>(Transform(genUid).Coordinates, component.Radius);
foreach (var humanoidUid in query)
{
if (!_mindSystem.TryGetMind(humanoidUid, out var mindId, out var mind))
continue;

_jobSystem.MindTryGetJobId(mindId, out var jobId);

// Player matches an immune role, should not be pacified.
if (jobId != null && component.ImmuneRoles.Contains(jobId.Value))
continue;

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, Alert);
}

// Hides our pacified zone alert.
private void DisableAlert(EntityUid entity)
{
_alerts.ClearAlert(entity, Alert);
}
}
}
2 changes: 2 additions & 0 deletions Resources/Locale/en-US/_NF/alerts/alerts.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
alerts-pacified-zone-name = [color=royalblue]Pacified Zone[/color]
alerts-pacified-zone-desc = You're in a pacified zone, you need to leave before harming living things.
4 changes: 4 additions & 0 deletions Resources/Locale/en-US/_NF/pacified/pacified.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

## Messages shown to Pacified players when they try to do violence:

pacified-cannot-throw-hairball = I can't possibly throw { THE($projectile) }, what if somebody vomits?
Loading
Loading