New event: Approaching unknown shuttle (#24490)

* setup codebase

* Add first shuttle

* tak

* sync striker

* sync 2

* pipipi

* Preloaded roundstart shuttles!

* Make it abstract "PreloaderGrid" not "PreloaderShuttle"

* to do

* added china cuisin shuttle

* fixes

* add disaster evacpod

* remove enemy

* final shuttles

* weight 5 -> 10

* move data to component

* remove autotrailer touching

* doc, respath

* fix frozen positioning

* fixes + cvar

* finally

* fix evacpod

* remove blacklistrules

* remove `UnknownShuttleSpawnRule`, refactor `LoadMapRule` to support preloaded grids

* use tryload

* cleanup

* fixes

* use preloadedgrid for loneops

* weight unknown shuttles differently (preliminal)

* leftover

* cleanup and raffling

* partial review

* singleton gridpreloader no station coupling

* fix grid atmoses

* `roleLoadout` support for `LoadoutComponent`, fix missing gear

* weighting changes

* init logic fix

---------

Co-authored-by: Kara <lunarautomaton6@gmail.com>
This commit is contained in:
Ed
2024-05-10 14:35:59 +03:00
committed by GitHub
parent d061aa437e
commit e522bbf90d
30 changed files with 8252 additions and 47 deletions

View File

@@ -22,6 +22,7 @@ public static partial class PoolManager
(CVars.ThreadParallelCount.Name, "1"), (CVars.ThreadParallelCount.Name, "1"),
(CCVars.GameRoleTimers.Name, "false"), (CCVars.GameRoleTimers.Name, "false"),
(CCVars.GridFill.Name, "false"), (CCVars.GridFill.Name, "false"),
(CCVars.PreloadGrids.Name, "false"),
(CCVars.ArrivalsShuttles.Name, "false"), (CCVars.ArrivalsShuttles.Name, "false"),
(CCVars.EmergencyShuttleEnabled.Name, "false"), (CCVars.EmergencyShuttleEnabled.Name, "false"),
(CCVars.ProcgenPreload.Name, "false"), (CCVars.ProcgenPreload.Name, "false"),

View File

@@ -1,4 +1,6 @@
using Content.Server.Maps; using Content.Server.Maps;
using Content.Shared.GridPreloader.Prototypes;
using Content.Shared.Storage;
using Content.Shared.Whitelist; using Content.Shared.Whitelist;
using Robust.Shared.Map; using Robust.Shared.Map;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
@@ -16,11 +18,14 @@ public sealed partial class LoadMapRuleComponent : Component
public MapId? Map; public MapId? Map;
[DataField] [DataField]
public ProtoId<GameMapPrototype>? GameMap ; public ProtoId<GameMapPrototype>? GameMap;
[DataField] [DataField]
public ResPath? MapPath; public ResPath? MapPath;
[DataField]
public ProtoId<PreloadedGridPrototype>? PreloadedGrid;
[DataField] [DataField]
public List<EntityUid> MapGrids = new(); public List<EntityUid> MapGrids = new();

View File

@@ -1,9 +1,11 @@
using Content.Server.Antag; using Content.Server.Antag;
using Content.Server.GameTicking.Components; using Content.Server.GameTicking.Components;
using Content.Server.GameTicking.Rules.Components; using Content.Server.GameTicking.Rules.Components;
using Content.Server.GridPreloader;
using Content.Server.Spawners.Components; using Content.Server.Spawners.Components;
using Robust.Server.GameObjects; using Robust.Server.GameObjects;
using Robust.Server.Maps; using Robust.Server.Maps;
using Robust.Shared.Map;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
namespace Content.Server.GameTicking.Rules; namespace Content.Server.GameTicking.Rules;
@@ -11,9 +13,12 @@ namespace Content.Server.GameTicking.Rules;
public sealed class LoadMapRuleSystem : GameRuleSystem<LoadMapRuleComponent> public sealed class LoadMapRuleSystem : GameRuleSystem<LoadMapRuleComponent>
{ {
[Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly MapSystem _map = default!; [Dependency] private readonly MapSystem _map = default!;
[Dependency] private readonly MapLoaderSystem _mapLoader = default!; [Dependency] private readonly MapLoaderSystem _mapLoader = default!;
[Dependency] private readonly MetaDataSystem _metaData = default!;
[Dependency] private readonly TransformSystem _transform = default!; [Dependency] private readonly TransformSystem _transform = default!;
[Dependency] private readonly GridPreloaderSystem _gridPreloader = default!;
public override void Initialize() public override void Initialize()
{ {
@@ -41,7 +46,9 @@ public sealed class LoadMapRuleSystem : GameRuleSystem<LoadMapRuleComponent>
if (comp.Map != null) if (comp.Map != null)
return; return;
_map.CreateMap(out var mapId); // 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; comp.Map = mapId;
if (comp.GameMap != null) if (comp.GameMap != null)
@@ -51,9 +58,30 @@ public sealed class LoadMapRuleSystem : GameRuleSystem<LoadMapRuleComponent>
} }
else if (comp.MapPath != null) else if (comp.MapPath != null)
{ {
if (_mapLoader.TryLoad(comp.Map.Value, comp.MapPath.Value.ToString(), out var roots, new MapLoadOptions { LoadMap = true })) if (!_mapLoader.TryLoad(comp.Map.Value,
comp.MapPath.Value.ToString(),
out var roots,
new MapLoadOptions { LoadMap = true }))
{
_mapManager.DeleteMap(mapId);
return;
}
comp.MapGrids.AddRange(roots); comp.MapGrids.AddRange(roots);
} }
else if (comp.PreloadedGrid != null)
{
// TODO: If there are no preloaded grids left, any rule announcements will still go off!
if (!_gridPreloader.TryGetPreloadedGrid(comp.PreloadedGrid.Value, out var loadedShuttle))
{
_mapManager.DeleteMap(mapId);
return;
}
_transform.SetParent(loadedShuttle.Value, mapUid);
comp.MapGrids.Add(loadedShuttle.Value);
_map.InitializeMap(mapId);
}
else else
{ {
Log.Error($"No valid map prototype or map path associated with the rule {ToPrettyString(uid)}"); Log.Error($"No valid map prototype or map path associated with the rule {ToPrettyString(uid)}");

View File

@@ -0,0 +1,16 @@
using Content.Shared.GridPreloader.Prototypes;
using Robust.Shared.Map;
using Robust.Shared.Prototypes;
namespace Content.Server.GridPreloader;
/// <summary>
/// Component storing data about preloaded grids and their location
/// Goes on the map entity
/// </summary>
[RegisterComponent, Access(typeof(GridPreloaderSystem))]
public sealed partial class GridPreloaderComponent : Component
{
[DataField]
public Dictionary<ProtoId<PreloadedGridPrototype>, List<EntityUid>> PreloadedGrids = new();
}

View File

@@ -0,0 +1,147 @@
using System.Diagnostics.CodeAnalysis;
using Content.Shared.CCVar;
using Content.Shared.GridPreloader.Prototypes;
using Content.Shared.GridPreloader.Systems;
using Robust.Server.GameObjects;
using Robust.Server.Maps;
using Robust.Shared.Configuration;
using Robust.Shared.Map;
using Robust.Shared.Map.Components;
using Robust.Shared.Physics.Components;
using Robust.Shared.Prototypes;
using System.Numerics;
using Content.Server.GameTicking;
using Content.Shared.GameTicking;
using JetBrains.Annotations;
namespace Content.Server.GridPreloader;
public sealed class GridPreloaderSystem : SharedGridPreloaderSystem
{
[Dependency] private readonly IConfigurationManager _cfg = default!;
[Dependency] private readonly MapSystem _map = default!;
[Dependency] private readonly MapLoaderSystem _mapLoader = default!;
[Dependency] private readonly MetaDataSystem _meta = default!;
[Dependency] private readonly IPrototypeManager _prototype = default!;
[Dependency] private readonly SharedTransformSystem _transform = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<RoundRestartCleanupEvent>(OnRoundRestart);
SubscribeLocalEvent<PostGameMapLoad>(OnPostGameMapLoad);
}
private void OnRoundRestart(RoundRestartCleanupEvent ev)
{
var ent = GetPreloaderEntity();
if (ent == null)
return;
Del(ent.Value.Owner);
}
private void OnPostGameMapLoad(PostGameMapLoad ev)
{
EnsurePreloadedGridMap();
}
private void EnsurePreloadedGridMap()
{
// Already have a preloader?
if (GetPreloaderEntity() != null)
return;
if (!_cfg.GetCVar(CCVars.PreloadGrids))
return;
var mapUid = _map.CreateMap(out var mapId, false);
var preloader = EnsureComp<GridPreloaderComponent>(mapUid);
_meta.SetEntityName(mapUid, "GridPreloader Map");
_map.SetPaused(mapId, true);
var globalXOffset = 0f;
foreach (var proto in _prototype.EnumeratePrototypes<PreloadedGridPrototype>())
{
for (var i = 0; i < proto.Copies; i++)
{
var options = new MapLoadOptions
{
LoadMap = false,
};
if (!_mapLoader.TryLoad(mapId, proto.Path.ToString(), out var roots, options))
continue;
// only supports loading maps with one grid.
if (roots.Count != 1)
continue;
var gridUid = roots[0];
// gets grid + also confirms that the root we loaded is actually a grid
if (!TryComp<MapGridComponent>(gridUid, out var mapGrid))
continue;
if (!TryComp<PhysicsComponent>(gridUid, out var physics))
continue;
// Position Calculating
globalXOffset += mapGrid.LocalAABB.Width / 2;
var coords = new Vector2(-physics.LocalCenter.X + globalXOffset, -physics.LocalCenter.Y);
_transform.SetCoordinates(gridUid, new EntityCoordinates(mapUid, coords));
globalXOffset += (mapGrid.LocalAABB.Width / 2) + 1;
// Add to list
if (!preloader.PreloadedGrids.ContainsKey(proto.ID))
preloader.PreloadedGrids[proto.ID] = new();
preloader.PreloadedGrids[proto.ID].Add(gridUid);
}
}
}
/// <summary>
/// Should be a singleton no matter station count, so we can assume 1
/// (better support for singleton component in engine at some point i guess)
/// </summary>
/// <returns></returns>
public Entity<GridPreloaderComponent>? GetPreloaderEntity()
{
var query = AllEntityQuery<GridPreloaderComponent>();
while (query.MoveNext(out var uid, out var comp))
{
return (uid, comp);
}
return null;
}
/// <summary>
/// An attempt to get a certain preloaded shuttle. If there are no more such shuttles left, returns null
/// </summary>
[PublicAPI]
public bool TryGetPreloadedGrid(ProtoId<PreloadedGridPrototype> proto, [NotNullWhen(true)] out EntityUid? preloadedGrid, GridPreloaderComponent? preloader = null)
{
preloadedGrid = null;
if (preloader == null)
{
preloader = GetPreloaderEntity();
if (preloader == null)
return false;
}
if (!preloader.PreloadedGrids.TryGetValue(proto, out var list) || list.Count <= 0)
return false;
preloadedGrid = list[0];
list.RemoveAt(0);
if (list.Count == 0)
preloader.PreloadedGrids.Remove(proto);
return true;
}
}

View File

@@ -200,27 +200,7 @@ public sealed class StationSpawningSystem : SharedStationSpawningSystem
loadout.SetDefault(_prototypeManager); loadout.SetDefault(_prototypeManager);
} }
// Order loadout selections by the order they appear on the prototype. EquipRoleLoadout(entity.Value, loadout, roleProto);
foreach (var group in loadout.SelectedLoadouts.OrderBy(x => roleProto.Groups.FindIndex(e => e == x.Key)))
{
foreach (var items in group.Value)
{
if (!_prototypeManager.TryIndex(items.Prototype, out var loadoutProto))
{
Log.Error($"Unable to find loadout prototype for {items.Prototype}");
continue;
}
if (!_prototypeManager.TryIndex(loadoutProto.Equipment, out var startingGear))
{
Log.Error($"Unable to find starting gear {loadoutProto.Equipment} for loadout {loadoutProto}");
continue;
}
// Handle any extra data here.
EquipStartingGear(entity.Value, startingGear, raiseEvent: false);
}
}
} }
var gearEquippedEv = new StartingGearEquippedEvent(entity.Value); var gearEquippedEv = new StartingGearEquippedEvent(entity.Value);

View File

@@ -1,4 +1,4 @@
using Robust.Shared.Audio; using Robust.Shared.Audio;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
namespace Content.Server.StationEvents.Components; namespace Content.Server.StationEvents.Components;
@@ -15,49 +15,49 @@ public sealed partial class StationEventComponent : Component
public const float WeightHigh = 15.0f; public const float WeightHigh = 15.0f;
public const float WeightVeryHigh = 20.0f; public const float WeightVeryHigh = 20.0f;
[DataField("weight")] [DataField]
public float Weight = WeightNormal; public float Weight = WeightNormal;
[DataField("startAnnouncement")] [DataField]
public string? StartAnnouncement; public string? StartAnnouncement;
[DataField("endAnnouncement")] [DataField]
public string? EndAnnouncement; public string? EndAnnouncement;
[DataField("startAudio")] [DataField]
public SoundSpecifier? StartAudio; public SoundSpecifier? StartAudio;
[DataField("endAudio")] [DataField]
public SoundSpecifier? EndAudio; public SoundSpecifier? EndAudio;
/// <summary> /// <summary>
/// In minutes, when is the first round time this event can start /// In minutes, when is the first round time this event can start
/// </summary> /// </summary>
[DataField("earliestStart")] [DataField]
public int EarliestStart = 5; public int EarliestStart = 5;
/// <summary> /// <summary>
/// In minutes, the amount of time before the same event can occur again /// In minutes, the amount of time before the same event can occur again
/// </summary> /// </summary>
[DataField("reoccurrenceDelay")] [DataField]
public int ReoccurrenceDelay = 30; public int ReoccurrenceDelay = 30;
/// <summary> /// <summary>
/// How long after being added does the event start /// How long after being added does the event start
/// </summary> /// </summary>
[DataField("startDelay")] [DataField]
public TimeSpan StartDelay = TimeSpan.Zero; public TimeSpan StartDelay = TimeSpan.Zero;
/// <summary> /// <summary>
/// How long the event lasts. /// How long the event lasts.
/// </summary> /// </summary>
[DataField("duration")] [DataField]
public TimeSpan? Duration = TimeSpan.FromSeconds(1); public TimeSpan? Duration = TimeSpan.FromSeconds(1);
/// <summary> /// <summary>
/// The max amount of time the event lasts. /// The max amount of time the event lasts.
/// </summary> /// </summary>
[DataField("maxDuration")] [DataField]
public TimeSpan? MaxDuration; public TimeSpan? MaxDuration;
/// <summary> /// <summary>
@@ -66,13 +66,13 @@ public sealed partial class StationEventComponent : Component
/// <remarks> /// <remarks>
/// To avoid running deadly events with low-pop /// To avoid running deadly events with low-pop
/// </remarks> /// </remarks>
[DataField("minimumPlayers")] [DataField]
public int MinimumPlayers; public int MinimumPlayers;
/// <summary> /// <summary>
/// How many times this even can occur in a single round /// How many times this even can occur in a single round
/// </summary> /// </summary>
[DataField("maxOccurrences")] [DataField]
public int? MaxOccurrences; public int? MaxOccurrences;
/// <summary> /// <summary>

View File

@@ -1,3 +1,4 @@
using System.Linq;
using Content.Server.Administration.Logs; using Content.Server.Administration.Logs;
using Content.Server.Chat.Systems; using Content.Server.Chat.Systems;
using Content.Server.GameTicking.Components; using Content.Server.GameTicking.Components;
@@ -42,6 +43,7 @@ public abstract class StationEventSystem<T> : GameRuleSystem<T> where T : ICompo
if (!TryComp<StationEventComponent>(uid, out var stationEvent)) if (!TryComp<StationEventComponent>(uid, out var stationEvent))
return; return;
AdminLogManager.Add(LogType.EventAnnounced, $"Event added / announced: {ToPrettyString(uid)}"); AdminLogManager.Add(LogType.EventAnnounced, $"Event added / announced: {ToPrettyString(uid)}");
if (stationEvent.StartAnnouncement != null) if (stationEvent.StartAnnouncement != null)

View File

@@ -1375,6 +1375,12 @@ namespace Content.Shared.CCVar
public static readonly CVarDef<bool> GridFill = public static readonly CVarDef<bool> GridFill =
CVarDef.Create("shuttle.grid_fill", true, CVar.SERVERONLY); CVarDef.Create("shuttle.grid_fill", true, CVar.SERVERONLY);
/// <summary>
/// Whether to automatically preloading grids by GridPreloaderSystem
/// </summary>
public static readonly CVarDef<bool> PreloadGrids =
CVarDef.Create("shuttle.preload_grids", true, CVar.SERVERONLY);
/* /*
* Emergency * Emergency
*/ */

View File

@@ -1,6 +1,7 @@
using Content.Shared.Preferences.Loadouts;
using Content.Shared.Roles; using Content.Shared.Roles;
using Robust.Shared.GameStates; using Robust.Shared.GameStates;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List; using Robust.Shared.Prototypes;
namespace Content.Shared.Clothing.Components; namespace Content.Shared.Clothing.Components;
@@ -10,7 +11,20 @@ public sealed partial class LoadoutComponent : Component
/// <summary> /// <summary>
/// A list of starting gears, of which one will be given. /// A list of starting gears, of which one will be given.
/// All elements are weighted the same in the list. /// All elements are weighted the same in the list.
///
/// If not specified, <see cref="RoleLoadout"/> will be used instead.
/// </summary> /// </summary>
[DataField("prototypes", required: true, customTypeSerializer: typeof(PrototypeIdListSerializer<StartingGearPrototype>)), AutoNetworkedField] [DataField("prototypes")]
public List<string>? Prototypes; [AutoNetworkedField]
public List<ProtoId<StartingGearPrototype>>? StartingGear;
/// <summary>
/// A list of role loadouts, of which one will be given.
/// All elements are weighted the same in the list.
///
/// If not specified, <see cref="StartingGear"/> will be used instead.
/// </summary>
[DataField]
[AutoNetworkedField]
public List<ProtoId<RoleLoadoutPrototype>>? RoleLoadout;
} }

View File

@@ -9,7 +9,7 @@ using Robust.Shared.Random;
namespace Content.Shared.Clothing; namespace Content.Shared.Clothing;
/// <summary> /// <summary>
/// Assigns a loadout to an entity based on the startingGear prototype /// Assigns a loadout to an entity based on the RoleLoadout prototype
/// </summary> /// </summary>
public sealed class LoadoutSystem : EntitySystem public sealed class LoadoutSystem : EntitySystem
{ {
@@ -110,10 +110,22 @@ public sealed class LoadoutSystem : EntitySystem
private void OnMapInit(EntityUid uid, LoadoutComponent component, MapInitEvent args) private void OnMapInit(EntityUid uid, LoadoutComponent component, MapInitEvent args)
{ {
if (component.Prototypes == null) // Use starting gear if specified
if (component.StartingGear != null)
{
var gear = _protoMan.Index(_random.Pick(component.StartingGear));
_station.EquipStartingGear(uid, gear);
return;
}
if (component.RoleLoadout == null)
return; return;
var proto = _protoMan.Index<StartingGearPrototype>(_random.Pick(component.Prototypes)); // ...otherwise equip from role loadout
_station.EquipStartingGear(uid, proto); var id = _random.Pick(component.RoleLoadout);
var proto = _protoMan.Index(id);
var loadout = new RoleLoadout(id);
loadout.SetDefault(_protoMan, true);
_station.EquipRoleLoadout(uid, loadout, proto);
} }
} }

View File

@@ -0,0 +1,21 @@
using Robust.Shared.Prototypes;
using Robust.Shared.Utility;
namespace Content.Shared.GridPreloader.Prototypes;
/// <summary>
/// Creating this prototype will automatically load the grid at the specified path at the beginning of the round,
/// and allow the GridPreloader system to load them in the middle of the round. This is needed for optimization,
/// because loading grids in the middle of a round causes the server to lag.
/// </summary>
[Prototype("preloadedGrid")]
public sealed partial class PreloadedGridPrototype : IPrototype
{
[IdDataField] public string ID { get; } = string.Empty;
[DataField(required: true)]
public ResPath Path;
[DataField]
public int Copies = 1;
}

View File

@@ -0,0 +1,4 @@
namespace Content.Shared.GridPreloader.Systems;
public abstract class SharedGridPreloaderSystem : EntitySystem
{
}

View File

@@ -1,6 +1,8 @@
using System.Linq;
using Content.Shared.Hands.Components; using Content.Shared.Hands.Components;
using Content.Shared.Hands.EntitySystems; using Content.Shared.Hands.EntitySystems;
using Content.Shared.Inventory; using Content.Shared.Inventory;
using Content.Shared.Preferences.Loadouts;
using Content.Shared.Roles; using Content.Shared.Roles;
using Content.Shared.Storage; using Content.Shared.Storage;
using Content.Shared.Storage.EntitySystems; using Content.Shared.Storage.EntitySystems;
@@ -31,6 +33,34 @@ public abstract class SharedStationSpawningSystem : EntitySystem
_xformQuery = GetEntityQuery<TransformComponent>(); _xformQuery = GetEntityQuery<TransformComponent>();
} }
/// <summary>
/// Equips the given starting gears from a `RoleLoadout` onto an entity.
/// </summary>
public void EquipRoleLoadout(EntityUid entity, RoleLoadout loadout, RoleLoadoutPrototype roleProto)
{
// Order loadout selections by the order they appear on the prototype.
foreach (var group in loadout.SelectedLoadouts.OrderBy(x => roleProto.Groups.FindIndex(e => e == x.Key)))
{
foreach (var items in group.Value)
{
if (!PrototypeManager.TryIndex(items.Prototype, out var loadoutProto))
{
Log.Error($"Unable to find loadout prototype for {items.Prototype}");
continue;
}
if (!PrototypeManager.TryIndex(loadoutProto.Equipment, out var startingGear))
{
Log.Error($"Unable to find starting gear {loadoutProto.Equipment} for loadout {loadoutProto}");
continue;
}
// Handle any extra data here.
EquipStartingGear(entity, startingGear, raiseEvent: false);
}
}
}
/// <summary> /// <summary>
/// <see cref="EquipStartingGear(Robust.Shared.GameObjects.EntityUid,System.Nullable{Robust.Shared.Prototypes.ProtoId{Content.Shared.Roles.StartingGearPrototype}},bool)"/> /// <see cref="EquipStartingGear(Robust.Shared.GameObjects.EntityUid,System.Nullable{Robust.Shared.Prototypes.ProtoId{Content.Shared.Roles.StartingGearPrototype}},bool)"/>
/// </summary> /// </summary>

View File

@@ -23,6 +23,7 @@ grid_fill = false
auto_call_time = 0 auto_call_time = 0
emergency = false emergency = false
arrivals = false arrivals = false
preload_grids = false
[admin] [admin]
see_own_notes = true see_own_notes = true

View File

@@ -224,6 +224,26 @@ ghost-role-information-syndicate-monkey-reinforcement-name = Syndicate Monkey Ag
ghost-role-information-syndicate-monkey-reinforcement-description = Someone needs reinforcements. You, a trained monkey, will help them. ghost-role-information-syndicate-monkey-reinforcement-description = Someone needs reinforcements. You, a trained monkey, will help them.
ghost-role-information-syndicate-monkey-reinforcement-rules = Normal syndicate antagonist rules apply. Work with whoever called you in, and don't harm them. ghost-role-information-syndicate-monkey-reinforcement-rules = Normal syndicate antagonist rules apply. Work with whoever called you in, and don't harm them.
ghost-role-information-lost-cargo-technical-name = Lost Cargo Technician
ghost-role-information-lost-cargo-technical-description = Something went wrong and your cargo shuttle with the goods was beamed into the sector to another station.
ghost-role-information-lost-cargo-technical-rules = You're a regular cargo technician from another station. Do what regular cargo do.
ghost-role-information-clown-troupe-name = Space Clown
ghost-role-information-clown-troupe-description = You and your troupe have come to cheer up this station with your best jokes. Honk!
ghost-role-information-clown-troupe-rules = Normal station crew rules apply.
ghost-role-information-traveling-chef-name = Traveling Chef
ghost-role-information-traveling-chef-description = You are a chef on a traveling shuttle of exotic cuisine. Delight the station with delicious food!
ghost-role-information-traveling-chef-rules = Normal station crew rules apply.
ghost-role-information-disaster-victim-name = Disaster Victim
ghost-role-information-disaster-victim-description = You were rescued in an escape pod from another station that suffered a terrible fate. Perhaps you will be found and rescued.
ghost-role-information-disaster-victim-rules = Normal station crew rules apply.
ghost-role-information-syndie-disaster-victim-name = Syndie Disaster Victim
ghost-role-information-syndie-disaster-victim-description = You're a regular passenger from a syndicate station. Unfortunately, an evacuation pod has thrown you into an enemy sector.....
ghost-role-information-syndie-disaster-victim-rules = Normal station crew rules apply. You are NOT an antagonist!
ghost-role-information-syndicate-kobold-reinforcement-name = Syndicate Kobold Agent ghost-role-information-syndicate-kobold-reinforcement-name = Syndicate Kobold Agent
ghost-role-information-syndicate-kobold-reinforcement-description = Someone needs reinforcements. You, a trained kobold, will help them. ghost-role-information-syndicate-kobold-reinforcement-description = Someone needs reinforcements. You, a trained kobold, will help them.
ghost-role-information-syndicate-kobold-reinforcement-rules = Normal syndicate antagonist rules apply. Work with whoever called you in, and don't harm them. ghost-role-information-syndicate-kobold-reinforcement-rules = Normal syndicate antagonist rules apply. Work with whoever called you in, and don't harm them.

View File

@@ -0,0 +1 @@
station-event-unknown-shuttle-incoming = Attention! An unidentified space shuttle has been spotted approaching your sector.

View File

@@ -0,0 +1,350 @@
meta:
format: 6
postmapinit: false
tilemap:
0: Space
82: FloorShuttleOrange
85: FloorShuttleWhite
120: Lattice
121: Plating
entities:
- proto: ""
entities:
- uid: 1
components:
- type: MetaData
name: Evacuation pod
- type: Transform
parent: invalid
- type: MapGrid
chunks:
0,0:
ind: 0,0
tiles: eQAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
version: 6
-1,0:
ind: -1,0
tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
version: 6
0,-1:
ind: 0,-1
tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUgAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVQAAAAAAeQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVQAAAAAAeQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
version: 6
-1,-1:
ind: -1,-1
tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeQAAAAAA
version: 6
- type: Broadphase
- type: Physics
bodyStatus: InAir
angularDamping: 0.05
linearDamping: 0.05
fixedRotation: False
bodyType: Dynamic
- type: Fixtures
fixtures: {}
- type: OccluderTree
- type: SpreaderGrid
- type: Shuttle
- type: GridPathfinding
- type: Gravity
gravityShakeSound: !type:SoundPathSpecifier
path: /Audio/Effects/alert.ogg
- type: DecalGrid
chunkCollection:
version: 2
nodes: []
- type: GridAtmosphere
version: 2
data:
tiles:
0,-1:
0: 4368
1: 32
0,0:
1: 2
-1,0:
1: 8
-1,-1:
1: 128
uniqueMixes:
- volume: 2500
temperature: 293.15
moles:
- 21.824879
- 82.10312
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- volume: 2500
immutable: True
moles:
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
chunkSize: 4
- type: GasTileOverlay
- type: RadiationGridResistance
- type: NavMap
- proto: AirlockShuttle
entities:
- uid: 2
components:
- type: Transform
pos: 0.5,-2.5
parent: 1
- proto: APCBasic
entities:
- uid: 3
components:
- type: Transform
rot: -1.5707963267948966 rad
pos: 1.5,-0.5
parent: 1
- proto: AtmosDeviceFanTiny
entities:
- uid: 4
components:
- type: Transform
pos: 0.5,-2.5
parent: 1
- proto: BoxMRE
entities:
- uid: 6
components:
- type: Transform
parent: 5
- type: Physics
canCollide: False
- type: InsideEntityStorage
- proto: CableApcExtension
entities:
- uid: 10
components:
- type: Transform
pos: 1.5,-0.5
parent: 1
- uid: 11
components:
- type: Transform
pos: 0.5,-0.5
parent: 1
- uid: 12
components:
- type: Transform
pos: 0.5,-1.5
parent: 1
- proto: CableHV
entities:
- uid: 13
components:
- type: Transform
pos: -0.5,-1.5
parent: 1
- uid: 14
components:
- type: Transform
pos: -0.5,-0.5
parent: 1
- proto: CableMV
entities:
- uid: 15
components:
- type: Transform
pos: -0.5,-0.5
parent: 1
- uid: 16
components:
- type: Transform
pos: 0.5,-0.5
parent: 1
- uid: 17
components:
- type: Transform
pos: 1.5,-0.5
parent: 1
- proto: ChairPilotSeat
entities:
- uid: 18
components:
- type: Transform
rot: 3.141592653589793 rad
pos: 0.5,-1.5
parent: 1
- proto: ClosetWallMaintenanceFilledRandom
entities:
- uid: 5
components:
- type: Transform
rot: -1.5707963267948966 rad
pos: 1.5,-1.5
parent: 1
- type: EntityStorage
air:
volume: 200
immutable: False
temperature: 293.14673
moles:
- 1.7459903
- 6.568249
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- type: ContainerContainer
containers:
entity_storage: !type:Container
showEnts: False
occludes: True
ents:
- 8
- 9
- 6
- 7
- proto: ClothingOuterSuitEmergency
entities:
- uid: 7
components:
- type: Transform
parent: 5
- type: Physics
canCollide: False
- type: InsideEntityStorage
- proto: ComputerShuttle
entities:
- uid: 19
components:
- type: Transform
pos: 0.5,-0.5
parent: 1
- proto: DisasterVictimSpawner
entities:
- uid: 20
components:
- type: Transform
pos: 0.5,-1.5
parent: 1
- proto: GeneratorWallmountAPU
entities:
- uid: 21
components:
- type: Transform
pos: -0.5,-1.5
parent: 1
- proto: Gyroscope
entities:
- uid: 32
components:
- type: Transform
pos: -0.5,-2.5
parent: 1
- proto: HandheldGPSBasic
entities:
- uid: 8
components:
- type: Transform
parent: 5
- type: Physics
canCollide: False
- type: InsideEntityStorage
- proto: Poweredlight
entities:
- uid: 22
components:
- type: Transform
rot: -1.5707963267948966 rad
pos: 0.5,-1.5
parent: 1
- proto: ShuttleWindow
entities:
- uid: 23
components:
- type: Transform
pos: 0.5,0.5
parent: 1
- proto: SubstationWallBasic
entities:
- uid: 24
components:
- type: Transform
rot: 1.5707963267948966 rad
pos: -0.5,-0.5
parent: 1
- proto: Thruster
entities:
- uid: 25
components:
- type: Transform
rot: 3.141592653589793 rad
pos: 1.5,-2.5
parent: 1
- proto: WallShuttle
entities:
- uid: 26
components:
- type: Transform
pos: -0.5,-0.5
parent: 1
- uid: 27
components:
- type: Transform
rot: 3.141592653589793 rad
pos: -0.5,-1.5
parent: 1
- uid: 28
components:
- type: Transform
rot: 3.141592653589793 rad
pos: 1.5,-0.5
parent: 1
- uid: 29
components:
- type: Transform
rot: 3.141592653589793 rad
pos: 1.5,-1.5
parent: 1
- proto: WallShuttleDiagonal
entities:
- uid: 30
components:
- type: Transform
pos: -0.5,0.5
parent: 1
- uid: 31
components:
- type: Transform
rot: -1.5707963267948966 rad
pos: 1.5,0.5
parent: 1
- proto: WeaponLaserSvalinn
entities:
- uid: 9
components:
- type: Transform
parent: 5
- type: Physics
canCollide: False
- type: InsideEntityStorage
...

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -838,3 +838,17 @@
- type: ConditionalSpawner - type: ConditionalSpawner
prototypes: prototypes:
- MobLuminousEntity - MobLuminousEntity
- type: entity
name: clown spider spawner
id: SpawnClownSpider
parent: MarkerBase
components:
- type: Sprite
layers:
- state: green
- state: clown
sprite: Mobs/Animals/clownspider.rsi
- type: ConditionalSpawner
prototypes:
- MobClownSpider

View File

@@ -589,3 +589,307 @@
settings: default settings: default
- type: GhostTakeoverAvailable - type: GhostTakeoverAvailable
- type: Cluwne - type: Cluwne
## Lost Cargo technician
- type: entity
name: lost cargo technician spawner
id: LostCargoTechnicianSpawner
parent: MarkerBase
components:
- type: Sprite
layers:
- state: red
- sprite: Objects/Tools/appraisal-tool.rsi
state: icon
- type: RandomSpawner
prototypes:
- RandomHumanoidLostCargoTechnician
chance: 1
- type: entity
id: RandomHumanoidLostCargoTechnician
name: lost cargo technician ghost role
components:
- type: Sprite
sprite: Objects/Tools/appraisal-tool.rsi
state: icon
- type: RandomHumanoidSpawner
settings: LostCargoTechnician
- type: randomHumanoidSettings
id: LostCargoTechnician
randomizeName: false
components:
- type: GhostRole
name: ghost-role-information-lost-cargo-technical-name
description: ghost-role-information-lost-cargo-technical-description
rules: ghost-role-information-lost-cargo-technical-rules
raffle:
settings: short
- type: GhostTakeoverAvailable
- type: Loadout
roleLoadout: [ JobCargoTechnician ]
- type: RandomMetadata
nameSegments:
- names_first
- names_last
# Clown troupe
- type: entity
name: clown troupe spawner
id: ClownTroupeSpawner
parent: MarkerBase
components:
- type: Sprite
layers:
- state: red
- sprite: Objects/Fun/bikehorn.rsi
state: icon
- type: RandomSpawner
prototypes:
- RandomHumanoidClownTroupe
rarePrototypes:
- RandomHumanoidClownTroupeBanana
rareChance: 0.3
- type: entity
id: RandomHumanoidClownTroupe
name: clown troupe ghost role
components:
- type: Sprite
sprite: Objects/Tools/appraisal-tool.rsi
state: icon
- type: RandomHumanoidSpawner
settings: ClownTroupe
- type: entity
id: RandomHumanoidClownTroupeBanana
name: banana clown troupe
parent: RandomHumanoidClownTroupe
components:
- type: RandomHumanoidSpawner
settings: ClownTroupeBanana
- type: randomHumanoidSettings
id: ClownTroupe
randomizeName: false
components:
- type: GhostRole
name: ghost-role-information-clown-troupe-name
description: ghost-role-information-clown-troupe-description
rules: ghost-role-information-clown-troupe-rules
raffle:
settings: short
- type: GhostTakeoverAvailable
- type: Loadout
roleLoadout: [ JobClown ]
- type: RandomMetadata
nameSegments:
- names_clown
- type: randomHumanoidSettings
id: ClownTroupeBanana
randomizeName: false
components:
- type: GhostRole
name: ghost-role-information-clown-troupe-name
description: ghost-role-information-clown-troupe-description
rules: ghost-role-information-clown-troupe-rules
- type: GhostTakeoverAvailable
- type: Loadout
prototypes: [ BananaClown ]
- type: RandomMetadata
nameSegments:
- names_clown
# Traveling exotic chef
- type: entity
name: traveling chef spawner
id: TravelingChefSpawner
parent: MarkerBase
components:
- type: Sprite
layers:
- state: red
- sprite: Objects/Weapons/Melee/kitchen_knife.rsi
state: icon
- type: RandomSpawner
prototypes:
- RandomHumanoidTravelingChef
- type: entity
id: RandomHumanoidTravelingChef
name: traveling chef ghost role
components:
- type: Sprite
sprite: Objects/Tools/appraisal-tool.rsi
state: icon
- type: RandomHumanoidSpawner
settings: TravelingChef
- type: randomHumanoidSettings
id: TravelingChef
randomizeName: false
components:
- type: GhostRole
name: ghost-role-information-traveling-chef-name
description: ghost-role-information-traveling-chef-description
rules: ghost-role-information-traveling-chef-rules
raffle:
settings: short
- type: GhostTakeoverAvailable
- type: Loadout
roleLoadout: [ JobChef ]
- type: RandomMetadata
nameSegments:
- names_first
- names_last
# Disaster victim
- type: entity
name: disaster victim spawner
id: DisasterVictimSpawner
parent: MarkerBase
components:
- type: Sprite
layers:
- state: red
- sprite: Clothing/OuterClothing/Hardsuits/basic.rsi
state: icon
- type: RandomSpawner
prototypes:
- RandomHumanoidDisasterVictimRD
- RandomHumanoidDisasterVictimCMO
- RandomHumanoidDisasterVictimCaptain
- MobSkeletonCloset
- type: entity
id: RandomHumanoidDisasterVictimRD
name: disaster victim RD ghost role
components:
- type: Sprite
sprite: Clothing/OuterClothing/Hardsuits/basic.rsi
state: icon
- type: RandomHumanoidSpawner
settings: DisasterVictimResearchDirector
- type: entity
id: RandomHumanoidDisasterVictimCMO
parent: RandomHumanoidDisasterVictimRD
name: disaster victim CMO ghost role
components:
- type: RandomHumanoidSpawner
settings: DisasterVictimCMO
- type: entity
id: RandomHumanoidDisasterVictimCaptain
parent: RandomHumanoidDisasterVictimRD
name: disaster victim Captain ghost role
components:
- type: RandomHumanoidSpawner
settings: DisasterVictimCaptain
- type: randomHumanoidSettings
id: DisasterVictimResearchDirector
randomizeName: false
components:
- type: GhostRole
name: ghost-role-information-disaster-victim-name
description: ghost-role-information-disaster-victim-description
rules: ghost-role-information-disaster-victim-rules
raffle:
settings: default
- type: GhostTakeoverAvailable
- type: Loadout
roleLoadout: [ JobResearchDirector ]
- type: RandomMetadata
nameSegments:
- names_first
- names_last
- type: randomHumanoidSettings
id: DisasterVictimCMO
randomizeName: false
components:
- type: GhostRole
name: ghost-role-information-disaster-victim-name
description: ghost-role-information-disaster-victim-description
rules: ghost-role-information-disaster-victim-rules
raffle:
settings: default
- type: GhostTakeoverAvailable
- type: Loadout
roleLoadout: [ JobChiefMedicalOfficer ]
- type: RandomMetadata
nameSegments:
- names_first
- names_last
- type: randomHumanoidSettings
id: DisasterVictimCaptain
randomizeName: false
components:
- type: GhostRole
name: ghost-role-information-disaster-victim-name
description: ghost-role-information-disaster-victim-description
rules: ghost-role-information-disaster-victim-rules
raffle:
settings: default
- type: GhostTakeoverAvailable
- type: Loadout
roleLoadout: [ JobCaptain ]
- type: RandomMetadata
nameSegments:
- names_first
- names_last
# Syndie Disaster Victim
- type: entity
name: syndie disaster victim spawner
id: SyndieDisasterVictimSpawner
parent: MarkerBase
components:
- type: Sprite
layers:
- state: red
- sprite: Structures/Decoration/banner.rsi
state: banner_syndicate
- type: RandomSpawner
prototypes:
- RandomHumanoidSyndieDisasterVictim
- type: entity
id: RandomHumanoidSyndieDisasterVictim
name: syndie disaster victim ghost role
components:
- type: Sprite
sprite: Structures/Decoration/banner.rsi
state: banner_syndicate
- type: RandomHumanoidSpawner
settings: SyndieDisasterVictim
- type: randomHumanoidSettings
id: SyndieDisasterVictim
randomizeName: false
components:
- type: NpcFactionMember
factions:
- Syndicate
- type: GhostRole
name: ghost-role-information-syndie-disaster-victim-name
description: ghost-role-information-syndie-disaster-victim-description
rules: ghost-role-information-syndie-disaster-victim-rules
raffle:
settings: short
- type: GhostTakeoverAvailable
- type: Loadout
prototypes: [ SyndicateOperativeGearCivilian ]
- type: RandomMetadata
nameSegments:
- names_first
- names_last

View File

@@ -404,7 +404,7 @@
minimumPlayers: 20 minimumPlayers: 20
duration: 1 duration: 1
- type: LoadMapRule - type: LoadMapRule
mapPath: /Maps/Shuttles/striker.yml preloadedGrid: ShuttleStriker
- type: NukeopsRule - type: NukeopsRule
roundEndBehavior: Nothing roundEndBehavior: Nothing
- type: AntagSelection - type: AntagSelection

View File

@@ -0,0 +1,74 @@
- type: entity
id: UnknownShuttleCargoLost
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: ShuttleCargoLost
- type: entity
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
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
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
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

View File

@@ -71,6 +71,15 @@
shoes: ClothingShoesBootsCombatFilled shoes: ClothingShoesBootsCombatFilled
gloves: ClothingHandsGlovesColorBlack gloves: ClothingHandsGlovesColorBlack
# Syndicate Operative Outfit - Civilian
- type: startingGear
id: SyndicateOperativeGearCivilian
equipment:
jumpsuit: ClothingUniformJumpsuitSyndieFormal
back: ClothingBackpackDuffelSyndicate
shoes: ClothingShoesBootsCombat
gloves: ClothingHandsGlovesColorBlack
#Syndicate Operative Outfit - Basic #Syndicate Operative Outfit - Basic
- type: startingGear - type: startingGear
id: SyndicateOperativeGearBasic id: SyndicateOperativeGearBasic

View File

@@ -0,0 +1,29 @@
- type: preloadedGrid
id: ShuttleStriker
path: /Maps/Shuttles/ShuttleEvent/striker.yml
copies: 2
- type: preloadedGrid
id: ShuttleCargoLost
path: /Maps/Shuttles/ShuttleEvent/lost_cargo.yml
copies: 2
- type: preloadedGrid
id: TravelingCuisine
path: /Maps/Shuttles/ShuttleEvent/traveling_china_cuisine.yml
copies: 2
- type: preloadedGrid
id: DisasterEvacPod
path: /Maps/Shuttles/ShuttleEvent/disaster_evacpod.yml
copies: 3
- type: preloadedGrid
id: Honki
path: /Maps/Shuttles/ShuttleEvent/honki.yml
copies: 1
- type: preloadedGrid
id: SyndieEvacPod
path: /Maps/Shuttles/ShuttleEvent/syndie_evacpod.yml
copies: 2