@@ -114,8 +114,8 @@ public sealed class NukeOpsTest
|
||||
|
||||
// The game rule exists, and all the stations/shuttles/maps are properly initialized
|
||||
var rule = entMan.AllComponents<NukeopsRuleComponent>().Single().Component;
|
||||
var mapRule = entMan.AllComponents<LoadMapRuleComponent>().Single().Component;
|
||||
foreach (var grid in mapRule.MapGrids)
|
||||
var gridsRule = entMan.AllComponents<RuleGridsComponent>().Single().Component;
|
||||
foreach (var grid in gridsRule.MapGrids)
|
||||
{
|
||||
Assert.That(entMan.EntityExists(grid));
|
||||
Assert.That(entMan.HasComponent<MapGridComponent>(grid));
|
||||
@@ -129,7 +129,7 @@ public sealed class NukeOpsTest
|
||||
Assert.That(entMan.EntityExists(nukieShuttlEnt));
|
||||
|
||||
EntityUid? nukieStationEnt = null;
|
||||
foreach (var grid in mapRule.MapGrids)
|
||||
foreach (var grid in gridsRule.MapGrids)
|
||||
{
|
||||
if (entMan.HasComponent<StationMemberComponent>(grid))
|
||||
{
|
||||
@@ -144,8 +144,8 @@ public sealed class NukeOpsTest
|
||||
Assert.That(entMan.EntityExists(nukieStation.Station));
|
||||
Assert.That(nukieStation.Station, Is.Not.EqualTo(rule.TargetStation));
|
||||
|
||||
Assert.That(server.MapMan.MapExists(mapRule.Map));
|
||||
var nukieMap = mapSys.GetMap(mapRule.Map!.Value);
|
||||
Assert.That(server.MapMan.MapExists(gridsRule.Map));
|
||||
var nukieMap = mapSys.GetMap(gridsRule.Map!.Value);
|
||||
|
||||
var targetStation = entMan.GetComponent<StationDataComponent>(rule.TargetStation!.Value);
|
||||
var targetGrid = targetStation.Grids.First();
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
using Content.Server.GameTicking.Rules;
|
||||
using Content.Server.Maps;
|
||||
using Content.Shared.GridPreloader.Prototypes;
|
||||
using Content.Shared.Storage;
|
||||
using Content.Shared.Whitelist;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
@@ -10,25 +8,27 @@ namespace Content.Server.GameTicking.Rules.Components;
|
||||
|
||||
/// <summary>
|
||||
/// This is used for a game rule that loads a map when activated.
|
||||
/// Works with <see cref="RuleGridsComponent"/>.
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
[RegisterComponent, Access(typeof(LoadMapRuleSystem))]
|
||||
public sealed partial class LoadMapRuleComponent : Component
|
||||
{
|
||||
[DataField]
|
||||
public MapId? Map;
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="GameMapPrototype"/> to load on a new map.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public ProtoId<GameMapPrototype>? GameMap;
|
||||
|
||||
/// <summary>
|
||||
/// A map path to load on a new map.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public ResPath? MapPath;
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="PreloadedGridPrototype"/> to move to a new map.
|
||||
/// If there are no instances left nothing is done.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public ProtoId<PreloadedGridPrototype>? PreloadedGrid;
|
||||
|
||||
[DataField]
|
||||
public List<EntityUid> MapGrids = new();
|
||||
|
||||
[DataField]
|
||||
public EntityWhitelist? SpawnerWhitelist;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
using Content.Server.GameTicking.Rules;
|
||||
using Content.Shared.Whitelist;
|
||||
using Robust.Shared.Map;
|
||||
|
||||
/// <summary>
|
||||
/// Stores grids created by another gamerule component.
|
||||
/// With <c>AntagSelection</c>, spawners on these grids can be used for its antags.
|
||||
/// </summary>
|
||||
[RegisterComponent, Access(typeof(RuleGridsSystem))]
|
||||
public sealed partial class RuleGridsComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// The map that was loaded.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public MapId? Map;
|
||||
|
||||
/// <summary>
|
||||
/// The grid entities that have been loaded.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public List<EntityUid> MapGrids = new();
|
||||
|
||||
/// <summary>
|
||||
/// Whitelist for a spawner to be considered for an antag.
|
||||
/// All spawners must have <c>SpawnPointComponent</c> regardless to be found.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public EntityWhitelist? SpawnerWhitelist;
|
||||
}
|
||||
@@ -126,4 +126,8 @@ public abstract partial class GameRuleSystem<T> where T: IComponent
|
||||
return found;
|
||||
}
|
||||
|
||||
protected void ForceEndSelf(EntityUid uid, GameRuleComponent? component = null)
|
||||
{
|
||||
GameTicker.EndGameRule(uid, component);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
using Content.Server.Antag;
|
||||
using Content.Server.GameTicking.Components;
|
||||
using Content.Server.GameTicking.Rules.Components;
|
||||
using Content.Server.GridPreloader;
|
||||
using Content.Server.Spawners.Components;
|
||||
using Content.Shared.Whitelist;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Server.Maps;
|
||||
using Robust.Shared.Map;
|
||||
@@ -14,97 +11,70 @@ namespace Content.Server.GameTicking.Rules;
|
||||
public sealed class LoadMapRuleSystem : GameRuleSystem<LoadMapRuleComponent>
|
||||
{
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||
[Dependency] private readonly MapSystem _map = default!;
|
||||
[Dependency] private readonly MapLoaderSystem _mapLoader = default!;
|
||||
[Dependency] private readonly MetaDataSystem _metaData = default!;
|
||||
[Dependency] private readonly TransformSystem _transform = default!;
|
||||
[Dependency] private readonly GridPreloaderSystem _gridPreloader = default!;
|
||||
[Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<LoadMapRuleComponent, AntagSelectLocationEvent>(OnSelectLocation);
|
||||
SubscribeLocalEvent<GridSplitEvent>(OnGridSplit);
|
||||
}
|
||||
|
||||
private void OnGridSplit(ref GridSplitEvent args)
|
||||
{
|
||||
var rule = QueryActiveRules();
|
||||
while (rule.MoveNext(out _, out var mapComp, out _))
|
||||
{
|
||||
if (!mapComp.MapGrids.Contains(args.Grid))
|
||||
continue;
|
||||
|
||||
mapComp.MapGrids.AddRange(args.NewGrids);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Added(EntityUid uid, LoadMapRuleComponent comp, GameRuleComponent rule, GameRuleAddedEvent args)
|
||||
{
|
||||
if (comp.Map != null)
|
||||
if (comp.PreloadedGrid != null && !_gridPreloader.PreloadingEnabled)
|
||||
{
|
||||
// Preloading will never work if it's disabled, duh
|
||||
Log.Debug($"Immediately ending {ToPrettyString(uid):rule} as preloading grids is disabled by cvar.");
|
||||
ForceEndSelf(uid, rule);
|
||||
return;
|
||||
}
|
||||
|
||||
// grid preloading needs map to init after moving it
|
||||
var mapUid = comp.PreloadedGrid != null ? _map.CreateMap(out var mapId, false) : _map.CreateMap(out mapId);
|
||||
_metaData.SetEntityName(mapUid, $"LoadMapRule destination for rule {ToPrettyString(uid)}");
|
||||
comp.Map = mapId;
|
||||
var mapUid = _map.CreateMap(out var mapId, runMapInit: comp.PreloadedGrid == null);
|
||||
|
||||
Log.Info($"Created map {mapId} for {ToPrettyString(uid):rule}");
|
||||
|
||||
IReadOnlyList<EntityUid> grids;
|
||||
if (comp.GameMap != null)
|
||||
{
|
||||
var gameMap = _prototypeManager.Index(comp.GameMap.Value);
|
||||
comp.MapGrids.AddRange(GameTicker.LoadGameMap(gameMap, comp.Map.Value, new MapLoadOptions()));
|
||||
grids = GameTicker.LoadGameMap(gameMap, mapId, new MapLoadOptions());
|
||||
}
|
||||
else if (comp.MapPath != null)
|
||||
else if (comp.MapPath is {} path)
|
||||
{
|
||||
if (!_mapLoader.TryLoad(comp.Map.Value,
|
||||
comp.MapPath.Value.ToString(),
|
||||
out var roots,
|
||||
new MapLoadOptions { LoadMap = true }))
|
||||
var options = new MapLoadOptions { LoadMap = true };
|
||||
if (!_mapLoader.TryLoad(mapId, path.ToString(), out var roots, options))
|
||||
{
|
||||
_mapManager.DeleteMap(mapId);
|
||||
Log.Error($"Failed to load map from {path}!");
|
||||
Del(mapUid);
|
||||
ForceEndSelf(uid, rule);
|
||||
return;
|
||||
}
|
||||
|
||||
comp.MapGrids.AddRange(roots);
|
||||
grids = roots;
|
||||
}
|
||||
else if (comp.PreloadedGrid != null)
|
||||
else if (comp.PreloadedGrid is {} preloaded)
|
||||
{
|
||||
// TODO: If there are no preloaded grids left, any rule announcements will still go off!
|
||||
if (!_gridPreloader.TryGetPreloadedGrid(comp.PreloadedGrid.Value, out var loadedShuttle))
|
||||
if (!_gridPreloader.TryGetPreloadedGrid(preloaded, out var loadedShuttle))
|
||||
{
|
||||
_mapManager.DeleteMap(mapId);
|
||||
Log.Error($"Failed to get a preloaded grid with {preloaded}!");
|
||||
Del(mapUid);
|
||||
ForceEndSelf(uid, rule);
|
||||
return;
|
||||
}
|
||||
|
||||
_transform.SetParent(loadedShuttle.Value, mapUid);
|
||||
comp.MapGrids.Add(loadedShuttle.Value);
|
||||
_map.InitializeMap(mapId);
|
||||
grids = new List<EntityUid>() { loadedShuttle.Value };
|
||||
_map.InitializeMap(mapUid);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Error($"No valid map prototype or map path associated with the rule {ToPrettyString(uid)}");
|
||||
Del(mapUid);
|
||||
ForceEndSelf(uid, rule);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnSelectLocation(Entity<LoadMapRuleComponent> ent, ref AntagSelectLocationEvent args)
|
||||
{
|
||||
var query = EntityQueryEnumerator<SpawnPointComponent, TransformComponent>();
|
||||
while (query.MoveNext(out var uid, out _, out var xform))
|
||||
{
|
||||
if (xform.MapID != ent.Comp.Map)
|
||||
continue;
|
||||
|
||||
if (xform.GridUid == null || !ent.Comp.MapGrids.Contains(xform.GridUid.Value))
|
||||
continue;
|
||||
|
||||
if (_whitelistSystem.IsWhitelistFail(ent.Comp.SpawnerWhitelist, uid))
|
||||
continue;
|
||||
|
||||
args.Coordinates.Add(_transform.GetMapCoordinates(xform));
|
||||
}
|
||||
var ev = new RuleLoadedGridsEvent(mapId, grids);
|
||||
RaiseLocalEvent(uid, ref ev);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,10 +260,10 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
|
||||
{
|
||||
var map = Transform(ent).MapID;
|
||||
|
||||
var rules = EntityQueryEnumerator<NukeopsRuleComponent, LoadMapRuleComponent>();
|
||||
while (rules.MoveNext(out var uid, out _, out var mapRule))
|
||||
var rules = EntityQueryEnumerator<NukeopsRuleComponent, RuleGridsComponent>();
|
||||
while (rules.MoveNext(out var uid, out _, out var grids))
|
||||
{
|
||||
if (map != mapRule.Map)
|
||||
if (map != grids.Map)
|
||||
continue;
|
||||
ent.Comp.AssociatedRule = uid;
|
||||
break;
|
||||
@@ -324,7 +324,7 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
|
||||
if (nukeops.WarDeclaredTime != null)
|
||||
continue;
|
||||
|
||||
if (TryComp<LoadMapRuleComponent>(uid, out var mapComp) && Transform(ev.DeclaratorEntity).MapID != mapComp.Map)
|
||||
if (TryComp<RuleGridsComponent>(uid, out var grids) && Transform(ev.DeclaratorEntity).MapID != grids.Map)
|
||||
continue;
|
||||
|
||||
var newStatus = GetWarCondition(nukeops, ev.Status);
|
||||
@@ -445,7 +445,7 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
|
||||
|
||||
// Check that there are spawns available and that they can access the shuttle.
|
||||
var spawnsAvailable = EntityQuery<NukeOperativeSpawnerComponent>(true).Any();
|
||||
if (spawnsAvailable && CompOrNull<LoadMapRuleComponent>(ent)?.Map == shuttleMapId)
|
||||
if (spawnsAvailable && CompOrNull<RuleGridsComponent>(ent)?.Map == shuttleMapId)
|
||||
return; // Ghost spawns can still access the shuttle. Continue the round.
|
||||
|
||||
// The shuttle is inaccessible to both living nuke operatives and yet to spawn nuke operatives,
|
||||
@@ -478,7 +478,7 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
|
||||
/// Is this method the shitty glue holding together the last of my sanity? yes.
|
||||
/// Do i have a better solution? not presently.
|
||||
/// </remarks>
|
||||
private EntityUid? GetOutpost(Entity<LoadMapRuleComponent?> ent)
|
||||
private EntityUid? GetOutpost(Entity<RuleGridsComponent?> ent)
|
||||
{
|
||||
if (!Resolve(ent, ref ent.Comp, false))
|
||||
return null;
|
||||
|
||||
78
Content.Server/GameTicking/Rules/RuleGridsSystem.cs
Normal file
78
Content.Server/GameTicking/Rules/RuleGridsSystem.cs
Normal file
@@ -0,0 +1,78 @@
|
||||
using Content.Server.Antag;
|
||||
using Content.Server.GameTicking.Rules.Components;
|
||||
using Content.Server.Spawners.Components;
|
||||
using Content.Shared.Whitelist;
|
||||
using Robust.Server.Physics;
|
||||
using Robust.Shared.Map;
|
||||
|
||||
namespace Content.Server.GameTicking.Rules;
|
||||
|
||||
/// <summary>
|
||||
/// Handles storing grids from <see cref="RuleLoadedGridsEvent"/> and antags spawning on their spawners.
|
||||
/// </summary>
|
||||
public sealed class RuleGridsSystem : GameRuleSystem<RuleGridsComponent>
|
||||
{
|
||||
[Dependency] private readonly EntityWhitelistSystem _whitelist = default!;
|
||||
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<GridSplitEvent>(OnGridSplit);
|
||||
|
||||
SubscribeLocalEvent<RuleGridsComponent, RuleLoadedGridsEvent>(OnLoadedGrids);
|
||||
SubscribeLocalEvent<RuleGridsComponent, AntagSelectLocationEvent>(OnSelectLocation);
|
||||
}
|
||||
|
||||
private void OnGridSplit(ref GridSplitEvent args)
|
||||
{
|
||||
var rule = QueryActiveRules();
|
||||
while (rule.MoveNext(out _, out var comp, out _))
|
||||
{
|
||||
if (!comp.MapGrids.Contains(args.Grid))
|
||||
continue;
|
||||
|
||||
comp.MapGrids.AddRange(args.NewGrids);
|
||||
break; // only 1 rule can own a grid, not multiple
|
||||
}
|
||||
}
|
||||
|
||||
private void OnLoadedGrids(Entity<RuleGridsComponent> ent, ref RuleLoadedGridsEvent args)
|
||||
{
|
||||
var (uid, comp) = ent;
|
||||
if (comp.Map != null && args.Map != comp.Map)
|
||||
{
|
||||
Log.Warning($"{ToPrettyString(uid):rule} loaded grids on multiple maps {comp.Map} and {args.Map}, the second will be ignored.");
|
||||
return;
|
||||
}
|
||||
|
||||
comp.Map = args.Map;
|
||||
comp.MapGrids.AddRange(args.Grids);
|
||||
}
|
||||
|
||||
private void OnSelectLocation(Entity<RuleGridsComponent> ent, ref AntagSelectLocationEvent args)
|
||||
{
|
||||
var query = EntityQueryEnumerator<SpawnPointComponent, TransformComponent>();
|
||||
while (query.MoveNext(out var uid, out _, out var xform))
|
||||
{
|
||||
if (xform.MapID != ent.Comp.Map)
|
||||
continue;
|
||||
|
||||
if (xform.GridUid is not {} grid || !ent.Comp.MapGrids.Contains(grid))
|
||||
continue;
|
||||
|
||||
if (_whitelist.IsWhitelistFail(ent.Comp.SpawnerWhitelist, uid))
|
||||
continue;
|
||||
|
||||
args.Coordinates.Add(_transform.GetMapCoordinates(xform));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raised by another gamerule system to store loaded grids, and have other systems work with it.
|
||||
/// A single rule can only load grids for a single map, attempts to load more are ignored.
|
||||
/// </summary>
|
||||
[ByRefEvent]
|
||||
public record struct RuleLoadedGridsEvent(MapId Map, IReadOnlyList<EntityUid> Grids);
|
||||
@@ -24,12 +24,19 @@ public sealed class GridPreloaderSystem : SharedGridPreloaderSystem
|
||||
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
||||
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the preloading CVar is set or not.
|
||||
/// </summary>
|
||||
public bool PreloadingEnabled;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<RoundRestartCleanupEvent>(OnRoundRestart);
|
||||
SubscribeLocalEvent<PostGameMapLoad>(OnPostGameMapLoad);
|
||||
|
||||
Subs.CVar(_cfg, CCVars.PreloadGrids, value => PreloadingEnabled = value, true);
|
||||
}
|
||||
|
||||
private void OnRoundRestart(RoundRestartCleanupEvent ev)
|
||||
@@ -52,7 +59,7 @@ public sealed class GridPreloaderSystem : SharedGridPreloaderSystem
|
||||
if (GetPreloaderEntity() != null)
|
||||
return;
|
||||
|
||||
if (!_cfg.GetCVar(CCVars.PreloadGrids))
|
||||
if (!PreloadingEnabled)
|
||||
return;
|
||||
|
||||
var mapUid = _map.CreateMap(out var mapId, false);
|
||||
|
||||
@@ -108,13 +108,4 @@ public abstract class StationEventSystem<T> : GameRuleSystem<T> where T : ICompo
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region Helper Functions
|
||||
|
||||
protected void ForceEndSelf(EntityUid uid, GameRuleComponent? component = null)
|
||||
{
|
||||
GameTicker.EndGameRule(uid, component);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -422,6 +422,7 @@
|
||||
weight: 5.5
|
||||
minimumPlayers: 20
|
||||
duration: 1
|
||||
- type: RuleGrids
|
||||
- type: LoadMapRule
|
||||
preloadedGrid: ShuttleStriker
|
||||
- type: NukeopsRule
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
- type: entity
|
||||
id: Ninja
|
||||
parent: BaseGameRule
|
||||
noSpawn: true
|
||||
components:
|
||||
- type: GenericAntagRule
|
||||
agentName: ninja-round-end-agent-name
|
||||
|
||||
@@ -78,6 +78,7 @@
|
||||
- operationPrefix
|
||||
- operationSuffix
|
||||
- type: NukeopsRule
|
||||
- type: RuleGrids
|
||||
- type: AntagSelection
|
||||
- type: AntagLoadProfileRule
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
- type: entity
|
||||
id: UnknownShuttleCargoLost
|
||||
- type: entity
|
||||
abstract: true
|
||||
parent: BaseGameRule
|
||||
noSpawn: true
|
||||
id: BaseUnknownShuttleRule
|
||||
components:
|
||||
- type: StationEvent
|
||||
startAnnouncement: station-event-unknown-shuttle-incoming
|
||||
@@ -10,65 +10,44 @@
|
||||
weight: 5
|
||||
reoccurrenceDelay: 30
|
||||
duration: 1
|
||||
- type: RuleGrids
|
||||
- type: LoadMapRule
|
||||
|
||||
- type: entity
|
||||
parent: BaseUnknownShuttleRule
|
||||
id: UnknownShuttleCargoLost
|
||||
components:
|
||||
- type: LoadMapRule
|
||||
preloadedGrid: ShuttleCargoLost
|
||||
|
||||
- type: entity
|
||||
parent: BaseUnknownShuttleRule
|
||||
id: UnknownShuttleTravelingCuisine
|
||||
parent: BaseGameRule
|
||||
noSpawn: true
|
||||
components:
|
||||
- type: StationEvent
|
||||
startAnnouncement: station-event-unknown-shuttle-incoming
|
||||
startAudio:
|
||||
path: /Audio/Announcements/attention.ogg
|
||||
weight: 5
|
||||
reoccurrenceDelay: 30
|
||||
duration: 1
|
||||
- type: LoadMapRule
|
||||
preloadedGrid: TravelingCuisine
|
||||
|
||||
- type: entity
|
||||
parent: BaseUnknownShuttleRule
|
||||
id: UnknownShuttleDisasterEvacPod
|
||||
parent: BaseGameRule
|
||||
noSpawn: true
|
||||
components:
|
||||
- type: StationEvent
|
||||
startAnnouncement: station-event-unknown-shuttle-incoming
|
||||
startAudio:
|
||||
path: /Audio/Announcements/attention.ogg
|
||||
weight: 5
|
||||
reoccurrenceDelay: 30
|
||||
duration: 1
|
||||
- type: LoadMapRule
|
||||
preloadedGrid: DisasterEvacPod
|
||||
|
||||
- type: entity
|
||||
parent: BaseUnknownShuttleRule
|
||||
id: UnknownShuttleHonki
|
||||
parent: BaseGameRule
|
||||
noSpawn: true
|
||||
components:
|
||||
- type: StationEvent
|
||||
startAnnouncement: station-event-unknown-shuttle-incoming
|
||||
startAudio:
|
||||
path: /Audio/Announcements/attention.ogg
|
||||
weight: 2
|
||||
reoccurrenceDelay: 30
|
||||
duration: 1
|
||||
- type: LoadMapRule
|
||||
preloadedGrid: Honki
|
||||
|
||||
- type: entity
|
||||
parent: BaseUnknownShuttleRule
|
||||
id: UnknownShuttleSyndieEvacPod
|
||||
parent: BaseGameRule
|
||||
noSpawn: true
|
||||
components:
|
||||
- type: StationEvent
|
||||
startAnnouncement: station-event-unknown-shuttle-incoming
|
||||
startAudio:
|
||||
path: /Audio/Announcements/attention.ogg
|
||||
weight: 2
|
||||
reoccurrenceDelay: 30
|
||||
duration: 1
|
||||
- type: LoadMapRule
|
||||
preloadedGrid: SyndieEvacPod
|
||||
|
||||
Reference in New Issue
Block a user