diff --git a/Content.Server/_NF/GameRule/Events/Components/RandomShipyardErrorRuleComponent.cs b/Content.Server/_NF/GameRule/Events/Components/RandomShipyardErrorRuleComponent.cs
new file mode 100644
index 00000000000..2c3be236f37
--- /dev/null
+++ b/Content.Server/_NF/GameRule/Events/Components/RandomShipyardErrorRuleComponent.cs
@@ -0,0 +1,22 @@
+namespace Content.Server._NF.GameRule.Events.Components;
+
+[RegisterComponent, Access(typeof(RandomShipyardErrorRule))]
+public sealed partial class RandomShipyardErrorRuleComponent : Component
+{
+ ///
+ /// Min vessels count for spawning
+ ///
+ [DataField("minGridCount")]
+ public int MinGridsCount = 2;
+ ///
+ /// Man vessels count for spawning
+ ///
+ [DataField("maxGridCount")]
+ public int MaxGridsCount = 5;
+
+ ///
+ /// The grid in question, set after starting the event
+ ///
+ [DataField("gridUid")]
+ public List GridUids = new();
+}
diff --git a/Content.Server/_NF/GameRule/Events/RandomShipyardErrorRule.cs b/Content.Server/_NF/GameRule/Events/RandomShipyardErrorRule.cs
new file mode 100644
index 00000000000..ab46c64300a
--- /dev/null
+++ b/Content.Server/_NF/GameRule/Events/RandomShipyardErrorRule.cs
@@ -0,0 +1,124 @@
+using System.Linq;
+using System.Numerics;
+using Content.Server._NF.GameRule.Events.Components;
+using Content.Server.Cargo.Components;
+using Content.Server.Cargo.Systems;
+using Robust.Server.GameObjects;
+using Robust.Server.Maps;
+using Robust.Shared.Map;
+using Content.Server.GameTicking.Rules.Components;
+using Content.Server.Shuttles.Components;
+using Content.Server.Shuttles.Systems;
+using Content.Server.StationEvents.Events;
+using Content.Shared.Humanoid;
+using Content.Shared.Mobs.Components;
+using Content.Shared.Shipyard.Prototypes;
+using Robust.Shared.Prototypes;
+using Robust.Shared.Random;
+
+namespace Content.Server._NF.GameRule.Events;
+
+public sealed class RandomShipyardErrorRule : StationEventSystem
+{
+ [Dependency] private readonly IMapManager _mapManager = default!;
+ [Dependency] private readonly MapLoaderSystem _map = default!;
+ [Dependency] private readonly ShuttleSystem _shuttle = default!;
+ [Dependency] private readonly IRobustRandom _random = default!;
+ [Dependency] private readonly SharedTransformSystem _transform = default!;
+ [Dependency] private readonly PricingSystem _pricing = default!;
+ [Dependency] private readonly CargoSystem _cargo = default!;
+ [Dependency] private readonly IPrototypeManager _proto = default!;
+
+ private List<(Entity Entity, EntityUid MapUid, Vector2 LocalPosition)> _playerMobs = new();
+
+ protected override void Started(EntityUid uid, RandomShipyardErrorRuleComponent component,
+ GameRuleComponent gameRule,
+ GameRuleStartedEvent args)
+ {
+ base.Started(uid, component, gameRule, args);
+ var vesselPrototypes = _proto.EnumeratePrototypes();
+ var prototypes = vesselPrototypes as VesselPrototype[] ?? vesselPrototypes.ToArray();
+ var rnd = new Random();
+ var vesselCount = rnd.Next(component.MinGridsCount, component.MaxGridsCount);
+
+ for (var i = 0; i < vesselCount; i++)
+ {
+ var index = rnd.Next(0, prototypes.Count());
+ var gridPath = prototypes.ElementAt(index).ShuttlePath.ToString();
+ var shuttleMap = _mapManager.CreateMap();
+ var options = new MapLoadOptions
+ {
+ LoadMap = true,
+ };
+ if (!_map.TryLoad(shuttleMap, gridPath, out var gridUids, options))
+ return;
+ component.GridUids.Add(gridUids[0]);
+ if (component.GridUids.Last() is not { } gridUid)
+ return;
+ _shuttle.SetIFFColor(gridUid, new Color(rnd.Next(256), rnd.Next(256), rnd.Next(256), 0));
+ var offset = _random.NextVector2(1800f, 2000f);
+ var mapId = GameTicker.DefaultMap;
+ var coords = new MapCoordinates(offset, mapId);
+ var location = Spawn(null, coords);
+ if (TryComp(component.GridUids.Last(), out var shuttle))
+ {
+ _shuttle.FTLTravel(gridUid, shuttle, location, 5.5f, 55f);
+ }
+ }
+ }
+
+ protected override void Ended(
+ EntityUid uid,
+ RandomShipyardErrorRuleComponent component,
+ GameRuleComponent gameRule,
+ GameRuleEndedEvent args)
+ {
+ base.Ended(uid, component, gameRule, args);
+ foreach (var gridId in component.GridUids)
+ {
+
+
+ if (!EntityManager.TryGetComponent(gridId, out var gridTransform))
+ {
+ Log.Error("bluespace error objective was missing transform component");
+ return;
+ }
+
+ if (gridTransform.GridUid is not EntityUid gridUid)
+ {
+ Log.Error("bluespace error has no associated grid?");
+ return;
+ }
+
+ var gridValue = _pricing.AppraiseGrid(gridUid, null);
+
+ var mobQuery = AllEntityQuery();
+ _playerMobs.Clear();
+
+ while (mobQuery.MoveNext(out var mobUid, out _, out _, out var xform))
+ {
+ if (xform.GridUid == null || xform.MapUid == null || xform.GridUid != gridUid)
+ continue;
+
+ // Can't parent directly to map as it runs grid traversal.
+ _playerMobs.Add(((mobUid, xform), xform.MapUid.Value, _transform.GetWorldPosition(xform)));
+ _transform.DetachParentToNull(mobUid, xform);
+ }
+
+ // Deletion has to happen before grid traversal re-parents players.
+ Del(gridUid);
+
+ foreach (var mob in _playerMobs)
+ {
+ _transform.SetCoordinates(mob.Entity.Owner, new EntityCoordinates(mob.MapUid, mob.LocalPosition));
+ }
+
+
+ var query = EntityQuery();
+ foreach (var account in query)
+ {
+ _cargo.DeductFunds(account, (int) -gridValue);
+ }
+ }
+ }
+}
diff --git a/Resources/Prototypes/_NF/Events/events.yml b/Resources/Prototypes/_NF/Events/events.yml
index a39ee0a9ae6..2dd5d25de5f 100644
--- a/Resources/Prototypes/_NF/Events/events.yml
+++ b/Resources/Prototypes/_NF/Events/events.yml
@@ -215,4 +215,21 @@
duration: 1800
maxDuration: 2400
- type: BluespaceErrorRule
- gridPath: /Maps/_NF/Bluespace/bloodmoon.yml
\ No newline at end of file
+ gridPath: /Maps/_NF/Bluespace/bloodmoon.yml
+
+- type: entity
+ id: ShipyardRandomVesselError
+ parent: BaseGameRule
+ noSpawn: true
+ components:
+ - type: StationEvent
+ startAnnouncement: Из-за ошибки в программном обеспечении верфи, некоторые новые суда были случайно отправлены в данный сектор.
+ startAudio:
+ path: /Audio/Misc/notice1.ogg
+ earliestStart: 80
+ minimumPlayers: 30
+ weight: 8
+ startDelay: 10
+ duration: 1800
+ maxDuration: 2400
+ - type: RandomShipyardErrorRule