Skip to content

Commit

Permalink
Pacified Zone marker (#1815)
Browse files Browse the repository at this point in the history
* PacifiedZone

* PacifiedlZoneGeneratorSystem.cs->PacifiedZone...

* Keep track of naturally pacified entities

* Comment cleanup

* PacifiedZone

* Update pacified_zone.yml

* Update pacified_zone.yml

* PacifiedZone: handle only non-pacified entities

* NetEntity->EntityUid (running locally on server)

* NextUpdate: not a DataField

* PacifiedZone: override alert

* fix meta

Clarification of the meta at the author's request.

* Whatstone fixup for hairballs

* Added zones

---------

Co-authored-by: Whatstone <[email protected]>
Co-authored-by: Dvir <[email protected]>
Co-authored-by: Dvir <[email protected]>
  • Loading branch information
4 people authored Aug 9, 2024
1 parent c3f7530 commit 1040db4
Show file tree
Hide file tree
Showing 12 changed files with 305 additions and 43 deletions.
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

0 comments on commit 1040db4

Please sign in to comment.