* Station event system Adds 2 basic events: (Power) GridCheck and RadiationStorm (based on the goonstation version). The system itself to choose events is based on tgstation's implementation. This also adds the event command that can be run to force specific events. There's still some other TODO items for these to be complete, to my knowledge: 1. There's no worldspace DrawCircle method (though the radstorm could look a lot nicer with a shader). 2. The PlayGlobal power_off / power_on audio seems to cut out halfway-through 3. (I think this is a known issue) lights still emit light until you get closer in a gridcheck so PVS range might need bumping. * Invariants for event names * Fix random event shutdown * Mix stereo announcements to mono * Address feedback * Remove redundant client system and use the overlay component instead * Drop the server prefix * Fix radiation overlay enum * use entityquery instead * zum's feedback * Use EntityQuery Co-authored-by: Metal Gear Sloth <metalgearsloth@gmail.com>
89 lines
3.6 KiB
C#
89 lines
3.6 KiB
C#
using System.Collections.Generic;
|
|
using Content.Server.GameObjects.Components.Damage;
|
|
using Content.Server.GameObjects.Components.Mobs;
|
|
using Content.Server.GameObjects.Components.StationEvents;
|
|
using Content.Shared.GameObjects;
|
|
using Content.Shared.GameObjects.Components.Damage;
|
|
using JetBrains.Annotations;
|
|
using Robust.Shared.GameObjects;
|
|
using Robust.Shared.GameObjects.Systems;
|
|
using Robust.Shared.Interfaces.GameObjects;
|
|
using Robust.Shared.IoC;
|
|
|
|
namespace Content.Server.GameObjects.EntitySystems.StationEvents
|
|
{
|
|
[UsedImplicitly]
|
|
public sealed class RadiationPulseSystem : EntitySystem
|
|
{
|
|
// Rather than stuffing around with collidables and checking entities on initialize etc. we'll just tick over
|
|
// for each entity in range. Seemed easier than checking entities on spawn, then checking collidables, etc.
|
|
// Especially considering each pulse is a big chonker, + no circle hitboxes yet.
|
|
|
|
private TypeEntityQuery _speciesQuery;
|
|
|
|
/// <summary>
|
|
/// Damage works with ints so we'll just accumulate damage and once we hit this threshold we'll apply it.
|
|
/// </summary>
|
|
/// This also server to stop spamming the damagethreshold with 1 damage continuously.
|
|
private const int DamageThreshold = 10;
|
|
|
|
private Dictionary<IEntity, float> _accumulatedDamage = new Dictionary<IEntity, float>();
|
|
|
|
public override void Initialize()
|
|
{
|
|
base.Initialize();
|
|
_speciesQuery = new TypeEntityQuery(typeof(SpeciesComponent));
|
|
}
|
|
|
|
public override void Update(float frameTime)
|
|
{
|
|
base.Update(frameTime);
|
|
var anyPulses = false;
|
|
|
|
foreach (var comp in ComponentManager.EntityQuery<RadiationPulseComponent>())
|
|
{
|
|
anyPulses = true;
|
|
|
|
foreach (var species in EntityManager.GetEntities(_speciesQuery))
|
|
{
|
|
// Work out if we're in range and accumulate more damage
|
|
// If we've hit the DamageThreshold we'll also apply that damage to the mob
|
|
// If we're really lagging server can apply multiples of the DamageThreshold at once
|
|
if (species.Transform.MapID != comp.Owner.Transform.MapID) continue;
|
|
|
|
if ((species.Transform.WorldPosition - comp.Owner.Transform.WorldPosition).Length > comp.Range)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var totalDamage = frameTime * comp.DPS;
|
|
|
|
if (!_accumulatedDamage.TryGetValue(species, out var accumulatedSpecies))
|
|
{
|
|
_accumulatedDamage[species] = 0.0f;
|
|
}
|
|
|
|
totalDamage += accumulatedSpecies;
|
|
_accumulatedDamage[species] = totalDamage;
|
|
|
|
if (totalDamage < DamageThreshold) continue;
|
|
if (!species.TryGetComponent(out DamageableComponent damageableComponent)) continue;
|
|
|
|
var damageMultiple = (int) (totalDamage / DamageThreshold);
|
|
_accumulatedDamage[species] = totalDamage % DamageThreshold;
|
|
|
|
damageableComponent.TakeDamage(DamageType.Heat, damageMultiple * DamageThreshold, comp.Owner, comp.Owner);
|
|
}
|
|
}
|
|
|
|
if (anyPulses)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// probably don't need to worry about clearing this at roundreset unless you have a radiation pulse at roundstart
|
|
// (which is currently not possible)
|
|
_accumulatedDamage.Clear();
|
|
}
|
|
}
|
|
} |