From 7d168b1c8ce779cdf35ad4db7c7a9069d349dfe2 Mon Sep 17 00:00:00 2001 From: M1and1B <153716654+M1and1B@users.noreply.github.com> Date: Thu, 2 Jan 2025 14:20:33 +0200 Subject: [PATCH] saves for later --- .../ActiveEdgeSupermatterSpreaderComponent.cs | 10 + .../EdgeSupermatterSpreaderComponent.cs | 14 + .../GrowingSupermatterKudzuComponent.cs | 14 + .../ADT/Spreader/SupermatterKudzuComponent.cs | 29 ++ .../ADT/Spreader/SupermatterKudzuSystem.cs | 111 ++++++ .../SupermatterSpreadNeighborsEvent.cs | 22 ++ .../SupermatterSpreaderGridComponent.cs | 8 + .../ADT/Spreader/SupermatterSpreaderSystem.cs | 351 ++++++++++++++++++ .../Spreader/SupermatterKudzuSystem.cs | 0 .../EdgeSupermatterSpreaderPrototype.cs | 19 + .../ADT/Spreader/SupermatterKudzuVisuals.cs | 10 + .../Supermatter/SupermatterKudzu.yml | 26 +- 12 files changed, 610 insertions(+), 4 deletions(-) create mode 100644 Content.Server/ADT/Spreader/ActiveEdgeSupermatterSpreaderComponent.cs create mode 100644 Content.Server/ADT/Spreader/EdgeSupermatterSpreaderComponent.cs create mode 100644 Content.Server/ADT/Spreader/GrowingSupermatterKudzuComponent.cs create mode 100644 Content.Server/ADT/Spreader/SupermatterKudzuComponent.cs create mode 100644 Content.Server/ADT/Spreader/SupermatterKudzuSystem.cs create mode 100644 Content.Server/ADT/Spreader/SupermatterSpreadNeighborsEvent.cs create mode 100644 Content.Server/ADT/Spreader/SupermatterSpreaderGridComponent.cs create mode 100644 Content.Server/ADT/Spreader/SupermatterSpreaderSystem.cs delete mode 100644 Content.Server/Spreader/SupermatterKudzuSystem.cs create mode 100644 Content.Shared/ADT/Spreader/EdgeSupermatterSpreaderPrototype.cs create mode 100644 Content.Shared/ADT/Spreader/SupermatterKudzuVisuals.cs diff --git a/Content.Server/ADT/Spreader/ActiveEdgeSupermatterSpreaderComponent.cs b/Content.Server/ADT/Spreader/ActiveEdgeSupermatterSpreaderComponent.cs new file mode 100644 index 00000000000..e20753e6089 --- /dev/null +++ b/Content.Server/ADT/Spreader/ActiveEdgeSupermatterSpreaderComponent.cs @@ -0,0 +1,10 @@ +namespace Content.Server.ADT.Spreader; + +/// +/// Added to entities being considered for spreading via . +/// This needs to be manually added and removed. +/// +[RegisterComponent] +public sealed partial class ActiveEdgeSupermatterSpreaderComponent : Component +{ +} diff --git a/Content.Server/ADT/Spreader/EdgeSupermatterSpreaderComponent.cs b/Content.Server/ADT/Spreader/EdgeSupermatterSpreaderComponent.cs new file mode 100644 index 00000000000..9ec92d2b477 --- /dev/null +++ b/Content.Server/ADT/Spreader/EdgeSupermatterSpreaderComponent.cs @@ -0,0 +1,14 @@ +using Content.Shared.ADT.Spreader; +using Robust.Shared.Prototypes; + +namespace Content.Server.ADT.Spreader; + +/// +/// Entity capable of becoming cloning and replicating itself to adjacent edges. See +/// +[RegisterComponent, Access(typeof(SupermatterSpreaderSystem))] +public sealed partial class EdgeSupermatterSpreaderComponent : Component +{ + [DataField(required:true)] + public ProtoId Id; +} diff --git a/Content.Server/ADT/Spreader/GrowingSupermatterKudzuComponent.cs b/Content.Server/ADT/Spreader/GrowingSupermatterKudzuComponent.cs new file mode 100644 index 00000000000..3c3c5ecf737 --- /dev/null +++ b/Content.Server/ADT/Spreader/GrowingSupermatterKudzuComponent.cs @@ -0,0 +1,14 @@ +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; + +namespace Content.Server.ADT.Spreader; + +[RegisterComponent, Access(typeof(SupermatterKudzuSystem)), AutoGenerateComponentPause] +public sealed partial class GrowingSupermatterKudzuComponent : Component +{ + /// + /// The next time kudzu will try to tick its growth level. + /// + [DataField("nextTick", customTypeSerializer:typeof(TimeOffsetSerializer))] + [AutoPausedField] + public TimeSpan NextTick = TimeSpan.Zero; +} diff --git a/Content.Server/ADT/Spreader/SupermatterKudzuComponent.cs b/Content.Server/ADT/Spreader/SupermatterKudzuComponent.cs new file mode 100644 index 00000000000..a3e464036ca --- /dev/null +++ b/Content.Server/ADT/Spreader/SupermatterKudzuComponent.cs @@ -0,0 +1,29 @@ +namespace Content.Server.ADT.Spreader; + +/// +/// Handles entities that spread out when they reach the relevant growth level. +/// +[RegisterComponent] +public sealed partial class SupermatterKudzuComponent : Component +{ + /// + /// At level 3 spreading can occur; prior to that we have a chance of increasing our growth level and changing our sprite. + /// + [DataField] + public int GrowthLevel = 1; + + /// + /// Chance to spread whenever an edge spread is possible. + /// + [DataField] + public float SpreadChance = 1f; + + [DataField] + public float GrowthTickChance = 1f; + + /// + /// number of sprite variations for kudzu + /// + [DataField] + public int SpriteVariants = 3; +} diff --git a/Content.Server/ADT/Spreader/SupermatterKudzuSystem.cs b/Content.Server/ADT/Spreader/SupermatterKudzuSystem.cs new file mode 100644 index 00000000000..cf378fb98cb --- /dev/null +++ b/Content.Server/ADT/Spreader/SupermatterKudzuSystem.cs @@ -0,0 +1,111 @@ +using Content.Shared.Damage; +using Content.Shared.ADT.Spreader; +using Robust.Shared.Random; +using Robust.Shared.Timing; +using Robust.Shared.Utility; + +namespace Content.Server.ADT.Spreader; + +public sealed class SupermatterKudzuSystem : EntitySystem +{ + [Dependency] private readonly IGameTiming _timing = default!; + [Dependency] private readonly IRobustRandom _robustRandom = default!; + [Dependency] private readonly SharedMapSystem _map = default!; + [Dependency] private readonly SharedAppearanceSystem _appearance = default!; + + [ValidatePrototypeId] + private const string SupermatterKudzuGroup = "SupermatterKudzu"; + + /// + public override void Initialize() + { + SubscribeLocalEvent(SetupKudzu); + SubscribeLocalEvent(OnKudzuSpread); + } + + private void OnKudzuSpread(EntityUid uid, SupermatterKudzuComponent component, ref SupermatterSpreadNeighborsEvent args) + { + if (component.GrowthLevel < 3) + return; + + if (args.NeighborFreeTiles.Count == 0) + { + RemCompDeferred(uid); + return; + } + + if (!_robustRandom.Prob(component.SpreadChance)) + return; + + var prototype = MetaData(uid).EntityPrototype?.ID; + + if (prototype == null) + { + RemCompDeferred(uid); + return; + } + + foreach (var neighbor in args.NeighborFreeTiles) + { + var neighborUid = Spawn(prototype, _map.GridTileToLocal(neighbor.Tile.GridUid, neighbor.Grid, neighbor.Tile.GridIndices)); + DebugTools.Assert(HasComp(neighborUid)); + DebugTools.Assert(HasComp(neighborUid)); + DebugTools.Assert(Comp(neighborUid).Id == SupermatterKudzuGroup); + args.Updates--; + if (args.Updates <= 0) + return; + } + } + + private void SetupKudzu(EntityUid uid, SupermatterKudzuComponent component, ComponentStartup args) + { + if (!EntityManager.TryGetComponent(uid, out var appearance)) + { + return; + } + + _appearance.SetData(uid, SupermatterKudzuVisuals.Variant, _robustRandom.Next(1, component.SpriteVariants), appearance); + _appearance.SetData(uid, SupermatterKudzuVisuals.GrowthLevel, 1, appearance); + } + + /// + public override void Update(float frameTime) + { + var appearanceQuery = GetEntityQuery(); + var query = EntityQueryEnumerator(); + var kudzuQuery = GetEntityQuery(); + var curTime = _timing.CurTime; + + while (query.MoveNext(out var uid, out var grow)) + { + if (grow.NextTick > curTime) + continue; + + grow.NextTick = curTime + TimeSpan.FromSeconds(0.5); + + if (!kudzuQuery.TryGetComponent(uid, out var kudzu)) + { + RemCompDeferred(uid, grow); + continue; + } + + if (!_robustRandom.Prob(kudzu.GrowthTickChance)) + { + continue; + } + + kudzu.GrowthLevel += 1; + + if (kudzu.GrowthLevel >= 3) + { + // why cache when you can simply cease to be? Also saves a bit of memory/time. + RemCompDeferred(uid, grow); + } + + if (appearanceQuery.TryGetComponent(uid, out var appearance)) + { + _appearance.SetData(uid, SupermatterKudzuVisuals.GrowthLevel, kudzu.GrowthLevel, appearance); + } + } + } +} diff --git a/Content.Server/ADT/Spreader/SupermatterSpreadNeighborsEvent.cs b/Content.Server/ADT/Spreader/SupermatterSpreadNeighborsEvent.cs new file mode 100644 index 00000000000..8bef4b33eff --- /dev/null +++ b/Content.Server/ADT/Spreader/SupermatterSpreadNeighborsEvent.cs @@ -0,0 +1,22 @@ +using Robust.Shared.Collections; +using Robust.Shared.Map; +using Robust.Shared.Map.Components; + +namespace Content.Server.ADT.Spreader; + +/// +/// Raised when trying to spread to neighboring tiles. +/// If the spread is no longer able to happen you MUST cancel this event! +/// +[ByRefEvent] +public record struct SupermatterSpreadNeighborsEvent +{ + public ValueList<(MapGridComponent Grid, TileRef Tile)> NeighborFreeTiles; + public ValueList Neighbors; + + /// + /// How many updates allowed are remaining. + /// Subscribers can handle as they wish. + /// + public int Updates; +} diff --git a/Content.Server/ADT/Spreader/SupermatterSpreaderGridComponent.cs b/Content.Server/ADT/Spreader/SupermatterSpreaderGridComponent.cs new file mode 100644 index 00000000000..ee4e51b442e --- /dev/null +++ b/Content.Server/ADT/Spreader/SupermatterSpreaderGridComponent.cs @@ -0,0 +1,8 @@ +namespace Content.Server.ADT.Spreader; + +[RegisterComponent] +public sealed partial class SupermatterSpreaderGridComponent : Component +{ + [DataField] + public float UpdateAccumulator = SupermatterSpreaderSystem.SpreadCooldownSeconds; +} diff --git a/Content.Server/ADT/Spreader/SupermatterSpreaderSystem.cs b/Content.Server/ADT/Spreader/SupermatterSpreaderSystem.cs new file mode 100644 index 00000000000..664a1a70af4 --- /dev/null +++ b/Content.Server/ADT/Spreader/SupermatterSpreaderSystem.cs @@ -0,0 +1,351 @@ +using Content.Server.Atmos.Components; +using Content.Server.Atmos.EntitySystems; +using Content.Server.Shuttles.Components; +using Content.Shared.Atmos; +using Content.Shared.Maps; +using Content.Shared.ADT.Spreader; +using Content.Shared.Tag; +using Robust.Shared.Collections; +using Robust.Shared.Map; +using Robust.Shared.Map.Components; +using Robust.Shared.Prototypes; +using Robust.Shared.Random; +using Robust.Shared.Utility; + +namespace Content.Server.ADT.Spreader; + +/// +/// Handles generic spreading logic, where one anchored entity spreads to neighboring tiles. +/// +public sealed class SupermatterSpreaderSystem : EntitySystem +{ + [Dependency] private readonly IPrototypeManager _prototype = default!; + [Dependency] private readonly IRobustRandom _robustRandom = default!; + [Dependency] private readonly SharedMapSystem _map = default!; + [Dependency] private readonly TagSystem _tag = default!; + + /// + /// Cached maximum number of updates per spreader prototype. This is applied per-grid. + /// + private Dictionary _prototypeUpdates = default!; + + /// + /// Remaining number of updates per grid & prototype. + /// + // TODO PERFORMANCE Assign each prototype to an index and convert dictionary to array + private readonly Dictionary> _gridUpdates = []; + + private EntityQuery _query; + + public const float SpreadCooldownSeconds = 1; + + private static readonly ProtoId IgnoredTag = "SpreaderIgnore"; + + /// + public override void Initialize() + { + SubscribeLocalEvent(OnAirtightChanged); + SubscribeLocalEvent(OnGridInit); + SubscribeLocalEvent(OnPrototypeReload); + + SubscribeLocalEvent(OnTerminating); + SetupPrototypes(); + + _query = GetEntityQuery(); + } + + private void OnPrototypeReload(PrototypesReloadedEventArgs obj) + { + if (obj.WasModified()) + SetupPrototypes(); + } + + private void SetupPrototypes() + { + _prototypeUpdates = []; + foreach (var proto in _prototype.EnumeratePrototypes()) + { + _prototypeUpdates.Add(proto.ID, proto.UpdatesPerSecond); + } + } + + private void OnAirtightChanged(ref AirtightChanged ev) + { + ActivateSpreadableNeighbors(ev.Entity, ev.Position); + } + + private void OnGridInit(GridInitializeEvent ev) + { + EnsureComp(ev.EntityUid); + } + + private void OnTerminating(Entity entity, ref EntityTerminatingEvent args) + { + ActivateSpreadableNeighbors(entity); + } + + /// + public override void Update(float frameTime) + { + // Check which grids are valid for spreading + var spreadGrids = EntityQueryEnumerator(); + + _gridUpdates.Clear(); + while (spreadGrids.MoveNext(out var uid, out var grid)) + { + grid.UpdateAccumulator -= frameTime; + if (grid.UpdateAccumulator > 0) + continue; + + _gridUpdates[uid] = _prototypeUpdates.ShallowClone(); + grid.UpdateAccumulator += SpreadCooldownSeconds; + } + + if (_gridUpdates.Count == 0) + return; + + var query = EntityQueryEnumerator(); + var xforms = GetEntityQuery(); + var spreaderQuery = GetEntityQuery(); + + var spreaders = new List<(EntityUid Uid, ActiveEdgeSupermatterSpreaderComponent Comp)>(Count()); + + // Build a list of all existing Edgespreaders, shuffle them + while (query.MoveNext(out var uid, out var comp)) + { + spreaders.Add((uid, comp)); + } + + _robustRandom.Shuffle(spreaders); + + // Remove the EdgeSpreaderComponent from any entity + // that doesn't meet a few trivial prerequisites + foreach (var (uid, comp) in spreaders) + { + // Get xform first, as entity may have been deleted due to interactions triggered by other spreaders. + if (!xforms.TryGetComponent(uid, out var xform)) + continue; + + if (xform.GridUid == null) + { + RemComp(uid, comp); + continue; + } + + if (!_gridUpdates.TryGetValue(xform.GridUid.Value, out var groupUpdates)) + continue; + + if (!spreaderQuery.TryGetComponent(uid, out var spreader)) + { + RemComp(uid, comp); + continue; + } + + if (!groupUpdates.TryGetValue(spreader.Id, out var updates) || updates < 1) + continue; + + // Edge detection logic is to be handled + // by the subscribing system, see KudzuSystem + // for a simple example + Spread(uid, xform, spreader.Id, ref updates); + + if (updates < 1) + groupUpdates.Remove(spreader.Id); + else + groupUpdates[spreader.Id] = updates; + } + } + + private void Spread(EntityUid uid, TransformComponent xform, ProtoId prototype, ref int updates) + { + GetNeighbors(uid, xform, prototype, out var freeTiles, out _, out var neighbors); + + var ev = new SupermatterSpreadNeighborsEvent() + { + NeighborFreeTiles = freeTiles, + Neighbors = neighbors, + Updates = updates, + }; + + RaiseLocalEvent(uid, ref ev); + updates = ev.Updates; + } + + /// + /// Gets the neighboring node data for the specified entity and the specified node group. + /// + public void GetNeighbors(EntityUid uid, TransformComponent comp, ProtoId prototype, out ValueList<(MapGridComponent, TileRef)> freeTiles, out ValueList occupiedTiles, out ValueList neighbors) + { + freeTiles = []; + occupiedTiles = []; + neighbors = []; + // TODO remove occupiedTiles -- its currently unused and just slows this method down. + if (!_prototype.TryIndex(prototype, out var spreaderPrototype)) + return; + + if (!TryComp(comp.GridUid, out var grid)) + return; + + var tile = _map.TileIndicesFor(comp.GridUid.Value, grid, comp.Coordinates); + var spreaderQuery = GetEntityQuery(); + var airtightQuery = GetEntityQuery(); + var dockQuery = GetEntityQuery(); + var xformQuery = GetEntityQuery(); + var blockedAtmosDirs = AtmosDirection.Invalid; + + // Due to docking ports they may not necessarily be opposite directions. + var neighborTiles = new ValueList<(EntityUid entity, MapGridComponent grid, Vector2i Indices, AtmosDirection OtherDir, AtmosDirection OurDir)>(); + + // Check if anything on our own tile blocking that direction. + var ourEnts = _map.GetAnchoredEntitiesEnumerator(comp.GridUid.Value, grid, tile); + + while (ourEnts.MoveNext(out var ent)) + { + // Spread via docks in a special-case. + if (dockQuery.TryGetComponent(ent, out var dock) && + dock.Docked && + xformQuery.TryGetComponent(ent, out var xform) && + xformQuery.TryGetComponent(dock.DockedWith, out var dockedXform) && + TryComp(dockedXform.GridUid, out var dockedGrid)) + { + neighborTiles.Add((dockedXform.GridUid.Value, dockedGrid, _map.CoordinatesToTile(dockedXform.GridUid.Value, dockedGrid, dockedXform.Coordinates), xform.LocalRotation.ToAtmosDirection(), dockedXform.LocalRotation.ToAtmosDirection())); + } + + // If we're on a blocked tile work out which directions we can go. + if (!airtightQuery.TryGetComponent(ent, out var airtight) || !airtight.AirBlocked || + _tag.HasTag(ent.Value, IgnoredTag)) + { + continue; + } + + foreach (var value in new[] { AtmosDirection.North, AtmosDirection.East, AtmosDirection.South, AtmosDirection.West }) + { + if ((value & airtight.AirBlockedDirection) == 0x0) + continue; + + blockedAtmosDirs |= value; + break; + } + break; + } + + // Add the normal neighbors. + for (var i = 0; i < 4; i++) + { + var atmosDir = (AtmosDirection) (1 << i); + var neighborPos = tile.Offset(atmosDir); + neighborTiles.Add((comp.GridUid.Value, grid, neighborPos, atmosDir, i.ToOppositeDir())); + } + + foreach (var (neighborEnt, neighborGrid, neighborPos, ourAtmosDir, otherAtmosDir) in neighborTiles) + { + // This tile is blocked to that direction. + if ((blockedAtmosDirs & ourAtmosDir) != 0x0) + continue; + + if (!_map.TryGetTileRef(neighborEnt, neighborGrid, neighborPos, out var tileRef) || tileRef.Tile.IsEmpty) + continue; + + if (spreaderPrototype.PreventSpreadOnSpaced && tileRef.Tile.IsSpace()) + continue; + + var directionEnumerator = _map.GetAnchoredEntitiesEnumerator(neighborEnt, neighborGrid, neighborPos); + var occupied = false; + + while (directionEnumerator.MoveNext(out var ent)) + { + if (!airtightQuery.TryGetComponent(ent, out var airtight) || !airtight.AirBlocked || _tag.HasTag(ent.Value, IgnoredTag)) + { + continue; + } + + if ((airtight.AirBlockedDirection & otherAtmosDir) == 0x0) + continue; + + occupied = true; + break; + } + + if (occupied) + continue; + + var oldCount = occupiedTiles.Count; + directionEnumerator = _map.GetAnchoredEntitiesEnumerator(neighborEnt, neighborGrid, neighborPos); + + while (directionEnumerator.MoveNext(out var ent)) + { + if (!spreaderQuery.TryGetComponent(ent, out var spreader)) + continue; + + if (spreader.Id != prototype) + continue; + + neighbors.Add(ent.Value); + occupiedTiles.Add(neighborPos); + break; + } + + if (oldCount == occupiedTiles.Count) + freeTiles.Add((neighborGrid, tileRef)); + } + } + + /// + /// This function activates all spreaders that are adjacent to a given entity. This also activates other spreaders + /// on the same tile as the current entity (for thin airtight entities like windoors). + /// + public void ActivateSpreadableNeighbors(EntityUid uid, (EntityUid Grid, Vector2i Tile)? position = null) + { + Vector2i tile; + EntityUid ent; + MapGridComponent? grid; + + if (position == null) + { + var transform = Transform(uid); + if (!TryComp(transform.GridUid, out grid) || TerminatingOrDeleted(transform.GridUid.Value)) + return; + + tile = _map.TileIndicesFor(transform.GridUid.Value, grid, transform.Coordinates); + ent = transform.GridUid.Value; + } + else + { + if (!TryComp(position.Value.Grid, out grid)) + return; + (ent, tile) = position.Value; + } + + var anchored = _map.GetAnchoredEntitiesEnumerator(ent, grid, tile); + while (anchored.MoveNext(out var entity)) + { + if (entity == ent) + continue; + DebugTools.Assert(Transform(entity.Value).Anchored); + if (_query.HasComponent(ent) && !TerminatingOrDeleted(entity.Value)) + EnsureComp(entity.Value); + } + + for (var i = 0; i < Atmospherics.Directions; i++) + { + var direction = (AtmosDirection) (1 << i); + var adjacentTile = SharedMapSystem.GetDirection(tile, direction.ToDirection()); + anchored = _map.GetAnchoredEntitiesEnumerator(ent, grid, adjacentTile); + + while (anchored.MoveNext(out var entity)) + { + DebugTools.Assert(Transform(entity.Value).Anchored); + if (_query.HasComponent(ent) && !TerminatingOrDeleted(entity.Value)) + EnsureComp(entity.Value); + } + } + } + + public bool RequiresFloorToSpread(EntProtoId spreader) + { + if (!_prototype.Index(spreader).TryGetComponent(out var spreaderComp, EntityManager.ComponentFactory)) + return false; + + return _prototype.Index(spreaderComp.Id).PreventSpreadOnSpaced; + } +} diff --git a/Content.Server/Spreader/SupermatterKudzuSystem.cs b/Content.Server/Spreader/SupermatterKudzuSystem.cs deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/Content.Shared/ADT/Spreader/EdgeSupermatterSpreaderPrototype.cs b/Content.Shared/ADT/Spreader/EdgeSupermatterSpreaderPrototype.cs new file mode 100644 index 00000000000..20dd2b432ab --- /dev/null +++ b/Content.Shared/ADT/Spreader/EdgeSupermatterSpreaderPrototype.cs @@ -0,0 +1,19 @@ +using Robust.Shared.Prototypes; + +namespace Content.Shared.ADT.Spreader; + +/// +/// Adds this node group to for tick updates. +/// +[Prototype("edgeSupermatterSpreader")] +public sealed partial class EdgeSupermatterSpreaderPrototype : IPrototype +{ + [IdDataField] public string ID { get; } = string.Empty; + [DataField(required:true)] public int UpdatesPerSecond; + + /// + /// If true, this spreader can't spread onto spaced tiles like lattice. + /// + [DataField] + public bool PreventSpreadOnSpaced = true; +} \ No newline at end of file diff --git a/Content.Shared/ADT/Spreader/SupermatterKudzuVisuals.cs b/Content.Shared/ADT/Spreader/SupermatterKudzuVisuals.cs new file mode 100644 index 00000000000..e3c6e419a24 --- /dev/null +++ b/Content.Shared/ADT/Spreader/SupermatterKudzuVisuals.cs @@ -0,0 +1,10 @@ +using Robust.Shared.Serialization; + +namespace Content.Shared.ADT.Spreader; + +[Serializable, NetSerializable] +public enum SupermatterKudzuVisuals : byte +{ + GrowthLevel, + Variant +} diff --git a/Resources/Prototypes/ADT/Entities/Structures/Power/Generation/Supermatter/SupermatterKudzu.yml b/Resources/Prototypes/ADT/Entities/Structures/Power/Generation/Supermatter/SupermatterKudzu.yml index e190c22dabd..5eeae9b37df 100644 --- a/Resources/Prototypes/ADT/Entities/Structures/Power/Generation/Supermatter/SupermatterKudzu.yml +++ b/Resources/Prototypes/ADT/Entities/Structures/Power/Generation/Supermatter/SupermatterKudzu.yml @@ -1,7 +1,25 @@ +- type: entity + id: BaseSupermatterKudzu + abstract: true + placement: + mode: SnapgridCenter + snap: + - Wall + components: + - type: Appearance + - type: Transform + anchored: true + - type: Physics + - type: SupermatterKudzu + - type: GrowingSupermatterKudzu + - type: ActiveEdgeSupermatterSpreader + - type: EdgeSupermatterSpreader + id: SupermatterKudzu + - type: entity id: SupermatterKudzu name: Сверхматерия? - parent: BaseKudzu + parent: BaseSupermatterKudzu description: Это такой конец... placement: mode: SnapgridCenter @@ -35,8 +53,8 @@ Radiation: 10 ignoreWhitelist: tags: - - Flesh - - type: Kudzu + - SupermatterKudzu + - type: SupermatterKudzu growthTickChance: 0.1 spreadChance: 0.4 - type: SpeedModifierContacts @@ -44,7 +62,7 @@ sprintSpeedModifier: 0.3 ignoreWhitelist: tags: - - Flesh + - SupermatterKudzu - type: Respirator damage: types: