Anomalous infections (#31876)
* inner anomaly * anomaly pulse action * test anom mine * Update anomalies.yml * fix action cooldown * pyro_eyes * clientsystem * experiments * blya * some telegraphy * shock eyes! * shadow eyes * separate files * frosty eyes * fix * flora eyes * bluespace eyes * flesh eyes * redoing injction * auto add layers * пипяу * new injector component * stupid me * nice marker injectors * anomaly spawn on shutdown * gravity anom * dead anomaly spawning * add VOX states * sprite specific layers support * technology anom infection * auto detach anomalies that have moved away * Update anomaly_injections.yml * anomalyspawner integration * rock anomaly! * Update anomaly_injections.yml * fix crash bug * tag filter * fix anom dublication spawns * Update anomaly.yml * Update InnerBodyAnomalyComponent.cs * Update anomaly_injections.yml * dont spawn anomalies after decay * fix morb sprite, add end message * gravity resprite * admin logging, double injection fix * make flesh and living light mobs friendly to anomaly hosts * popups * severity feedback * sloth review * A * keep organs after gib * punpun host * sloth synchronization * Update arachnid.yml * increase infections spawnrate
50
Content.Client/Anomaly/Effects/ClientInnerBodySystem.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
using Content.Shared.Anomaly.Components;
|
||||
using Content.Shared.Anomaly.Effects;
|
||||
using Content.Shared.Body.Components;
|
||||
using Robust.Client.GameObjects;
|
||||
|
||||
namespace Content.Client.Anomaly.Effects;
|
||||
|
||||
public sealed class ClientInnerBodyAnomalySystem : SharedInnerBodyAnomalySystem
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
SubscribeLocalEvent<InnerBodyAnomalyComponent, AfterAutoHandleStateEvent>(OnAfterHandleState);
|
||||
SubscribeLocalEvent<InnerBodyAnomalyComponent, ComponentShutdown>(OnCompShutdown);
|
||||
}
|
||||
|
||||
private void OnAfterHandleState(Entity<InnerBodyAnomalyComponent> ent, ref AfterAutoHandleStateEvent args)
|
||||
{
|
||||
if (!TryComp<SpriteComponent>(ent, out var sprite))
|
||||
return;
|
||||
|
||||
if (ent.Comp.FallbackSprite is null)
|
||||
return;
|
||||
|
||||
if (!sprite.LayerMapTryGet(ent.Comp.LayerMap, out var index))
|
||||
index = sprite.LayerMapReserveBlank(ent.Comp.LayerMap);
|
||||
|
||||
if (TryComp<BodyComponent>(ent, out var body) &&
|
||||
body.Prototype is not null &&
|
||||
ent.Comp.SpeciesSprites.TryGetValue(body.Prototype.Value, out var speciesSprite))
|
||||
{
|
||||
sprite.LayerSetSprite(index, speciesSprite);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprite.LayerSetSprite(index, ent.Comp.FallbackSprite);
|
||||
}
|
||||
|
||||
sprite.LayerSetVisible(index, true);
|
||||
sprite.LayerSetShader(index, "unshaded");
|
||||
}
|
||||
|
||||
private void OnCompShutdown(Entity<InnerBodyAnomalyComponent> ent, ref ComponentShutdown args)
|
||||
{
|
||||
if (!TryComp<SpriteComponent>(ent, out var sprite))
|
||||
return;
|
||||
|
||||
var index = sprite.LayerMapGet(ent.Comp.LayerMap);
|
||||
sprite.LayerSetVisible(index, false);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Content.Server.Anomaly.Components;
|
||||
using Content.Server.DeviceLinking.Systems;
|
||||
using Content.Server.Power.Components;
|
||||
@@ -10,6 +11,7 @@ using Content.Shared.Popups;
|
||||
using Content.Shared.Power;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
using Content.Shared.Verbs;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Server.Anomaly;
|
||||
|
||||
@@ -25,6 +27,7 @@ public sealed partial class AnomalySynchronizerSystem : EntitySystem
|
||||
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
||||
[Dependency] private readonly SharedPopupSystem _popup = default!;
|
||||
[Dependency] private readonly PowerReceiverSystem _power = default!;
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -40,6 +43,34 @@ public sealed partial class AnomalySynchronizerSystem : EntitySystem
|
||||
SubscribeLocalEvent<AnomalyStabilityChangedEvent>(OnAnomalyStabilityChanged);
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
base.Update(frameTime);
|
||||
|
||||
var query = EntityQueryEnumerator<AnomalySynchronizerComponent, TransformComponent>();
|
||||
while (query.MoveNext(out var uid, out var sync, out var xform))
|
||||
{
|
||||
if (sync.ConnectedAnomaly is null)
|
||||
continue;
|
||||
|
||||
if (_timing.CurTime < sync.NextCheckTime)
|
||||
continue;
|
||||
sync.NextCheckTime += sync.CheckFrequency;
|
||||
|
||||
if (Transform(sync.ConnectedAnomaly.Value).MapUid != Transform(uid).MapUid)
|
||||
{
|
||||
DisconnectFromAnomaly((uid, sync), sync.ConnectedAnomaly.Value);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!xform.Coordinates.TryDistance(EntityManager, Transform(sync.ConnectedAnomaly.Value).Coordinates, out var distance))
|
||||
continue;
|
||||
|
||||
if (distance > sync.AttachRange)
|
||||
DisconnectFromAnomaly((uid, sync), sync.ConnectedAnomaly.Value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If powered, try to attach a nearby anomaly.
|
||||
/// </summary>
|
||||
@@ -73,10 +104,10 @@ public sealed partial class AnomalySynchronizerSystem : EntitySystem
|
||||
if (args.Powered)
|
||||
return;
|
||||
|
||||
if (!TryComp<AnomalyComponent>(ent.Comp.ConnectedAnomaly, out var anomaly))
|
||||
if (ent.Comp.ConnectedAnomaly is null)
|
||||
return;
|
||||
|
||||
DisconnectFromAnomaly(ent, anomaly);
|
||||
DisconnectFromAnomaly(ent, ent.Comp.ConnectedAnomaly.Value);
|
||||
}
|
||||
|
||||
private void OnExamined(Entity<AnomalySynchronizerComponent> ent, ref ExaminedEvent args)
|
||||
@@ -125,13 +156,16 @@ public sealed partial class AnomalySynchronizerSystem : EntitySystem
|
||||
|
||||
//TODO: disconnection from the anomaly should also be triggered if the anomaly is far away from the synchronizer.
|
||||
//Currently only bluespace anomaly can do this, but for some reason it is the only one that cannot be connected to the synchronizer.
|
||||
private void DisconnectFromAnomaly(Entity<AnomalySynchronizerComponent> ent, AnomalyComponent anomaly)
|
||||
private void DisconnectFromAnomaly(Entity<AnomalySynchronizerComponent> ent, EntityUid other)
|
||||
{
|
||||
if (ent.Comp.ConnectedAnomaly == null)
|
||||
return;
|
||||
|
||||
if (TryComp<AnomalyComponent>(other, out var anomaly))
|
||||
{
|
||||
if (ent.Comp.PulseOnDisconnect)
|
||||
_anomaly.DoAnomalyPulse(ent.Comp.ConnectedAnomaly.Value, anomaly);
|
||||
}
|
||||
|
||||
_popup.PopupEntity(Loc.GetString("anomaly-sync-disconnected"), ent, PopupType.Large);
|
||||
_audio.PlayPvs(ent.Comp.ConnectedSound, ent);
|
||||
|
||||
@@ -55,6 +55,7 @@ public sealed partial class AnomalySystem : SharedAnomalySystem
|
||||
SubscribeLocalEvent<AnomalyComponent, ComponentShutdown>(OnShutdown);
|
||||
SubscribeLocalEvent<AnomalyComponent, StartCollideEvent>(OnStartCollide);
|
||||
|
||||
|
||||
InitializeGenerator();
|
||||
InitializeScanner();
|
||||
InitializeVessel();
|
||||
@@ -86,7 +87,10 @@ public sealed partial class AnomalySystem : SharedAnomalySystem
|
||||
|
||||
private void OnShutdown(Entity<AnomalyComponent> anomaly, ref ComponentShutdown args)
|
||||
{
|
||||
EndAnomaly(anomaly);
|
||||
if (anomaly.Comp.CurrentBehavior is not null)
|
||||
RemoveBehavior(anomaly, anomaly.Comp.CurrentBehavior.Value);
|
||||
|
||||
EndAnomaly(anomaly, spawnCore: false);
|
||||
}
|
||||
|
||||
private void OnStartCollide(Entity<AnomalyComponent> anomaly, ref StartCollideEvent args)
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace Content.Server.Anomaly.Components;
|
||||
/// <summary>
|
||||
/// a device that allows you to translate anomaly activity into multitool signals.
|
||||
/// </summary>
|
||||
[RegisterComponent, Access(typeof(AnomalySynchronizerSystem))]
|
||||
[RegisterComponent, AutoGenerateComponentPause, Access(typeof(AnomalySynchronizerSystem))]
|
||||
public sealed partial class AnomalySynchronizerComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
@@ -34,6 +34,15 @@ public sealed partial class AnomalySynchronizerComponent : Component
|
||||
[DataField]
|
||||
public float AttachRange = 0.4f;
|
||||
|
||||
/// <summary>
|
||||
/// Periodicheski checks to see if the anomaly has moved to disconnect it.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public TimeSpan CheckFrequency = TimeSpan.FromSeconds(1f);
|
||||
|
||||
[DataField, AutoPausedField]
|
||||
public TimeSpan NextCheckTime = TimeSpan.Zero;
|
||||
|
||||
[DataField]
|
||||
public ProtoId<SourcePortPrototype> DecayingPort = "Decaying";
|
||||
|
||||
|
||||
236
Content.Server/Anomaly/Effects/InnerBodyAnomalySystem.cs
Normal file
@@ -0,0 +1,236 @@
|
||||
using Content.Server.Administration.Logs;
|
||||
using Content.Server.Body.Systems;
|
||||
using Content.Server.Chat.Managers;
|
||||
using Content.Server.Jittering;
|
||||
using Content.Server.Mind;
|
||||
using Content.Server.Stunnable;
|
||||
using Content.Shared.Actions;
|
||||
using Content.Shared.Anomaly;
|
||||
using Content.Shared.Anomaly.Components;
|
||||
using Content.Shared.Anomaly.Effects;
|
||||
using Content.Shared.Body.Components;
|
||||
using Content.Shared.Chat;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.Mobs;
|
||||
using Content.Shared.Popups;
|
||||
using Content.Shared.Whitelist;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
using Robust.Shared.Physics.Events;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Anomaly.Effects;
|
||||
|
||||
public sealed class InnerBodyAnomalySystem : SharedInnerBodyAnomalySystem
|
||||
{
|
||||
[Dependency] private readonly IAdminLogManager _adminLog = default!;
|
||||
[Dependency] private readonly AnomalySystem _anomaly = default!;
|
||||
[Dependency] private readonly ActionContainerSystem _actionContainer = default!;
|
||||
[Dependency] private readonly SharedActionsSystem _actions = default!;
|
||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||
[Dependency] private readonly BodySystem _body = default!;
|
||||
[Dependency] private readonly IChatManager _chat = default!;
|
||||
[Dependency] private readonly EntityWhitelistSystem _whitelist = default!;
|
||||
[Dependency] private readonly JitteringSystem _jitter = default!;
|
||||
[Dependency] private readonly MindSystem _mind = default!;
|
||||
[Dependency] private readonly SharedPopupSystem _popup = default!;
|
||||
[Dependency] private readonly IPrototypeManager _proto = default!;
|
||||
[Dependency] private readonly StunSystem _stun = default!;
|
||||
|
||||
private readonly Color _messageColor = Color.FromSrgb(new Color(201, 22, 94));
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<InnerBodyAnomalyInjectorComponent, StartCollideEvent>(OnStartCollideInjector);
|
||||
|
||||
SubscribeLocalEvent<InnerBodyAnomalyComponent, MapInitEvent>(OnMapInit);
|
||||
SubscribeLocalEvent<InnerBodyAnomalyComponent, ComponentShutdown>(OnCompShutdown);
|
||||
|
||||
SubscribeLocalEvent<InnerBodyAnomalyComponent, AnomalyPulseEvent>(OnAnomalyPulse);
|
||||
SubscribeLocalEvent<InnerBodyAnomalyComponent, AnomalyShutdownEvent>(OnAnomalyShutdown);
|
||||
SubscribeLocalEvent<InnerBodyAnomalyComponent, AnomalySupercriticalEvent>(OnAnomalySupercritical);
|
||||
SubscribeLocalEvent<InnerBodyAnomalyComponent, AnomalySeverityChangedEvent>(OnSeverityChanged);
|
||||
|
||||
SubscribeLocalEvent<InnerBodyAnomalyComponent, MobStateChangedEvent>(OnMobStateChanged);
|
||||
|
||||
SubscribeLocalEvent<AnomalyComponent, ActionAnomalyPulseEvent>(OnActionPulse);
|
||||
}
|
||||
|
||||
private void OnActionPulse(Entity<AnomalyComponent> ent, ref ActionAnomalyPulseEvent args)
|
||||
{
|
||||
if (args.Handled)
|
||||
return;
|
||||
|
||||
_anomaly.DoAnomalyPulse(ent, ent.Comp);
|
||||
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
private void OnStartCollideInjector(Entity<InnerBodyAnomalyInjectorComponent> ent, ref StartCollideEvent args)
|
||||
{
|
||||
if (ent.Comp.Whitelist is not null && !_whitelist.IsValid(ent.Comp.Whitelist, args.OtherEntity))
|
||||
return;
|
||||
if (TryComp<InnerBodyAnomalyComponent>(args.OtherEntity, out var innerAnom) && innerAnom.Injected)
|
||||
return;
|
||||
if (!_mind.TryGetMind(args.OtherEntity, out _, out var mindComponent))
|
||||
return;
|
||||
|
||||
EntityManager.AddComponents(args.OtherEntity, ent.Comp.InjectionComponents);
|
||||
QueueDel(ent);
|
||||
}
|
||||
|
||||
private void OnMapInit(Entity<InnerBodyAnomalyComponent> ent, ref MapInitEvent args)
|
||||
{
|
||||
AddAnomalyToBody(ent);
|
||||
}
|
||||
|
||||
private void AddAnomalyToBody(Entity<InnerBodyAnomalyComponent> ent)
|
||||
{
|
||||
if (!_proto.TryIndex(ent.Comp.InjectionProto, out var injectedAnom))
|
||||
return;
|
||||
|
||||
if (ent.Comp.Injected)
|
||||
return;
|
||||
|
||||
ent.Comp.Injected = true;
|
||||
|
||||
EntityManager.AddComponents(ent, injectedAnom.Components);
|
||||
|
||||
_stun.TryParalyze(ent, TimeSpan.FromSeconds(ent.Comp.StunDuration), true);
|
||||
_jitter.DoJitter(ent, TimeSpan.FromSeconds(ent.Comp.StunDuration), true);
|
||||
|
||||
if (ent.Comp.StartSound is not null)
|
||||
_audio.PlayPvs(ent.Comp.StartSound, ent);
|
||||
|
||||
if (ent.Comp.StartMessage is not null &&
|
||||
_mind.TryGetMind(ent, out _, out var mindComponent) &&
|
||||
mindComponent.Session != null)
|
||||
{
|
||||
var message = Loc.GetString(ent.Comp.StartMessage);
|
||||
var wrappedMessage = Loc.GetString("chat-manager-server-wrap-message", ("message", message));
|
||||
_chat.ChatMessageToOne(ChatChannel.Server,
|
||||
message,
|
||||
wrappedMessage,
|
||||
default,
|
||||
false,
|
||||
mindComponent.Session.Channel,
|
||||
_messageColor);
|
||||
|
||||
_popup.PopupEntity(message, ent, ent, PopupType.MediumCaution);
|
||||
|
||||
_adminLog.Add(LogType.Anomaly,LogImpact.Extreme,$"{ToPrettyString(ent)} became anomaly host.");
|
||||
}
|
||||
Dirty(ent);
|
||||
}
|
||||
|
||||
private void OnAnomalyPulse(Entity<InnerBodyAnomalyComponent> ent, ref AnomalyPulseEvent args)
|
||||
{
|
||||
_stun.TryParalyze(ent, TimeSpan.FromSeconds(ent.Comp.StunDuration / 2 * args.Severity), true);
|
||||
_jitter.DoJitter(ent, TimeSpan.FromSeconds(ent.Comp.StunDuration / 2 * args.Severity), true);
|
||||
}
|
||||
|
||||
private void OnAnomalySupercritical(Entity<InnerBodyAnomalyComponent> ent, ref AnomalySupercriticalEvent args)
|
||||
{
|
||||
if (!TryComp<BodyComponent>(ent, out var body))
|
||||
return;
|
||||
|
||||
_body.GibBody(ent, true, body, splatModifier: 5f);
|
||||
}
|
||||
|
||||
private void OnSeverityChanged(Entity<InnerBodyAnomalyComponent> ent, ref AnomalySeverityChangedEvent args)
|
||||
{
|
||||
if (!_mind.TryGetMind(ent, out _, out var mindComponent) || mindComponent.Session == null)
|
||||
return;
|
||||
|
||||
var message = string.Empty;
|
||||
|
||||
if (args.Severity >= 0.5 && ent.Comp.LastSeverityInformed < 0.5)
|
||||
{
|
||||
ent.Comp.LastSeverityInformed = 0.5f;
|
||||
message = Loc.GetString("inner-anomaly-severity-info-50");
|
||||
}
|
||||
if (args.Severity >= 0.75 && ent.Comp.LastSeverityInformed < 0.75)
|
||||
{
|
||||
ent.Comp.LastSeverityInformed = 0.75f;
|
||||
message = Loc.GetString("inner-anomaly-severity-info-75");
|
||||
}
|
||||
if (args.Severity >= 0.9 && ent.Comp.LastSeverityInformed < 0.9)
|
||||
{
|
||||
ent.Comp.LastSeverityInformed = 0.9f;
|
||||
message = Loc.GetString("inner-anomaly-severity-info-90");
|
||||
}
|
||||
if (args.Severity >= 1 && ent.Comp.LastSeverityInformed < 1)
|
||||
{
|
||||
ent.Comp.LastSeverityInformed = 1f;
|
||||
message = Loc.GetString("inner-anomaly-severity-info-100");
|
||||
}
|
||||
|
||||
if (message == string.Empty)
|
||||
return;
|
||||
|
||||
var wrappedMessage = Loc.GetString("chat-manager-server-wrap-message", ("message", message));
|
||||
_chat.ChatMessageToOne(ChatChannel.Server,
|
||||
message,
|
||||
wrappedMessage,
|
||||
default,
|
||||
false,
|
||||
mindComponent.Session.Channel,
|
||||
_messageColor);
|
||||
|
||||
_popup.PopupEntity(message, ent, ent, PopupType.MediumCaution);
|
||||
}
|
||||
|
||||
private void OnMobStateChanged(Entity<InnerBodyAnomalyComponent> ent, ref MobStateChangedEvent args)
|
||||
{
|
||||
if (args.NewMobState != MobState.Dead)
|
||||
return;
|
||||
|
||||
_anomaly.ChangeAnomalyHealth(ent, -2); //Shutdown it
|
||||
}
|
||||
|
||||
private void OnAnomalyShutdown(Entity<InnerBodyAnomalyComponent> ent, ref AnomalyShutdownEvent args)
|
||||
{
|
||||
RemoveAnomalyFromBody(ent);
|
||||
RemCompDeferred<InnerBodyAnomalyComponent>(ent);
|
||||
}
|
||||
|
||||
private void OnCompShutdown(Entity<InnerBodyAnomalyComponent> ent, ref ComponentShutdown args)
|
||||
{
|
||||
RemoveAnomalyFromBody(ent);
|
||||
}
|
||||
|
||||
private void RemoveAnomalyFromBody(Entity<InnerBodyAnomalyComponent> ent)
|
||||
{
|
||||
if (!ent.Comp.Injected)
|
||||
return;
|
||||
|
||||
if (_proto.TryIndex(ent.Comp.InjectionProto, out var injectedAnom))
|
||||
EntityManager.RemoveComponents(ent, injectedAnom.Components);
|
||||
|
||||
_stun.TryParalyze(ent, TimeSpan.FromSeconds(ent.Comp.StunDuration), true);
|
||||
|
||||
if (ent.Comp.EndMessage is not null &&
|
||||
_mind.TryGetMind(ent, out _, out var mindComponent) &&
|
||||
mindComponent.Session != null)
|
||||
{
|
||||
var message = Loc.GetString(ent.Comp.EndMessage);
|
||||
var wrappedMessage = Loc.GetString("chat-manager-server-wrap-message", ("message", message));
|
||||
_chat.ChatMessageToOne(ChatChannel.Server,
|
||||
message,
|
||||
wrappedMessage,
|
||||
default,
|
||||
false,
|
||||
mindComponent.Session.Channel,
|
||||
_messageColor);
|
||||
|
||||
|
||||
_popup.PopupEntity(message, ent, ent, PopupType.MediumCaution);
|
||||
|
||||
_adminLog.Add(LogType.Anomaly, LogImpact.Medium,$"{ToPrettyString(ent)} is no longer a host for the anomaly.");
|
||||
}
|
||||
|
||||
ent.Comp.Injected = false;
|
||||
RemCompDeferred<AnomalyComponent>(ent);
|
||||
}
|
||||
}
|
||||
@@ -202,6 +202,7 @@ namespace Content.Server.Explosion.EntitySystems
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
|
||||
private void HandleRattleTrigger(EntityUid uid, RattleComponent component, TriggerEvent args)
|
||||
{
|
||||
if (!TryComp<SubdermalImplantComponent>(uid, out var implanted))
|
||||
@@ -230,7 +231,7 @@ namespace Content.Server.Explosion.EntitySystems
|
||||
private void OnTriggerCollide(EntityUid uid, TriggerOnCollideComponent component, ref StartCollideEvent args)
|
||||
{
|
||||
if (args.OurFixtureId == component.FixtureID && (!component.IgnoreOtherNonHard || args.OtherFixture.Hard))
|
||||
Trigger(uid);
|
||||
Trigger(uid, args.OtherEntity);
|
||||
}
|
||||
|
||||
private void OnSpawnTriggered(EntityUid uid, TriggerOnSpawnComponent component, MapInitEvent args)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using System.Numerics;
|
||||
using Content.Shared.Anomaly.Effects;
|
||||
using Content.Shared.Anomaly.Prototypes;
|
||||
using Content.Shared.Damage;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Prototypes;
|
||||
@@ -16,7 +16,7 @@ namespace Content.Shared.Anomaly.Components;
|
||||
/// Anomalies and their related components were designed here: https://hackmd.io/@ss14-design/r1sQbkJOs
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, AutoGenerateComponentPause]
|
||||
[Access(typeof(SharedAnomalySystem))]
|
||||
[Access(typeof(SharedAnomalySystem), typeof(SharedInnerBodyAnomalySystem))]
|
||||
public sealed partial class AnomalyComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
@@ -184,21 +184,21 @@ public sealed partial class AnomalyComponent : Component
|
||||
/// <summary>
|
||||
/// The minimum amount of research points generated per second
|
||||
/// </summary>
|
||||
[DataField("minPointsPerSecond")]
|
||||
[DataField]
|
||||
public int MinPointsPerSecond = 10;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum amount of research points generated per second
|
||||
/// This doesn't include the point bonus for being unstable.
|
||||
/// </summary>
|
||||
[DataField("maxPointsPerSecond")]
|
||||
[DataField]
|
||||
public int MaxPointsPerSecond = 70;
|
||||
|
||||
/// <summary>
|
||||
/// The multiplier applied to the point value for the
|
||||
/// anomaly being above the <see cref="GrowthThreshold"/>
|
||||
/// </summary>
|
||||
[DataField("growingPointMultiplier")]
|
||||
[DataField]
|
||||
public float GrowingPointMultiplier = 1.5f;
|
||||
#endregion
|
||||
|
||||
@@ -252,10 +252,13 @@ public sealed partial class AnomalyComponent : Component
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField("offset")]
|
||||
public Vector2 FloatingOffset = new(0, 0.15f);
|
||||
public Vector2 FloatingOffset = new(0, 0);
|
||||
|
||||
public readonly string AnimationKey = "anomalyfloat";
|
||||
#endregion
|
||||
|
||||
[DataField]
|
||||
public bool DeleteEntity = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
using Content.Shared.Anomaly.Effects;
|
||||
using Content.Shared.Body.Prototypes;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Shared.Anomaly.Components;
|
||||
|
||||
/// <summary>
|
||||
/// An anomaly within the body of a living being. Controls the ability to return to the standard state.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState(true), Access(typeof(SharedInnerBodyAnomalySystem))]
|
||||
public sealed partial class InnerBodyAnomalyComponent : Component
|
||||
{
|
||||
[DataField]
|
||||
public bool Injected;
|
||||
|
||||
/// <summary>
|
||||
/// A prototype of an entity whose components will be added to the anomaly host **AND** then removed at the right time
|
||||
/// </summary>
|
||||
[DataField(required: true)]
|
||||
public EntProtoId? InjectionProto;
|
||||
|
||||
/// <summary>
|
||||
/// Duration of stun from the effect of the anomaly
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public float StunDuration = 4f;
|
||||
|
||||
/// <summary>
|
||||
/// A message sent in chat to a player who has become infected by an anomaly
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public LocId? StartMessage = null;
|
||||
|
||||
/// <summary>
|
||||
/// A message sent in chat to a player who has cleared an anomaly
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public LocId? EndMessage = "inner-anomaly-end-message";
|
||||
|
||||
/// <summary>
|
||||
/// Sound, playing on becoming anomaly
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public SoundSpecifier? StartSound = new SoundPathSpecifier("/Audio/Effects/inneranomaly.ogg");
|
||||
|
||||
/// <summary>
|
||||
/// Used to display messages to the player about their level of disease progression
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public float LastSeverityInformed = 0f;
|
||||
|
||||
/// <summary>
|
||||
/// The fallback sprite to be added on the original entity. Allows you to visually identify the feature and type of anomaly to other players
|
||||
/// </summary>
|
||||
[DataField, AutoNetworkedField]
|
||||
public SpriteSpecifier? FallbackSprite = null;
|
||||
|
||||
/// <summary>
|
||||
/// Ability to use unique sprites for different body types
|
||||
/// </summary>
|
||||
[DataField, AutoNetworkedField]
|
||||
public Dictionary<ProtoId<BodyPrototype>, SpriteSpecifier> SpeciesSprites = new();
|
||||
|
||||
/// <summary>
|
||||
/// The key of the entity layer into which the sprite will be inserted
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public string LayerMap = "inner_anomaly_layer";
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using Content.Shared.Anomaly.Effects;
|
||||
using Content.Shared.Whitelist;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared.Anomaly.Components;
|
||||
|
||||
/// <summary>
|
||||
/// On contact with an entity, if it meets the conditions, it will transfer the specified components to it
|
||||
/// </summary>
|
||||
[RegisterComponent, Access(typeof(SharedInnerBodyAnomalySystem))]
|
||||
public sealed partial class InnerBodyAnomalyInjectorComponent : Component
|
||||
{
|
||||
[DataField]
|
||||
public EntityWhitelist? Whitelist;
|
||||
|
||||
/// <summary>
|
||||
/// components that will be automatically removed after “curing”
|
||||
/// </summary>
|
||||
[DataField(required: true)]
|
||||
public ComponentRegistry InjectionComponents = default!;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
namespace Content.Shared.Anomaly.Effects;
|
||||
|
||||
public abstract class SharedInnerBodyAnomalySystem : EntitySystem
|
||||
{
|
||||
}
|
||||
@@ -1,13 +1,10 @@
|
||||
using Content.Shared.Administration.Logs;
|
||||
using Content.Shared.Anomaly.Components;
|
||||
using Content.Shared.Anomaly.Prototypes;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Physics;
|
||||
using Content.Shared.Popups;
|
||||
using Content.Shared.Weapons.Melee.Components;
|
||||
using Content.Shared.Weapons.Melee.Events;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Map.Components;
|
||||
@@ -21,6 +18,7 @@ using Robust.Shared.Timing;
|
||||
using Robust.Shared.Utility;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Content.Shared.Actions;
|
||||
|
||||
namespace Content.Shared.Anomaly;
|
||||
|
||||
@@ -36,6 +34,7 @@ public abstract class SharedAnomalySystem : EntitySystem
|
||||
[Dependency] protected readonly SharedPopupSystem Popup = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -145,7 +144,7 @@ public abstract class SharedAnomalySystem : EntitySystem
|
||||
if (!Timing.IsFirstTimePredicted)
|
||||
return;
|
||||
|
||||
Audio.PlayPvs(component.SupercriticalSound, uid);
|
||||
Audio.PlayPvs(component.SupercriticalSound, Transform(uid).Coordinates);
|
||||
|
||||
if (_net.IsServer)
|
||||
Log.Info($"Raising supercritical event. Entity: {ToPrettyString(uid)}");
|
||||
@@ -169,7 +168,8 @@ public abstract class SharedAnomalySystem : EntitySystem
|
||||
/// <param name="uid">The anomaly being shut down</param>
|
||||
/// <param name="component"></param>
|
||||
/// <param name="supercritical">Whether or not the anomaly ended via supercritical event</param>
|
||||
public void EndAnomaly(EntityUid uid, AnomalyComponent? component = null, bool supercritical = false)
|
||||
/// <param name="spawnCore">Create anomaly cores based on the result of completing an anomaly?</param>
|
||||
public void EndAnomaly(EntityUid uid, AnomalyComponent? component = null, bool supercritical = false, bool spawnCore = true)
|
||||
{
|
||||
// Logging before resolve, in case the anomaly has deleted itself.
|
||||
if (_net.IsServer)
|
||||
@@ -186,8 +186,13 @@ public abstract class SharedAnomalySystem : EntitySystem
|
||||
if (Terminating(uid) || _net.IsClient)
|
||||
return;
|
||||
|
||||
Spawn(supercritical ? component.CorePrototype : component.CoreInertPrototype, Transform(uid).Coordinates);
|
||||
if (spawnCore)
|
||||
{
|
||||
var core = Spawn(supercritical ? component.CorePrototype : component.CoreInertPrototype, Transform(uid).Coordinates);
|
||||
_transform.PlaceNextTo(core, uid);
|
||||
}
|
||||
|
||||
if (component.DeleteEntity)
|
||||
QueueDel(uid);
|
||||
}
|
||||
|
||||
@@ -458,3 +463,5 @@ public partial record struct AnomalySpawnSettings()
|
||||
/// </summary>
|
||||
public bool SpawnOnSeverityChanged { get; set; } = false;
|
||||
}
|
||||
|
||||
public sealed partial class ActionAnomalyPulseEvent : InstantActionEvent { }
|
||||
|
||||
@@ -231,3 +231,8 @@
|
||||
copyright: '"beep_landmine.ogg" by kaktuscsc of Discord for SS14'
|
||||
license: "CC-BY-SA-3.0"
|
||||
source: https://github.com/YuriyKiss/space-station-14/commit/971a135a9c83aed46e967aac9302ab5b35562b5f
|
||||
|
||||
- files: [inneranomaly.ogg]
|
||||
copyright: 'created by waveplaySFX on Freesound'
|
||||
license: "CC0-1.0"
|
||||
source: https://freesound.org/people/waveplaySFX/sounds/553744/
|
||||
|
||||
BIN
Resources/Audio/Effects/inneranomaly.ogg
Normal file
17
Resources/Locale/en-US/anomaly/inner_anomaly.ftl
Normal file
@@ -0,0 +1,17 @@
|
||||
inner-anomaly-start-message-pyro = You can feel the insane flame inside of you. You became the host of a pyroclastic anomaly.
|
||||
inner-anomaly-start-message-shock = Lightning bolts quivering at your fingertips! You became the host of a electric anomaly.
|
||||
inner-anomaly-start-message-shadow = There's an impenetrable darkness oozing out of you... You became the host of a shadow anomaly.
|
||||
inner-anomaly-start-message-frost = The icy frost is binding your bones. You became the host of a ice anomaly.
|
||||
inner-anomaly-start-message-flora = Leaves and flowers sprout through your skin! You became the host of a floral anomaly.
|
||||
inner-anomaly-start-message-bluespace = Your thoughts are racing like mad! You became the host of a bluespace anomaly.
|
||||
inner-anomaly-start-message-flesh = Your body is growing frantically. You became the host of a flesh anomaly.
|
||||
inner-anomaly-start-message-grav = Everything becames unnaturally heavy and light at the same time... You became the host of a gravity anomaly.
|
||||
inner-anomaly-start-message-tech = Your head is buzzing with the amount of chaotic information! You became the host of a tech anomaly.
|
||||
inner-anomaly-start-message-rock = The crystals are growing through your bones! You became the host of a rock anomaly.
|
||||
|
||||
inner-anomaly-end-message = The abnormal activity within you disappears without a trace....
|
||||
|
||||
inner-anomaly-severity-info-50 = You feel that the anomaly is taking over half your body.
|
||||
inner-anomaly-severity-info-75 = You feel that the anomaly is taking over a large part of your body.
|
||||
inner-anomaly-severity-info-90 = You feel that the anomaly has almost completely taken over your body.
|
||||
inner-anomaly-severity-info-100 = The anomaly inside you is growing uncontrollably, causing immense pain, and tearing you apart!
|
||||
9
Resources/Prototypes/Actions/anomaly.yml
Normal file
@@ -0,0 +1,9 @@
|
||||
- type: entity
|
||||
id: ActionAnomalyPulse
|
||||
name: Anomaly pulse
|
||||
description: Release a pulse of energy of your abnormal nature
|
||||
components:
|
||||
- type: InstantAction
|
||||
icon: Structures/Specific/anomaly.rsi/anom1.png
|
||||
event: !type:ActionAnomalyPulseEvent
|
||||
useDelay: 30
|
||||
@@ -9,6 +9,7 @@
|
||||
- sprite: Structures/Specific/anomaly.rsi
|
||||
state: anom1
|
||||
- type: RandomSpawner
|
||||
chance: 1
|
||||
prototypes:
|
||||
- AnomalyPyroclastic
|
||||
- AnomalyGravity
|
||||
@@ -21,7 +22,9 @@
|
||||
- AnomalyFlora
|
||||
- AnomalyShadow
|
||||
- AnomalyTech
|
||||
chance: 1
|
||||
rareChance: 0.3
|
||||
rarePrototypes:
|
||||
- RandomAnomalyInjectorSpawner
|
||||
offset: 0.15 # not to put it higher. The anomaly sychnronizer looks for anomalies within this radius, and if the radius is higher, the anomaly can be attracted from a neighboring tile.
|
||||
|
||||
- type: entity
|
||||
@@ -41,3 +44,27 @@
|
||||
- AnomalyRockUranium
|
||||
chance: 1
|
||||
offset: 0.15
|
||||
|
||||
- type: entity
|
||||
id: RandomAnomalyInjectorSpawner
|
||||
parent: MarkerBase
|
||||
components:
|
||||
- type: Sprite
|
||||
layers:
|
||||
- state: red
|
||||
- sprite: Structures/Specific/Anomalies/tech_anom.rsi
|
||||
state: pulse
|
||||
- type: RandomSpawner
|
||||
prototypes:
|
||||
- AnomalyTrapPyroclastic
|
||||
- AnomalyTrapElectricity
|
||||
- AnomalyTrapShadow
|
||||
- AnomalyTrapIce
|
||||
- AnomalyTrapFlora
|
||||
- AnomalyTrapBluespace
|
||||
- AnomalyTrapFlesh
|
||||
- AnomalyTrapGravity
|
||||
- AnomalyTrapTech
|
||||
- AnomalyTrapRock
|
||||
chance: 1
|
||||
|
||||
@@ -1316,6 +1316,7 @@
|
||||
tags:
|
||||
- VimPilot
|
||||
- DoorBumpOpener
|
||||
- AnomalyHost
|
||||
- type: Reactive
|
||||
groups:
|
||||
Flammable: [ Touch ]
|
||||
|
||||
@@ -13,6 +13,11 @@
|
||||
true
|
||||
NavSmash: !type:Bool
|
||||
true
|
||||
- type: NPCImprintingOnSpawnBehaviour
|
||||
spawnFriendsSearchRadius: 10
|
||||
whitelist:
|
||||
components:
|
||||
- Anomaly # Friendly to inner anomaly host
|
||||
- type: NpcFactionMember
|
||||
factions:
|
||||
- SimpleHostile
|
||||
|
||||
@@ -16,6 +16,11 @@
|
||||
- type: NpcFactionMember
|
||||
factions:
|
||||
- SimpleHostile
|
||||
- type: NPCImprintingOnSpawnBehaviour
|
||||
spawnFriendsSearchRadius: 10
|
||||
whitelist:
|
||||
components:
|
||||
- Anomaly # Friendly to inner anomaly host
|
||||
- type: MovementIgnoreGravity
|
||||
- type: MovementSpeedModifier
|
||||
baseWalkSpeed: 3.5
|
||||
|
||||
@@ -809,6 +809,7 @@
|
||||
- CannotSuicide
|
||||
- DoorBumpOpener
|
||||
- VimPilot
|
||||
- AnomalyHost
|
||||
- type: Loadout
|
||||
prototypes: [ MobMonkeyGear ]
|
||||
- type: Grammar
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
- FootstepSound
|
||||
- DoorBumpOpener
|
||||
- SpiderCraft
|
||||
- AnomalyHost
|
||||
- type: Butcherable
|
||||
butcheringType: Spike
|
||||
spawned:
|
||||
|
||||
@@ -212,6 +212,7 @@
|
||||
- CanPilot
|
||||
- FootstepSound
|
||||
- DoorBumpOpener
|
||||
- AnomalyHost
|
||||
|
||||
- type: entity
|
||||
save: false
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
description: An impossible object. Should you be standing this close to it?
|
||||
components:
|
||||
- type: Anomaly
|
||||
offset: 0, 0.15
|
||||
pulseSound:
|
||||
collection: RadiationPulse
|
||||
params:
|
||||
|
||||
@@ -0,0 +1,353 @@
|
||||
- type: entity
|
||||
id: AnomalyInjectionBase
|
||||
abstract: true
|
||||
components:
|
||||
- type: PointLight
|
||||
radius: 1.3
|
||||
energy: 2.5
|
||||
castShadows: false
|
||||
- type: ActionGrant
|
||||
actions:
|
||||
- ActionAnomalyPulse
|
||||
|
||||
- type: entity
|
||||
parent: AnomalyInjectionBase
|
||||
id: AnomalyInjectionPyroclastic
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: PointLight
|
||||
color: "#E25822"
|
||||
- type: PyroclasticAnomaly
|
||||
maximumIgnitionRadius: 3
|
||||
- type: TempAffectingAnomaly
|
||||
tempChangePerSecond: 10
|
||||
hotspotExposeTemperature: 500
|
||||
- type: GasProducerAnomaly
|
||||
releasedGas: 3
|
||||
releaseOnMaxSeverity: true
|
||||
spawnRadius: 4
|
||||
tileCount: 5
|
||||
tempChange: 420
|
||||
- type: ProjectileAnomaly
|
||||
projectilePrototype: ProjectileAnomalyFireball
|
||||
projectileSpeed: 0.5
|
||||
minProjectiles: 1
|
||||
maxProjectiles: 3
|
||||
|
||||
- type: entity
|
||||
parent: AnomalyInjectionBase
|
||||
id: AnomalyInjectionElectric
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: PointLight
|
||||
color: "#ffffaa"
|
||||
- type: ElectricityAnomaly
|
||||
minBoltCount: 1
|
||||
maxBoltCount: 3
|
||||
maxElectrocuteRange: 4
|
||||
maxElectrocuteDamage: 10
|
||||
maxElectrocuteDuration: 4
|
||||
|
||||
- type: entity
|
||||
parent: AnomalyInjectionBase
|
||||
id: AnomalyInjectionShadow
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: PointLight
|
||||
color: "#793a80"
|
||||
- type: EntitySpawnAnomaly
|
||||
entries:
|
||||
- settings:
|
||||
spawnOnPulse: true
|
||||
spawnOnSuperCritical: true
|
||||
minAmount: 5
|
||||
maxAmount: 10
|
||||
maxRange: 2
|
||||
spawns:
|
||||
- ShadowKudzuWeak
|
||||
- settings:
|
||||
spawnOnSuperCritical: true
|
||||
minAmount: 15
|
||||
maxAmount: 20
|
||||
maxRange: 25
|
||||
spawns:
|
||||
- ShadowKudzu
|
||||
|
||||
- type: entity
|
||||
parent: AnomalyInjectionBase
|
||||
id: AnomalyInjectionIce
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: PointLight
|
||||
color: "#befaff"
|
||||
- type: ExplosionAnomaly
|
||||
supercriticalExplosion: Cryo
|
||||
explosionTotalIntensity: 150
|
||||
explosionDropoff: 2
|
||||
explosionMaxTileIntensity: 20
|
||||
- type: ProjectileAnomaly
|
||||
projectilePrototype: ProjectileIcicle
|
||||
minProjectiles: 1
|
||||
maxProjectiles: 4
|
||||
- type: EntitySpawnAnomaly
|
||||
entries:
|
||||
- settings:
|
||||
spawnOnStabilityChanged: true
|
||||
minAmount: 3
|
||||
maxAmount: 8
|
||||
maxRange: 2
|
||||
spawns:
|
||||
- IceCrust
|
||||
- type: TempAffectingAnomaly
|
||||
tempChangePerSecond: -10
|
||||
hotspotExposeTemperature: -500
|
||||
- type: GasProducerAnomaly
|
||||
releasedGas: 8 # Frezon. Please replace if there is a better way to specify this
|
||||
releaseOnMaxSeverity: true
|
||||
spawnRadius: 0
|
||||
|
||||
- type: entity
|
||||
parent: AnomalyInjectionBase
|
||||
id: AnomalyInjectionFlora
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: PointLight
|
||||
color: "#6270bb"
|
||||
- type: TileSpawnAnomaly
|
||||
entries:
|
||||
- settings:
|
||||
spawnOnPulse: true
|
||||
minAmount: 2
|
||||
maxAmount: 5
|
||||
maxRange: 2
|
||||
floor: FloorAstroGrass
|
||||
- settings:
|
||||
spawnOnSuperCritical: true
|
||||
minAmount: 5
|
||||
maxAmount: 15
|
||||
maxRange: 7
|
||||
floor: FloorAstroGrass
|
||||
- type: EntitySpawnAnomaly
|
||||
entries:
|
||||
- settings:
|
||||
spawnOnPulse: true
|
||||
minAmount: 1
|
||||
maxAmount: 3
|
||||
maxRange: 1
|
||||
spawns:
|
||||
- KudzuFlowerFriendly
|
||||
- settings:
|
||||
spawnOnSuperCritical: true
|
||||
minAmount: 2
|
||||
maxAmount: 6
|
||||
maxRange: 3
|
||||
spawns:
|
||||
- KudzuFlowerAngry
|
||||
|
||||
- type: entity
|
||||
parent: AnomalyInjectionBase
|
||||
id: AnomalyInjectionBluespace
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: PointLight
|
||||
color: "#00ccff"
|
||||
- type: BluespaceAnomaly
|
||||
|
||||
- type: entity
|
||||
parent: AnomalyInjectionBase
|
||||
id: AnomalyInjectionFlesh
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: PointLight
|
||||
color: "#cb5b7e"
|
||||
- type: TileSpawnAnomaly
|
||||
entries:
|
||||
- settings:
|
||||
spawnOnPulse: true
|
||||
spawnOnStabilityChanged: true
|
||||
minAmount: 1
|
||||
maxAmount: 3
|
||||
maxRange: 2
|
||||
floor: FloorFlesh
|
||||
- settings:
|
||||
spawnOnSuperCritical: true
|
||||
minAmount: 5
|
||||
maxAmount: 15
|
||||
maxRange: 5
|
||||
floor: FloorFlesh
|
||||
- type: EntitySpawnAnomaly
|
||||
entries:
|
||||
- settings:
|
||||
spawnOnPulse: true
|
||||
minAmount: 1
|
||||
maxAmount: 2
|
||||
minRange: 1.5
|
||||
maxRange: 2.5
|
||||
spawns:
|
||||
- FleshBlocker
|
||||
- settings:
|
||||
spawnOnPulse: true
|
||||
maxAmount: 1
|
||||
minRange: 2.5
|
||||
maxRange: 4.5
|
||||
spawns:
|
||||
- MobFleshJared
|
||||
- MobFleshGolem
|
||||
- MobFleshClamp
|
||||
- MobFleshLover
|
||||
- settings:
|
||||
spawnOnSuperCritical: true
|
||||
minAmount: 5
|
||||
maxAmount: 8
|
||||
minRange: 5
|
||||
maxRange: 15
|
||||
spawns:
|
||||
- FleshBlocker
|
||||
- settings:
|
||||
spawnOnSuperCritical: true
|
||||
minAmount: 2
|
||||
maxAmount: 5
|
||||
maxRange: 8
|
||||
spawns:
|
||||
- MobFleshJared
|
||||
- MobFleshGolem
|
||||
- MobFleshClamp
|
||||
- MobFleshLover
|
||||
- settings:
|
||||
spawnOnSuperCritical: true
|
||||
minAmount: 2
|
||||
maxAmount: 4
|
||||
maxRange: 10
|
||||
spawns:
|
||||
- FleshKudzu
|
||||
- settings:
|
||||
spawnOnShutdown: true
|
||||
maxAmount: 2
|
||||
maxRange: 1
|
||||
spawns:
|
||||
- MobFleshJared
|
||||
- MobFleshGolem
|
||||
- MobFleshClamp
|
||||
- MobFleshLover
|
||||
- FleshKudzu
|
||||
|
||||
- type: entity
|
||||
parent: AnomalyInjectionBase
|
||||
id: AnomalyInjectionGravity
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: PointLight
|
||||
color: "#1e070e"
|
||||
- type: GravityAnomaly
|
||||
maxGravityWellRange: 4
|
||||
maxThrowRange: 3
|
||||
maxThrowStrength: 5
|
||||
spaceRange: 1
|
||||
- type: GravityWell
|
||||
maxRange: 0.7
|
||||
- type: SingularityDistortion
|
||||
intensity: 100
|
||||
falloffPower: 2.7
|
||||
|
||||
- type: entity
|
||||
parent: AnomalyInjectionBase
|
||||
id: AnomalyInjectionTech
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: PointLight
|
||||
color: "#56c1e8"
|
||||
- type: TechAnomaly
|
||||
linkRadius:
|
||||
min: 2
|
||||
max: 5
|
||||
linkCountPerPulse:
|
||||
min: 1
|
||||
max: 4
|
||||
linkCountSupercritical: 15
|
||||
- type: DeviceLinkSource
|
||||
ports:
|
||||
- Pulse
|
||||
- Timer
|
||||
- type: WirelessNetworkConnection
|
||||
range: 10
|
||||
- type: DeviceNetwork
|
||||
deviceNetId: Wireless
|
||||
receiveFrequencyId: BasicDevice
|
||||
|
||||
- type: entity
|
||||
parent: AnomalyInjectionBase
|
||||
id: AnomalyInjectionRock
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: PointLight
|
||||
color: "#5ca8cb"
|
||||
- type: TileSpawnAnomaly
|
||||
entries:
|
||||
- settings:
|
||||
spawnOnPulse: true
|
||||
minAmount: 7
|
||||
maxAmount: 10
|
||||
maxRange: 4
|
||||
floor: FloorAsteroidTile
|
||||
- settings:
|
||||
spawnOnSuperCritical: true
|
||||
minAmount: 15
|
||||
maxAmount: 25
|
||||
maxRange: 6
|
||||
floor: FloorAsteroidTile
|
||||
- type: EntitySpawnAnomaly
|
||||
entries:
|
||||
- settings:
|
||||
spawnOnPulse: true
|
||||
minAmount: 4
|
||||
maxAmount: 8
|
||||
minRange: 1
|
||||
maxRange: 3
|
||||
spawns:
|
||||
- WallSpawnAsteroid
|
||||
- WallSpawnAsteroid
|
||||
- WallSpawnAsteroid
|
||||
- WallSpawnAsteroid
|
||||
- WallSpawnAsteroid
|
||||
- WallSpawnAsteroidSilver
|
||||
- WallSpawnAsteroidSilverCrab
|
||||
- WallSpawnAsteroidIron
|
||||
- WallSpawnAsteroidIronCrab
|
||||
- WallSpawnAsteroidQuartz
|
||||
- WallSpawnAsteroidQuartzCrab
|
||||
- settings:
|
||||
spawnOnPulse: true
|
||||
maxAmount: 3
|
||||
minRange: 2.5
|
||||
maxRange: 4.5
|
||||
spawns:
|
||||
- CrystalPink
|
||||
- CrystalCyan
|
||||
- settings:
|
||||
spawnOnSuperCritical: true
|
||||
minAmount: 15
|
||||
maxAmount: 20
|
||||
minRange: 2
|
||||
maxRange: 7
|
||||
spawns:
|
||||
- CrystalPink
|
||||
- CrystalCyan
|
||||
- WallSpawnAsteroid
|
||||
- WallSpawnAsteroid
|
||||
- WallSpawnAsteroid
|
||||
- WallSpawnAsteroid
|
||||
- WallSpawnAsteroidSilver
|
||||
- WallSpawnAsteroidSilverCrab
|
||||
- WallSpawnAsteroidIron
|
||||
- WallSpawnAsteroidIronCrab
|
||||
- WallSpawnAsteroidQuartz
|
||||
- WallSpawnAsteroidQuartzCrab
|
||||
- settings:
|
||||
spawnOnSuperCritical: true
|
||||
minAmount: 3
|
||||
maxAmount: 5
|
||||
maxRange: 3
|
||||
spawns:
|
||||
- MobSpawnCrabSilver
|
||||
- MobSpawnCrabIron
|
||||
- MobSpawnCrabQuartz
|
||||
@@ -0,0 +1,320 @@
|
||||
- type: entity
|
||||
name: anomaly injector
|
||||
parent: MarkerBase
|
||||
id: BaseAnomalyInjector
|
||||
abstract: true
|
||||
components:
|
||||
- type: Physics
|
||||
bodyType: Static
|
||||
fixedRotation: true
|
||||
- type: AmbientSound
|
||||
range: 5
|
||||
volume: -5
|
||||
sound:
|
||||
path: /Audio/Ambience/anomaly_drone.ogg
|
||||
- type: Fixtures
|
||||
fixtures:
|
||||
anom:
|
||||
shape:
|
||||
!type:PhysShapeCircle
|
||||
radius: 2.27 # i love 27
|
||||
hard: false
|
||||
mask:
|
||||
- MobMask
|
||||
layer:
|
||||
- MobLayer
|
||||
- type: InnerBodyAnomalyInjector
|
||||
whitelist:
|
||||
tags:
|
||||
- AnomalyHost
|
||||
|
||||
- type: entity
|
||||
parent: BaseAnomalyInjector
|
||||
id: AnomalyTrapPyroclastic
|
||||
suffix: Pyroclastic
|
||||
components:
|
||||
- type: Sprite
|
||||
layers:
|
||||
- state: pink
|
||||
- sprite: Structures/Specific/Anomalies/pyro_anom.rsi
|
||||
state: pulse
|
||||
- sprite: Mobs/Species/Human/parts.rsi
|
||||
state: full
|
||||
- type: InnerBodyAnomalyInjector
|
||||
injectionComponents:
|
||||
- type: Anomaly
|
||||
deleteEntity: false
|
||||
maxPointsPerSecond: 100
|
||||
corePrototype: AnomalyCorePyroclastic
|
||||
- type: InnerBodyAnomaly
|
||||
injectionProto: AnomalyInjectionPyroclastic
|
||||
startMessage: inner-anomaly-start-message-pyro
|
||||
fallbackSprite:
|
||||
sprite: Structures/Specific/Anomalies/inner_anom_layer.rsi
|
||||
state: fire
|
||||
speciesSprites:
|
||||
Vox:
|
||||
sprite: Structures/Specific/Anomalies/inner_anom_layer.rsi
|
||||
state: fire_VOX
|
||||
|
||||
- type: entity
|
||||
parent: BaseAnomalyInjector
|
||||
id: AnomalyTrapElectricity
|
||||
suffix: Electricity
|
||||
components:
|
||||
- type: Sprite
|
||||
layers:
|
||||
- state: pink
|
||||
- sprite: Structures/Specific/anomaly.rsi
|
||||
state: anom3-pulse
|
||||
- sprite: Mobs/Species/Human/parts.rsi
|
||||
state: full
|
||||
- type: InnerBodyAnomalyInjector
|
||||
injectionComponents:
|
||||
- type: Anomaly
|
||||
deleteEntity: false
|
||||
maxPointsPerSecond: 100
|
||||
corePrototype: AnomalyCoreElectricity
|
||||
- type: InnerBodyAnomaly
|
||||
injectionProto: AnomalyInjectionElectric
|
||||
startMessage: inner-anomaly-start-message-shock
|
||||
fallbackSprite:
|
||||
sprite: Structures/Specific/Anomalies/inner_anom_layer.rsi
|
||||
state: shock
|
||||
speciesSprites:
|
||||
Vox:
|
||||
sprite: Structures/Specific/Anomalies/inner_anom_layer.rsi
|
||||
state: shock_VOX
|
||||
|
||||
- type: entity
|
||||
parent: BaseAnomalyInjector
|
||||
id: AnomalyTrapShadow
|
||||
suffix: Shadow
|
||||
components:
|
||||
- type: Sprite
|
||||
layers:
|
||||
- state: pink
|
||||
- sprite: Structures/Specific/Anomalies/shadow_anom.rsi
|
||||
state: pulse
|
||||
- sprite: Mobs/Species/Human/parts.rsi
|
||||
state: full
|
||||
- type: InnerBodyAnomalyInjector
|
||||
injectionComponents:
|
||||
- type: Anomaly
|
||||
deleteEntity: false
|
||||
maxPointsPerSecond: 100
|
||||
corePrototype: AnomalyCoreShadow
|
||||
- type: InnerBodyAnomaly
|
||||
injectionProto: AnomalyInjectionShadow
|
||||
startMessage: inner-anomaly-start-message-shadow
|
||||
fallbackSprite:
|
||||
sprite: Structures/Specific/Anomalies/inner_anom_layer.rsi
|
||||
state: shadow
|
||||
speciesSprites:
|
||||
Vox:
|
||||
sprite: Structures/Specific/Anomalies/inner_anom_layer.rsi
|
||||
state: shadow_VOX
|
||||
|
||||
- type: entity
|
||||
parent: BaseAnomalyInjector
|
||||
id: AnomalyTrapIce
|
||||
suffix: Ice
|
||||
components:
|
||||
- type: Sprite
|
||||
layers:
|
||||
- state: pink
|
||||
- sprite: Structures/Specific/Anomalies/ice_anom.rsi
|
||||
state: pulse
|
||||
- sprite: Mobs/Species/Human/parts.rsi
|
||||
state: full
|
||||
- type: InnerBodyAnomalyInjector
|
||||
injectionComponents:
|
||||
- type: Anomaly
|
||||
deleteEntity: false
|
||||
maxPointsPerSecond: 100
|
||||
corePrototype: AnomalyCoreIce
|
||||
- type: InnerBodyAnomaly
|
||||
injectionProto: AnomalyInjectionIce
|
||||
startMessage: inner-anomaly-start-message-frost
|
||||
fallbackSprite:
|
||||
sprite: Structures/Specific/Anomalies/inner_anom_layer.rsi
|
||||
state: frost
|
||||
speciesSprites:
|
||||
Vox:
|
||||
sprite: Structures/Specific/Anomalies/inner_anom_layer.rsi
|
||||
state: frost_VOX
|
||||
|
||||
- type: entity
|
||||
parent: BaseAnomalyInjector
|
||||
id: AnomalyTrapFlora
|
||||
suffix: Flora
|
||||
components:
|
||||
- type: Sprite
|
||||
layers:
|
||||
- state: pink
|
||||
- sprite: Structures/Specific/Anomalies/flora_anom.rsi
|
||||
state: pulse
|
||||
- sprite: Mobs/Species/Human/parts.rsi
|
||||
state: full
|
||||
- type: InnerBodyAnomalyInjector
|
||||
injectionComponents:
|
||||
- type: Anomaly
|
||||
deleteEntity: false
|
||||
maxPointsPerSecond: 100
|
||||
corePrototype: AnomalyCoreFlora
|
||||
- type: InnerBodyAnomaly
|
||||
injectionProto: AnomalyInjectionFlora
|
||||
startMessage: inner-anomaly-start-message-flora
|
||||
fallbackSprite:
|
||||
sprite: Structures/Specific/Anomalies/inner_anom_layer.rsi
|
||||
state: flora
|
||||
speciesSprites:
|
||||
Vox:
|
||||
sprite: Structures/Specific/Anomalies/inner_anom_layer.rsi
|
||||
state: flora_VOX
|
||||
|
||||
- type: entity
|
||||
parent: BaseAnomalyInjector
|
||||
id: AnomalyTrapBluespace
|
||||
suffix: Bluespace
|
||||
components:
|
||||
- type: Sprite
|
||||
layers:
|
||||
- state: pink
|
||||
- sprite: Structures/Specific/anomaly.rsi
|
||||
state: anom4-pulse
|
||||
- sprite: Mobs/Species/Human/parts.rsi
|
||||
state: full
|
||||
- type: InnerBodyAnomalyInjector
|
||||
injectionComponents:
|
||||
- type: Anomaly
|
||||
deleteEntity: false
|
||||
maxPointsPerSecond: 100
|
||||
corePrototype: AnomalyCoreBluespace
|
||||
- type: InnerBodyAnomaly
|
||||
injectionProto: AnomalyInjectionBluespace
|
||||
startMessage: inner-anomaly-start-message-bluespace
|
||||
fallbackSprite:
|
||||
sprite: Structures/Specific/Anomalies/inner_anom_layer.rsi
|
||||
state: bluespace
|
||||
speciesSprites:
|
||||
Vox:
|
||||
sprite: Structures/Specific/Anomalies/inner_anom_layer.rsi
|
||||
state: bluespace_VOX
|
||||
|
||||
- type: entity
|
||||
parent: BaseAnomalyInjector
|
||||
id: AnomalyTrapFlesh
|
||||
suffix: Flesh
|
||||
components:
|
||||
- type: Sprite
|
||||
layers:
|
||||
- state: pink
|
||||
- sprite: Structures/Specific/anomaly.rsi
|
||||
state: anom5-pulse
|
||||
- sprite: Mobs/Species/Human/parts.rsi
|
||||
state: full
|
||||
- type: InnerBodyAnomalyInjector
|
||||
injectionComponents:
|
||||
- type: Anomaly
|
||||
deleteEntity: false
|
||||
maxPointsPerSecond: 100
|
||||
corePrototype: AnomalyCoreFlesh
|
||||
- type: InnerBodyAnomaly
|
||||
injectionProto: AnomalyInjectionFlesh
|
||||
startMessage: inner-anomaly-start-message-flesh
|
||||
fallbackSprite:
|
||||
sprite: Structures/Specific/Anomalies/inner_anom_layer.rsi
|
||||
state: flesh
|
||||
speciesSprites:
|
||||
Vox:
|
||||
sprite: Structures/Specific/Anomalies/inner_anom_layer.rsi
|
||||
state: flesh_VOX
|
||||
|
||||
- type: entity
|
||||
parent: BaseAnomalyInjector
|
||||
id: AnomalyTrapGravity
|
||||
suffix: Gravity
|
||||
components:
|
||||
- type: Sprite
|
||||
layers:
|
||||
- state: pink
|
||||
- sprite: Structures/Specific/anomaly.rsi
|
||||
state: anom2-pulse
|
||||
- sprite: Mobs/Species/Human/parts.rsi
|
||||
state: full
|
||||
- type: InnerBodyAnomalyInjector
|
||||
injectionComponents:
|
||||
- type: Anomaly
|
||||
deleteEntity: false
|
||||
maxPointsPerSecond: 100
|
||||
corePrototype: AnomalyCoreGravity
|
||||
- type: InnerBodyAnomaly
|
||||
injectionProto: AnomalyInjectionGravity
|
||||
startMessage: inner-anomaly-start-message-grav
|
||||
fallbackSprite:
|
||||
sprite: Structures/Specific/Anomalies/inner_anom_layer.rsi
|
||||
state: grav
|
||||
speciesSprites:
|
||||
Vox:
|
||||
sprite: Structures/Specific/Anomalies/inner_anom_layer.rsi
|
||||
state: grav_VOX
|
||||
|
||||
- type: entity
|
||||
parent: BaseAnomalyInjector
|
||||
id: AnomalyTrapTech
|
||||
suffix: Tech
|
||||
components:
|
||||
- type: Sprite
|
||||
layers:
|
||||
- state: pink
|
||||
- sprite: Structures/Specific/Anomalies/tech_anom.rsi
|
||||
state: pulse
|
||||
- sprite: Mobs/Species/Human/parts.rsi
|
||||
state: full
|
||||
- type: InnerBodyAnomalyInjector
|
||||
injectionComponents:
|
||||
- type: Anomaly
|
||||
deleteEntity: false
|
||||
maxPointsPerSecond: 100
|
||||
corePrototype: AnomalyCoreTech
|
||||
- type: InnerBodyAnomaly
|
||||
injectionProto: AnomalyInjectionTech
|
||||
startMessage: inner-anomaly-start-message-tech
|
||||
fallbackSprite:
|
||||
sprite: Structures/Specific/Anomalies/inner_anom_layer.rsi
|
||||
state: tech
|
||||
speciesSprites:
|
||||
Vox:
|
||||
sprite: Structures/Specific/Anomalies/inner_anom_layer.rsi
|
||||
state: tech_VOX
|
||||
|
||||
- type: entity
|
||||
parent: BaseAnomalyInjector
|
||||
id: AnomalyTrapRock
|
||||
suffix: Rock
|
||||
components:
|
||||
- type: Sprite
|
||||
layers:
|
||||
- state: pink
|
||||
- sprite: Structures/Specific/anomaly.rsi
|
||||
state: anom6-pulse
|
||||
color: "#5ca8cb"
|
||||
- sprite: Mobs/Species/Human/parts.rsi
|
||||
state: full
|
||||
- type: InnerBodyAnomalyInjector
|
||||
injectionComponents:
|
||||
- type: Anomaly
|
||||
deleteEntity: false
|
||||
maxPointsPerSecond: 100
|
||||
corePrototype: AnomalyCoreRock
|
||||
- type: InnerBodyAnomaly
|
||||
injectionProto: AnomalyInjectionRock
|
||||
startMessage: inner-anomaly-start-message-rock
|
||||
fallbackSprite:
|
||||
sprite: Structures/Specific/Anomalies/inner_anom_layer.rsi
|
||||
state: rock
|
||||
speciesSprites:
|
||||
Vox:
|
||||
sprite: Structures/Specific/Anomalies/inner_anom_layer.rsi
|
||||
state: rock_VOX
|
||||
@@ -15,6 +15,9 @@
|
||||
- type: Tag
|
||||
id: Ambrosia
|
||||
|
||||
- type: Tag
|
||||
id: AnomalyHost
|
||||
|
||||
- type: Tag
|
||||
id: AppraisalTool
|
||||
|
||||
|
||||
|
After Width: | Height: | Size: 864 B |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 1007 B |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
@@ -0,0 +1,643 @@
|
||||
{
|
||||
"version": 1,
|
||||
"size": {
|
||||
"x": 32,
|
||||
"y": 32
|
||||
},
|
||||
"license": "CC-BY-SA-3.0",
|
||||
"copyright": "Created by TheShuEd (github) for Space Station 14",
|
||||
"states": [
|
||||
{
|
||||
"name": "bluespace",
|
||||
"directions": 4,
|
||||
"delays": [
|
||||
[
|
||||
0.3,
|
||||
0.3,
|
||||
0.3,
|
||||
0.3
|
||||
],
|
||||
[
|
||||
0.3,
|
||||
0.3,
|
||||
0.3,
|
||||
0.3
|
||||
],
|
||||
[
|
||||
0.3,
|
||||
0.3,
|
||||
0.3,
|
||||
0.3
|
||||
],
|
||||
[
|
||||
0.3,
|
||||
0.3,
|
||||
0.3,
|
||||
0.3
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "bluespace_VOX",
|
||||
"directions": 4,
|
||||
"delays": [
|
||||
[
|
||||
0.3,
|
||||
0.3,
|
||||
0.3,
|
||||
0.3
|
||||
],
|
||||
[
|
||||
0.3,
|
||||
0.3,
|
||||
0.3,
|
||||
0.3
|
||||
],
|
||||
[
|
||||
0.3,
|
||||
0.3,
|
||||
0.3,
|
||||
0.3
|
||||
],
|
||||
[
|
||||
0.3,
|
||||
0.3,
|
||||
0.3,
|
||||
0.3
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "fire",
|
||||
"directions": 4,
|
||||
"delays": [
|
||||
[
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2
|
||||
],
|
||||
[
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2
|
||||
],
|
||||
[
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2
|
||||
],
|
||||
[
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "fire_VOX",
|
||||
"directions": 4,
|
||||
"delays": [
|
||||
[
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2
|
||||
],
|
||||
[
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2
|
||||
],
|
||||
[
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2
|
||||
],
|
||||
[
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "flesh",
|
||||
"directions": 4,
|
||||
"delays": [
|
||||
[
|
||||
0.8,
|
||||
0.2,
|
||||
0.2
|
||||
],
|
||||
[
|
||||
0.8,
|
||||
0.2,
|
||||
0.2
|
||||
],
|
||||
[
|
||||
0.8,
|
||||
0.2,
|
||||
0.2
|
||||
],
|
||||
[
|
||||
0.8,
|
||||
0.2,
|
||||
0.2
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "flesh_VOX",
|
||||
"directions": 4,
|
||||
"delays": [
|
||||
[
|
||||
0.8,
|
||||
0.2,
|
||||
0.2
|
||||
],
|
||||
[
|
||||
0.8,
|
||||
0.2,
|
||||
0.2
|
||||
],
|
||||
[
|
||||
0.8,
|
||||
0.2,
|
||||
0.2
|
||||
],
|
||||
[
|
||||
0.8,
|
||||
0.2,
|
||||
0.2
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "flora",
|
||||
"directions": 4,
|
||||
"delays": [
|
||||
[
|
||||
0.3,
|
||||
0.3,
|
||||
0.3,
|
||||
0.3,
|
||||
0.3,
|
||||
0.3
|
||||
],
|
||||
[
|
||||
0.3,
|
||||
0.3,
|
||||
0.3,
|
||||
0.3,
|
||||
0.3,
|
||||
0.3
|
||||
],
|
||||
[
|
||||
0.3,
|
||||
0.3,
|
||||
0.3,
|
||||
0.3,
|
||||
0.3,
|
||||
0.3
|
||||
],
|
||||
[
|
||||
0.3,
|
||||
0.3,
|
||||
0.3,
|
||||
0.3,
|
||||
0.3,
|
||||
0.3
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "flora_VOX",
|
||||
"directions": 4,
|
||||
"delays": [
|
||||
[
|
||||
0.3,
|
||||
0.3,
|
||||
0.3,
|
||||
0.3,
|
||||
0.3,
|
||||
0.3
|
||||
],
|
||||
[
|
||||
0.3,
|
||||
0.3,
|
||||
0.3,
|
||||
0.3,
|
||||
0.3,
|
||||
0.3
|
||||
],
|
||||
[
|
||||
0.3,
|
||||
0.3,
|
||||
0.3,
|
||||
0.3,
|
||||
0.3,
|
||||
0.3
|
||||
],
|
||||
[
|
||||
0.3,
|
||||
0.3,
|
||||
0.3,
|
||||
0.3,
|
||||
0.3,
|
||||
0.3
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "frost",
|
||||
"directions": 4,
|
||||
"delays": [
|
||||
[
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2
|
||||
],
|
||||
[
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2
|
||||
],
|
||||
[
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2
|
||||
],
|
||||
[
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "frost_VOX",
|
||||
"directions": 4,
|
||||
"delays": [
|
||||
[
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2
|
||||
],
|
||||
[
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2
|
||||
],
|
||||
[
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2
|
||||
],
|
||||
[
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "grav",
|
||||
"directions": 4,
|
||||
"delays": [
|
||||
[
|
||||
0.3,
|
||||
0.3,
|
||||
0.3,
|
||||
0.3
|
||||
],
|
||||
[
|
||||
0.3,
|
||||
0.3,
|
||||
0.3,
|
||||
0.3
|
||||
],
|
||||
[
|
||||
0.3,
|
||||
0.3,
|
||||
0.3,
|
||||
0.3
|
||||
],
|
||||
[
|
||||
0.3,
|
||||
0.3,
|
||||
0.3,
|
||||
0.3
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "grav_VOX",
|
||||
"directions": 4,
|
||||
"delays": [
|
||||
[
|
||||
0.3,
|
||||
0.3,
|
||||
0.3,
|
||||
0.3
|
||||
],
|
||||
[
|
||||
0.3,
|
||||
0.3,
|
||||
0.3,
|
||||
0.3
|
||||
],
|
||||
[
|
||||
0.3,
|
||||
0.3,
|
||||
0.3,
|
||||
0.3
|
||||
],
|
||||
[
|
||||
0.3,
|
||||
0.3,
|
||||
0.3,
|
||||
0.3
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "rock",
|
||||
"directions": 4,
|
||||
"delays": [
|
||||
[
|
||||
0.9,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2
|
||||
],
|
||||
[
|
||||
0.9,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2
|
||||
],
|
||||
[
|
||||
0.9,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2
|
||||
],
|
||||
[
|
||||
0.9,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "rock_VOX",
|
||||
"directions": 4,
|
||||
"delays": [
|
||||
[
|
||||
0.9,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2
|
||||
],
|
||||
[
|
||||
0.9,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2
|
||||
],
|
||||
[
|
||||
0.9,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2
|
||||
],
|
||||
[
|
||||
0.9,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "shadow",
|
||||
"directions": 4,
|
||||
"delays": [
|
||||
[
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2
|
||||
],
|
||||
[
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2
|
||||
],
|
||||
[
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2
|
||||
],
|
||||
[
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "shadow_VOX",
|
||||
"directions": 4,
|
||||
"delays": [
|
||||
[
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2
|
||||
],
|
||||
[
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2
|
||||
],
|
||||
[
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2
|
||||
],
|
||||
[
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "shock",
|
||||
"directions": 4,
|
||||
"delays": [
|
||||
[
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2
|
||||
],
|
||||
[
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2
|
||||
],
|
||||
[
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2
|
||||
],
|
||||
[
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "shock_VOX",
|
||||
"directions": 4,
|
||||
"delays": [
|
||||
[
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2
|
||||
],
|
||||
[
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2
|
||||
],
|
||||
[
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2
|
||||
],
|
||||
[
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "tech",
|
||||
"directions": 4,
|
||||
"delays": [
|
||||
[
|
||||
0.2,
|
||||
0.4,
|
||||
0.2,
|
||||
0.4
|
||||
],
|
||||
[
|
||||
0.2,
|
||||
0.4,
|
||||
0.2,
|
||||
0.4
|
||||
],
|
||||
[
|
||||
0.2,
|
||||
0.4,
|
||||
0.2,
|
||||
0.4
|
||||
],
|
||||
[
|
||||
0.2,
|
||||
0.4,
|
||||
0.2,
|
||||
0.4
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "tech_VOX",
|
||||
"directions": 4,
|
||||
"delays": [
|
||||
[
|
||||
0.2,
|
||||
0.4,
|
||||
0.2,
|
||||
0.4
|
||||
],
|
||||
[
|
||||
0.2,
|
||||
0.4,
|
||||
0.2,
|
||||
0.4
|
||||
],
|
||||
[
|
||||
0.2,
|
||||
0.4,
|
||||
0.2,
|
||||
0.4
|
||||
],
|
||||
[
|
||||
0.2,
|
||||
0.4,
|
||||
0.2,
|
||||
0.4
|
||||
]
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 768 B |
|
After Width: | Height: | Size: 1002 B |
|
After Width: | Height: | Size: 879 B |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 429 B After Width: | Height: | Size: 513 B |