diff --git a/Content.Client/Anomaly/AnomalySystem.cs b/Content.Client/Anomaly/AnomalySystem.cs
index 57f1f90f10..b8e3e74393 100644
--- a/Content.Client/Anomaly/AnomalySystem.cs
+++ b/Content.Client/Anomaly/AnomalySystem.cs
@@ -1,4 +1,5 @@
-using Content.Shared.Anomaly;
+using Content.Client.Gravity;
+using Content.Shared.Anomaly;
using Content.Shared.Anomaly.Components;
using Robust.Client.GameObjects;
using Robust.Shared.Timing;
@@ -8,6 +9,7 @@ namespace Content.Client.Anomaly;
public sealed class AnomalySystem : SharedAnomalySystem
{
[Dependency] private readonly IGameTiming _timing = default!;
+ [Dependency] private readonly FloatingVisualizerSystem _floating = default!;
///
public override void Initialize()
@@ -15,6 +17,20 @@ public sealed class AnomalySystem : SharedAnomalySystem
base.Initialize();
SubscribeLocalEvent(OnAppearanceChanged);
+ SubscribeLocalEvent(OnStartup);
+ SubscribeLocalEvent(OnAnimationComplete);
+ }
+
+ private void OnStartup(EntityUid uid, AnomalyComponent component, ComponentStartup args)
+ {
+ _floating.FloatAnimation(uid, component.FloatingOffset, component.AnimationKey, component.AnimationTime);
+ }
+
+ private void OnAnimationComplete(EntityUid uid, AnomalyComponent component, AnimationCompletedEvent args)
+ {
+ if (args.Key != component.AnimationKey)
+ return;
+ _floating.FloatAnimation(uid, component.FloatingOffset, component.AnimationKey, component.AnimationTime);
}
private void OnAppearanceChanged(EntityUid uid, AnomalyComponent component, ref AppearanceChangeEvent args)
diff --git a/Content.Server/Anomaly/AnomalySystem.Generator.cs b/Content.Server/Anomaly/AnomalySystem.Generator.cs
index 2baacf6b52..7a2deb8611 100644
--- a/Content.Server/Anomaly/AnomalySystem.Generator.cs
+++ b/Content.Server/Anomaly/AnomalySystem.Generator.cs
@@ -4,7 +4,10 @@ using Content.Server.Power.EntitySystems;
using Content.Shared.Anomaly;
using Content.Shared.CCVar;
using Content.Shared.Materials;
+using Content.Shared.Physics;
using Robust.Shared.Map.Components;
+using Robust.Shared.Physics;
+using Robust.Shared.Physics.Components;
namespace Content.Server.Anomaly;
@@ -91,12 +94,32 @@ public sealed partial class AnomalySystem
var randomY = Random.Next((int) gridBounds.Bottom, (int)gridBounds.Top);
var tile = new Vector2i(randomX, randomY);
- if (_atmosphere.IsTileSpace(grid, xform.MapUid, tile,
- mapGridComp: gridComp) || _atmosphere.IsTileAirBlocked(grid, tile, mapGridComp: gridComp))
+
+ // no air-blocked areas.
+ if (_atmosphere.IsTileSpace(grid, xform.MapUid, tile, mapGridComp: gridComp) ||
+ _atmosphere.IsTileAirBlocked(grid, tile, mapGridComp: gridComp))
{
continue;
}
+ // don't spawn inside of solid objects
+ var physQuery = GetEntityQuery();
+ var valid = true;
+ foreach (var ent in gridComp.GetAnchoredEntities(tile))
+ {
+ if (!physQuery.TryGetComponent(ent, out var body))
+ continue;
+ if (body.BodyType != BodyType.Static ||
+ !body.Hard ||
+ (body.CollisionLayer & (int) CollisionGroup.Impassable) == 0)
+ continue;
+
+ valid = false;
+ break;
+ }
+ if (!valid)
+ continue;
+
targetCoords = gridComp.GridTileToLocal(tile);
break;
}
diff --git a/Content.Server/Anomaly/AnomalySystem.cs b/Content.Server/Anomaly/AnomalySystem.cs
index 8dce08c406..e48fc328c4 100644
--- a/Content.Server/Anomaly/AnomalySystem.cs
+++ b/Content.Server/Anomaly/AnomalySystem.cs
@@ -23,7 +23,6 @@ public sealed partial class AnomalySystem : SharedAnomalySystem
[Dependency] private readonly DoAfterSystem _doAfter = default!;
[Dependency] private readonly ExplosionSystem _explosion = default!;
[Dependency] private readonly MaterialStorageSystem _material = default!;
- [Dependency] private readonly TransformSystem _transform = default!;
[Dependency] private readonly UserInterfaceSystem _ui = default!;
public const float MinParticleVariation = 0.8f;
@@ -100,13 +99,13 @@ public sealed partial class AnomalySystem : SharedAnomalySystem
var multiplier = 1f;
if (component.Stability > component.GrowthThreshold)
multiplier = component.GrowingPointMultiplier; //more points for unstable
- else if (component.Stability < component.DecayThreshold)
- multiplier = component.DecayingPointMultiplier; //less points if it's dying
//penalty of up to 50% based on health
multiplier *= MathF.Pow(1.5f, component.Health) - 0.5f;
- return (int) ((component.MaxPointsPerSecond - component.MinPointsPerSecond) * component.Severity * multiplier);
+ var severityValue = 1 / (1 + MathF.Pow(MathF.E, -7 * (component.Severity - 0.5f)));
+
+ return (int) ((component.MaxPointsPerSecond - component.MinPointsPerSecond) * severityValue * multiplier) + component.MinPointsPerSecond;
}
///
diff --git a/Content.Server/Anomaly/Effects/ElectricityAnomalySystem.cs b/Content.Server/Anomaly/Effects/ElectricityAnomalySystem.cs
index 55c7b1bfa5..6c473d3570 100644
--- a/Content.Server/Anomaly/Effects/ElectricityAnomalySystem.cs
+++ b/Content.Server/Anomaly/Effects/ElectricityAnomalySystem.cs
@@ -6,11 +6,13 @@ using Content.Shared.Anomaly.Effects.Components;
using Content.Shared.Mobs.Components;
using Content.Shared.StatusEffect;
using Robust.Shared.Random;
+using Robust.Shared.Timing;
namespace Content.Server.Anomaly.Effects;
public sealed class ElectricityAnomalySystem : EntitySystem
{
+ [Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly LightningSystem _lightning = default!;
[Dependency] private readonly ElectrocutionSystem _electrocution = default!;
@@ -25,16 +27,12 @@ public sealed class ElectricityAnomalySystem : EntitySystem
private void OnPulse(EntityUid uid, ElectricityAnomalyComponent component, ref AnomalyPulseEvent args)
{
- var range = component.MaxElectrocuteRange * args.Stabiltiy;
- var damage = (int) (component.MaxElectrocuteDamage * args.Severity);
- var duration = component.MaxElectrocuteDuration * args.Severity;
-
+ var range = component.MaxElectrocuteRange * args.Stability;
var xform = Transform(uid);
- foreach (var comp in _lookup.GetComponentsInRange(xform.MapPosition, range))
+ foreach (var comp in _lookup.GetComponentsInRange(xform.MapPosition, range))
{
var ent = comp.Owner;
-
- _electrocution.TryDoElectrocution(ent, uid, damage, duration, true, statusEffects: comp, ignoreInsulation: true);
+ _lightning.ShootLightning(uid, ent);
}
}
@@ -48,7 +46,7 @@ public sealed class ElectricityAnomalySystem : EntitySystem
if (mobQuery.HasComponent(ent))
validEnts.Add(ent);
- if (_random.Prob(0.1f) && poweredQuery.HasComponent(ent))
+ if (_random.Prob(0.2f) && poweredQuery.HasComponent(ent))
validEnts.Add(ent);
}
@@ -58,4 +56,32 @@ public sealed class ElectricityAnomalySystem : EntitySystem
_lightning.ShootLightning(uid, ent);
}
}
+
+ public override void Update(float frameTime)
+ {
+ base.Update(frameTime);
+
+ foreach (var (elec, anom, xform) in EntityQuery())
+ {
+ if (_timing.CurTime < elec.NextSecond)
+ continue;
+ elec.NextSecond = _timing.CurTime + TimeSpan.FromSeconds(1);
+
+ var owner = xform.Owner;
+
+ if (!_random.Prob(elec.PassiveElectrocutionChance * anom.Stability))
+ continue;
+
+ var range = elec.MaxElectrocuteRange * anom.Stability;
+ var damage = (int) (elec.MaxElectrocuteDamage * anom.Severity);
+ var duration = elec.MaxElectrocuteDuration * anom.Severity;
+
+ foreach (var comp in _lookup.GetComponentsInRange(xform.MapPosition, range))
+ {
+ var ent = comp.Owner;
+
+ _electrocution.TryDoElectrocution(ent, owner, damage, duration, true, statusEffects: comp, ignoreInsulation: true);
+ }
+ }
+ }
}
diff --git a/Content.Server/Anomaly/Effects/FleshAnomalySystem.cs b/Content.Server/Anomaly/Effects/FleshAnomalySystem.cs
new file mode 100644
index 0000000000..227721fd7a
--- /dev/null
+++ b/Content.Server/Anomaly/Effects/FleshAnomalySystem.cs
@@ -0,0 +1,97 @@
+using System.Linq;
+using Content.Server.Maps;
+using Content.Shared.Anomaly.Components;
+using Content.Shared.Anomaly.Effects.Components;
+using Content.Shared.Maps;
+using Content.Shared.Physics;
+using Robust.Shared.Map;
+using Robust.Shared.Physics;
+using Robust.Shared.Physics.Components;
+using Robust.Shared.Random;
+
+namespace Content.Server.Anomaly.Effects;
+
+public sealed class FleshAnomalySystem : EntitySystem
+{
+ [Dependency] private readonly IMapManager _map = default!;
+ [Dependency] private readonly IRobustRandom _random = default!;
+ [Dependency] private readonly ITileDefinitionManager _tiledef = default!;
+ [Dependency] private readonly TileSystem _tile = default!;
+
+ ///
+ public override void Initialize()
+ {
+ SubscribeLocalEvent(OnPulse);
+ SubscribeLocalEvent(OnSupercritical);
+ SubscribeLocalEvent(OnSeverityChanged);
+ }
+
+ private void OnPulse(EntityUid uid, FleshAnomalyComponent component, ref AnomalyPulseEvent args)
+ {
+ var range = component.SpawnRange * args.Stability;
+ var amount = (int) (component.MaxSpawnAmount * args.Severity + 0.5f);
+
+ var xform = Transform(uid);
+ SpawnMonstersOnOpenTiles(component, xform, amount, range);
+ }
+
+ private void OnSupercritical(EntityUid uid, FleshAnomalyComponent component, ref AnomalySupercriticalEvent args)
+ {
+ var xform = Transform(uid);
+ SpawnMonstersOnOpenTiles(component, xform, component.MaxSpawnAmount, component.SpawnRange);
+ Spawn(component.SupercriticalSpawn, xform.Coordinates);
+ }
+
+ private void OnSeverityChanged(EntityUid uid, FleshAnomalyComponent component, ref AnomalyStabilityChangedEvent args)
+ {
+ var xform = Transform(uid);
+ if (!_map.TryGetGrid(xform.GridUid, out var grid))
+ return;
+
+ var radius = component.SpawnRange * args.Stability;
+ var fleshTile = (ContentTileDefinition) _tiledef[component.FleshTileId];
+ var localpos = xform.Coordinates.Position;
+ var tilerefs = grid.GetLocalTilesIntersecting(
+ new Box2(localpos + (-radius, -radius), localpos + (radius, radius)));
+ foreach (var tileref in tilerefs)
+ {
+ if (!_random.Prob(0.33f))
+ continue;
+ _tile.ReplaceTile(tileref, fleshTile);
+ }
+ }
+
+ private void SpawnMonstersOnOpenTiles(FleshAnomalyComponent component, TransformComponent xform, int amount, float radius)
+ {
+ if (!_map.TryGetGrid(xform.GridUid, out var grid))
+ return;
+
+ var localpos = xform.Coordinates.Position;
+ var tilerefs = grid.GetLocalTilesIntersecting(
+ new Box2(localpos + (-radius, -radius), localpos + (radius, radius))).ToArray();
+ _random.Shuffle(tilerefs);
+ var physQuery = GetEntityQuery();
+ var amountCounter = 0;
+ foreach (var tileref in tilerefs)
+ {
+ var valid = true;
+ foreach (var ent in grid.GetAnchoredEntities(tileref.GridIndices))
+ {
+ if (!physQuery.TryGetComponent(ent, out var body))
+ continue;
+ if (body.BodyType != BodyType.Static ||
+ !body.Hard ||
+ (body.CollisionLayer & (int) CollisionGroup.Impassable) == 0)
+ continue;
+ valid = false;
+ break;
+ }
+ if (!valid)
+ continue;
+ amountCounter++;
+ Spawn(_random.Pick(component.Spawns), tileref.GridIndices.ToEntityCoordinates(xform.GridUid.Value, _map));
+ if (amountCounter >= amount)
+ return;
+ }
+ }
+}
diff --git a/Content.Server/Anomaly/Effects/PyroclasticAnomalySystem.cs b/Content.Server/Anomaly/Effects/PyroclasticAnomalySystem.cs
index 12f0b31343..8e656a58c8 100644
--- a/Content.Server/Anomaly/Effects/PyroclasticAnomalySystem.cs
+++ b/Content.Server/Anomaly/Effects/PyroclasticAnomalySystem.cs
@@ -29,7 +29,7 @@ public sealed class PyroclasticAnomalySystem : EntitySystem
private void OnPulse(EntityUid uid, PyroclasticAnomalyComponent component, ref AnomalyPulseEvent args)
{
var xform = Transform(uid);
- var ignitionRadius = component.MaximumIgnitionRadius * args.Stabiltiy;
+ var ignitionRadius = component.MaximumIgnitionRadius * args.Stability;
IgniteNearby(xform.Coordinates, args.Severity, ignitionRadius);
}
diff --git a/Content.Server/Maps/TileSystem.cs b/Content.Server/Maps/TileSystem.cs
index 0b888cf225..ddf5efc7f1 100644
--- a/Content.Server/Maps/TileSystem.cs
+++ b/Content.Server/Maps/TileSystem.cs
@@ -3,6 +3,7 @@ using Content.Server.Decals;
using Content.Shared.Decals;
using Content.Shared.Maps;
using Robust.Shared.Map;
+using Robust.Shared.Map.Components;
using Robust.Shared.Random;
namespace Content.Server.Maps;
@@ -54,6 +55,28 @@ public sealed class TileSystem : EntitySystem
return DeconstructTile(tileRef);
}
+ public bool ReplaceTile(TileRef tileref, ContentTileDefinition replacementTile)
+ {
+ if (!TryComp(tileref.GridUid, out var grid))
+ return false;
+ return ReplaceTile(tileref, replacementTile, tileref.GridUid, grid);
+ }
+
+ public bool ReplaceTile(TileRef tileref, ContentTileDefinition replacementTile, EntityUid grid, MapGridComponent? component = null)
+ {
+ if (!Resolve(grid, ref component))
+ return false;
+
+ var variant = _robustRandom.Pick(replacementTile.PlacementVariants);
+ var decals = _decal.GetDecalsInRange(tileref.GridUid, tileref.GridPosition().SnapToGrid(EntityManager, _mapManager).Position, 0.5f);
+ foreach (var (id, _) in decals)
+ {
+ _decal.RemoveDecal(tileref.GridUid, id);
+ }
+ component.SetTile(tileref.GridIndices, new Tile(replacementTile.TileId, 0, variant));
+ return true;
+ }
+
private bool DeconstructTile(TileRef tileRef)
{
var indices = tileRef.GridIndices;
diff --git a/Content.Shared/Anomaly/Components/AnomalyComponent.cs b/Content.Shared/Anomaly/Components/AnomalyComponent.cs
index cdee844b1f..50f128d145 100644
--- a/Content.Shared/Anomaly/Components/AnomalyComponent.cs
+++ b/Content.Shared/Anomaly/Components/AnomalyComponent.cs
@@ -62,7 +62,7 @@ public sealed class AnomalyComponent : Component
/// The amount of health lost when the stability is below the
///
[DataField("healthChangePerSecond"), ViewVariables(VVAccess.ReadWrite)]
- public float HealthChangePerSecond = -0.05f;
+ public float HealthChangePerSecond = -0.01f;
#endregion
#region Growth
@@ -208,21 +208,14 @@ public sealed class AnomalyComponent : Component
/// This doesn't include the point bonus for being unstable.
///
[DataField("maxPointsPerSecond")]
- public int MaxPointsPerSecond = 65;
+ public int MaxPointsPerSecond = 100;
///
/// The multiplier applied to the point value for the
/// anomaly being above the
///
[DataField("growingPointMultiplier")]
- public float GrowingPointMultiplier = 1.2f;
-
- ///
- /// The multiplier applied to the point value for the
- /// anomaly being below the
- ///
- [DataField("decayingPointMultiplier")]
- public float DecayingPointMultiplier = 0.75f;
+ public float GrowingPointMultiplier = 1.5f;
#endregion
///
@@ -238,6 +231,24 @@ public sealed class AnomalyComponent : Component
///
[DataField("anomalyContactDamageSound")]
public SoundSpecifier AnomalyContactDamageSound = new SoundPathSpecifier("/Audio/Effects/lightburn.ogg");
+
+ #region Floating Animation
+ ///
+ /// How long it takes to go from the bottom of the animation to the top.
+ ///
+ [ViewVariables(VVAccess.ReadWrite)]
+ [DataField("animationTime")]
+ public readonly float AnimationTime = 2f;
+
+ ///
+ /// How far it goes in any direction.
+ ///
+ [ViewVariables(VVAccess.ReadWrite)]
+ [DataField("offset")]
+ public readonly Vector2 FloatingOffset = (0, 0.15f);
+
+ public readonly string AnimationKey = "anomalyfloat";
+ #endregion
}
[Serializable, NetSerializable]
@@ -260,14 +271,10 @@ public sealed class AnomalyComponentState : ComponentState
///
/// Event raised at regular intervals on an anomaly to do whatever its effect is.
///
-///
+///
///
[ByRefEvent]
-public readonly record struct AnomalyPulseEvent(float Stabiltiy, float Severity)
-{
- public readonly float Stabiltiy = Stabiltiy;
- public readonly float Severity = Severity;
-}
+public readonly record struct AnomalyPulseEvent(float Stability, float Severity);
///
/// Event raised on an anomaly when it reaches a supercritical point.
diff --git a/Content.Shared/Anomaly/Effects/BluespaceAnomalySystem.cs b/Content.Shared/Anomaly/Effects/BluespaceAnomalySystem.cs
new file mode 100644
index 0000000000..920cc26e52
--- /dev/null
+++ b/Content.Shared/Anomaly/Effects/BluespaceAnomalySystem.cs
@@ -0,0 +1,73 @@
+using System.Linq;
+using Content.Shared.Anomaly.Components;
+using Content.Shared.Anomaly.Effects.Components;
+using Content.Shared.Mobs.Components;
+using Content.Shared.Teleportation.Components;
+using Robust.Shared.Map;
+using Robust.Shared.Random;
+
+namespace Content.Shared.Anomaly.Effects;
+
+public sealed class BluespaceAnomalySystem : EntitySystem
+{
+ [Dependency] private readonly IRobustRandom _random = default!;
+ [Dependency] private readonly SharedAudioSystem _audio = default!;
+ [Dependency] private readonly EntityLookupSystem _lookup = default!;
+ [Dependency] private readonly SharedTransformSystem _xform = default!;
+
+ ///
+ public override void Initialize()
+ {
+ SubscribeLocalEvent(OnPulse);
+ SubscribeLocalEvent(OnSupercritical);
+ SubscribeLocalEvent(OnSeverityChanged);
+ }
+
+ private void OnPulse(EntityUid uid, BluespaceAnomalyComponent component, ref AnomalyPulseEvent args)
+ {
+ var xform = Transform(uid);
+ var range = component.MaxShuffleRadius * args.Severity;
+ var allEnts = _lookup.GetComponentsInRange(xform.Coordinates, range)
+ .Select(x => x.Owner).ToList();
+ allEnts.Add(uid);
+
+ var xformQuery = GetEntityQuery();
+ var coords = new List();
+ foreach (var ent in allEnts)
+ {
+ if (xformQuery.TryGetComponent(ent, out var xf))
+ coords.Add(xf.Coordinates);
+ }
+
+ _random.Shuffle(coords);
+ for (var i = 0; i < allEnts.Count; i++)
+ {
+ _xform.SetCoordinates(allEnts[i], coords[i]);
+ }
+ }
+
+ private void OnSupercritical(EntityUid uid, BluespaceAnomalyComponent component, ref AnomalySupercriticalEvent args)
+ {
+ var xform = Transform(uid);
+ var mapPos = _xform.GetWorldPosition(xform);
+ var radius = component.SupercriticalTeleportRadius;
+ var gridBounds = new Box2(mapPos - (radius, radius), mapPos + (radius, radius));
+ foreach (var comp in _lookup.GetComponentsInRange(xform.Coordinates, component.MaxShuffleRadius))
+ {
+ var ent = comp.Owner;
+ var randomX = _random.NextFloat(gridBounds.Left, gridBounds.Right);
+ var randomY = _random.NextFloat(gridBounds.Bottom, gridBounds.Top);
+
+ var pos = new Vector2(randomX, randomY);
+ _xform.SetWorldPosition(ent, pos);
+ _audio.PlayPvs(component.TeleportSound, ent);
+ }
+ }
+
+ private void OnSeverityChanged(EntityUid uid, BluespaceAnomalyComponent component, ref AnomalySeverityChangedEvent args)
+ {
+ if (!TryComp(uid, out var portal))
+ return;
+ portal.MaxRandomRadius = (component.MaxPortalRadius - component.MinPortalRadius) * args.Severity + component.MinPortalRadius;
+ }
+}
diff --git a/Content.Shared/Anomaly/Effects/Components/BluespaceAnomalyComponent.cs b/Content.Shared/Anomaly/Effects/Components/BluespaceAnomalyComponent.cs
new file mode 100644
index 0000000000..446194188b
--- /dev/null
+++ b/Content.Shared/Anomaly/Effects/Components/BluespaceAnomalyComponent.cs
@@ -0,0 +1,40 @@
+using Robust.Shared.Audio;
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Anomaly.Effects.Components;
+
+[RegisterComponent, NetworkedComponent]
+[Access(typeof(BluespaceAnomalySystem))]
+public sealed class BluespaceAnomalyComponent : Component
+{
+ ///
+ /// The maximum radius that the shuffle effect will extend for
+ /// scales with stability
+ ///
+ [DataField("maxShuffleRadius"), ViewVariables(VVAccess.ReadWrite)]
+ public float MaxShuffleRadius = 10;
+
+ ///
+ /// The maximum MAX distance the portal this anomaly is tied to can teleport you.
+ ///
+ [DataField("maxPortalRadius"), ViewVariables(VVAccess.ReadWrite)]
+ public float MaxPortalRadius = 25;
+
+ ///
+ /// The minimum MAX distance the portal this anomaly is tied to can teleport you.
+ ///
+ [DataField("minPortalRadius"), ViewVariables(VVAccess.ReadWrite)]
+ public float MinPortalRadius = 10;
+
+ ///
+ /// How far the supercritical event can teleport you
+ ///
+ [DataField("superCriticalTeleportRadius"), ViewVariables(VVAccess.ReadWrite)]
+ public float SupercriticalTeleportRadius = 50f;
+
+ ///
+ /// The sound played after players are shuffled/teleported around
+ ///
+ [DataField("teleportSound"), ViewVariables(VVAccess.ReadWrite)]
+ public SoundSpecifier TeleportSound = new SoundPathSpecifier("/Audio/Effects/teleport_arrival.ogg");
+}
diff --git a/Content.Shared/Anomaly/Effects/Components/ElectricityAnomalyComponent.cs b/Content.Shared/Anomaly/Effects/Components/ElectricityAnomalyComponent.cs
index fc430127ef..9afdd0aaa2 100644
--- a/Content.Shared/Anomaly/Effects/Components/ElectricityAnomalyComponent.cs
+++ b/Content.Shared/Anomaly/Effects/Components/ElectricityAnomalyComponent.cs
@@ -1,14 +1,41 @@
-namespace Content.Shared.Anomaly.Effects.Components;
+using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
+
+namespace Content.Shared.Anomaly.Effects.Components;
[RegisterComponent]
public sealed class ElectricityAnomalyComponent : Component
{
+ ///
+ /// The maximum radius of the passive electrocution effect
+ /// scales with stability
+ ///
[DataField("maxElectrocutionRange"), ViewVariables(VVAccess.ReadWrite)]
- public float MaxElectrocuteRange = 6f;
+ public float MaxElectrocuteRange = 7f;
+ ///
+ /// The maximum amount of damage the electrocution can do
+ /// scales with severity
+ ///
[DataField("maxElectrocuteDamage"), ViewVariables(VVAccess.ReadWrite)]
public float MaxElectrocuteDamage = 20f;
+ ///
+ /// The maximum amount of time the electrocution lasts
+ /// scales with severity
+ ///
[DataField("maxElectrocuteDuration"), ViewVariables(VVAccess.ReadWrite)]
public TimeSpan MaxElectrocuteDuration = TimeSpan.FromSeconds(8);
+
+ ///
+ /// The maximum chance that each second, when in range of the anomaly, you will be electrocuted.
+ /// scales with stability
+ ///
+ [DataField("passiveElectrocutionChance"), ViewVariables(VVAccess.ReadWrite)]
+ public float PassiveElectrocutionChance = 0.05f;
+
+ ///
+ /// Used for tracking seconds, so that we can shock people in a non-tick-dependent way.
+ ///
+ [DataField("nextSecond", customTypeSerializer: typeof(TimeOffsetSerializer)), ViewVariables(VVAccess.ReadWrite)]
+ public TimeSpan NextSecond = TimeSpan.Zero;
}
diff --git a/Content.Shared/Anomaly/Effects/Components/FleshAnomalyComponent.cs b/Content.Shared/Anomaly/Effects/Components/FleshAnomalyComponent.cs
new file mode 100644
index 0000000000..abd0b01939
--- /dev/null
+++ b/Content.Shared/Anomaly/Effects/Components/FleshAnomalyComponent.cs
@@ -0,0 +1,43 @@
+using Content.Shared.Maps;
+using Robust.Shared.Prototypes;
+using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
+using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
+
+namespace Content.Shared.Anomaly.Effects.Components;
+
+[RegisterComponent]
+public sealed class FleshAnomalyComponent : Component
+{
+ ///
+ /// A list of entities that are random picked to be spawned on each pulse
+ ///
+ [DataField("spawns", required: true, customTypeSerializer: typeof(PrototypeIdListSerializer)), ViewVariables(VVAccess.ReadWrite)]
+ public List Spawns = new();
+
+ ///
+ /// The maximum number of entities that spawn per pulse
+ /// scales with severity.
+ ///
+ [DataField("maxSpawnAmount"), ViewVariables(VVAccess.ReadWrite)]
+ public int MaxSpawnAmount = 8;
+
+ ///
+ /// The maximum radius the entities will spawn in.
+ /// Also governs the maximum reach of flesh tiles
+ /// scales with stability
+ ///
+ [DataField("spawnRange"), ViewVariables(VVAccess.ReadWrite)]
+ public float SpawnRange = 4f;
+
+ ///
+ /// The tile that is spawned by the anomaly's effect
+ ///
+ [DataField("fleshTileId", customTypeSerializer: typeof(PrototypeIdSerializer)), ViewVariables(VVAccess.ReadWrite)]
+ public string FleshTileId = "FloorFlesh";
+
+ ///
+ /// The entity spawned when the anomaly goes supercritical
+ ///
+ [DataField("superCriticalSpawn", customTypeSerializer: typeof(PrototypeIdSerializer)), ViewVariables(VVAccess.ReadWrite)]
+ public string SupercriticalSpawn = "FleshKudzu";
+}
diff --git a/Content.Shared/Anomaly/Effects/Components/GravityAnomalyComponent.cs b/Content.Shared/Anomaly/Effects/Components/GravityAnomalyComponent.cs
index a6f80aeda0..761bc9daec 100644
--- a/Content.Shared/Anomaly/Effects/Components/GravityAnomalyComponent.cs
+++ b/Content.Shared/Anomaly/Effects/Components/GravityAnomalyComponent.cs
@@ -1,6 +1,8 @@
-namespace Content.Shared.Anomaly.Effects.Components;
+using Robust.Shared.GameStates;
-[RegisterComponent]
+namespace Content.Shared.Anomaly.Effects.Components;
+
+[RegisterComponent, NetworkedComponent]
public sealed class GravityAnomalyComponent : Component
{
///
diff --git a/Content.Shared/Anomaly/Effects/Components/PyroclasticAnomalyComponent.cs b/Content.Shared/Anomaly/Effects/Components/PyroclasticAnomalyComponent.cs
index 5f3c1c2595..9cfa56bcc2 100644
--- a/Content.Shared/Anomaly/Effects/Components/PyroclasticAnomalyComponent.cs
+++ b/Content.Shared/Anomaly/Effects/Components/PyroclasticAnomalyComponent.cs
@@ -13,7 +13,7 @@ public sealed class PyroclasticAnomalyComponent : Component
/// I have no clue if this is balanced.
///
[DataField("heatPerSecond")]
- public float HeatPerSecond = 50;
+ public float HeatPerSecond = 25;
///
/// The maximum distance from which you can be ignited by the anomaly.
@@ -50,5 +50,5 @@ public sealed class PyroclasticAnomalyComponent : Component
/// The amount of gas released when the anomaly goes supercritical
///
[DataField("supercriticalMoleAmount")]
- public float SupercriticalMoleAmount = 50f;
+ public float SupercriticalMoleAmount = 75f;
}
diff --git a/Content.Shared/Anomaly/Effects/SharedGravityAnomalySystem.cs b/Content.Shared/Anomaly/Effects/SharedGravityAnomalySystem.cs
index d7cf92c17d..09f8ec35ee 100644
--- a/Content.Shared/Anomaly/Effects/SharedGravityAnomalySystem.cs
+++ b/Content.Shared/Anomaly/Effects/SharedGravityAnomalySystem.cs
@@ -29,9 +29,8 @@ public abstract class SharedGravityAnomalySystem : EntitySystem
foreach (var ent in lookup)
{
var tempXform = Transform(ent);
-
var foo = tempXform.MapPosition.Position - xform.MapPosition.Position;
- _throwing.TryThrow(ent, foo.Normalized * 10, strength, uid, 0);
+ _throwing.TryThrow(ent, foo * 10, strength, uid, 0);
}
}
@@ -54,7 +53,6 @@ public abstract class SharedGravityAnomalySystem : EntitySystem
var tempXform = Transform(ent);
var foo = tempXform.MapPosition.Position - xform.MapPosition.Position;
- Logger.Debug($"{ToPrettyString(ent)}: {foo}: {foo.Normalized}: {foo.Normalized * 10}");
_throwing.TryThrow(ent, foo * 5, strength, uid, 0);
}
}
diff --git a/Content.Shared/Anomaly/SharedAnomalySystem.cs b/Content.Shared/Anomaly/SharedAnomalySystem.cs
index 6106112a1d..874e28ebcd 100644
--- a/Content.Shared/Anomaly/SharedAnomalySystem.cs
+++ b/Content.Shared/Anomaly/SharedAnomalySystem.cs
@@ -119,6 +119,9 @@ public abstract class SharedAnomalySystem : EntitySystem
if (!Resolve(uid, ref component))
return;
+ if (!Timing.IsFirstTimePredicted)
+ return;
+
DebugTools.Assert(component.MinPulseLength > TimeSpan.FromSeconds(3)); // this is just to prevent lagspikes mispredicting pulses
var variation = Random.NextFloat(-component.PulseVariation, component.PulseVariation) + 1;
component.NextPulseTime = Timing.CurTime + GetPulseLength(component) * variation;
@@ -173,6 +176,10 @@ public abstract class SharedAnomalySystem : EntitySystem
{
if (!Resolve(uid, ref component))
return;
+
+ if (!Timing.IsFirstTimePredicted)
+ return;
+
Audio.PlayPvs(component.SupercriticalSound, uid);
var ev = new AnomalySupercriticalEvent();
diff --git a/Resources/Locale/en-US/tiles/tiles.ftl b/Resources/Locale/en-US/tiles/tiles.ftl
index a53fa1988f..974db2ab6e 100644
--- a/Resources/Locale/en-US/tiles/tiles.ftl
+++ b/Resources/Locale/en-US/tiles/tiles.ftl
@@ -82,6 +82,7 @@ tiles-asteroid-ironsand-pebbles = asteroid ironsand pebbles
tiles-asteroid-ironsand-rock = asteroid ironsand rock
tiles-cave = cave
tiles-cave-drought = cave drought
+tiles-flesh-floor = flesh floor
tiles-techmaint3-floor = grated maintenance floor
tiles-techmaint2-floor = steel maintenance floor
tiles-wood2 = wood pattern floor
diff --git a/Resources/Prototypes/Entities/Markers/Spawners/Random/anomaly.yml b/Resources/Prototypes/Entities/Markers/Spawners/Random/anomaly.yml
index a082fae7d6..a21437fd77 100644
--- a/Resources/Prototypes/Entities/Markers/Spawners/Random/anomaly.yml
+++ b/Resources/Prototypes/Entities/Markers/Spawners/Random/anomaly.yml
@@ -13,4 +13,6 @@
- AnomalyPyroclastic
- AnomalyGravity
- AnomalyElectricity
+ - AnomalyFlesh
+ - AnomalyBluespace
chance: 1
diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/flesh.yml b/Resources/Prototypes/Entities/Mobs/NPCs/flesh.yml
new file mode 100644
index 0000000000..68dde1d1b5
--- /dev/null
+++ b/Resources/Prototypes/Entities/Mobs/NPCs/flesh.yml
@@ -0,0 +1,160 @@
+- type: entity
+ parent: SimpleMobBase
+ id: BaseMobFlesh
+ name: aberrant flesh
+ description: A shambling mass of flesh, animated through anomalous energy.
+ abstract: true
+ components:
+ - type: HTN
+ rootTask: SimpleHostileCompound
+ - type: Faction
+ factions:
+ - SimpleHostile
+ - type: Tag
+ tags:
+ - DoorBumpOpener
+ - Flesh
+ - type: Sprite
+ drawdepth: Mobs
+ sprite: Mobs/Aliens/flesh.rsi
+ - type: MovementAlwaysTouching
+ - type: MovementSpeedModifier
+ baseWalkSpeed: 1
+ baseSprintSpeed: 1.5
+ - type: MobState
+ allowedStates:
+ - Alive
+ - Dead
+ - type: MobThresholds
+ thresholds:
+ 0: Alive
+ 75: Dead
+ - type: Stamina
+ excess: 50
+ - type: Appearance
+ - type: Butcherable
+ spawned:
+ - id: FoodMeat
+ amount: 1
+ - type: Bloodstream
+ bloodMaxVolume: 500
+ - type: CombatMode
+ disarmAction:
+ enabled: false
+ autoPopulate: false
+ name: action-name-disarm
+ - type: MeleeWeapon
+ hidden: true
+ soundHit:
+ path: /Audio/Weapons/Xeno/alien_claw_flesh3.ogg
+ angle: 0
+ animation: WeaponArcClaw
+ damage:
+ types:
+ Slash: 3
+ - type: ReplacementAccent
+ accent: genericAggressive
+
+- type: entity
+ parent: BaseMobFlesh
+ id: MobFleshJared
+ components:
+ - type: Sprite
+ layers:
+ - map: [ "enum.DamageStateVisualLayers.Base" ]
+ state: jared
+ - type: DamageStateVisuals
+ states:
+ Alive:
+ Base: jared
+ Critical:
+ Base: dead
+ Dead:
+ Base: dead
+ - type: MeleeWeapon
+ hidden: true
+ soundHit:
+ path: /Audio/Weapons/Xeno/alien_claw_flesh3.ogg
+ angle: 0
+ animation: WeaponArcClaw
+ damage:
+ types:
+ Slash: 5
+
+- type: entity
+ parent: BaseMobFlesh
+ id: MobFleshGolem
+ components:
+ - type: Sprite
+ layers:
+ - map: [ "enum.DamageStateVisualLayers.Base" ]
+ state: golem
+ - type: DamageStateVisuals
+ states:
+ Alive:
+ Base: golem
+ Critical:
+ Base: dead
+ Dead:
+ Base: dead
+ - type: MobThresholds
+ thresholds:
+ 0: Alive
+ 50: Dead
+ - type: MeleeWeapon
+ hidden: true
+ soundHit:
+ path: /Audio/Weapons/Xeno/alien_claw_flesh3.ogg
+ angle: 0
+ animation: WeaponArcClaw
+ damage:
+ types:
+ Slash: 5
+
+- type: entity
+ parent: BaseMobFlesh
+ id: MobFleshClamp
+ components:
+ - type: Sprite
+ layers:
+ - map: [ "enum.DamageStateVisualLayers.Base" ]
+ state: clamp
+ - type: DamageStateVisuals
+ states:
+ Alive:
+ Base: clamp
+ Critical:
+ Base: dead
+ Dead:
+ Base: dead
+ - type: MobThresholds
+ thresholds:
+ 0: Alive
+ 30: Dead
+ - type: MovementSpeedModifier
+ baseWalkSpeed: 2
+ baseSprintSpeed: 2.5
+
+- type: entity
+ parent: BaseMobFlesh
+ id: MobFleshLover
+ components:
+ - type: Sprite
+ layers:
+ - map: [ "enum.DamageStateVisualLayers.Base" ]
+ state: lover
+ - type: DamageStateVisuals
+ states:
+ Alive:
+ Base: lover
+ Critical:
+ Base: dead
+ Dead:
+ Base: dead
+ - type: MobThresholds
+ thresholds:
+ 0: Alive
+ 30: Dead
+ - type: MovementSpeedModifier
+ baseWalkSpeed: 2
+ baseSprintSpeed: 2.5
diff --git a/Resources/Prototypes/Entities/Objects/Misc/kudzu.yml b/Resources/Prototypes/Entities/Objects/Misc/kudzu.yml
index d2942f45cc..280ce2c7e3 100644
--- a/Resources/Prototypes/Entities/Objects/Misc/kudzu.yml
+++ b/Resources/Prototypes/Entities/Objects/Misc/kudzu.yml
@@ -14,6 +14,7 @@
"/Audio/Weapons/slash.ogg"
- type: Sprite
sprite: Objects/Misc/kudzu.rsi
+ color: "#ff0000"
state: kudzu_11
drawdepth: Overdoors
netsync: false
@@ -77,3 +78,55 @@
- type: SlowContacts
walkSpeedModifier: 0.2
sprintSpeedModifier: 0.2
+
+- type: entity
+ id: FleshKudzu
+ name: tendons
+ description: A rapidly growing cluster of meaty tendons. WHY ARE YOU STOPPING TO LOOK AT IT?!
+ placement:
+ mode: SnapgridCenter
+ snap:
+ - Wall
+ components:
+ - type: MeleeSound
+ soundGroups:
+ Brute:
+ path:
+ "/Audio/Weapons/slash.ogg"
+ - type: Sprite
+ sprite: Objects/Misc/fleshkudzu.rsi
+ state: base
+ drawdepth: Overdoors
+ netsync: false
+ - type: Appearance
+ - type: Clickable
+ - type: Transform
+ anchored: true
+ - type: Physics
+ - type: Fixtures
+ fixtures:
+ - hard: false
+ density: 7
+ shape:
+ !type:PhysShapeAabb
+ bounds: "-0.5,-0.5,0.5,0.5"
+ layer:
+ - MidImpassable
+ - type: Damageable
+ - type: Destructible
+ thresholds:
+ - trigger:
+ !type:DamageTrigger
+ damage: 10
+ behaviors:
+ - !type:DoActsBehavior
+ acts: [ "Destruction" ]
+ - type: Spreader
+ growthResult: FleshKudzu
+ chance: 1
+ - type: SlowContacts
+ walkSpeedModifier: 0.2
+ sprintSpeedModifier: 0.2
+ ignoreWhitelist:
+ tags:
+ - Flesh
diff --git a/Resources/Prototypes/Entities/Structures/Decoration/flesh_blockers.yml b/Resources/Prototypes/Entities/Structures/Decoration/flesh_blockers.yml
new file mode 100644
index 0000000000..e883177707
--- /dev/null
+++ b/Resources/Prototypes/Entities/Structures/Decoration/flesh_blockers.yml
@@ -0,0 +1,40 @@
+- type: entity
+ id: FleshBlocker
+ parent: BaseStructure
+ name: flesh clump
+ description: An annoying clump of flesh.
+ components:
+ - type: InteractionOutline
+ - type: Sprite
+ noRot: true
+ sprite: Structures/Decoration/flesh_decoration.rsi
+ layers:
+ - state: closed
+ map: [ "enum.DamageStateVisualLayers.Base" ]
+ - type: Fixtures
+ fixtures:
+ - shape:
+ !type:PhysShapeCircle
+ radius: 0.3
+ density: 190
+ mask:
+ - MachineMask
+ layer:
+ - Impassable
+ - type: RandomSprite
+ available:
+ - enum.DamageStateVisualLayers.Base:
+ closed: ""
+ - enum.DamageStateVisualLayers.Base:
+ ajar: ""
+ - enum.DamageStateVisualLayers.Base:
+ open: ""
+ - type: Damageable
+ - type: Destructible
+ thresholds:
+ - trigger:
+ !type:DamageTrigger
+ damage: 25
+ behaviors:
+ - !type:DoActsBehavior
+ acts: [ "Destruction" ]
diff --git a/Resources/Prototypes/Entities/Structures/Specific/anomalies.yml b/Resources/Prototypes/Entities/Structures/Specific/anomalies.yml
index 5d57d343a7..1dfeefff36 100644
--- a/Resources/Prototypes/Entities/Structures/Specific/anomalies.yml
+++ b/Resources/Prototypes/Entities/Structures/Specific/anomalies.yml
@@ -20,7 +20,7 @@
- type: Transform
anchored: true
- type: Physics
- bodyType: Static
+ bodyType: Static
- type: Fixtures
fixtures:
- shape:
@@ -33,12 +33,14 @@
- MobLayer
- type: Sprite
netsync: false
- drawdepth: Items
+ noRot: true
+ drawdepth: Effects #it needs to draw over stuff.
sprite: Structures/Specific/anomaly.rsi
- type: InteractionOutline
- type: Clickable
- type: Damageable
- type: Appearance
+ - type: AnimationPlayer
- type: GuideHelp
guides:
- AnomalousResearch
@@ -71,7 +73,6 @@
suffix: Gravity
components:
- type: Sprite
- drawdepth: Effects #it needs to draw over stuff.
layers:
- state: anom2
map: ["enum.AnomalyVisualLayers.Base"]
@@ -105,4 +106,76 @@
color: "#ffffaa"
castShadows: false
- type: ElectricityAnomaly
- - type: Electrified
\ No newline at end of file
+ - type: Electrified
+
+- type: entity
+ id: AnomalyFlesh
+ parent: BaseAnomaly
+ suffix: Flesh
+ components:
+ - type: Sprite
+ layers:
+ - state: anom5
+ map: ["enum.AnomalyVisualLayers.Base"]
+ - state: anom5-pulse
+ map: ["enum.AnomalyVisualLayers.Animated"]
+ visible: false
+ - type: PointLight
+ radius: 2.0
+ energy: 7.5
+ color: "#cb5b7e"
+ castShadows: false
+ - type: FleshAnomaly
+ spawns:
+ - MobFleshJared
+ - MobFleshGolem
+ - MobFleshClamp
+ - MobFleshLover
+ - FleshBlocker
+
+- type: entity
+ id: AnomalyBluespace
+ parent: BaseAnomaly
+ suffix: Bluespace
+ components:
+ - type: Sprite
+ layers:
+ - state: anom4
+ map: ["enum.AnomalyVisualLayers.Base"]
+ - state: anom4-pulse
+ map: ["enum.AnomalyVisualLayers.Animated"]
+ visible: false
+ - type: PointLight
+ radius: 2.0
+ energy: 7.5
+ color: "#00ccff"
+ castShadows: false
+ - type: BluespaceAnomaly
+ - type: Portal
+ - type: Fixtures
+ fixtures:
+ - shape:
+ !type:PhysShapeCircle
+ radius: 0.35
+ density: 50
+ mask:
+ - MobMask
+ layer:
+ - MobLayer
+ - id: portalFixture
+ shape:
+ !type:PhysShapeAabb
+ bounds: "-0.25,-0.48,0.25,0.48"
+ mask:
+ - FullTileMask
+ layer:
+ - WallLayer
+ hard: false
+ - type: Anomaly
+ pulseSound:
+ collection: RadiationPulse
+ params:
+ volume: 5
+ anomalyContactDamage:
+ types:
+ Radiation: 10
diff --git a/Resources/Prototypes/Tiles/floors.yml b/Resources/Prototypes/Tiles/floors.yml
index 9043d57afa..a23e9493a4 100644
--- a/Resources/Prototypes/Tiles/floors.yml
+++ b/Resources/Prototypes/Tiles/floors.yml
@@ -1367,6 +1367,22 @@
thermalConductivity: 0.04
heatCapacity: 10000
+- type: tile
+ id: FloorFlesh
+ name: tiles-flesh-floor
+ sprite: /Textures/Tiles/meat.png
+ variants: 4
+ placementVariants: [0, 1, 2, 3]
+ baseTurfs:
+ - Plating
+ isSubfloor: false
+ canCrowbar: true
+ footstepSounds:
+ collection: BarestepCarpet
+ friction: 0.20 #slippy
+ thermalConductivity: 0.04
+ heatCapacity: 10000
+
- type: tile
id: FloorTechMaint2
name: tiles-techmaint2-floor
diff --git a/Resources/Prototypes/tags.yml b/Resources/Prototypes/tags.yml
index 859eff49db..dbb2562846 100644
--- a/Resources/Prototypes/tags.yml
+++ b/Resources/Prototypes/tags.yml
@@ -216,6 +216,9 @@
- type: Tag
id: FireAxe
+- type: Tag
+ id: Flesh
+
- type: Tag
id: WhitelistChameleon
diff --git a/Resources/Textures/Mobs/Aliens/flesh.rsi/clamp.png b/Resources/Textures/Mobs/Aliens/flesh.rsi/clamp.png
new file mode 100644
index 0000000000..d9085d75b9
Binary files /dev/null and b/Resources/Textures/Mobs/Aliens/flesh.rsi/clamp.png differ
diff --git a/Resources/Textures/Mobs/Aliens/flesh.rsi/dead.png b/Resources/Textures/Mobs/Aliens/flesh.rsi/dead.png
new file mode 100644
index 0000000000..826d4e0acd
Binary files /dev/null and b/Resources/Textures/Mobs/Aliens/flesh.rsi/dead.png differ
diff --git a/Resources/Textures/Mobs/Aliens/flesh.rsi/golem.png b/Resources/Textures/Mobs/Aliens/flesh.rsi/golem.png
new file mode 100644
index 0000000000..e7744ad985
Binary files /dev/null and b/Resources/Textures/Mobs/Aliens/flesh.rsi/golem.png differ
diff --git a/Resources/Textures/Mobs/Aliens/flesh.rsi/jared.png b/Resources/Textures/Mobs/Aliens/flesh.rsi/jared.png
new file mode 100644
index 0000000000..da20b436ae
Binary files /dev/null and b/Resources/Textures/Mobs/Aliens/flesh.rsi/jared.png differ
diff --git a/Resources/Textures/Mobs/Aliens/flesh.rsi/lover.png b/Resources/Textures/Mobs/Aliens/flesh.rsi/lover.png
new file mode 100644
index 0000000000..0b5229c37f
Binary files /dev/null and b/Resources/Textures/Mobs/Aliens/flesh.rsi/lover.png differ
diff --git a/Resources/Textures/Mobs/Aliens/flesh.rsi/meta.json b/Resources/Textures/Mobs/Aliens/flesh.rsi/meta.json
new file mode 100644
index 0000000000..6c81c52037
--- /dev/null
+++ b/Resources/Textures/Mobs/Aliens/flesh.rsi/meta.json
@@ -0,0 +1,27 @@
+{
+ "version": 1,
+ "size": {
+ "x": 32,
+ "y": 32
+ },
+ "license": "CC-BY-SA-3.0",
+ "copyright": "Created by EmoGarbage404 (github) for space-station-14, credit to Aleksh#7552 (discord) for original concepts and designs",
+ "states": [
+ {
+ "name": "clamp"
+ },
+ {
+ "name": "dead"
+ },
+ {
+ "name": "golem",
+ "directions": 4
+ },
+ {
+ "name": "jared"
+ },
+ {
+ "name": "lover"
+ }
+ ]
+}
diff --git a/Resources/Textures/Objects/Misc/fleshkudzu.rsi/base.png b/Resources/Textures/Objects/Misc/fleshkudzu.rsi/base.png
new file mode 100644
index 0000000000..659b2ea979
Binary files /dev/null and b/Resources/Textures/Objects/Misc/fleshkudzu.rsi/base.png differ
diff --git a/Resources/Textures/Objects/Misc/fleshkudzu.rsi/meta.json b/Resources/Textures/Objects/Misc/fleshkudzu.rsi/meta.json
new file mode 100644
index 0000000000..fc8bf10c30
--- /dev/null
+++ b/Resources/Textures/Objects/Misc/fleshkudzu.rsi/meta.json
@@ -0,0 +1,14 @@
+{
+ "version": 1,
+ "license": "CC0-1.0",
+ "copyright": "Created by EmoGarbage404 (github) for space-station-14",
+ "size": {
+ "x": 32,
+ "y": 32
+ },
+ "states": [
+ {
+ "name": "base"
+ }
+ ]
+}
diff --git a/Resources/Textures/Structures/Decoration/flesh_decoration.rsi/ajar.png b/Resources/Textures/Structures/Decoration/flesh_decoration.rsi/ajar.png
new file mode 100644
index 0000000000..c4e0b26773
Binary files /dev/null and b/Resources/Textures/Structures/Decoration/flesh_decoration.rsi/ajar.png differ
diff --git a/Resources/Textures/Structures/Decoration/flesh_decoration.rsi/closed.png b/Resources/Textures/Structures/Decoration/flesh_decoration.rsi/closed.png
new file mode 100644
index 0000000000..dec70d0bb5
Binary files /dev/null and b/Resources/Textures/Structures/Decoration/flesh_decoration.rsi/closed.png differ
diff --git a/Resources/Textures/Structures/Decoration/flesh_decoration.rsi/meta.json b/Resources/Textures/Structures/Decoration/flesh_decoration.rsi/meta.json
new file mode 100644
index 0000000000..8b58bd6a12
--- /dev/null
+++ b/Resources/Textures/Structures/Decoration/flesh_decoration.rsi/meta.json
@@ -0,0 +1,20 @@
+{
+ "version": 1,
+ "size": {
+ "x": 32,
+ "y": 32
+ },
+ "license": "CC-BY-SA-3.0",
+ "copyright": "Created by Aleksh#7552 (discord) for space-station-14",
+ "states": [
+ {
+ "name": "ajar"
+ },
+ {
+ "name": "closed"
+ },
+ {
+ "name": "open"
+ }
+ ]
+}
diff --git a/Resources/Textures/Structures/Decoration/flesh_decoration.rsi/open.png b/Resources/Textures/Structures/Decoration/flesh_decoration.rsi/open.png
new file mode 100644
index 0000000000..5f7bfd3f13
Binary files /dev/null and b/Resources/Textures/Structures/Decoration/flesh_decoration.rsi/open.png differ
diff --git a/Resources/Textures/Structures/Specific/anomaly.rsi/anom5-pulse.png b/Resources/Textures/Structures/Specific/anomaly.rsi/anom5-pulse.png
new file mode 100644
index 0000000000..c0e547f8dd
Binary files /dev/null and b/Resources/Textures/Structures/Specific/anomaly.rsi/anom5-pulse.png differ
diff --git a/Resources/Textures/Structures/Specific/anomaly.rsi/anom5.png b/Resources/Textures/Structures/Specific/anomaly.rsi/anom5.png
new file mode 100644
index 0000000000..6117776649
Binary files /dev/null and b/Resources/Textures/Structures/Specific/anomaly.rsi/anom5.png differ
diff --git a/Resources/Textures/Structures/Specific/anomaly.rsi/meta.json b/Resources/Textures/Structures/Specific/anomaly.rsi/meta.json
index f9d4be792f..c318e8116b 100644
--- a/Resources/Textures/Structures/Specific/anomaly.rsi/meta.json
+++ b/Resources/Textures/Structures/Specific/anomaly.rsi/meta.json
@@ -1,7 +1,7 @@
{
"version": 1,
"license": "CC0-1.0",
- "copyright": "Created by EmoGarbage; anom3, anom3-pulse, anom4, anom4-pulse are CC-BY-SA-3.0 at https://github.com/ParadiseSS13/Paradise/blob/master/icons/effects/effects.dmi",
+ "copyright": "Created by EmoGarbage; anom3, anom3-pulse, anom4, anom4-pulse are CC-BY-SA-3.0 at https://github.com/ParadiseSS13/Paradise/blob/master/icons/effects/effects.dmi; anom5, anom5-pulse are CC-BY-SA-3.0 by Aleksh#7552 (discord) for space-station-14",
"size": {
"x": 32,
"y": 32
@@ -92,6 +92,20 @@
0.15
]
]
+ },
+ {
+ "name": "anom5"
+ },
+ {
+ "name": "anom5-pulse",
+ "delays": [
+ [
+ 0.25,
+ 0.25,
+ 0.25,
+ 0.25
+ ]
+ ]
}
]
-}
\ No newline at end of file
+}
diff --git a/Resources/Textures/Tiles/attributions.yml b/Resources/Textures/Tiles/attributions.yml
index 9fec6d6c0e..9ce6c90cd0 100644
--- a/Resources/Textures/Tiles/attributions.yml
+++ b/Resources/Textures/Tiles/attributions.yml
@@ -56,3 +56,7 @@
copyright: "by brainfood for space-station-14, ."
source: "https://github.com/space-wizards/space-station-14/pull/12193"
+- files: ["meat.png"]
+ license: "CC0-1.0"
+ copyright: "Created by EmoGarbage404 (github) for space-station-14."
+ source: "https://github.com/space-wizards/space-station-14/pull/13766"
diff --git a/Resources/Textures/Tiles/meat.png b/Resources/Textures/Tiles/meat.png
new file mode 100644
index 0000000000..d593c1bdfc
Binary files /dev/null and b/Resources/Textures/Tiles/meat.png differ