Refactor stations to properly use entity prototypes. (stationsv3) (#16570)
* Update StationSpawningSystem.cs Web-edit to allow feeding in an existing entity. * Update StationSpawningSystem.cs value type moment * Update StationSpawningSystem.cs * Oh goddamnit this is a refactor now. * awawawa * aaaaaaaaaaa * ee * forgot records. * no records? no records. * What's in a name? * Sloth forcing me to do the refactor properly smh. * e * optional evac in test. * tests pls work * awa --------- Co-authored-by: moonheart08 <moonheart08@users.noreply.github.com>
This commit is contained in:
@@ -227,51 +227,61 @@ namespace Content.IntegrationTests.Tests
|
||||
// Test shuttle can dock.
|
||||
// This is done inside gamemap test because loading the map takes ages and we already have it.
|
||||
var station = entManager.GetComponent<StationMemberComponent>(targetGrid!.Value).Station;
|
||||
var stationConfig = entManager.GetComponent<StationDataComponent>(station).StationConfig;
|
||||
Assert.IsNotNull(stationConfig, $"{entManager.ToPrettyString(station)} had null StationConfig.");
|
||||
var shuttlePath = stationConfig.EmergencyShuttlePath.ToString();
|
||||
var shuttle = mapLoader.LoadGrid(shuttleMap, shuttlePath);
|
||||
Assert.That(shuttle != null && shuttleSystem.TryFTLDock(shuttle.Value, entManager.GetComponent<ShuttleComponent>(shuttle.Value), targetGrid.Value), $"Unable to dock {shuttlePath} to {mapProto}");
|
||||
if (entManager.TryGetComponent<StationEmergencyShuttleComponent>(station, out var stationEvac))
|
||||
{
|
||||
var shuttlePath = stationEvac.EmergencyShuttlePath;
|
||||
var shuttle = mapLoader.LoadGrid(shuttleMap, shuttlePath.ToString());
|
||||
Assert.That(
|
||||
shuttle != null && shuttleSystem.TryFTLDock(shuttle.Value,
|
||||
entManager.GetComponent<ShuttleComponent>(shuttle.Value), targetGrid.Value),
|
||||
$"Unable to dock {shuttlePath} to {mapProto}");
|
||||
}
|
||||
|
||||
mapManager.DeleteMap(shuttleMap);
|
||||
|
||||
// Test that the map has valid latejoin spawn points
|
||||
if (!NoSpawnMaps.Contains(mapProto))
|
||||
if (entManager.HasComponent<StationJobsComponent>(station))
|
||||
{
|
||||
var lateSpawns = 0;
|
||||
|
||||
foreach (var comp in entManager.EntityQuery<SpawnPointComponent>(true))
|
||||
// Test that the map has valid latejoin spawn points
|
||||
if (!NoSpawnMaps.Contains(mapProto))
|
||||
{
|
||||
if (comp.SpawnType != SpawnPointType.LateJoin ||
|
||||
!xformQuery.TryGetComponent(comp.Owner, out var xform) ||
|
||||
xform.GridUid == null ||
|
||||
!gridUids.Contains(xform.GridUid.Value))
|
||||
var lateSpawns = 0;
|
||||
|
||||
foreach (var comp in entManager.EntityQuery<SpawnPointComponent>(true))
|
||||
{
|
||||
continue;
|
||||
if (comp.SpawnType != SpawnPointType.LateJoin ||
|
||||
!xformQuery.TryGetComponent(comp.Owner, out var xform) ||
|
||||
xform.GridUid == null ||
|
||||
!gridUids.Contains(xform.GridUid.Value))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
lateSpawns++;
|
||||
break;
|
||||
}
|
||||
|
||||
lateSpawns++;
|
||||
break;
|
||||
Assert.That(lateSpawns, Is.GreaterThan(0), $"Found no latejoin spawn points on {mapProto}");
|
||||
}
|
||||
|
||||
Assert.That(lateSpawns, Is.GreaterThan(0), $"Found no latejoin spawn points on {mapProto}");
|
||||
// Test all availableJobs have spawnPoints
|
||||
// This is done inside gamemap test because loading the map takes ages and we already have it.
|
||||
var jobList = entManager.GetComponent<StationJobsComponent>(station).RoundStartJobList
|
||||
.Where(x => x.Value != 0)
|
||||
.Select(x => x.Key);
|
||||
var spawnPoints = entManager.EntityQuery<SpawnPointComponent>()
|
||||
.Where(spawnpoint => spawnpoint.SpawnType == SpawnPointType.Job)
|
||||
.Select(spawnpoint => spawnpoint.Job.ID)
|
||||
.Distinct();
|
||||
List<string> missingSpawnPoints = new();
|
||||
foreach (var spawnpoint in jobList.Except(spawnPoints))
|
||||
{
|
||||
if (protoManager.Index<JobPrototype>(spawnpoint).SetPreference)
|
||||
missingSpawnPoints.Add(spawnpoint);
|
||||
}
|
||||
|
||||
Assert.That(missingSpawnPoints.Count() == 0,
|
||||
$"There is no spawnpoint for {String.Join(", ", missingSpawnPoints)} on {mapProto}.");
|
||||
}
|
||||
// Test all availableJobs have spawnPoints
|
||||
// This is done inside gamemap test because loading the map takes ages and we already have it.
|
||||
var jobList = entManager.GetComponent<StationJobsComponent>(station).RoundStartJobList
|
||||
.Where(x => x.Value != 0)
|
||||
.Select(x => x.Key);
|
||||
var spawnPoints = entManager.EntityQuery<SpawnPointComponent>()
|
||||
.Where(spawnpoint => spawnpoint.SpawnType == SpawnPointType.Job)
|
||||
.Select(spawnpoint => spawnpoint.Job.ID)
|
||||
.Distinct();
|
||||
List<string> missingSpawnPoints = new();
|
||||
foreach (var spawnpoint in jobList.Except(spawnPoints))
|
||||
{
|
||||
if (protoManager.Index<JobPrototype>(spawnpoint).SetPreference)
|
||||
missingSpawnPoints.Add(spawnpoint);
|
||||
}
|
||||
Assert.That(missingSpawnPoints.Count() == 0, $"There is no spawnpoint for {String.Join(", ", missingSpawnPoints)} on {mapProto}.");
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server.Maps;
|
||||
using Content.Server.Station.Components;
|
||||
using Content.Server.Station.Systems;
|
||||
using Content.Shared.Preferences;
|
||||
using Content.Shared.Roles;
|
||||
@@ -32,13 +33,16 @@ public sealed class StationJobsTest
|
||||
stations:
|
||||
Station:
|
||||
mapNameTemplate: FooStation
|
||||
overflowJobs:
|
||||
- Assistant
|
||||
availableJobs:
|
||||
TMime: [0, -1]
|
||||
TAssistant: [-1, -1]
|
||||
TCaptain: [5, 5]
|
||||
TClown: [5, 6]
|
||||
stationProto: StandardNanotrasenStation
|
||||
components:
|
||||
- type: StationJobs
|
||||
overflowJobs:
|
||||
- Assistant
|
||||
availableJobs:
|
||||
TMime: [0, -1]
|
||||
TAssistant: [-1, -1]
|
||||
TCaptain: [5, 5]
|
||||
TClown: [5, 6]
|
||||
|
||||
- type: job
|
||||
id: TAssistant
|
||||
@@ -213,7 +217,10 @@ public sealed class StationJobsTest
|
||||
{
|
||||
foreach (var (stationId, station) in gameMap.Stations)
|
||||
{
|
||||
foreach (var job in station.AvailableJobs.Keys)
|
||||
if (!station.StationComponentOverrides.TryGetComponent("StationJobs", out var comp))
|
||||
continue;
|
||||
|
||||
foreach (var (job, _) in ((StationJobsComponent)comp).SetupAvailableJobs)
|
||||
{
|
||||
Assert.That(invalidJobs.Contains(job), Is.False, $"Station {stationId} contains job prototype {job} which cannot be present roundstart.");
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using Content.Server.Station.Components;
|
||||
using Content.Server.Station.Systems;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.Roles;
|
||||
@@ -9,6 +10,10 @@ namespace Content.Server.Administration.Commands.Station;
|
||||
[AdminCommand(AdminFlags.Round)]
|
||||
public sealed class AdjustStationJobCommand : IConsoleCommand
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
[Dependency] private readonly IEntitySystemManager _entSysManager = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
|
||||
public string Command => "adjstationjob";
|
||||
|
||||
public string Description => "Adjust the job manifest on a station.";
|
||||
@@ -23,19 +28,15 @@ public sealed class AdjustStationJobCommand : IConsoleCommand
|
||||
return;
|
||||
}
|
||||
|
||||
var prototypeManager = IoCManager.Resolve<IPrototypeManager>();
|
||||
var stationSystem = EntitySystem.Get<StationSystem>();
|
||||
var stationJobs = EntitySystem.Get<StationJobsSystem>();
|
||||
var stationJobs = _entSysManager.GetEntitySystem<StationJobsSystem>();
|
||||
|
||||
if (!int.TryParse(args[0], out var stationInt) || !stationSystem.Stations.Contains(new EntityUid(stationInt)))
|
||||
if (!EntityUid.TryParse(args[0], out var station) || _entityManager.HasComponent<StationDataComponent>(station))
|
||||
{
|
||||
shell.WriteError(Loc.GetString("shell-argument-station-id-invalid", ("index", 1)));
|
||||
return;
|
||||
}
|
||||
|
||||
var station = new EntityUid(stationInt);
|
||||
|
||||
if (!prototypeManager.TryIndex<JobPrototype>(args[1], out var job))
|
||||
if (!_prototypeManager.TryIndex<JobPrototype>(args[1], out var job))
|
||||
{
|
||||
shell.WriteError(Loc.GetString("shell-argument-must-be-prototype",
|
||||
("index", 2), ("prototypeName", nameof(JobPrototype))));
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using Content.Server.Station.Components;
|
||||
using Content.Server.Station.Systems;
|
||||
using Content.Shared.Administration;
|
||||
using Robust.Shared.Console;
|
||||
@@ -7,6 +8,9 @@ namespace Content.Server.Administration.Commands.Station;
|
||||
[AdminCommand(AdminFlags.Admin)]
|
||||
public sealed class ListStationJobsCommand : IConsoleCommand
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
[Dependency] private readonly IEntitySystemManager _entSysManager = default!;
|
||||
|
||||
public string Command => "lsstationjobs";
|
||||
|
||||
public string Description => "Lists all jobs on the given station.";
|
||||
@@ -21,16 +25,16 @@ public sealed class ListStationJobsCommand : IConsoleCommand
|
||||
return;
|
||||
}
|
||||
|
||||
var stationSystem = EntitySystem.Get<StationSystem>();
|
||||
var stationJobs = EntitySystem.Get<StationJobsSystem>();
|
||||
var stationSystem = _entSysManager.GetEntitySystem<StationSystem>();
|
||||
var stationJobs = _entSysManager.GetEntitySystem<StationJobsSystem>();
|
||||
|
||||
if (!int.TryParse(args[0], out var station) || !stationSystem.Stations.Contains(new EntityUid(station)))
|
||||
if (!EntityUid.TryParse(args[0], out var station) || !_entityManager.HasComponent<StationJobsComponent>(station))
|
||||
{
|
||||
shell.WriteError(Loc.GetString("shell-argument-station-id-invalid", ("index", 1)));
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var (job, amount) in stationJobs.GetJobs(new EntityUid(station)))
|
||||
foreach (var (job, amount) in stationJobs.GetJobs(station))
|
||||
{
|
||||
var amountText = amount is null ? "Infinite" : amount.ToString();
|
||||
shell.WriteLine($"{job}: {amountText}");
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using Content.Server.Station.Components;
|
||||
using Content.Server.Station.Systems;
|
||||
using Content.Shared.Administration;
|
||||
using Robust.Shared.Console;
|
||||
@@ -17,7 +18,9 @@ public sealed class ListStationsCommand : IConsoleCommand
|
||||
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
foreach (var station in EntitySystem.Get<StationSystem>().Stations)
|
||||
var query = _entityManager.EntityQueryEnumerator<StationDataComponent>();
|
||||
|
||||
while (query.MoveNext(out var station, out _))
|
||||
{
|
||||
var name = _entityManager.GetComponent<MetaDataComponent>(station).EntityName;
|
||||
shell.WriteLine($"{station, -10} | {name}");
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using Content.Server.Station.Components;
|
||||
using Content.Server.Station.Systems;
|
||||
using Content.Shared.Administration;
|
||||
using Robust.Shared.Console;
|
||||
@@ -7,6 +8,9 @@ namespace Content.Server.Administration.Commands.Station;
|
||||
[AdminCommand(AdminFlags.Admin)]
|
||||
public sealed class RenameStationCommand : IConsoleCommand
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
[Dependency] private readonly IEntitySystemManager _entSysManager = default!;
|
||||
|
||||
public string Command => "renamestation";
|
||||
|
||||
public string Description => "Renames the given station";
|
||||
@@ -21,14 +25,14 @@ public sealed class RenameStationCommand : IConsoleCommand
|
||||
return;
|
||||
}
|
||||
|
||||
var stationSystem = EntitySystem.Get<StationSystem>();
|
||||
var stationSystem = _entSysManager.GetEntitySystem<StationSystem>();
|
||||
|
||||
if (!int.TryParse(args[0], out var station) || !stationSystem.Stations.Contains(new EntityUid(station)))
|
||||
if (!EntityUid.TryParse(args[0], out var station) || _entityManager.HasComponent<StationDataComponent>(station))
|
||||
{
|
||||
shell.WriteError(Loc.GetString("shell-argument-station-id-invalid", ("index", 1)));
|
||||
return;
|
||||
}
|
||||
|
||||
stationSystem.RenameStation(new EntityUid(station), args[1]);
|
||||
stationSystem.RenameStation(station, args[1]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
|
||||
namespace Content.Server.AlertLevel;
|
||||
|
||||
/// <summary>
|
||||
@@ -14,7 +16,7 @@ public sealed class AlertLevelComponent : Component
|
||||
public AlertLevelPrototype? AlertLevels;
|
||||
|
||||
// Once stations are a prototype, this should be used.
|
||||
[DataField("alertLevelPrototype")]
|
||||
[DataField("alertLevelPrototype", required: true, customTypeSerializer: typeof(PrototypeIdSerializer<AlertLevelPrototype>))]
|
||||
public string AlertLevelPrototype = default!;
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -32,13 +32,10 @@ public sealed class AlertLevelSystem : EntitySystem
|
||||
|
||||
public override void Update(float time)
|
||||
{
|
||||
foreach (var station in _stationSystem.Stations)
|
||||
{
|
||||
if (!TryComp(station, out AlertLevelComponent? alert))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var query = EntityQueryEnumerator<AlertLevelComponent>();
|
||||
|
||||
while (query.MoveNext(out var station, out var alert))
|
||||
{
|
||||
if (alert.CurrentDelay <= 0)
|
||||
{
|
||||
if (alert.ActiveDelay)
|
||||
@@ -55,9 +52,10 @@ public sealed class AlertLevelSystem : EntitySystem
|
||||
|
||||
private void OnStationInitialize(StationInitializedEvent args)
|
||||
{
|
||||
var alertLevelComponent = AddComp<AlertLevelComponent>(args.Station);
|
||||
if (!TryComp<AlertLevelComponent>(args.Station, out var alertLevelComponent))
|
||||
return;
|
||||
|
||||
if (!_prototypeManager.TryIndex(DefaultAlertLevelSet, out AlertLevelPrototype? alerts))
|
||||
if (!_prototypeManager.TryIndex(alertLevelComponent.AlertLevelPrototype, out AlertLevelPrototype? alerts))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ public sealed partial class CargoSystem : SharedCargoSystem
|
||||
InitializeConsole();
|
||||
InitializeShuttle();
|
||||
InitializeTelepad();
|
||||
SubscribeLocalEvent<StationInitializedEvent>(OnStationInit);
|
||||
}
|
||||
|
||||
public override void Shutdown()
|
||||
@@ -32,12 +31,6 @@ public sealed partial class CargoSystem : SharedCargoSystem
|
||||
CleanupShuttle();
|
||||
}
|
||||
|
||||
private void OnStationInit(StationInitializedEvent ev)
|
||||
{
|
||||
EnsureComp<StationBankAccountComponent>(ev.Station);
|
||||
EnsureComp<StationCargoOrderDatabaseComponent>(ev.Station);
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
base.Update(frameTime);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Linq;
|
||||
using Content.Server.Administration;
|
||||
using Content.Server.EUI;
|
||||
using Content.Server.Station.Components;
|
||||
using Content.Server.Station.Systems;
|
||||
using Content.Server.StationRecords;
|
||||
using Content.Server.StationRecords.Systems;
|
||||
@@ -270,13 +271,12 @@ public sealed class CrewManifestCommand : IConsoleCommand
|
||||
}
|
||||
|
||||
var stations = _entityManager
|
||||
.System<StationSystem>()
|
||||
.Stations
|
||||
.Select(station =>
|
||||
.EntityQuery<StationDataComponent>()
|
||||
.Select(stationData =>
|
||||
{
|
||||
var meta = _entityManager.GetComponent<MetaDataComponent>(station);
|
||||
var meta = _entityManager.GetComponent<MetaDataComponent>(stationData.Owner);
|
||||
|
||||
return new CompletionOption(station.ToString(), meta.EntityName);
|
||||
return new CompletionOption(stationData.Owner.ToString(), meta.EntityName);
|
||||
});
|
||||
|
||||
return CompletionResult.FromHintOptions(stations, null);
|
||||
|
||||
@@ -31,10 +31,13 @@ public sealed partial class DragonSystem
|
||||
{
|
||||
base.Started(uid, component, gameRule, args);
|
||||
|
||||
if (!_station.Stations.Any())
|
||||
var eligible = EntityQuery<StationEventEligibleComponent>().Select(x => x.Owner).ToList();
|
||||
|
||||
if (!eligible.Any())
|
||||
return;
|
||||
|
||||
var station = _random.Pick(_station.Stations);
|
||||
var station = _random.Pick(eligible);
|
||||
|
||||
if (_station.GetLargestGrid(EntityManager.GetComponent<StationDataComponent>(station)) is not { } grid)
|
||||
return;
|
||||
|
||||
|
||||
@@ -174,7 +174,6 @@ namespace Content.Server.Entry
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
_playTimeTracking?.Shutdown();
|
||||
_sysMan?.GetEntitySystemOrNull<StationSystem>()?.OnServerDispose();
|
||||
_dbManager?.Shutdown();
|
||||
}
|
||||
|
||||
|
||||
@@ -52,23 +52,22 @@ namespace Content.Server.GameTicking
|
||||
var playerCount = $"{_playerManager.PlayerCount}";
|
||||
var readyCount = _playerGameStatuses.Values.Count(x => x == PlayerGameStatus.ReadyToPlay);
|
||||
|
||||
StringBuilder stationNames = new StringBuilder();
|
||||
if (_stationSystem.Stations.Count != 0)
|
||||
{
|
||||
foreach (EntityUid entUID in _stationSystem.Stations)
|
||||
{
|
||||
StationDataComponent? stationData = null;
|
||||
MetaDataComponent? metaData = null;
|
||||
if (Resolve(entUID, ref stationData, ref metaData, logMissing: true))
|
||||
{
|
||||
if (stationNames.Length > 0)
|
||||
stationNames.Append('\n');
|
||||
var stationNames = new StringBuilder();
|
||||
var query =
|
||||
EntityQueryEnumerator<StationJobsComponent, StationSpawningComponent, MetaDataComponent>();
|
||||
|
||||
stationNames.Append(metaData.EntityName);
|
||||
}
|
||||
}
|
||||
var foundOne = false;
|
||||
|
||||
while (query.MoveNext(out _, out _, out var meta))
|
||||
{
|
||||
foundOne = true;
|
||||
if (stationNames.Length > 0)
|
||||
stationNames.Append('\n');
|
||||
|
||||
stationNames.Append(meta.EntityName);
|
||||
}
|
||||
else
|
||||
|
||||
if (!foundOne)
|
||||
{
|
||||
stationNames.Append(Loc.GetString("game-ticker-no-map-selected"));
|
||||
}
|
||||
|
||||
@@ -50,7 +50,9 @@ namespace Content.Server.GameTicking
|
||||
|
||||
foreach (var (player, _) in profiles)
|
||||
{
|
||||
if (playerNetIds.Contains(player)) continue;
|
||||
if (playerNetIds.Contains(player))
|
||||
continue;
|
||||
|
||||
toRemove.Add(player);
|
||||
}
|
||||
|
||||
@@ -60,12 +62,14 @@ namespace Content.Server.GameTicking
|
||||
}
|
||||
}
|
||||
|
||||
var assignedJobs = _stationJobs.AssignJobs(profiles, _stationSystem.Stations.ToList());
|
||||
var spawnableStations = EntityQuery<StationJobsComponent, StationSpawningComponent>().Select(x => x.Item1.Owner).ToList();
|
||||
|
||||
_stationJobs.AssignOverflowJobs(ref assignedJobs, playerNetIds, profiles, _stationSystem.Stations.ToList());
|
||||
var assignedJobs = _stationJobs.AssignJobs(profiles, spawnableStations);
|
||||
|
||||
_stationJobs.AssignOverflowJobs(ref assignedJobs, playerNetIds, profiles, spawnableStations);
|
||||
|
||||
// Calculate extended access for stations.
|
||||
var stationJobCounts = _stationSystem.Stations.ToDictionary(e => e, _ => 0);
|
||||
var stationJobCounts = spawnableStations.ToDictionary(e => e, _ => 0);
|
||||
foreach (var (netUser, (job, station)) in assignedJobs)
|
||||
{
|
||||
if (job == null)
|
||||
@@ -117,7 +121,7 @@ namespace Content.Server.GameTicking
|
||||
|
||||
if (station == EntityUid.Invalid)
|
||||
{
|
||||
var stations = _stationSystem.Stations.ToList();
|
||||
var stations = EntityQuery<StationJobsComponent, StationSpawningComponent>().Select(x => x.Item1.Owner).ToList();
|
||||
_robustRandom.Shuffle(stations);
|
||||
if (stations.Count == 0)
|
||||
station = EntityUid.Invalid;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using Content.Server.NPC.Components;
|
||||
using Content.Server.StationEvents.Events;
|
||||
using Content.Shared.Dataset;
|
||||
using Content.Shared.Humanoid.Prototypes;
|
||||
@@ -7,6 +8,7 @@ using Robust.Shared.Audio;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Set;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Server.GameTicking.Rules.Components;
|
||||
@@ -119,6 +121,9 @@ public sealed class NukeopsRuleComponent : Component
|
||||
/// todo: don't store sessions, dingus
|
||||
[DataField("operativePlayers")]
|
||||
public readonly Dictionary<string, IPlayerSession> OperativePlayers = new();
|
||||
|
||||
[DataField("faction", customTypeSerializer: typeof(PrototypeIdSerializer<FactionPrototype>), required: true)]
|
||||
public string Faction = default!;
|
||||
}
|
||||
|
||||
public enum WinType : byte
|
||||
|
||||
@@ -6,6 +6,7 @@ using Content.Server.Ghost.Roles.Components;
|
||||
using Content.Server.Ghost.Roles.Events;
|
||||
using Content.Server.Humanoid;
|
||||
using Content.Server.Mind.Components;
|
||||
using Content.Server.NPC.Components;
|
||||
using Content.Server.NPC.Systems;
|
||||
using Content.Server.Nuke;
|
||||
using Content.Server.Preferences.Managers;
|
||||
@@ -175,12 +176,16 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
|
||||
// we can only currently guarantee that NT stations are the only station to
|
||||
// exist in the base game.
|
||||
|
||||
component.TargetStation = _stationSystem.Stations.FirstOrNull();
|
||||
var eligible = EntityQuery<StationEventEligibleComponent, FactionComponent>()
|
||||
.Where(x =>
|
||||
_faction.IsFactionHostile(component.Faction, x.Item2.Owner, x.Item2))
|
||||
.Select(x => x.Item1.Owner)
|
||||
.ToList();
|
||||
|
||||
if (component.TargetStation == null)
|
||||
{
|
||||
if (!eligible.Any())
|
||||
return;
|
||||
}
|
||||
|
||||
component.TargetStation = _random.Pick(eligible);
|
||||
|
||||
var filter = Filter.Empty();
|
||||
var query = EntityQueryEnumerator<NukeOperativeComponent, ActorComponent>();
|
||||
|
||||
@@ -144,8 +144,8 @@ public sealed class PiratesRuleSystem : GameRuleSystem<PiratesRuleComponent>
|
||||
var map = "/Maps/Shuttles/pirate.yml";
|
||||
var xformQuery = GetEntityQuery<TransformComponent>();
|
||||
|
||||
var aabbs = _stationSystem.Stations.SelectMany(x =>
|
||||
Comp<StationDataComponent>(x).Grids.Select(x =>
|
||||
var aabbs = EntityQuery<StationDataComponent>().SelectMany(x =>
|
||||
x.Grids.Select(x =>
|
||||
xformQuery.GetComponent(x).WorldMatrix.TransformBox(_mapManager.GetGridComp(x).LocalAABB)))
|
||||
.ToArray();
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace Content.Server.Jobs
|
||||
|
||||
[DataField("components")]
|
||||
[AlwaysPushInheritance]
|
||||
public EntityPrototype.ComponentRegistry Components { get; } = new();
|
||||
public ComponentRegistry Components { get; } = new();
|
||||
|
||||
public override void AfterEquip(EntityUid mob)
|
||||
{
|
||||
|
||||
@@ -13,7 +13,7 @@ public sealed class ChangeComponentsSpellEvent : EntityTargetActionEvent, ISpeak
|
||||
|
||||
[DataField("toAdd")]
|
||||
[AlwaysPushInheritance]
|
||||
public EntityPrototype.ComponentRegistry ToAdd = new();
|
||||
public ComponentRegistry ToAdd = new();
|
||||
|
||||
[DataField("toRemove")]
|
||||
[AlwaysPushInheritance]
|
||||
|
||||
@@ -8,5 +8,5 @@ namespace Content.Server.NPC.Queries.Queries;
|
||||
public sealed class ComponentQuery : UtilityQuery
|
||||
{
|
||||
[DataField("components", required: true)]
|
||||
public EntityPrototype.ComponentRegistry Components = default!;
|
||||
public ComponentRegistry Components = default!;
|
||||
}
|
||||
|
||||
@@ -5,5 +5,5 @@ namespace Content.Server.NPC.Queries.Queries;
|
||||
public sealed class NearbyComponentsQuery : UtilityQuery
|
||||
{
|
||||
[DataField("components")]
|
||||
public EntityPrototype.ComponentRegistry Component = default!;
|
||||
public ComponentRegistry Component = default!;
|
||||
}
|
||||
|
||||
@@ -153,7 +153,7 @@ public sealed class FactionSystem : EntitySystem
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsFriendly(EntityUid uidA, EntityUid uidB, FactionComponent? factionA = null, FactionComponent? factionB = null)
|
||||
public bool IsEntityFriendly(EntityUid uidA, EntityUid uidB, FactionComponent? factionA = null, FactionComponent? factionB = null)
|
||||
{
|
||||
if (!Resolve(uidA, ref factionA, false) || !Resolve(uidB, ref factionB, false))
|
||||
return false;
|
||||
@@ -161,6 +161,39 @@ public sealed class FactionSystem : EntitySystem
|
||||
return factionA.Factions.Overlaps(factionB.Factions) || factionA.FriendlyFactions.Overlaps(factionB.Factions);
|
||||
}
|
||||
|
||||
public bool IsFactionFriendly(string target, string with)
|
||||
{
|
||||
return _factions[target].Friendly.Contains(with) && _factions[with].Friendly.Contains(target);
|
||||
}
|
||||
|
||||
public bool IsFactionFriendly(string target, EntityUid with, FactionComponent? factionWith = null)
|
||||
{
|
||||
if (!Resolve(with, ref factionWith, false))
|
||||
return false;
|
||||
|
||||
return factionWith.Factions.All(x => IsFactionFriendly(target, x)) ||
|
||||
factionWith.FriendlyFactions.Contains(target);
|
||||
}
|
||||
|
||||
public bool IsFactionHostile(string target, string with)
|
||||
{
|
||||
return _factions[target].Hostile.Contains(with) && _factions[with].Hostile.Contains(target);
|
||||
}
|
||||
|
||||
public bool IsFactionHostile(string target, EntityUid with, FactionComponent? factionWith = null)
|
||||
{
|
||||
if (!Resolve(with, ref factionWith, false))
|
||||
return false;
|
||||
|
||||
return factionWith.Factions.All(x => IsFactionHostile(target, x)) ||
|
||||
factionWith.HostileFactions.Contains(target);
|
||||
}
|
||||
|
||||
public bool IsFactionNeutral(string target, string with)
|
||||
{
|
||||
return !IsFactionFriendly(target, with) && !IsFactionHostile(target, with);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Makes the source faction friendly to the target faction, 1-way.
|
||||
/// </summary>
|
||||
|
||||
@@ -470,7 +470,7 @@ public sealed partial class NPCSteeringSystem
|
||||
(mask & otherBody.CollisionLayer) == 0x0 &&
|
||||
(layer & otherBody.CollisionMask) == 0x0 ||
|
||||
!factionQuery.TryGetComponent(ent, out var otherFaction) ||
|
||||
!_faction.IsFriendly(uid, ent, ourFaction, otherFaction) ||
|
||||
!_faction.IsEntityFriendly(uid, ent, ourFaction, otherFaction) ||
|
||||
// Use <= 0 so we ignore stationary friends in case.
|
||||
Vector2.Dot(otherBody.LinearVelocity, ourVelocity) <= 0f)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Linq;
|
||||
using Content.Server.Administration;
|
||||
using Content.Server.Station.Components;
|
||||
using Content.Server.Station.Systems;
|
||||
using Content.Shared.Administration;
|
||||
using JetBrains.Annotations;
|
||||
@@ -47,13 +48,12 @@ namespace Content.Server.Nuke.Commands
|
||||
}
|
||||
|
||||
var stations = _entityManager
|
||||
.System<StationSystem>()
|
||||
.Stations
|
||||
.Select(station =>
|
||||
.EntityQuery<StationDataComponent>()
|
||||
.Select(stationData =>
|
||||
{
|
||||
var meta = _entityManager.GetComponent<MetaDataComponent>(station);
|
||||
var meta = _entityManager.GetComponent<MetaDataComponent>(stationData.Owner);
|
||||
|
||||
return new CompletionOption(station.ToString(), meta.EntityName);
|
||||
return new CompletionOption(stationData.Owner.ToString(), meta.EntityName);
|
||||
});
|
||||
|
||||
return CompletionResult.FromHintOptions(stations, null);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Content.Server.Objectives.Interfaces;
|
||||
using Content.Server.Shuttles.Components;
|
||||
using Content.Server.Station.Components;
|
||||
using Content.Shared.Cuffs.Components;
|
||||
using JetBrains.Annotations;
|
||||
@@ -61,7 +62,7 @@ namespace Content.Server.Objectives.Conditions
|
||||
agentIsEscaping = false;
|
||||
|
||||
// Any emergency shuttle counts for this objective.
|
||||
foreach (var stationData in entMan.EntityQuery<StationDataComponent>())
|
||||
foreach (var stationData in entMan.EntityQuery<StationEmergencyShuttleComponent>())
|
||||
{
|
||||
if (IsAgentOnShuttle(xform, stationData.EmergencyShuttle)) {
|
||||
shuttleContainsAgent = true;
|
||||
|
||||
@@ -28,8 +28,6 @@ public sealed partial class SalvageSystem
|
||||
|
||||
private void InitializeExpeditions()
|
||||
{
|
||||
SubscribeLocalEvent<StationInitializedEvent>(OnSalvageExpStationInit);
|
||||
|
||||
SubscribeLocalEvent<SalvageExpeditionConsoleComponent, ComponentInit>(OnSalvageConsoleInit);
|
||||
SubscribeLocalEvent<SalvageExpeditionConsoleComponent, EntParentChangedMessage>(OnSalvageConsoleParent);
|
||||
SubscribeLocalEvent<SalvageExpeditionConsoleComponent, ClaimSalvageMessage>(OnSalvageClaimMessage);
|
||||
@@ -115,11 +113,6 @@ public sealed partial class SalvageSystem
|
||||
component.EndTime += args.PausedTime;
|
||||
}
|
||||
|
||||
private void OnSalvageExpStationInit(StationInitializedEvent ev)
|
||||
{
|
||||
EnsureComp<SalvageExpeditionDataComponent>(ev.Station);
|
||||
}
|
||||
|
||||
private void UpdateExpeditions()
|
||||
{
|
||||
var currentTime = _timing.CurTime;
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
using Content.Server.Shuttles.Systems;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Server.Shuttles.Components;
|
||||
|
||||
/// <summary>
|
||||
/// This is used for controlling evacuation for a station.
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public sealed class StationEmergencyShuttleComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// The emergency shuttle assigned to this station.
|
||||
/// </summary>
|
||||
[ViewVariables, Access(typeof(ShuttleSystem), typeof(EmergencyShuttleSystem), Friend = AccessPermissions.ReadWrite)]
|
||||
public EntityUid? EmergencyShuttle;
|
||||
|
||||
/// <summary>
|
||||
/// Emergency shuttle map path for this station.
|
||||
/// </summary>
|
||||
[DataField("emergencyShuttlePath", customTypeSerializer: typeof(ResPathSerializer))]
|
||||
public ResPath EmergencyShuttlePath { get; set; } = new("/Maps/Shuttles/emergency.yml");
|
||||
}
|
||||
@@ -57,7 +57,6 @@ public sealed class ArrivalsSystem : EntitySystem
|
||||
SubscribeLocalEvent<ArrivalsShuttleComponent, EntityUnpausedEvent>(OnShuttleUnpaused);
|
||||
SubscribeLocalEvent<ArrivalsShuttleComponent, FTLTagEvent>(OnShuttleTag);
|
||||
|
||||
SubscribeLocalEvent<StationInitializedEvent>(OnStationInit);
|
||||
SubscribeLocalEvent<RoundStartingEvent>(OnRoundStarting);
|
||||
SubscribeLocalEvent<ArrivalsShuttleComponent, FTLStartedEvent>(OnArrivalsFTL);
|
||||
|
||||
@@ -207,17 +206,15 @@ public sealed class ArrivalsSystem : EntitySystem
|
||||
}
|
||||
}
|
||||
|
||||
private void OnStationInit(StationInitializedEvent ev)
|
||||
{
|
||||
EnsureComp<StationArrivalsComponent>(ev.Station);
|
||||
}
|
||||
|
||||
private void OnPlayerSpawn(PlayerSpawningEvent ev)
|
||||
{
|
||||
// Only works on latejoin even if enabled.
|
||||
if (!Enabled || _ticker.RunLevel != GameRunLevel.InRound)
|
||||
return;
|
||||
|
||||
if (!HasComp<StationArrivalsComponent>(ev.Station))
|
||||
return;
|
||||
|
||||
var points = EntityQuery<SpawnPointComponent, TransformComponent>().ToList();
|
||||
_random.Shuffle(points);
|
||||
TryGetArrivals(out var arrivals);
|
||||
|
||||
@@ -156,7 +156,7 @@ public sealed partial class EmergencyShuttleSystem
|
||||
|
||||
if (CentComMap != null)
|
||||
{
|
||||
var dataQuery = AllEntityQuery<StationDataComponent>();
|
||||
var dataQuery = AllEntityQuery<StationEmergencyShuttleComponent>();
|
||||
|
||||
while (dataQuery.MoveNext(out var comp))
|
||||
{
|
||||
|
||||
@@ -73,7 +73,7 @@ public sealed partial class EmergencyShuttleSystem : EntitySystem
|
||||
// Don't immediately invoke as roundstart will just handle it.
|
||||
_configManager.OnValueChanged(CCVars.EmergencyShuttleEnabled, SetEmergencyShuttleEnabled);
|
||||
SubscribeLocalEvent<RoundStartingEvent>(OnRoundStart);
|
||||
SubscribeLocalEvent<StationDataComponent, ComponentStartup>(OnStationStartup);
|
||||
SubscribeLocalEvent<StationEmergencyShuttleComponent, ComponentStartup>(OnStationStartup);
|
||||
SubscribeNetworkEvent<EmergencyShuttleRequestPositionMessage>(OnShuttleRequestPosition);
|
||||
InitializeEmergencyConsole();
|
||||
}
|
||||
@@ -115,19 +115,22 @@ public sealed partial class EmergencyShuttleSystem : EntitySystem
|
||||
return;
|
||||
|
||||
var player = args.SenderSession.AttachedEntity;
|
||||
if (player is null)
|
||||
return;
|
||||
|
||||
if (player == null ||
|
||||
!TryComp<StationDataComponent>(_station.GetOwningStation(player.Value), out var stationData) ||
|
||||
!HasComp<ShuttleComponent>(stationData.EmergencyShuttle))
|
||||
var station = _station.GetOwningStation(player.Value);
|
||||
|
||||
if (!TryComp<StationEmergencyShuttleComponent>(station, out var stationShuttle) ||
|
||||
!HasComp<ShuttleComponent>(stationShuttle.EmergencyShuttle))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var targetGrid = _station.GetLargestGrid(stationData);
|
||||
var targetGrid = _station.GetLargestGrid(Comp<StationDataComponent>(station.Value));
|
||||
if (targetGrid == null)
|
||||
return;
|
||||
|
||||
var config = _dock.GetDockingConfig(stationData.EmergencyShuttle.Value, targetGrid.Value, DockTag);
|
||||
var config = _dock.GetDockingConfig(stationShuttle.EmergencyShuttle.Value, targetGrid.Value, DockTag);
|
||||
if (config == null)
|
||||
return;
|
||||
|
||||
@@ -143,14 +146,14 @@ public sealed partial class EmergencyShuttleSystem : EntitySystem
|
||||
/// </summary>
|
||||
public void CallEmergencyShuttle(EntityUid? stationUid)
|
||||
{
|
||||
if (!TryComp<StationDataComponent>(stationUid, out var stationData) ||
|
||||
!TryComp<TransformComponent>(stationData.EmergencyShuttle, out var xform) ||
|
||||
!TryComp<ShuttleComponent>(stationData.EmergencyShuttle, out var shuttle))
|
||||
if (!TryComp<StationEmergencyShuttleComponent>(stationUid, out var stationShuttle) ||
|
||||
!TryComp<TransformComponent>(stationShuttle.EmergencyShuttle, out var xform) ||
|
||||
!TryComp<ShuttleComponent>(stationShuttle.EmergencyShuttle, out var shuttle))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var targetGrid = _station.GetLargestGrid(stationData);
|
||||
var targetGrid = _station.GetLargestGrid(Comp<StationDataComponent>(stationUid.Value));
|
||||
|
||||
// UHH GOOD LUCK
|
||||
if (targetGrid == null)
|
||||
@@ -164,11 +167,11 @@ public sealed partial class EmergencyShuttleSystem : EntitySystem
|
||||
|
||||
var xformQuery = GetEntityQuery<TransformComponent>();
|
||||
|
||||
if (_shuttle.TryFTLDock(stationData.EmergencyShuttle.Value, shuttle, targetGrid.Value, DockTag))
|
||||
if (_shuttle.TryFTLDock(stationShuttle.EmergencyShuttle.Value, shuttle, targetGrid.Value, DockTag))
|
||||
{
|
||||
if (TryComp<TransformComponent>(targetGrid.Value, out var targetXform))
|
||||
{
|
||||
var angle = _dock.GetAngle(stationData.EmergencyShuttle.Value, xform, targetGrid.Value, targetXform, xformQuery);
|
||||
var angle = _dock.GetAngle(stationShuttle.EmergencyShuttle.Value, xform, targetGrid.Value, targetXform, xformQuery);
|
||||
_chatSystem.DispatchStationAnnouncement(stationUid.Value, Loc.GetString("emergency-shuttle-docked", ("time", $"{_consoleAccumulator:0}"), ("direction", angle.GetDir())), playDefaultSound: false);
|
||||
}
|
||||
|
||||
@@ -180,7 +183,7 @@ public sealed partial class EmergencyShuttleSystem : EntitySystem
|
||||
{
|
||||
if (TryComp<TransformComponent>(targetGrid.Value, out var targetXform))
|
||||
{
|
||||
var angle = _dock.GetAngle(stationData.EmergencyShuttle.Value, xform, targetGrid.Value, targetXform, xformQuery);
|
||||
var angle = _dock.GetAngle(stationShuttle.EmergencyShuttle.Value, xform, targetGrid.Value, targetXform, xformQuery);
|
||||
_chatSystem.DispatchStationAnnouncement(stationUid.Value, Loc.GetString("emergency-shuttle-nearby", ("direction", angle.GetDir())), playDefaultSound: false);
|
||||
}
|
||||
|
||||
@@ -190,7 +193,7 @@ public sealed partial class EmergencyShuttleSystem : EntitySystem
|
||||
}
|
||||
}
|
||||
|
||||
private void OnStationStartup(EntityUid uid, StationDataComponent component, ComponentStartup args)
|
||||
private void OnStationStartup(EntityUid uid, StationEmergencyShuttleComponent component, ComponentStartup args)
|
||||
{
|
||||
AddEmergencyShuttle(component);
|
||||
}
|
||||
@@ -254,24 +257,23 @@ public sealed partial class EmergencyShuttleSystem : EntitySystem
|
||||
_sawmill.Info("No CentCom map found, skipping setup.");
|
||||
}
|
||||
|
||||
foreach (var comp in EntityQuery<StationDataComponent>(true))
|
||||
foreach (var comp in EntityQuery<StationEmergencyShuttleComponent>(true))
|
||||
{
|
||||
AddEmergencyShuttle(comp);
|
||||
}
|
||||
}
|
||||
|
||||
private void AddEmergencyShuttle(StationDataComponent component)
|
||||
private void AddEmergencyShuttle(StationEmergencyShuttleComponent component)
|
||||
{
|
||||
if (!_emergencyShuttleEnabled
|
||||
|| CentComMap == null
|
||||
|| component.EmergencyShuttle != null
|
||||
|| component.StationConfig == null)
|
||||
|| component.EmergencyShuttle != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Load escape shuttle
|
||||
var shuttlePath = component.StationConfig.EmergencyShuttlePath;
|
||||
var shuttlePath = component.EmergencyShuttlePath;
|
||||
var shuttle = _map.LoadGrid(CentComMap.Value, shuttlePath.ToString(), new MapLoadOptions()
|
||||
{
|
||||
// Should be far enough... right? I'm too lazy to bounds check CentCom rn.
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
using Content.Server.GameTicking;
|
||||
|
||||
namespace Content.Server.Station.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Added to grids saved in maps to designate them as 'part of a station' and not main grids. I.e. ancillary
|
||||
/// shuttles for multi-grid stations.
|
||||
/// </summary>
|
||||
[RegisterComponent, Access(typeof(GameTicker)), Obsolete("Performs the exact same function as BecomesStationComponent.")]
|
||||
public sealed class PartOfStationComponent : Component
|
||||
{
|
||||
[DataField("id", required: true)]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public string Id = default!;
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
using Content.Server.Shuttles.Systems;
|
||||
using Content.Server.Station.Systems;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Server.Station.Components;
|
||||
|
||||
@@ -19,15 +21,6 @@ public sealed class StationDataComponent : Component
|
||||
/// <summary>
|
||||
/// List of all grids this station is part of.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// You should not mutate this yourself, go through StationSystem so the appropriate events get fired.
|
||||
/// </remarks>
|
||||
[DataField("grids")]
|
||||
public readonly HashSet<EntityUid> Grids = new();
|
||||
|
||||
/// <summary>
|
||||
/// The emergency shuttle assigned to this station.
|
||||
/// </summary>
|
||||
[ViewVariables, Access(typeof(ShuttleSystem), typeof(EmergencyShuttleSystem), Friend = AccessPermissions.ReadWrite)]
|
||||
public EntityUid? EmergencyShuttle;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace Content.Server.Station.Components;
|
||||
|
||||
/// <summary>
|
||||
/// This is used for event eligibility.
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public sealed class StationEventEligibleComponent : Component
|
||||
{
|
||||
|
||||
}
|
||||
@@ -32,6 +32,16 @@ public sealed class StationJobsComponent : Component
|
||||
/// </summary>
|
||||
[DataField("extendedAccess")] public bool ExtendedAccess;
|
||||
|
||||
/// <summary>
|
||||
/// If there are less than or equal this amount of players in the game at round start,
|
||||
/// people get extended access levels from job prototypes.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Set to -1 to disable extended access.
|
||||
/// </remarks>
|
||||
[DataField("extendedAccessThreshold")]
|
||||
public int ExtendedAccessThreshold { get; set; } = 15;
|
||||
|
||||
/// <summary>
|
||||
/// The percentage of jobs remaining.
|
||||
/// </summary>
|
||||
@@ -62,5 +72,10 @@ public sealed class StationJobsComponent : Component
|
||||
/// <summary>
|
||||
/// Overflow jobs that round-start can spawn infinitely many of.
|
||||
/// </summary>
|
||||
[DataField("overflowJobs", customTypeSerializer: typeof(PrototypeIdHashSetSerializer<JobPrototype>))] public HashSet<string> OverflowJobs = new();
|
||||
[DataField("overflowJobs", customTypeSerializer: typeof(PrototypeIdHashSetSerializer<JobPrototype>))]
|
||||
public HashSet<string> OverflowJobs = new();
|
||||
|
||||
[DataField("availableJobs", required: true,
|
||||
customTypeSerializer: typeof(PrototypeIdDictionarySerializer<List<int?>, JobPrototype>))]
|
||||
public readonly Dictionary<string, List<int?>> SetupAvailableJobs = default!;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
using Content.Server.Maps.NameGenerators;
|
||||
|
||||
namespace Content.Server.Station.Components;
|
||||
|
||||
/// <summary>
|
||||
/// This is used for setting up a station's name.
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public sealed class StationNameSetupComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// The name template to use for the station.
|
||||
/// If there's a name generator this should follow it's required format.
|
||||
/// </summary>
|
||||
[DataField("mapNameTemplate", required: true)]
|
||||
public string StationNameTemplate { get; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Name generator to use for the station, if any.
|
||||
/// </summary>
|
||||
[DataField("nameGenerator")]
|
||||
public StationNameGenerator? NameGenerator { get; }
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
using Content.Shared.Roles;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Dictionary;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
|
||||
|
||||
namespace Content.Server.Station;
|
||||
|
||||
public sealed partial class StationConfig
|
||||
{
|
||||
[DataField("overflowJobs", required: true, customTypeSerializer: typeof(PrototypeIdListSerializer<JobPrototype>))]
|
||||
private readonly List<string> _overflowJobs = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Jobs used at round start should the station run out of job slots.
|
||||
/// Doesn't necessarily mean the station has infinite slots for the given jobs mid-round!
|
||||
/// </summary>
|
||||
public IReadOnlyList<string> OverflowJobs => _overflowJobs;
|
||||
|
||||
|
||||
[DataField("availableJobs", required: true,
|
||||
customTypeSerializer: typeof(PrototypeIdDictionarySerializer<List<int?>, JobPrototype>))]
|
||||
private readonly Dictionary<string, List<int?>> _availableJobs = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Index of all jobs available on the station, of form
|
||||
/// job name: [round-start, mid-round]
|
||||
/// </summary>
|
||||
public IReadOnlyDictionary<string, List<int?>> AvailableJobs => _availableJobs;
|
||||
|
||||
/// <summary>
|
||||
/// If there are less than or equal this amount of players in the game at round start,
|
||||
/// people get extended access levels from job prototypes.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Set to -1 to disable extended access.
|
||||
/// </remarks>
|
||||
[DataField("extendedAccessThreshold")]
|
||||
public int ExtendedAccessThreshold { get; set; } = 15;
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
using Robust.Shared.Utility;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations;
|
||||
|
||||
namespace Content.Server.Station;
|
||||
|
||||
public sealed partial class StationConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// Emergency shuttle map path for this station.
|
||||
/// </summary>
|
||||
[DataField("emergencyShuttlePath", customTypeSerializer: typeof(ResPathSerializer))]
|
||||
public ResPath EmergencyShuttlePath { get; set; } = new("/Maps/Shuttles/emergency.yml");
|
||||
}
|
||||
@@ -1,30 +1,19 @@
|
||||
using Content.Server.Maps.NameGenerators;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Station;
|
||||
|
||||
/// <summary>
|
||||
/// A config for a station. Specifies name and job slots.
|
||||
/// This is the only part of stations a downstream should ideally need to modify directly.
|
||||
/// A config for a station. Specifies name and component modifications.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Forks should not directly edit existing parts of this class.
|
||||
/// Make a new partial for your fancy new feature, it'll save you time later.
|
||||
/// </remarks>
|
||||
[DataDefinition, PublicAPI]
|
||||
public sealed partial class StationConfig
|
||||
public sealed class StationConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// The name template to use for the station.
|
||||
/// If there's a name generator this should follow it's required format.
|
||||
/// </summary>
|
||||
[DataField("mapNameTemplate", required: true)]
|
||||
public string StationNameTemplate { get; } = default!;
|
||||
[DataField("stationProto", required: true)]
|
||||
public string StationPrototype = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Name generator to use for the station, if any.
|
||||
/// </summary>
|
||||
[DataField("nameGenerator")]
|
||||
public StationNameGenerator? NameGenerator { get; }
|
||||
[DataField("components", required: true)]
|
||||
public ComponentRegistry StationComponentOverrides = default!;
|
||||
}
|
||||
|
||||
|
||||
@@ -292,7 +292,7 @@ public sealed partial class StationJobsSystem
|
||||
assignedJobs.Add(player, (null, EntityUid.Invalid));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
_random.Shuffle(givenStations);
|
||||
|
||||
foreach (var station in givenStations)
|
||||
@@ -318,9 +318,8 @@ public sealed partial class StationJobsSystem
|
||||
foreach (var (station, count) in jobsCount)
|
||||
{
|
||||
var jobs = Comp<StationJobsComponent>(station);
|
||||
var data = Comp<StationDataComponent>(station);
|
||||
|
||||
var thresh = data.StationConfig?.ExtendedAccessThreshold ?? -1;
|
||||
var thresh = jobs.ExtendedAccessThreshold;
|
||||
|
||||
jobs.ExtendedAccess = count <= thresh;
|
||||
|
||||
|
||||
@@ -53,30 +53,32 @@ public sealed partial class StationJobsSystem : EntitySystem
|
||||
|
||||
private void OnStationInitialized(StationInitializedEvent msg)
|
||||
{
|
||||
var stationJobs = AddComp<StationJobsComponent>(msg.Station);
|
||||
var stationData = Comp<StationDataComponent>(msg.Station);
|
||||
|
||||
if (stationData.StationConfig == null)
|
||||
if (!TryComp<StationJobsComponent>(msg.Station, out var stationJobs))
|
||||
return;
|
||||
|
||||
var mapJobList = stationData.StationConfig.AvailableJobs;
|
||||
var mapJobList = stationJobs.SetupAvailableJobs;
|
||||
|
||||
stationJobs.RoundStartTotalJobs = mapJobList.Values.Where(x => x[0] is not null && x[0] > 0).Sum(x => x[0]!.Value);
|
||||
stationJobs.MidRoundTotalJobs = mapJobList.Values.Where(x => x[1] is not null && x[1] > 0).Sum(x => x[1]!.Value);
|
||||
|
||||
stationJobs.TotalJobs = stationJobs.MidRoundTotalJobs;
|
||||
|
||||
stationJobs.JobList = mapJobList.ToDictionary(x => x.Key, x =>
|
||||
{
|
||||
if (x.Value[1] <= -1)
|
||||
return null;
|
||||
return (uint?) x.Value[1];
|
||||
});
|
||||
|
||||
stationJobs.RoundStartJobList = mapJobList.ToDictionary(x => x.Key, x =>
|
||||
{
|
||||
if (x.Value[0] <= -1)
|
||||
return null;
|
||||
return (uint?) x.Value[0];
|
||||
});
|
||||
stationJobs.OverflowJobs = stationData.StationConfig.OverflowJobs.ToHashSet();
|
||||
|
||||
stationJobs.OverflowJobs = stationJobs.OverflowJobs.ToHashSet();
|
||||
|
||||
UpdateJobsAvailable();
|
||||
}
|
||||
|
||||
@@ -464,9 +466,11 @@ public sealed partial class StationJobsSystem : EntitySystem
|
||||
var jobs = new Dictionary<EntityUid, Dictionary<string, uint?>>();
|
||||
var stationNames = new Dictionary<EntityUid, string>();
|
||||
|
||||
foreach (var station in _stationSystem.Stations)
|
||||
var query = EntityQueryEnumerator<StationJobsComponent>();
|
||||
|
||||
while (query.MoveNext(out var station, out var comp))
|
||||
{
|
||||
var list = Comp<StationJobsComponent>(station).JobList.ToDictionary(x => x.Key, x => x.Value);
|
||||
var list = comp.JobList.ToDictionary(x => x.Key, x => x.Value);
|
||||
jobs.Add(station, list);
|
||||
stationNames.Add(station, Name(station));
|
||||
}
|
||||
|
||||
35
Content.Server/Station/Systems/StationNameSystem.cs
Normal file
35
Content.Server/Station/Systems/StationNameSystem.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using Content.Server.Station.Components;
|
||||
|
||||
namespace Content.Server.Station.Systems;
|
||||
|
||||
/// <summary>
|
||||
/// This handles naming stations.
|
||||
/// </summary>
|
||||
public sealed class StationNameSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly StationSystem _station = default!;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Initialize()
|
||||
{
|
||||
SubscribeLocalEvent<StationNameSetupComponent, ComponentInit>(OnStationNameSetupInit);
|
||||
}
|
||||
|
||||
private void OnStationNameSetupInit(EntityUid uid, StationNameSetupComponent component, ComponentInit args)
|
||||
{
|
||||
if (!HasComp<StationDataComponent>(uid))
|
||||
return;
|
||||
|
||||
_station.RenameStation(uid, GenerateStationName(component), false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates a station name from the given config.
|
||||
/// </summary>
|
||||
private static string GenerateStationName(StationNameSetupComponent config)
|
||||
{
|
||||
return config.NameGenerator is not null
|
||||
? config.NameGenerator.FormatName(config.StationNameTemplate)
|
||||
: config.StationNameTemplate;
|
||||
}
|
||||
}
|
||||
@@ -50,15 +50,9 @@ public sealed class StationSpawningSystem : EntitySystem
|
||||
/// <inheritdoc/>
|
||||
public override void Initialize()
|
||||
{
|
||||
SubscribeLocalEvent<StationInitializedEvent>(OnStationInitialized);
|
||||
_configurationManager.OnValueChanged(CCVars.ICRandomCharacters, e => _randomizeCharacters = e, true);
|
||||
}
|
||||
|
||||
private void OnStationInitialized(StationInitializedEvent ev)
|
||||
{
|
||||
AddComp<StationSpawningComponent>(ev.Station);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to spawn a player character onto the given station.
|
||||
/// </summary>
|
||||
@@ -95,16 +89,19 @@ public sealed class StationSpawningSystem : EntitySystem
|
||||
/// <param name="job">Job to assign to the character, if any.</param>
|
||||
/// <param name="profile">Appearance profile to use for the character.</param>
|
||||
/// <param name="station">The station this player is being spawned on.</param>
|
||||
/// <param name="entity">The entity to use, if one already exists.</param>
|
||||
/// <returns>The spawned entity</returns>
|
||||
public EntityUid SpawnPlayerMob(
|
||||
EntityCoordinates coordinates,
|
||||
Job? job,
|
||||
HumanoidCharacterProfile? profile,
|
||||
EntityUid? station)
|
||||
EntityUid? station,
|
||||
EntityUid? entity = null)
|
||||
{
|
||||
// If we're not spawning a humanoid, we're gonna exit early without doing all the humanoid stuff.
|
||||
if (job?.JobEntity != null)
|
||||
{
|
||||
DebugTools.Assert(entity is null);
|
||||
var jobEntity = EntityManager.SpawnEntity(job.JobEntity, coordinates);
|
||||
MakeSentientCommand.MakeSentient(jobEntity, EntityManager);
|
||||
DoJobSpecials(job, jobEntity);
|
||||
@@ -131,7 +128,7 @@ public sealed class StationSpawningSystem : EntitySystem
|
||||
if (!_prototypeManager.TryIndex<SpeciesPrototype>(speciesId, out var species))
|
||||
throw new ArgumentException($"Invalid species prototype was used: {speciesId}");
|
||||
|
||||
var entity = Spawn(species.Prototype, coordinates);
|
||||
entity ??= Spawn(species.Prototype, coordinates);
|
||||
|
||||
if (_randomizeCharacters)
|
||||
{
|
||||
@@ -141,24 +138,24 @@ public sealed class StationSpawningSystem : EntitySystem
|
||||
if (job?.StartingGear != null)
|
||||
{
|
||||
var startingGear = _prototypeManager.Index<StartingGearPrototype>(job.StartingGear);
|
||||
EquipStartingGear(entity, startingGear, profile);
|
||||
EquipStartingGear(entity.Value, startingGear, profile);
|
||||
if (profile != null)
|
||||
EquipIdCard(entity, profile.Name, job.Prototype, station);
|
||||
EquipIdCard(entity.Value, profile.Name, job.Prototype, station);
|
||||
}
|
||||
|
||||
if (profile != null)
|
||||
{
|
||||
_humanoidSystem.LoadProfile(entity, profile);
|
||||
MetaData(entity).EntityName = profile.Name;
|
||||
_humanoidSystem.LoadProfile(entity.Value, profile);
|
||||
MetaData(entity.Value).EntityName = profile.Name;
|
||||
if (profile.FlavorText != "" && _configurationManager.GetCVar(CCVars.FlavorText))
|
||||
{
|
||||
AddComp<DetailExaminableComponent>(entity).Content = profile.FlavorText;
|
||||
AddComp<DetailExaminableComponent>(entity.Value).Content = profile.FlavorText;
|
||||
}
|
||||
}
|
||||
|
||||
DoJobSpecials(job, entity);
|
||||
_identity.QueueIdentityUpdate(entity);
|
||||
return entity;
|
||||
DoJobSpecials(job, entity.Value);
|
||||
_identity.QueueIdentityUpdate(entity.Value);
|
||||
return entity.Value;
|
||||
}
|
||||
|
||||
private void DoJobSpecials(Job? job, EntityUid entity)
|
||||
|
||||
@@ -13,6 +13,7 @@ using Robust.Shared.Map;
|
||||
using Robust.Shared.Map.Components;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Random;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Server.Station.Systems;
|
||||
|
||||
@@ -35,16 +36,6 @@ public sealed class StationSystem : EntitySystem
|
||||
|
||||
private ISawmill _sawmill = default!;
|
||||
|
||||
private readonly HashSet<EntityUid> _stations = new();
|
||||
|
||||
/// <summary>
|
||||
/// All stations that currently exist.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// I'd have this just invoke an entity query, but I want this to be a hashset for convenience and it allocating on use would be lame.
|
||||
/// </remarks>
|
||||
public IReadOnlySet<EntityUid> Stations => _stations;
|
||||
|
||||
private bool _randomStationOffset;
|
||||
private bool _randomStationRotation;
|
||||
private float _maxRandomStationOffset;
|
||||
@@ -57,9 +48,8 @@ public sealed class StationSystem : EntitySystem
|
||||
SubscribeLocalEvent<GameRunLevelChangedEvent>(OnRoundEnd);
|
||||
SubscribeLocalEvent<PreGameMapLoad>(OnPreGameMapLoad);
|
||||
SubscribeLocalEvent<PostGameMapLoad>(OnPostGameMapLoad);
|
||||
SubscribeLocalEvent<StationDataComponent, ComponentAdd>(OnStationAdd);
|
||||
SubscribeLocalEvent<StationDataComponent, ComponentStartup>(OnStationAdd);
|
||||
SubscribeLocalEvent<StationDataComponent, ComponentShutdown>(OnStationDeleted);
|
||||
SubscribeLocalEvent<StationDataComponent, EntParentChangedMessage>(OnParentChanged);
|
||||
SubscribeLocalEvent<StationMemberComponent, ComponentShutdown>(OnStationGridDeleted);
|
||||
SubscribeLocalEvent<StationMemberComponent, PostGridSplitEvent>(OnStationSplitEvent);
|
||||
|
||||
@@ -89,68 +79,34 @@ public sealed class StationSystem : EntitySystem
|
||||
_player.PlayerStatusChanged -= OnPlayerStatusChanged;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the server shuts down or restarts to avoid uneccesarily logging mid-round station deletion errors.
|
||||
/// </summary>
|
||||
public void OnServerDispose()
|
||||
{
|
||||
_stations.Clear();
|
||||
}
|
||||
|
||||
private void OnPlayerStatusChanged(object? sender, SessionStatusEventArgs e)
|
||||
{
|
||||
if (e.NewStatus == SessionStatus.Connected)
|
||||
{
|
||||
RaiseNetworkEvent(new StationsUpdatedEvent(_stations), e.Session);
|
||||
RaiseNetworkEvent(new StationsUpdatedEvent(GetStationsSet()), e.Session);
|
||||
}
|
||||
}
|
||||
|
||||
#region Event handlers
|
||||
|
||||
private void OnStationAdd(EntityUid uid, StationDataComponent component, ComponentAdd args)
|
||||
private void OnStationAdd(EntityUid uid, StationDataComponent component, ComponentStartup args)
|
||||
{
|
||||
_stations.Add(uid);
|
||||
RaiseNetworkEvent(new StationsUpdatedEvent(GetStationsSet()), Filter.Broadcast());
|
||||
|
||||
var metaData = MetaData(uid);
|
||||
RaiseLocalEvent(new StationInitializedEvent(uid));
|
||||
_sawmill.Info($"Set up station {metaData.EntityName} ({uid}).");
|
||||
|
||||
RaiseNetworkEvent(new StationsUpdatedEvent(_stations), Filter.Broadcast());
|
||||
}
|
||||
|
||||
private void OnStationDeleted(EntityUid uid, StationDataComponent component, ComponentShutdown args)
|
||||
{
|
||||
if (_stations.Contains(uid) && // Was not deleted via DeleteStation()
|
||||
_gameTicker.RunLevel == GameRunLevel.InRound && // And not due to a round restart
|
||||
_gameTicker.LobbyEnabled) // If there isn't a lobby, this is probably sandbox, single player, or a test
|
||||
{
|
||||
// printing a stack trace, rather than throwing an exception so that entity deletion continues as normal.
|
||||
Logger.Error($"Station entity {ToPrettyString(uid)} is getting deleted mid-round. Trace: {Environment.StackTrace}");
|
||||
}
|
||||
|
||||
foreach (var grid in component.Grids)
|
||||
{
|
||||
RemComp<StationMemberComponent>(grid);
|
||||
}
|
||||
|
||||
_stations.Remove(uid);
|
||||
RaiseNetworkEvent(new StationsUpdatedEvent(_stations), Filter.Broadcast());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If a station data entity is getting re-parented mid-round, this will log an error.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This doesn't really achieve anything, it just for debugging any future station data bugs.
|
||||
/// </remarks>
|
||||
private void OnParentChanged(EntityUid uid, StationDataComponent component, ref EntParentChangedMessage args)
|
||||
{
|
||||
if (_gameTicker.RunLevel != GameRunLevel.InRound ||
|
||||
MetaData(uid).EntityLifeStage >= EntityLifeStage.MapInitialized ||
|
||||
component.LifeStage <= ComponentLifeStage.Initializing)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Yeah this doesn't actually stop the parent change..... it just ineffectually yells about it.
|
||||
// STOP RIGHT THERE CRIMINAL SCUM
|
||||
_sawmill.Error($"Station entity {ToPrettyString(uid)} is getting reparented from {ToPrettyString(args.OldParent ?? EntityUid.Invalid)} to {ToPrettyString(args.Transform.ParentUid)}");
|
||||
RaiseNetworkEvent(new StationsUpdatedEvent(GetStationsSet()), Filter.Broadcast());
|
||||
}
|
||||
|
||||
private void OnPreGameMapLoad(PreGameMapLoad ev)
|
||||
@@ -199,23 +155,18 @@ public sealed class StationSystem : EntitySystem
|
||||
_sawmill.Error($"There were no station grids for {ev.GameMap.ID}!");
|
||||
}
|
||||
|
||||
// Iterate over all PartOfStation
|
||||
// TODO: Remove this whenever pillar finally gets replaced. It's the sole user.
|
||||
foreach (var grid in ev.Grids)
|
||||
{
|
||||
if (!TryComp<PartOfStationComponent>(grid, out var partOfStation))
|
||||
continue;
|
||||
|
||||
AddGrid(partOfStation.Id, grid);
|
||||
}
|
||||
|
||||
foreach (var (id, gridIds) in dict)
|
||||
{
|
||||
StationConfig? stationConfig = null;
|
||||
StationConfig stationConfig;
|
||||
|
||||
if (ev.GameMap.Stations.ContainsKey(id))
|
||||
stationConfig = ev.GameMap.Stations[id];
|
||||
else
|
||||
{
|
||||
_sawmill.Error($"The station {id} in map {ev.GameMap.ID} does not have an associated station config!");
|
||||
continue;
|
||||
}
|
||||
|
||||
InitializeNewStation(stationConfig, gridIds, ev.StationName);
|
||||
}
|
||||
}
|
||||
@@ -225,9 +176,10 @@ public sealed class StationSystem : EntitySystem
|
||||
if (eventArgs.New != GameRunLevel.PreRoundLobby)
|
||||
return;
|
||||
|
||||
foreach (var entity in _stations)
|
||||
var query = EntityQueryEnumerator<StationDataComponent>();
|
||||
while (query.MoveNext(out var station, out _))
|
||||
{
|
||||
DeleteStation(entity);
|
||||
QueueDel(station);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -326,47 +278,26 @@ public sealed class StationSystem : EntitySystem
|
||||
return filter;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates a station name from the given config.
|
||||
/// </summary>
|
||||
public static string GenerateStationName(StationConfig config)
|
||||
{
|
||||
return config.NameGenerator is not null
|
||||
? config.NameGenerator.FormatName(config.StationNameTemplate)
|
||||
: config.StationNameTemplate;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new station with the given information.
|
||||
/// </summary>
|
||||
/// <param name="stationConfig">The game map prototype used, if any.</param>
|
||||
/// <param name="gridIds">All grids that should be added to the station.</param>
|
||||
/// <param name="name">Optional override for the station name.</param>
|
||||
/// <remarks>This is for ease of use, manually spawning the entity works just fine.</remarks>
|
||||
/// <returns>The initialized station.</returns>
|
||||
public EntityUid InitializeNewStation(StationConfig? stationConfig, IEnumerable<EntityUid>? gridIds, string? name = null)
|
||||
public EntityUid InitializeNewStation(StationConfig stationConfig, IEnumerable<EntityUid>? gridIds, string? name = null)
|
||||
{
|
||||
var station = Spawn(null, MapCoordinates.Nullspace);
|
||||
// Use overrides for setup.
|
||||
var station = EntityManager.SpawnEntity(stationConfig.StationPrototype, MapCoordinates.Nullspace, stationConfig.StationComponentOverrides);
|
||||
|
||||
// TODO SERIALIZATION The station data needs to be saveable somehow, but when a map gets saved, this entity
|
||||
// won't be included because its in null-space. Also, what happens to shuttles on other maps?
|
||||
if (name is not null)
|
||||
RenameStation(station, name, false);
|
||||
|
||||
var data = AddComp<StationDataComponent>(station);
|
||||
var metaData = MetaData(station);
|
||||
data.StationConfig = stationConfig;
|
||||
DebugTools.Assert(HasComp<StationDataComponent>(station), "Stations should have StationData in their prototype.");
|
||||
|
||||
if (stationConfig is not null && name is null)
|
||||
{
|
||||
name = GenerateStationName(stationConfig);
|
||||
}
|
||||
else if (name is null)
|
||||
{
|
||||
_sawmill.Error($"When setting up station {station}, was unable to find a valid name in the config and no name was provided.");
|
||||
name = "unnamed station";
|
||||
}
|
||||
|
||||
metaData.EntityName = name;
|
||||
RaiseLocalEvent(new StationInitializedEvent(station));
|
||||
_sawmill.Info($"Set up station {metaData.EntityName} ({station}).");
|
||||
var data = Comp<StationDataComponent>(station);
|
||||
name ??= MetaData(station).EntityName;
|
||||
|
||||
foreach (var grid in gridIds ?? Array.Empty<EntityUid>())
|
||||
{
|
||||
@@ -397,11 +328,11 @@ public sealed class StationSystem : EntitySystem
|
||||
|
||||
var stationMember = AddComp<StationMemberComponent>(mapGrid);
|
||||
stationMember.Station = station;
|
||||
stationData.Grids.Add(gridComponent.Owner);
|
||||
stationData.Grids.Add(mapGrid);
|
||||
|
||||
RaiseLocalEvent(station, new StationGridAddedEvent(gridComponent.Owner, false), true);
|
||||
RaiseLocalEvent(station, new StationGridAddedEvent(mapGrid, false), true);
|
||||
|
||||
_sawmill.Info($"Adding grid {mapGrid}:{gridComponent.Owner} to station {Name(station)} ({station})");
|
||||
_sawmill.Info($"Adding grid {mapGrid} to station {Name(station)} ({station})");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -420,10 +351,10 @@ public sealed class StationSystem : EntitySystem
|
||||
throw new ArgumentException("Tried to use a non-station entity as a station!", nameof(station));
|
||||
|
||||
RemComp<StationMemberComponent>(mapGrid);
|
||||
stationData.Grids.Remove(gridComponent.Owner);
|
||||
stationData.Grids.Remove(mapGrid);
|
||||
|
||||
RaiseLocalEvent(station, new StationGridRemovedEvent(gridComponent.Owner), true);
|
||||
_sawmill.Info($"Removing grid {mapGrid}:{gridComponent.Owner} from station {Name(station)} ({station})");
|
||||
RaiseLocalEvent(station, new StationGridRemovedEvent(mapGrid), true);
|
||||
_sawmill.Info($"Removing grid {mapGrid} from station {Name(station)} ({station})");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -462,9 +393,7 @@ public sealed class StationSystem : EntitySystem
|
||||
if (!Resolve(station, ref stationData))
|
||||
throw new ArgumentException("Tried to use a non-station entity as a station!", nameof(station));
|
||||
|
||||
// component shutdown will error if the station was not removed from _stations prior to deletion.
|
||||
_stations.Remove(station);
|
||||
Del(station);
|
||||
QueueDel(station);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -501,6 +430,16 @@ public sealed class StationSystem : EntitySystem
|
||||
|
||||
return CompOrNull<StationMemberComponent>(xform.GridUid)?.Station;
|
||||
}
|
||||
|
||||
public List<EntityUid> GetStations()
|
||||
{
|
||||
return EntityQuery<StationDataComponent>().Select(x => x.Owner).ToList();
|
||||
}
|
||||
|
||||
public HashSet<EntityUid> GetStationsSet()
|
||||
{
|
||||
return EntityQuery<StationDataComponent>().Select(x => x.Owner).ToHashSet();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -24,9 +24,9 @@ public sealed class AnomalySpawnRule : StationEventSystem<AnomalySpawnRuleCompon
|
||||
{
|
||||
base.Started(uid, component, gameRule, args);
|
||||
|
||||
if (StationSystem.Stations.Count == 0)
|
||||
return; // No stations
|
||||
var chosenStation = RobustRandom.Pick(StationSystem.Stations.ToList());
|
||||
if (!TryGetRandomStation(out var chosenStation))
|
||||
return;
|
||||
|
||||
if (!TryComp<StationDataComponent>(chosenStation, out var stationData))
|
||||
return;
|
||||
|
||||
|
||||
@@ -26,9 +26,8 @@ public sealed class BreakerFlipRule : StationEventSystem<BreakerFlipRuleComponen
|
||||
{
|
||||
base.Started(uid, component, gameRule, args);
|
||||
|
||||
if (StationSystem.Stations.Count == 0)
|
||||
if (!TryGetRandomStation(out var chosenStation))
|
||||
return;
|
||||
var chosenStation = RobustRandom.Pick(StationSystem.Stations.ToList());
|
||||
|
||||
var stationApcs = new List<ApcComponent>();
|
||||
foreach (var (apc, transform) in EntityQuery<ApcComponent, TransformComponent>())
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Linq;
|
||||
using Content.Server.GameTicking.Rules.Components;
|
||||
using Content.Server.Station.Components;
|
||||
using Content.Server.Station.Systems;
|
||||
using Content.Server.StationEvents.Components;
|
||||
using JetBrains.Annotations;
|
||||
@@ -16,10 +17,13 @@ public sealed class BureaucraticErrorRule : StationEventSystem<BureaucraticError
|
||||
{
|
||||
base.Started(uid, component, gameRule, args);
|
||||
|
||||
if (StationSystem.Stations.Count == 0)
|
||||
return; // No stations
|
||||
var chosenStation = RobustRandom.Pick(StationSystem.Stations.ToList());
|
||||
var jobList = _stationJobs.GetJobs(chosenStation).Keys.ToList();
|
||||
if (!TryGetRandomStation(out var chosenStation, HasComp<StationJobsComponent>))
|
||||
return;
|
||||
|
||||
var jobList = _stationJobs.GetJobs(chosenStation.Value).Keys.ToList();
|
||||
|
||||
if (jobList.Count == 0)
|
||||
return;
|
||||
|
||||
var mod = GetSeverityModifier();
|
||||
|
||||
@@ -28,12 +32,12 @@ public sealed class BureaucraticErrorRule : StationEventSystem<BureaucraticError
|
||||
if (RobustRandom.Prob(Math.Min(0.25f * MathF.Sqrt(mod), 1.0f)))
|
||||
{
|
||||
var chosenJob = RobustRandom.PickAndTake(jobList);
|
||||
_stationJobs.MakeJobUnlimited(chosenStation, chosenJob); // INFINITE chaos.
|
||||
_stationJobs.MakeJobUnlimited(chosenStation.Value, chosenJob); // INFINITE chaos.
|
||||
foreach (var job in jobList)
|
||||
{
|
||||
if (_stationJobs.IsJobUnlimited(chosenStation, job))
|
||||
if (_stationJobs.IsJobUnlimited(chosenStation.Value, job))
|
||||
continue;
|
||||
_stationJobs.TrySetJobSlot(chosenStation, job, 0);
|
||||
_stationJobs.TrySetJobSlot(chosenStation.Value, job, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -45,10 +49,10 @@ public sealed class BureaucraticErrorRule : StationEventSystem<BureaucraticError
|
||||
for (var i = 0; i < num; i++)
|
||||
{
|
||||
var chosenJob = RobustRandom.PickAndTake(jobList);
|
||||
if (_stationJobs.IsJobUnlimited(chosenStation, chosenJob))
|
||||
if (_stationJobs.IsJobUnlimited(chosenStation.Value, chosenJob))
|
||||
continue;
|
||||
|
||||
_stationJobs.TryAdjustJobSlot(chosenStation, chosenJob, RobustRandom.Next(-3, 6), clamp: true);
|
||||
_stationJobs.TryAdjustJobSlot(chosenStation.Value, chosenJob, RobustRandom.Next(-3, 6), clamp: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,8 +22,9 @@ namespace Content.Server.StationEvents.Events
|
||||
var mod = MathF.Sqrt(GetSeverityModifier());
|
||||
|
||||
// Essentially we'll pick out a target amount of gas to leak, then a rate to leak it at, then work out the duration from there.
|
||||
if (TryFindRandomTile(out component.TargetTile, out component.TargetStation, out component.TargetGrid, out component.TargetCoords))
|
||||
if (TryFindRandomTile(out component.TargetTile, out var target, out component.TargetGrid, out component.TargetCoords))
|
||||
{
|
||||
component.TargetStation = target.Value;
|
||||
component.FoundTile = true;
|
||||
|
||||
component.LeakGas = RobustRandom.Pick(component.LeakableGases);
|
||||
|
||||
@@ -23,9 +23,8 @@ namespace Content.Server.StationEvents.Events
|
||||
{
|
||||
base.Started(uid, component, gameRule, args);
|
||||
|
||||
if (StationSystem.Stations.Count == 0)
|
||||
if (!TryGetRandomStation(out var chosenStation))
|
||||
return;
|
||||
var chosenStation = RobustRandom.Pick(StationSystem.Stations.ToList());
|
||||
|
||||
foreach (var (apc, transform) in EntityQuery<ApcComponent, TransformComponent>(true))
|
||||
{
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using Content.Server.Administration.Logs;
|
||||
using Content.Server.Atmos.EntitySystems;
|
||||
using Content.Server.Chat.Systems;
|
||||
@@ -131,19 +133,37 @@ public abstract class StationEventSystem<T> : GameRuleSystem<T> where T : Compon
|
||||
GameTicker.EndGameRule(uid, component);
|
||||
}
|
||||
|
||||
protected bool TryFindRandomTile(out Vector2i tile, out EntityUid targetStation, out EntityUid targetGrid, out EntityCoordinates targetCoords)
|
||||
protected bool TryGetRandomStation([NotNullWhen(true)] out EntityUid? station, Func<EntityUid, bool>? filter = null)
|
||||
{
|
||||
filter ??= _ => true;
|
||||
|
||||
// augh. sorry sloth there's no better API and my goal today isn't adding 50 entitymanager methods :waa:
|
||||
var stations = EntityManager.GetAllComponents(typeof(StationEventEligibleComponent)).Select(x => x.Owner).Where(filter).ToArray();
|
||||
|
||||
if (stations.Length == 0)
|
||||
{
|
||||
station = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
station = RobustRandom.Pick(stations);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected bool TryFindRandomTile(out Vector2i tile, [NotNullWhen(true)] out EntityUid? targetStation, out EntityUid targetGrid, out EntityCoordinates targetCoords)
|
||||
{
|
||||
tile = default;
|
||||
|
||||
targetCoords = EntityCoordinates.Invalid;
|
||||
if (StationSystem.Stations.Count == 0)
|
||||
if (!TryGetRandomStation(out targetStation))
|
||||
{
|
||||
targetStation = EntityUid.Invalid;
|
||||
targetGrid = EntityUid.Invalid;
|
||||
return false;
|
||||
}
|
||||
targetStation = RobustRandom.Pick(StationSystem.Stations);
|
||||
var possibleTargets = Comp<StationDataComponent>(targetStation).Grids;
|
||||
var possibleTargets = Comp<StationDataComponent>(targetStation.Value).Grids;
|
||||
if (possibleTargets.Count == 0)
|
||||
{
|
||||
targetGrid = EntityUid.Invalid;
|
||||
|
||||
@@ -22,9 +22,8 @@ public sealed class VentClogRule : StationEventSystem<VentClogRuleComponent>
|
||||
{
|
||||
base.Started(uid, component, gameRule, args);
|
||||
|
||||
if (StationSystem.Stations.Count == 0)
|
||||
if (!TryGetRandomStation(out var chosenStation))
|
||||
return;
|
||||
var chosenStation = RobustRandom.Pick(StationSystem.Stations.ToList());
|
||||
|
||||
// TODO: "safe random" for chems. Right now this includes admin chemicals.
|
||||
var allReagents = PrototypeManager.EnumeratePrototypes<ReagentPrototype>()
|
||||
|
||||
@@ -44,17 +44,14 @@ public sealed class StationRecordsSystem : EntitySystem
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<StationInitializedEvent>(OnStationInitialize);
|
||||
SubscribeLocalEvent<PlayerSpawnCompleteEvent>(OnPlayerSpawn);
|
||||
}
|
||||
|
||||
private void OnStationInitialize(StationInitializedEvent args)
|
||||
{
|
||||
AddComp<StationRecordsComponent>(args.Station);
|
||||
}
|
||||
|
||||
private void OnPlayerSpawn(PlayerSpawnCompleteEvent args)
|
||||
{
|
||||
if (!HasComp<StationRecordsComponent>(args.Station))
|
||||
return;
|
||||
|
||||
CreateGeneralRecord(args.Station, args.Mob, args.Profile, args.JobId);
|
||||
}
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ public sealed class BiomePrototype : IPrototype, IInheritingPrototype
|
||||
/// </summary>
|
||||
[DataField("chunkComponents")]
|
||||
[AlwaysPushInheritance]
|
||||
public EntityPrototype.ComponentRegistry ChunkComponents { get; } = new();
|
||||
public ComponentRegistry ChunkComponents { get; } = new();
|
||||
|
||||
//TODO: Get someone to make this a method on componentregistry that does it Correctly.
|
||||
/// <summary>
|
||||
|
||||
@@ -18,7 +18,7 @@ public sealed class WorldgenConfigPrototype : IPrototype
|
||||
/// The components that get added to the target map.
|
||||
/// </summary>
|
||||
[DataField("components", required: true)]
|
||||
public EntityPrototype.ComponentRegistry Components { get; } = default!;
|
||||
public ComponentRegistry Components { get; } = default!;
|
||||
|
||||
//TODO: Get someone to make this a method on componentregistry that does it Correctly.
|
||||
/// <summary>
|
||||
|
||||
@@ -33,5 +33,5 @@ public sealed class RandomHumanoidSettingsPrototype : IPrototype, IInheritingPro
|
||||
/// Extra components to add to this entity.
|
||||
/// </summary>
|
||||
[DataField("components")]
|
||||
public EntityPrototype.ComponentRegistry? Components { get; }
|
||||
public ComponentRegistry? Components { get; }
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ public sealed class PayloadTriggerComponent : Component
|
||||
/// List of components to add or remove from an entity when this trigger is (un)installed.
|
||||
/// </summary>
|
||||
[DataField("components", serverOnly:true, readOnly: true)]
|
||||
public readonly EntityPrototype.ComponentRegistry? Components = null;
|
||||
public readonly ComponentRegistry? Components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Keeps track of what components this trigger has granted to the payload case.
|
||||
|
||||
@@ -21,13 +21,13 @@ public sealed class ArtifactEffectPrototype : IPrototype
|
||||
/// These are removed after the node is exited and the effect is changed.
|
||||
/// </summary>
|
||||
[DataField("components", serverOnly: true)]
|
||||
public EntityPrototype.ComponentRegistry Components = new();
|
||||
public ComponentRegistry Components = new();
|
||||
|
||||
/// <summary>
|
||||
/// Components that are permanently added to an entity when the effect's node is entered.
|
||||
/// </summary>
|
||||
[DataField("permanentComponents")]
|
||||
public EntityPrototype.ComponentRegistry PermanentComponents = new();
|
||||
public ComponentRegistry PermanentComponents = new();
|
||||
|
||||
//TODO: make this a list so we can have multiple target depths
|
||||
[DataField("targetDepth")]
|
||||
|
||||
@@ -17,7 +17,7 @@ public sealed class ArtifactTriggerPrototype : IPrototype
|
||||
public string ID { get; } = default!;
|
||||
|
||||
[DataField("components", serverOnly: true)]
|
||||
public EntityPrototype.ComponentRegistry Components = new();
|
||||
public ComponentRegistry Components = new();
|
||||
|
||||
[DataField("targetDepth")]
|
||||
public int TargetDepth = 0;
|
||||
|
||||
57
Resources/Prototypes/Entities/Stations/base.yml
Normal file
57
Resources/Prototypes/Entities/Stations/base.yml
Normal file
@@ -0,0 +1,57 @@
|
||||
- type: entity
|
||||
id: BaseStation
|
||||
abstract: true
|
||||
components:
|
||||
- type: StationData
|
||||
|
||||
- type: entity
|
||||
id: BaseStationCargo
|
||||
abstract: true
|
||||
components:
|
||||
- type: StationBankAccount
|
||||
- type: StationCargoOrderDatabase
|
||||
|
||||
- type: entity
|
||||
id: BaseStationJobsSpawning
|
||||
abstract: true
|
||||
components:
|
||||
- type: StationJobs
|
||||
availableJobs: {}
|
||||
- type: StationSpawning
|
||||
|
||||
- type: entity
|
||||
id: BaseStationRecords
|
||||
abstract: true
|
||||
components:
|
||||
- type: StationRecords
|
||||
|
||||
- type: entity
|
||||
id: BaseStationArrivals
|
||||
abstract: true
|
||||
components:
|
||||
- type: StationArrivals
|
||||
|
||||
- type: entity
|
||||
id: BaseStationEvacuation
|
||||
abstract: true
|
||||
components:
|
||||
- type: StationEmergencyShuttle
|
||||
|
||||
- type: entity
|
||||
id: BaseStationAlertLevels
|
||||
abstract: true
|
||||
components:
|
||||
- type: AlertLevel
|
||||
alertLevelPrototype: stationAlerts
|
||||
|
||||
- type: entity
|
||||
id: BaseStationExpeditions
|
||||
abstract: true
|
||||
components:
|
||||
- type: SalvageExpeditionData
|
||||
|
||||
- type: entity
|
||||
id: BaseStationAllEventsEligible
|
||||
abstract: true
|
||||
components:
|
||||
- type: StationEventEligible # For when someone makes this more granular in the future.
|
||||
33
Resources/Prototypes/Entities/Stations/nanotrasen.yml
Normal file
33
Resources/Prototypes/Entities/Stations/nanotrasen.yml
Normal file
@@ -0,0 +1,33 @@
|
||||
- type: entity
|
||||
id: BaseStationNanotrasen
|
||||
components:
|
||||
- type: Faction
|
||||
factions:
|
||||
- NanoTrasen
|
||||
|
||||
- type: entity
|
||||
id: StandardNanotrasenStation
|
||||
parent:
|
||||
- BaseStation
|
||||
- BaseStationCargo
|
||||
- BaseStationJobsSpawning
|
||||
- BaseStationRecords
|
||||
- BaseStationArrivals
|
||||
- BaseStationEvacuation
|
||||
- BaseStationAlertLevels
|
||||
- BaseStationExpeditions
|
||||
- BaseStationAllEventsEligible
|
||||
- BaseStationNanotrasen
|
||||
noSpawn: true
|
||||
components:
|
||||
- type: Transform
|
||||
|
||||
- type: entity
|
||||
id: NanotrasenCentralCommand
|
||||
parent:
|
||||
- BaseStation
|
||||
- BaseStationAlertLevels
|
||||
- BaseStationNanotrasen
|
||||
noSpawn: true
|
||||
components:
|
||||
- type: Transform
|
||||
@@ -36,6 +36,7 @@
|
||||
noSpawn: true
|
||||
components:
|
||||
- type: NukeopsRule
|
||||
faction: Syndicate
|
||||
|
||||
- type: entity
|
||||
id: Pirates
|
||||
|
||||
@@ -6,45 +6,50 @@
|
||||
maxPlayers: 70
|
||||
stations:
|
||||
Aspid:
|
||||
mapNameTemplate: '{0} NCS Aspid {1}'
|
||||
emergencyShuttlePath: /Maps/Shuttles/emergency_courser.yml
|
||||
nameGenerator:
|
||||
!type:NanotrasenNameGenerator
|
||||
prefixCreator: '14'
|
||||
overflowJobs:
|
||||
- Passenger
|
||||
availableJobs:
|
||||
CargoTechnician: [ 2, 3 ]
|
||||
Passenger: [ -1, -1 ]
|
||||
Bartender: [ 1, 2 ]
|
||||
Botanist: [ 2, 3 ]
|
||||
Chef: [ 1, 3 ]
|
||||
Clown: [ 1, 1 ]
|
||||
Janitor: [ 2, 3 ]
|
||||
Mime: [ 1, 1 ]
|
||||
Captain: [ 1, 1 ]
|
||||
HeadOfPersonnel: [ 1, 1 ]
|
||||
ChiefEngineer: [ 1, 1 ]
|
||||
StationEngineer: [ 2, 3 ]
|
||||
ChiefMedicalOfficer: [ 1, 1 ]
|
||||
MedicalDoctor: [ 3, 3 ]
|
||||
Chemist: [ 1, 2 ]
|
||||
ResearchDirector: [ 1, 1 ]
|
||||
ResearchAssistant: [ 2, 2 ]
|
||||
Scientist: [ 3, 4 ]
|
||||
HeadOfSecurity: [ 1, 1 ]
|
||||
SecurityOfficer: [ 3, 4 ]
|
||||
Chaplain: [ 1, 1 ]
|
||||
Warden: [ 1, 1 ]
|
||||
Librarian: [ 1, 1 ]
|
||||
Lawyer: [ 2, 2 ]
|
||||
Quartermaster: [ 1, 1 ]
|
||||
SalvageSpecialist: [ 3, 4 ]
|
||||
Musician: [ 1, 1 ]
|
||||
AtmosphericTechnician: [ 2, 2 ]
|
||||
TechnicalAssistant: [ 2, 2 ]
|
||||
MedicalIntern: [ 2, 2 ]
|
||||
ServiceWorker: [ 1, 1 ]
|
||||
SecurityCadet: [ 2, 2 ]
|
||||
Detective: [ 1, 1 ]
|
||||
Paramedic: [1, 1]
|
||||
stationProto: StandardNanotrasenStation
|
||||
components:
|
||||
- type: StationNameSetup
|
||||
mapNameTemplate: '{0} NCS Aspid {1}'
|
||||
nameGenerator:
|
||||
!type:NanotrasenNameGenerator
|
||||
prefixCreator: '14'
|
||||
- type: StationEmergencyShuttle
|
||||
emergencyShuttlePath: /Maps/Shuttles/emergency_courser.yml
|
||||
- type: StationJobs
|
||||
overflowJobs:
|
||||
- Passenger
|
||||
availableJobs:
|
||||
CargoTechnician: [ 2, 3 ]
|
||||
Passenger: [ -1, -1 ]
|
||||
Bartender: [ 1, 2 ]
|
||||
Botanist: [ 2, 3 ]
|
||||
Chef: [ 1, 3 ]
|
||||
Clown: [ 1, 1 ]
|
||||
Janitor: [ 2, 3 ]
|
||||
Mime: [ 1, 1 ]
|
||||
Captain: [ 1, 1 ]
|
||||
HeadOfPersonnel: [ 1, 1 ]
|
||||
ChiefEngineer: [ 1, 1 ]
|
||||
StationEngineer: [ 2, 3 ]
|
||||
ChiefMedicalOfficer: [ 1, 1 ]
|
||||
MedicalDoctor: [ 3, 3 ]
|
||||
Chemist: [ 1, 2 ]
|
||||
ResearchDirector: [ 1, 1 ]
|
||||
ResearchAssistant: [ 2, 2 ]
|
||||
Scientist: [ 3, 4 ]
|
||||
HeadOfSecurity: [ 1, 1 ]
|
||||
SecurityOfficer: [ 3, 4 ]
|
||||
Chaplain: [ 1, 1 ]
|
||||
Warden: [ 1, 1 ]
|
||||
Librarian: [ 1, 1 ]
|
||||
Lawyer: [ 2, 2 ]
|
||||
Quartermaster: [ 1, 1 ]
|
||||
SalvageSpecialist: [ 3, 4 ]
|
||||
Musician: [ 1, 1 ]
|
||||
AtmosphericTechnician: [ 2, 2 ]
|
||||
TechnicalAssistant: [ 2, 2 ]
|
||||
MedicalIntern: [ 2, 2 ]
|
||||
ServiceWorker: [ 1, 1 ]
|
||||
SecurityCadet: [ 2, 2 ]
|
||||
Detective: [ 1, 1 ]
|
||||
Paramedic: [1, 1]
|
||||
|
||||
@@ -6,46 +6,51 @@
|
||||
maxPlayers: 75
|
||||
stations:
|
||||
Bagel:
|
||||
mapNameTemplate: '{0} Bagel Station {1}'
|
||||
emergencyShuttlePath: /Maps/Shuttles/emergency_lox.yml
|
||||
nameGenerator:
|
||||
!type:NanotrasenNameGenerator
|
||||
prefixCreator: '14'
|
||||
overflowJobs:
|
||||
- Passenger
|
||||
availableJobs:
|
||||
CargoTechnician: [ 3, 3 ]
|
||||
Passenger: [ -1, -1 ]
|
||||
Bartender: [ 2, 2 ]
|
||||
Botanist: [ 3, 3 ]
|
||||
Chef: [ 2, 2 ]
|
||||
Clown: [ 1, 1 ]
|
||||
Janitor: [ 3, 3 ]
|
||||
Mime: [ 1, 1 ]
|
||||
Captain: [ 1, 1 ]
|
||||
HeadOfPersonnel: [ 1, 1 ]
|
||||
ChiefEngineer: [ 1, 1 ]
|
||||
StationEngineer: [ 4, 4 ]
|
||||
ChiefMedicalOfficer: [ 1, 1 ]
|
||||
MedicalDoctor: [ 3, 3 ]
|
||||
Chemist: [ 2, 3 ]
|
||||
ResearchDirector: [ 1, 1 ]
|
||||
Scientist: [ 4, 4 ]
|
||||
HeadOfSecurity: [ 1, 1 ]
|
||||
SecurityOfficer: [ 4, 4 ]
|
||||
Chaplain: [ 1, 1 ]
|
||||
Warden: [ 1, 1 ]
|
||||
Librarian: [ 1, 1 ]
|
||||
Lawyer: [ 2, 2 ]
|
||||
Quartermaster: [ 1, 1 ]
|
||||
SalvageSpecialist: [ 3, 3 ]
|
||||
Musician: [ 1, 1 ]
|
||||
AtmosphericTechnician: [ 3, 3 ]
|
||||
TechnicalAssistant: [ 2, 2 ]
|
||||
MedicalIntern: [ 2, 2 ]
|
||||
ServiceWorker: [ 2, 2 ]
|
||||
SecurityCadet: [ 2, 2 ]
|
||||
Reporter: [ 2, 2 ]
|
||||
Detective: [ 1, 1 ]
|
||||
ResearchAssistant: [ 2, 2 ]
|
||||
Paramedic: [ 1, 1 ]
|
||||
stationProto: StandardNanotrasenStation
|
||||
components:
|
||||
- type: StationNameSetup
|
||||
mapNameTemplate: '{0} Bagel Station {1}'
|
||||
nameGenerator:
|
||||
!type:NanotrasenNameGenerator
|
||||
prefixCreator: '14'
|
||||
- type: StationEmergencyShuttle
|
||||
emergencyShuttlePath: /Maps/Shuttles/emergency_lox.yml
|
||||
- type: StationJobs
|
||||
overflowJobs:
|
||||
- Passenger
|
||||
availableJobs:
|
||||
CargoTechnician: [ 3, 3 ]
|
||||
Passenger: [ -1, -1 ]
|
||||
Bartender: [ 2, 2 ]
|
||||
Botanist: [ 3, 3 ]
|
||||
Chef: [ 2, 2 ]
|
||||
Clown: [ 1, 1 ]
|
||||
Janitor: [ 3, 3 ]
|
||||
Mime: [ 1, 1 ]
|
||||
Captain: [ 1, 1 ]
|
||||
HeadOfPersonnel: [ 1, 1 ]
|
||||
ChiefEngineer: [ 1, 1 ]
|
||||
StationEngineer: [ 4, 4 ]
|
||||
ChiefMedicalOfficer: [ 1, 1 ]
|
||||
MedicalDoctor: [ 3, 3 ]
|
||||
Chemist: [ 2, 3 ]
|
||||
ResearchDirector: [ 1, 1 ]
|
||||
Scientist: [ 4, 4 ]
|
||||
HeadOfSecurity: [ 1, 1 ]
|
||||
SecurityOfficer: [ 4, 4 ]
|
||||
Chaplain: [ 1, 1 ]
|
||||
Warden: [ 1, 1 ]
|
||||
Librarian: [ 1, 1 ]
|
||||
Lawyer: [ 2, 2 ]
|
||||
Quartermaster: [ 1, 1 ]
|
||||
SalvageSpecialist: [ 3, 3 ]
|
||||
Musician: [ 1, 1 ]
|
||||
AtmosphericTechnician: [ 3, 3 ]
|
||||
TechnicalAssistant: [ 2, 2 ]
|
||||
MedicalIntern: [ 2, 2 ]
|
||||
ServiceWorker: [ 2, 2 ]
|
||||
SecurityCadet: [ 2, 2 ]
|
||||
Reporter: [ 2, 2 ]
|
||||
Detective: [ 1, 1 ]
|
||||
ResearchAssistant: [ 2, 2 ]
|
||||
Paramedic: [ 1, 1 ]
|
||||
|
||||
@@ -6,44 +6,49 @@
|
||||
maxPlayers: 70
|
||||
stations:
|
||||
Barratry:
|
||||
mapNameTemplate: '{0} Barratry {1}'
|
||||
emergencyShuttlePath: /Maps/Shuttles/emergency_raven.yml
|
||||
nameGenerator:
|
||||
!type:NanotrasenNameGenerator
|
||||
prefixCreator: '14'
|
||||
overflowJobs:
|
||||
- Passenger
|
||||
availableJobs:
|
||||
CargoTechnician: [ 3, 3 ]
|
||||
Passenger: [ -1, -1 ]
|
||||
Bartender: [ 2, 2 ]
|
||||
Botanist: [ 3, 4]
|
||||
Chef: [ 2, 2 ]
|
||||
Clown: [ 1, 1 ]
|
||||
Janitor: [ 2, 3 ]
|
||||
Mime: [ 1, 1 ]
|
||||
Captain: [ 1, 1 ]
|
||||
HeadOfPersonnel: [ 1, 1 ]
|
||||
ChiefEngineer: [ 1, 1 ]
|
||||
StationEngineer: [ 4, 5 ]
|
||||
ChiefMedicalOfficer: [ 1, 1 ]
|
||||
MedicalDoctor: [ 4, 4 ]
|
||||
Chemist: [ 2, 3 ]
|
||||
ResearchDirector: [ 1, 1 ]
|
||||
Scientist: [ 4, 4 ]
|
||||
HeadOfSecurity: [ 1, 1 ]
|
||||
SecurityOfficer: [ 5, 5 ]
|
||||
Chaplain: [ 1, 1 ]
|
||||
Warden: [ 1, 1 ]
|
||||
Librarian: [ 1, 1 ]
|
||||
Lawyer: [ 2, 2 ]
|
||||
Quartermaster: [ 1, 1 ]
|
||||
SalvageSpecialist: [ 3, 3 ]
|
||||
Musician: [ 1, 1 ]
|
||||
AtmosphericTechnician: [ 2, 3 ]
|
||||
TechnicalAssistant: [ 1, 2 ]
|
||||
MedicalIntern: [ 1, 2 ]
|
||||
ServiceWorker: [ 1, 2 ]
|
||||
SecurityCadet: [ 1, 2 ]
|
||||
Detective: [ 1, 1 ]
|
||||
ResearchAssistant: [1, 2]
|
||||
stationProto: StandardNanotrasenStation
|
||||
components:
|
||||
- type: StationNameSetup
|
||||
mapNameTemplate: '{0} Barratry {1}'
|
||||
nameGenerator:
|
||||
!type:NanotrasenNameGenerator
|
||||
prefixCreator: '14'
|
||||
- type: StationEmergencyShuttle
|
||||
emergencyShuttlePath: /Maps/Shuttles/emergency_raven.yml
|
||||
- type: StationJobs
|
||||
overflowJobs:
|
||||
- Passenger
|
||||
availableJobs:
|
||||
CargoTechnician: [ 3, 3 ]
|
||||
Passenger: [ -1, -1 ]
|
||||
Bartender: [ 2, 2 ]
|
||||
Botanist: [ 3, 4]
|
||||
Chef: [ 2, 2 ]
|
||||
Clown: [ 1, 1 ]
|
||||
Janitor: [ 2, 3 ]
|
||||
Mime: [ 1, 1 ]
|
||||
Captain: [ 1, 1 ]
|
||||
HeadOfPersonnel: [ 1, 1 ]
|
||||
ChiefEngineer: [ 1, 1 ]
|
||||
StationEngineer: [ 4, 5 ]
|
||||
ChiefMedicalOfficer: [ 1, 1 ]
|
||||
MedicalDoctor: [ 4, 4 ]
|
||||
Chemist: [ 2, 3 ]
|
||||
ResearchDirector: [ 1, 1 ]
|
||||
Scientist: [ 4, 4 ]
|
||||
HeadOfSecurity: [ 1, 1 ]
|
||||
SecurityOfficer: [ 5, 5 ]
|
||||
Chaplain: [ 1, 1 ]
|
||||
Warden: [ 1, 1 ]
|
||||
Librarian: [ 1, 1 ]
|
||||
Lawyer: [ 2, 2 ]
|
||||
Quartermaster: [ 1, 1 ]
|
||||
SalvageSpecialist: [ 3, 3 ]
|
||||
Musician: [ 1, 1 ]
|
||||
AtmosphericTechnician: [ 2, 3 ]
|
||||
TechnicalAssistant: [ 1, 2 ]
|
||||
MedicalIntern: [ 1, 2 ]
|
||||
ServiceWorker: [ 1, 2 ]
|
||||
SecurityCadet: [ 1, 2 ]
|
||||
Detective: [ 1, 1 ]
|
||||
ResearchAssistant: [1, 2]
|
||||
|
||||
@@ -5,45 +5,50 @@
|
||||
minPlayers: 50
|
||||
stations:
|
||||
Boxstation:
|
||||
mapNameTemplate: '{0} Box Station {1}'
|
||||
emergencyShuttlePath: /Maps/Shuttles/emergency_box.yml
|
||||
nameGenerator:
|
||||
!type:NanotrasenNameGenerator
|
||||
prefixCreator: 'TG'
|
||||
overflowJobs:
|
||||
- Passenger
|
||||
availableJobs:
|
||||
CargoTechnician: [ 3, 3 ]
|
||||
Passenger: [ -1, -1 ]
|
||||
Bartender: [ 2, 2 ]
|
||||
Botanist: [ 3, 3 ]
|
||||
Chef: [ 2, 2 ]
|
||||
Clown: [ 1, 1 ]
|
||||
Janitor: [ 3, 3 ]
|
||||
Mime: [ 1, 1 ]
|
||||
Captain: [ 1, 1 ]
|
||||
HeadOfPersonnel: [ 1, 1 ]
|
||||
ChiefEngineer: [ 1, 1 ]
|
||||
StationEngineer: [ 4, 4 ]
|
||||
ChiefMedicalOfficer: [ 1, 1 ]
|
||||
MedicalDoctor: [ 4, 4 ]
|
||||
Chemist: [ 3, 3 ]
|
||||
ResearchDirector: [ 1, 1 ]
|
||||
Scientist: [ 5, 5 ]
|
||||
HeadOfSecurity: [ 1, 1 ]
|
||||
SecurityOfficer: [ 6, 6 ]
|
||||
Chaplain: [ 2, 2 ]
|
||||
Warden: [ 1, 1 ]
|
||||
Librarian: [ 2, 2 ]
|
||||
Lawyer: [ 2, 2 ]
|
||||
Quartermaster: [ 1, 1 ]
|
||||
SalvageSpecialist: [ 3, 3 ]
|
||||
Musician: [ 2, 2 ]
|
||||
AtmosphericTechnician: [ 3, 3 ]
|
||||
TechnicalAssistant: [ 4, 4 ]
|
||||
MedicalIntern: [ 4, 4 ]
|
||||
ServiceWorker: [ 4, 4 ]
|
||||
SecurityCadet: [ 4, 4 ]
|
||||
Detective: [ 1, 1 ]
|
||||
ResearchAssistant: [ 4, 4 ]
|
||||
Paramedic: [ 1, 1 ]
|
||||
stationProto: StandardNanotrasenStation
|
||||
components:
|
||||
- type: StationNameSetup
|
||||
mapNameTemplate: '{0} Box Station {1}'
|
||||
nameGenerator:
|
||||
!type:NanotrasenNameGenerator
|
||||
prefixCreator: 'TG'
|
||||
- type: StationEmergencyShuttle
|
||||
emergencyShuttlePath: /Maps/Shuttles/emergency_box.yml
|
||||
- type: StationJobs
|
||||
overflowJobs:
|
||||
- Passenger
|
||||
availableJobs:
|
||||
CargoTechnician: [ 3, 3 ]
|
||||
Passenger: [ -1, -1 ]
|
||||
Bartender: [ 2, 2 ]
|
||||
Botanist: [ 3, 3 ]
|
||||
Chef: [ 2, 2 ]
|
||||
Clown: [ 1, 1 ]
|
||||
Janitor: [ 3, 3 ]
|
||||
Mime: [ 1, 1 ]
|
||||
Captain: [ 1, 1 ]
|
||||
HeadOfPersonnel: [ 1, 1 ]
|
||||
ChiefEngineer: [ 1, 1 ]
|
||||
StationEngineer: [ 4, 4 ]
|
||||
ChiefMedicalOfficer: [ 1, 1 ]
|
||||
MedicalDoctor: [ 4, 4 ]
|
||||
Chemist: [ 3, 3 ]
|
||||
ResearchDirector: [ 1, 1 ]
|
||||
Scientist: [ 5, 5 ]
|
||||
HeadOfSecurity: [ 1, 1 ]
|
||||
SecurityOfficer: [ 6, 6 ]
|
||||
Chaplain: [ 2, 2 ]
|
||||
Warden: [ 1, 1 ]
|
||||
Librarian: [ 2, 2 ]
|
||||
Lawyer: [ 2, 2 ]
|
||||
Quartermaster: [ 1, 1 ]
|
||||
SalvageSpecialist: [ 3, 3 ]
|
||||
Musician: [ 2, 2 ]
|
||||
AtmosphericTechnician: [ 3, 3 ]
|
||||
TechnicalAssistant: [ 4, 4 ]
|
||||
MedicalIntern: [ 4, 4 ]
|
||||
ServiceWorker: [ 4, 4 ]
|
||||
SecurityCadet: [ 4, 4 ]
|
||||
Detective: [ 1, 1 ]
|
||||
ResearchAssistant: [ 4, 4 ]
|
||||
Paramedic: [ 1, 1 ]
|
||||
|
||||
@@ -5,11 +5,10 @@
|
||||
minPlayers: 10
|
||||
stations:
|
||||
centcomm:
|
||||
mapNameTemplate: '{0} Central Command {1}'
|
||||
nameGenerator:
|
||||
!type:NanotrasenNameGenerator
|
||||
prefixCreator: 'TG'
|
||||
overflowJobs:
|
||||
- Passenger
|
||||
availableJobs:
|
||||
Passenger: [ 0, 1 ]
|
||||
stationProto: NanotrasenCentralCommand
|
||||
components:
|
||||
- type: StationNameSetup
|
||||
mapNameTemplate: '{0} Central Command {1}'
|
||||
nameGenerator:
|
||||
!type:NanotrasenNameGenerator
|
||||
prefixCreator: 'TG'
|
||||
|
||||
@@ -6,43 +6,47 @@
|
||||
maxPlayers: 35
|
||||
stations:
|
||||
Cluster:
|
||||
mapNameTemplate: '{0} Cluster Station {1}'
|
||||
nameGenerator:
|
||||
!type:NanotrasenNameGenerator
|
||||
prefixCreator: '14'
|
||||
overflowJobs:
|
||||
- Passenger
|
||||
availableJobs:
|
||||
CargoTechnician: [ 1, 1 ]
|
||||
Passenger: [ -1, -1 ]
|
||||
Bartender: [ 1, 1 ]
|
||||
Botanist: [ 2, 2 ]
|
||||
Chef: [ 1, 1 ]
|
||||
Clown: [ 1, 1 ]
|
||||
Janitor: [ 1, 1 ]
|
||||
Mime: [ 1, 1 ]
|
||||
Captain: [ 1, 1 ]
|
||||
HeadOfPersonnel: [ 1, 1 ]
|
||||
ChiefEngineer: [ 1, 1 ]
|
||||
StationEngineer: [ 2, 2 ]
|
||||
ChiefMedicalOfficer: [ 1, 1 ]
|
||||
MedicalDoctor: [ 1, 1 ]
|
||||
Chemist: [ 1, 1 ]
|
||||
ResearchDirector: [ 1, 1 ]
|
||||
Scientist: [ 2, 2 ]
|
||||
ResearchAssistant: [ 1, 1 ]
|
||||
HeadOfSecurity: [ 1, 1 ]
|
||||
SecurityOfficer: [ 2, 2 ]
|
||||
Chaplain: [ 1, 1 ]
|
||||
Warden: [ 1, 1 ]
|
||||
Librarian: [ 1, 1 ]
|
||||
Lawyer: [ 1, 1 ]
|
||||
Musician: [ 1, 1 ]
|
||||
AtmosphericTechnician: [ 2, 2 ]
|
||||
Detective: [ 1, 1 ]
|
||||
TechnicalAssistant: [ 1, 1 ]
|
||||
MedicalIntern: [ 1, 1 ]
|
||||
ServiceWorker: [ 1, 1 ]
|
||||
SecurityCadet: [ 1, 1 ]
|
||||
SalvageSpecialist: [ 2, 2 ]
|
||||
Quartermaster: [ 1, 1 ]
|
||||
stationProto: StandardNanotrasenStation
|
||||
components:
|
||||
- type: StationNameSetup
|
||||
mapNameTemplate: '{0} Cluster Station {1}'
|
||||
nameGenerator:
|
||||
!type:NanotrasenNameGenerator
|
||||
prefixCreator: '14'
|
||||
- type: StationJobs
|
||||
overflowJobs:
|
||||
- Passenger
|
||||
availableJobs:
|
||||
CargoTechnician: [ 1, 1 ]
|
||||
Passenger: [ -1, -1 ]
|
||||
Bartender: [ 1, 1 ]
|
||||
Botanist: [ 2, 2 ]
|
||||
Chef: [ 1, 1 ]
|
||||
Clown: [ 1, 1 ]
|
||||
Janitor: [ 1, 1 ]
|
||||
Mime: [ 1, 1 ]
|
||||
Captain: [ 1, 1 ]
|
||||
HeadOfPersonnel: [ 1, 1 ]
|
||||
ChiefEngineer: [ 1, 1 ]
|
||||
StationEngineer: [ 2, 2 ]
|
||||
ChiefMedicalOfficer: [ 1, 1 ]
|
||||
MedicalDoctor: [ 1, 1 ]
|
||||
Chemist: [ 1, 1 ]
|
||||
ResearchDirector: [ 1, 1 ]
|
||||
Scientist: [ 2, 2 ]
|
||||
ResearchAssistant: [ 1, 1 ]
|
||||
HeadOfSecurity: [ 1, 1 ]
|
||||
SecurityOfficer: [ 2, 2 ]
|
||||
Chaplain: [ 1, 1 ]
|
||||
Warden: [ 1, 1 ]
|
||||
Librarian: [ 1, 1 ]
|
||||
Lawyer: [ 1, 1 ]
|
||||
Musician: [ 1, 1 ]
|
||||
AtmosphericTechnician: [ 2, 2 ]
|
||||
Detective: [ 1, 1 ]
|
||||
TechnicalAssistant: [ 1, 1 ]
|
||||
MedicalIntern: [ 1, 1 ]
|
||||
ServiceWorker: [ 1, 1 ]
|
||||
SecurityCadet: [ 1, 1 ]
|
||||
SalvageSpecialist: [ 2, 2 ]
|
||||
Quartermaster: [ 1, 1 ]
|
||||
|
||||
@@ -5,11 +5,15 @@
|
||||
minPlayers: 0
|
||||
stations:
|
||||
Empty:
|
||||
mapNameTemplate: "Empty"
|
||||
overflowJobs:
|
||||
- Passenger
|
||||
availableJobs:
|
||||
Passenger: [ -1, -1 ]
|
||||
stationProto: StandardNanotrasenStation
|
||||
components:
|
||||
- type: StationNameSetup
|
||||
mapNameTemplate: "Empty"
|
||||
- type: StationJobs
|
||||
overflowJobs:
|
||||
- Passenger
|
||||
availableJobs:
|
||||
Passenger: [ -1, -1 ]
|
||||
|
||||
- type: gameMap
|
||||
id: Dev
|
||||
@@ -18,8 +22,12 @@
|
||||
minPlayers: 0
|
||||
stations:
|
||||
Dev:
|
||||
mapNameTemplate: "Dev"
|
||||
overflowJobs:
|
||||
- Captain
|
||||
availableJobs:
|
||||
Captain: [ -1, -1 ]
|
||||
stationProto: StandardNanotrasenStation
|
||||
components:
|
||||
- type: StationNameSetup
|
||||
mapNameTemplate: "Dev"
|
||||
- type: StationJobs
|
||||
overflowJobs:
|
||||
- Captain
|
||||
availableJobs:
|
||||
Captain: [ -1, -1 ]
|
||||
|
||||
@@ -5,45 +5,50 @@
|
||||
minPlayers: 70
|
||||
stations:
|
||||
Fland:
|
||||
mapNameTemplate: '{0} Fland Installation {1}'
|
||||
emergencyShuttlePath: /Maps/Shuttles/emergency_courser.yml
|
||||
nameGenerator:
|
||||
!type:NanotrasenNameGenerator
|
||||
prefixCreator: 'B'
|
||||
overflowJobs:
|
||||
- Passenger
|
||||
availableJobs:
|
||||
CargoTechnician: [ 4, 4 ]
|
||||
Passenger: [ -1, -1 ]
|
||||
Bartender: [ 2, 2 ]
|
||||
Botanist: [ 4, 4 ]
|
||||
Chef: [ 2, 2 ]
|
||||
Clown: [ 1, 1 ]
|
||||
Janitor: [ 3, 3 ]
|
||||
Mime: [ 1, 1 ]
|
||||
Captain: [ 1, 1 ]
|
||||
HeadOfPersonnel: [ 1, 1 ]
|
||||
ChiefEngineer: [ 1, 1 ]
|
||||
StationEngineer: [ 6, 6 ]
|
||||
ChiefMedicalOfficer: [ 1, 1 ]
|
||||
MedicalDoctor: [ 6, 6 ]
|
||||
Chemist: [ 3, 3 ]
|
||||
ResearchDirector: [ 1, 1 ]
|
||||
Scientist: [ 4, 4 ]
|
||||
HeadOfSecurity: [ 1, 1 ]
|
||||
SecurityOfficer: [ 7, 7 ]
|
||||
Chaplain: [ 1, 1 ]
|
||||
Warden: [ 1, 1 ]
|
||||
Librarian: [ 1, 1 ]
|
||||
Lawyer: [ 2, 2 ]
|
||||
Quartermaster: [ 1, 1 ]
|
||||
SalvageSpecialist: [ 3, 3 ]
|
||||
Musician: [ 1, 1 ]
|
||||
AtmosphericTechnician: [ 3, 3 ]
|
||||
TechnicalAssistant: [ 2, 2 ]
|
||||
MedicalIntern: [ 2, 2 ]
|
||||
ServiceWorker: [ 2, 2 ]
|
||||
SecurityCadet: [ 2, 2 ]
|
||||
Detective: [ 1, 1 ]
|
||||
ResearchAssistant: [ 3, 3 ]
|
||||
Paramedic: [ 2, 2 ]
|
||||
stationProto: StandardNanotrasenStation
|
||||
components:
|
||||
- type: StationNameSetup
|
||||
mapNameTemplate: '{0} Fland Installation {1}'
|
||||
nameGenerator:
|
||||
!type:NanotrasenNameGenerator
|
||||
prefixCreator: 'B'
|
||||
- type: StationEmergencyShuttle
|
||||
emergencyShuttlePath: /Maps/Shuttles/emergency_courser.yml
|
||||
- type: StationJobs
|
||||
overflowJobs:
|
||||
- Passenger
|
||||
availableJobs:
|
||||
CargoTechnician: [ 4, 4 ]
|
||||
Passenger: [ -1, -1 ]
|
||||
Bartender: [ 2, 2 ]
|
||||
Botanist: [ 4, 4 ]
|
||||
Chef: [ 2, 2 ]
|
||||
Clown: [ 1, 1 ]
|
||||
Janitor: [ 3, 3 ]
|
||||
Mime: [ 1, 1 ]
|
||||
Captain: [ 1, 1 ]
|
||||
HeadOfPersonnel: [ 1, 1 ]
|
||||
ChiefEngineer: [ 1, 1 ]
|
||||
StationEngineer: [ 6, 6 ]
|
||||
ChiefMedicalOfficer: [ 1, 1 ]
|
||||
MedicalDoctor: [ 6, 6 ]
|
||||
Chemist: [ 3, 3 ]
|
||||
ResearchDirector: [ 1, 1 ]
|
||||
Scientist: [ 4, 4 ]
|
||||
HeadOfSecurity: [ 1, 1 ]
|
||||
SecurityOfficer: [ 7, 7 ]
|
||||
Chaplain: [ 1, 1 ]
|
||||
Warden: [ 1, 1 ]
|
||||
Librarian: [ 1, 1 ]
|
||||
Lawyer: [ 2, 2 ]
|
||||
Quartermaster: [ 1, 1 ]
|
||||
SalvageSpecialist: [ 3, 3 ]
|
||||
Musician: [ 1, 1 ]
|
||||
AtmosphericTechnician: [ 3, 3 ]
|
||||
TechnicalAssistant: [ 2, 2 ]
|
||||
MedicalIntern: [ 2, 2 ]
|
||||
ServiceWorker: [ 2, 2 ]
|
||||
SecurityCadet: [ 2, 2 ]
|
||||
Detective: [ 1, 1 ]
|
||||
ResearchAssistant: [ 3, 3 ]
|
||||
Paramedic: [ 2, 2 ]
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
- type: gameMap
|
||||
id: Infiltrator
|
||||
mapName: 'Syndicate Infiltrator'
|
||||
mapPath: /Maps/infiltrator.yml
|
||||
minPlayers: 0
|
||||
stations:
|
||||
Station: #TODO: Mapper, add a BecomesStation component to the primary grid of the map.
|
||||
mapNameTemplate: '{0} Infiltrator {1}'
|
||||
nameGenerator:
|
||||
!type:NanotrasenNameGenerator
|
||||
prefixCreator: '14'
|
||||
overflowJobs: []
|
||||
availableJobs:
|
||||
Captain: [ 1, 1 ]
|
||||
@@ -5,46 +5,51 @@
|
||||
minPlayers: 35
|
||||
stations:
|
||||
Kettle:
|
||||
mapNameTemplate: '{0} Kettle {1}'
|
||||
emergencyShuttlePath: /Maps/Shuttles/emergency_courser.yml
|
||||
nameGenerator:
|
||||
!type:NanotrasenNameGenerator
|
||||
prefixCreator: '14'
|
||||
overflowJobs:
|
||||
- Passenger
|
||||
availableJobs:
|
||||
CargoTechnician: [ 3, 3 ]
|
||||
Passenger: [ -1, -1 ]
|
||||
Bartender: [ 1, 2 ]
|
||||
Botanist: [ 3, 4 ]
|
||||
Chef: [ 2, 3 ]
|
||||
Clown: [ 1, 2 ]
|
||||
Janitor: [ 4, 4 ]
|
||||
Mime: [ 1, 2 ]
|
||||
Captain: [ 1, 1 ]
|
||||
HeadOfPersonnel: [ 1, 1 ]
|
||||
ChiefEngineer: [ 1, 1 ]
|
||||
StationEngineer: [ 4, 6 ]
|
||||
ChiefMedicalOfficer: [ 1, 1 ]
|
||||
MedicalDoctor: [ 3, 5 ]
|
||||
Chemist: [ 2, 3 ]
|
||||
ResearchDirector: [ 1, 1 ]
|
||||
Scientist: [ 4, 6 ]
|
||||
ResearchAssistant: [ 4, 4 ]
|
||||
HeadOfSecurity: [ 1, 1 ]
|
||||
SecurityOfficer: [ 4, 6 ]
|
||||
Chaplain: [ 1, 2 ]
|
||||
Warden: [ 1, 1 ]
|
||||
Librarian: [ 1, 2 ]
|
||||
Lawyer: [ 2, 3 ]
|
||||
Quartermaster: [ 1, 1 ]
|
||||
SalvageSpecialist: [ 3, 4 ]
|
||||
Musician: [ 1, 2 ]
|
||||
AtmosphericTechnician: [ 3, 3 ]
|
||||
TechnicalAssistant: [ 4, 4 ]
|
||||
MedicalIntern: [ 4, 4 ]
|
||||
ServiceWorker: [ 4, 4 ]
|
||||
SecurityCadet: [ 4, 4 ]
|
||||
Detective: [ 1, 1 ]
|
||||
Zookeeper: [1, 1]
|
||||
Paramedic: [2, 2]
|
||||
stationProto: StandardNanotrasenStation
|
||||
components:
|
||||
- type: StationNameSetup
|
||||
mapNameTemplate: '{0} Kettle {1}'
|
||||
nameGenerator:
|
||||
!type:NanotrasenNameGenerator
|
||||
prefixCreator: '14'
|
||||
- type: StationEmergencyShuttle
|
||||
emergencyShuttlePath: /Maps/Shuttles/emergency_courser.yml
|
||||
- type: StationJobs
|
||||
overflowJobs:
|
||||
- Passenger
|
||||
availableJobs:
|
||||
CargoTechnician: [ 3, 3 ]
|
||||
Passenger: [ -1, -1 ]
|
||||
Bartender: [ 1, 2 ]
|
||||
Botanist: [ 3, 4 ]
|
||||
Chef: [ 2, 3 ]
|
||||
Clown: [ 1, 2 ]
|
||||
Janitor: [ 4, 4 ]
|
||||
Mime: [ 1, 2 ]
|
||||
Captain: [ 1, 1 ]
|
||||
HeadOfPersonnel: [ 1, 1 ]
|
||||
ChiefEngineer: [ 1, 1 ]
|
||||
StationEngineer: [ 4, 6 ]
|
||||
ChiefMedicalOfficer: [ 1, 1 ]
|
||||
MedicalDoctor: [ 3, 5 ]
|
||||
Chemist: [ 2, 3 ]
|
||||
ResearchDirector: [ 1, 1 ]
|
||||
Scientist: [ 4, 6 ]
|
||||
ResearchAssistant: [ 4, 4 ]
|
||||
HeadOfSecurity: [ 1, 1 ]
|
||||
SecurityOfficer: [ 4, 6 ]
|
||||
Chaplain: [ 1, 2 ]
|
||||
Warden: [ 1, 1 ]
|
||||
Librarian: [ 1, 2 ]
|
||||
Lawyer: [ 2, 3 ]
|
||||
Quartermaster: [ 1, 1 ]
|
||||
SalvageSpecialist: [ 3, 4 ]
|
||||
Musician: [ 1, 2 ]
|
||||
AtmosphericTechnician: [ 3, 3 ]
|
||||
TechnicalAssistant: [ 4, 4 ]
|
||||
MedicalIntern: [ 4, 4 ]
|
||||
ServiceWorker: [ 4, 4 ]
|
||||
SecurityCadet: [ 4, 4 ]
|
||||
Detective: [ 1, 1 ]
|
||||
Zookeeper: [1, 1]
|
||||
Paramedic: [2, 2]
|
||||
|
||||
@@ -6,45 +6,50 @@
|
||||
maxPlayers: 70
|
||||
stations:
|
||||
Marathon:
|
||||
mapNameTemplate: '{0} Marathon Station {1}'
|
||||
emergencyShuttlePath: /Maps/Shuttles/emergency_courser.yml
|
||||
nameGenerator:
|
||||
!type:NanotrasenNameGenerator
|
||||
prefixCreator: '14'
|
||||
overflowJobs:
|
||||
- Passenger
|
||||
availableJobs:
|
||||
CargoTechnician: [ 2, 3 ]
|
||||
Passenger: [ -1, -1 ]
|
||||
Bartender: [ 2, 2 ]
|
||||
Botanist: [ 3, 3]
|
||||
Chef: [ 2, 2 ]
|
||||
Clown: [ 1, 1 ]
|
||||
Janitor: [ 1, 2 ]
|
||||
Mime: [ 1, 1 ]
|
||||
Captain: [ 1, 1 ]
|
||||
HeadOfPersonnel: [ 1, 1 ]
|
||||
ChiefEngineer: [ 1, 1 ]
|
||||
StationEngineer: [ 4, 6 ]
|
||||
ChiefMedicalOfficer: [ 1, 1 ]
|
||||
MedicalDoctor: [ 3, 4 ]
|
||||
Chemist: [ 2, 3 ]
|
||||
ResearchDirector: [ 1, 1 ]
|
||||
Scientist: [ 3, 4 ]
|
||||
HeadOfSecurity: [ 1, 1 ]
|
||||
SecurityOfficer: [ 4, 4 ]
|
||||
Chaplain: [ 1, 1 ]
|
||||
Warden: [ 1, 1 ]
|
||||
Librarian: [ 1, 1 ]
|
||||
Lawyer: [ 2, 2 ]
|
||||
Quartermaster: [ 1, 1 ]
|
||||
SalvageSpecialist: [ 3, 3 ]
|
||||
Musician: [ 1, 1 ]
|
||||
AtmosphericTechnician: [ 3, 3 ]
|
||||
TechnicalAssistant: [ 2, 2 ]
|
||||
MedicalIntern: [ 2, 2 ]
|
||||
ServiceWorker: [ 2, 2 ]
|
||||
SecurityCadet: [ 2, 2 ]
|
||||
Psychologist: [ 1, 1 ]
|
||||
Detective: [ 1, 1 ]
|
||||
ResearchAssistant: [ 2, 2 ]
|
||||
stationProto: StandardNanotrasenStation
|
||||
components:
|
||||
- type: StationNameSetup
|
||||
mapNameTemplate: '{0} Marathon Station {1}'
|
||||
nameGenerator:
|
||||
!type:NanotrasenNameGenerator
|
||||
prefixCreator: '14'
|
||||
- type: StationEmergencyShuttle
|
||||
emergencyShuttlePath: /Maps/Shuttles/emergency_courser.yml
|
||||
- type: StationJobs
|
||||
overflowJobs:
|
||||
- Passenger
|
||||
availableJobs:
|
||||
CargoTechnician: [ 2, 3 ]
|
||||
Passenger: [ -1, -1 ]
|
||||
Bartender: [ 2, 2 ]
|
||||
Botanist: [ 3, 3]
|
||||
Chef: [ 2, 2 ]
|
||||
Clown: [ 1, 1 ]
|
||||
Janitor: [ 1, 2 ]
|
||||
Mime: [ 1, 1 ]
|
||||
Captain: [ 1, 1 ]
|
||||
HeadOfPersonnel: [ 1, 1 ]
|
||||
ChiefEngineer: [ 1, 1 ]
|
||||
StationEngineer: [ 4, 6 ]
|
||||
ChiefMedicalOfficer: [ 1, 1 ]
|
||||
MedicalDoctor: [ 3, 4 ]
|
||||
Chemist: [ 2, 3 ]
|
||||
ResearchDirector: [ 1, 1 ]
|
||||
Scientist: [ 3, 4 ]
|
||||
HeadOfSecurity: [ 1, 1 ]
|
||||
SecurityOfficer: [ 4, 4 ]
|
||||
Chaplain: [ 1, 1 ]
|
||||
Warden: [ 1, 1 ]
|
||||
Librarian: [ 1, 1 ]
|
||||
Lawyer: [ 2, 2 ]
|
||||
Quartermaster: [ 1, 1 ]
|
||||
SalvageSpecialist: [ 3, 3 ]
|
||||
Musician: [ 1, 1 ]
|
||||
AtmosphericTechnician: [ 3, 3 ]
|
||||
TechnicalAssistant: [ 2, 2 ]
|
||||
MedicalIntern: [ 2, 2 ]
|
||||
ServiceWorker: [ 2, 2 ]
|
||||
SecurityCadet: [ 2, 2 ]
|
||||
Psychologist: [ 1, 1 ]
|
||||
Detective: [ 1, 1 ]
|
||||
ResearchAssistant: [ 2, 2 ]
|
||||
|
||||
@@ -5,45 +5,50 @@
|
||||
minPlayers: 50
|
||||
stations:
|
||||
Meta:
|
||||
mapNameTemplate: '{0} Meta Station {1}'
|
||||
emergencyShuttlePath: /Maps/Shuttles/emergency_courser.yml
|
||||
nameGenerator:
|
||||
!type:NanotrasenNameGenerator
|
||||
prefixCreator: 'TG'
|
||||
overflowJobs:
|
||||
- Passenger
|
||||
availableJobs:
|
||||
CargoTechnician: [ 3, 3 ]
|
||||
Passenger: [ -1, -1 ]
|
||||
Bartender: [ 2, 2 ]
|
||||
Botanist: [ 3, 3 ]
|
||||
Chef: [ 2, 2 ]
|
||||
Clown: [ 1, 1 ]
|
||||
Janitor: [ 3, 3 ]
|
||||
Mime: [ 1, 1 ]
|
||||
Captain: [ 1, 1 ]
|
||||
HeadOfPersonnel: [ 1, 1 ]
|
||||
ChiefEngineer: [ 1, 1 ]
|
||||
StationEngineer: [ 4, 4 ]
|
||||
ChiefMedicalOfficer: [ 1, 1 ]
|
||||
MedicalDoctor: [ 4, 4 ]
|
||||
Chemist: [ 3, 3 ]
|
||||
ResearchDirector: [ 1, 1 ]
|
||||
Scientist: [ 6, 6 ]
|
||||
HeadOfSecurity: [ 1, 1 ]
|
||||
SecurityOfficer: [ 6, 6 ]
|
||||
Chaplain: [ 2, 2 ]
|
||||
Warden: [ 1, 1 ]
|
||||
Librarian: [ 2, 2 ]
|
||||
Lawyer: [ 2, 2 ]
|
||||
Quartermaster: [ 1, 1 ]
|
||||
SalvageSpecialist: [ 3, 3 ]
|
||||
Musician: [ 2, 2 ]
|
||||
AtmosphericTechnician: [ 3, 3 ]
|
||||
TechnicalAssistant: [ 4, 4 ]
|
||||
MedicalIntern: [ 4, 4 ]
|
||||
ServiceWorker: [ 4, 4 ]
|
||||
SecurityCadet: [ 4, 4 ]
|
||||
Detective: [ 1, 1 ]
|
||||
ResearchAssistant: [ 4, 4 ]
|
||||
Paramedic: [ 1, 1 ]
|
||||
stationProto: StandardNanotrasenStation
|
||||
components:
|
||||
- type: StationNameSetup
|
||||
mapNameTemplate: '{0} Meta Station {1}'
|
||||
nameGenerator:
|
||||
!type:NanotrasenNameGenerator
|
||||
prefixCreator: 'TG'
|
||||
- type: StationEmergencyShuttle
|
||||
emergencyShuttlePath: /Maps/Shuttles/emergency_courser.yml
|
||||
- type: StationJobs
|
||||
overflowJobs:
|
||||
- Passenger
|
||||
availableJobs:
|
||||
CargoTechnician: [ 3, 3 ]
|
||||
Passenger: [ -1, -1 ]
|
||||
Bartender: [ 2, 2 ]
|
||||
Botanist: [ 3, 3 ]
|
||||
Chef: [ 2, 2 ]
|
||||
Clown: [ 1, 1 ]
|
||||
Janitor: [ 3, 3 ]
|
||||
Mime: [ 1, 1 ]
|
||||
Captain: [ 1, 1 ]
|
||||
HeadOfPersonnel: [ 1, 1 ]
|
||||
ChiefEngineer: [ 1, 1 ]
|
||||
StationEngineer: [ 4, 4 ]
|
||||
ChiefMedicalOfficer: [ 1, 1 ]
|
||||
MedicalDoctor: [ 4, 4 ]
|
||||
Chemist: [ 3, 3 ]
|
||||
ResearchDirector: [ 1, 1 ]
|
||||
Scientist: [ 6, 6 ]
|
||||
HeadOfSecurity: [ 1, 1 ]
|
||||
SecurityOfficer: [ 6, 6 ]
|
||||
Chaplain: [ 2, 2 ]
|
||||
Warden: [ 1, 1 ]
|
||||
Librarian: [ 2, 2 ]
|
||||
Lawyer: [ 2, 2 ]
|
||||
Quartermaster: [ 1, 1 ]
|
||||
SalvageSpecialist: [ 3, 3 ]
|
||||
Musician: [ 2, 2 ]
|
||||
AtmosphericTechnician: [ 3, 3 ]
|
||||
TechnicalAssistant: [ 4, 4 ]
|
||||
MedicalIntern: [ 4, 4 ]
|
||||
ServiceWorker: [ 4, 4 ]
|
||||
SecurityCadet: [ 4, 4 ]
|
||||
Detective: [ 1, 1 ]
|
||||
ResearchAssistant: [ 4, 4 ]
|
||||
Paramedic: [ 1, 1 ]
|
||||
|
||||
@@ -7,43 +7,47 @@
|
||||
fallback: true
|
||||
stations:
|
||||
Moose:
|
||||
mapNameTemplate: '{0} Moose {1}'
|
||||
nameGenerator:
|
||||
!type:NanotrasenNameGenerator
|
||||
prefixCreator: '14'
|
||||
overflowJobs:
|
||||
- Passenger
|
||||
availableJobs:
|
||||
CargoTechnician: [ 2, 2 ]
|
||||
Passenger: [ -1, -1 ]
|
||||
Bartender: [ 1, 1 ]
|
||||
Botanist: [ 2, 2 ]
|
||||
Chef: [ 1, 1 ]
|
||||
Clown: [ 1, 1 ]
|
||||
Janitor: [ 1, 1 ]
|
||||
Mime: [ 1, 1 ]
|
||||
Captain: [ 1, 1 ]
|
||||
HeadOfPersonnel: [ 1, 1 ]
|
||||
ChiefEngineer: [ 1, 1 ]
|
||||
StationEngineer: [ 2, 3 ]
|
||||
AtmosphericTechnician: [ 2, 2 ]
|
||||
ChiefMedicalOfficer: [ 1, 1 ]
|
||||
MedicalDoctor: [ 2, 2 ]
|
||||
Chemist: [ 2, 2 ]
|
||||
ResearchDirector: [ 1, 1 ]
|
||||
Scientist: [ 3, 3 ]
|
||||
ResearchAssistant: [ 2, 2 ]
|
||||
HeadOfSecurity: [ 1, 1 ]
|
||||
SecurityOfficer: [ 2, 3 ]
|
||||
Chaplain: [ 1, 1 ]
|
||||
Librarian: [ 1, 1 ]
|
||||
Musician: [ 1, 1 ]
|
||||
Lawyer: [ 1, 1 ]
|
||||
SalvageSpecialist: [ 1, 2 ]
|
||||
Quartermaster: [ 1, 1 ]
|
||||
TechnicalAssistant: [ 2, 2 ]
|
||||
MedicalIntern: [ 2, 2 ]
|
||||
ServiceWorker: [ 2, 2 ]
|
||||
SecurityCadet: [ 2, 2 ]
|
||||
Detective: [ 1, 1 ]
|
||||
Warden: [ 1, 1 ]
|
||||
stationProto: StandardNanotrasenStation
|
||||
components:
|
||||
- type: StationNameSetup
|
||||
mapNameTemplate: '{0} Moose {1}'
|
||||
nameGenerator:
|
||||
!type:NanotrasenNameGenerator
|
||||
prefixCreator: '14'
|
||||
- type: StationJobs
|
||||
overflowJobs:
|
||||
- Passenger
|
||||
availableJobs:
|
||||
CargoTechnician: [ 2, 2 ]
|
||||
Passenger: [ -1, -1 ]
|
||||
Bartender: [ 1, 1 ]
|
||||
Botanist: [ 2, 2 ]
|
||||
Chef: [ 1, 1 ]
|
||||
Clown: [ 1, 1 ]
|
||||
Janitor: [ 1, 1 ]
|
||||
Mime: [ 1, 1 ]
|
||||
Captain: [ 1, 1 ]
|
||||
HeadOfPersonnel: [ 1, 1 ]
|
||||
ChiefEngineer: [ 1, 1 ]
|
||||
StationEngineer: [ 2, 3 ]
|
||||
AtmosphericTechnician: [ 2, 2 ]
|
||||
ChiefMedicalOfficer: [ 1, 1 ]
|
||||
MedicalDoctor: [ 2, 2 ]
|
||||
Chemist: [ 2, 2 ]
|
||||
ResearchDirector: [ 1, 1 ]
|
||||
Scientist: [ 3, 3 ]
|
||||
ResearchAssistant: [ 2, 2 ]
|
||||
HeadOfSecurity: [ 1, 1 ]
|
||||
SecurityOfficer: [ 2, 3 ]
|
||||
Chaplain: [ 1, 1 ]
|
||||
Librarian: [ 1, 1 ]
|
||||
Musician: [ 1, 1 ]
|
||||
Lawyer: [ 1, 1 ]
|
||||
SalvageSpecialist: [ 1, 2 ]
|
||||
Quartermaster: [ 1, 1 ]
|
||||
TechnicalAssistant: [ 2, 2 ]
|
||||
MedicalIntern: [ 2, 2 ]
|
||||
ServiceWorker: [ 2, 2 ]
|
||||
SecurityCadet: [ 2, 2 ]
|
||||
Detective: [ 1, 1 ]
|
||||
Warden: [ 1, 1 ]
|
||||
|
||||
@@ -6,43 +6,47 @@
|
||||
maxPlayers: 35
|
||||
stations:
|
||||
Omega:
|
||||
mapNameTemplate: '{0} Omega Station {1}'
|
||||
nameGenerator:
|
||||
!type:NanotrasenNameGenerator
|
||||
prefixCreator: 'TG'
|
||||
overflowJobs:
|
||||
- Passenger
|
||||
availableJobs:
|
||||
CargoTechnician: [ 2, 2 ]
|
||||
Passenger: [ -1, -1 ]
|
||||
Bartender: [ 1, 1 ]
|
||||
Botanist: [ 2, 2 ]
|
||||
Chef: [ 1, 1 ]
|
||||
Clown: [ 1, 1 ]
|
||||
Janitor: [ 1, 1 ]
|
||||
Mime: [ 1, 1 ]
|
||||
Captain: [ 1, 1 ]
|
||||
HeadOfPersonnel: [ 1, 1 ]
|
||||
ChiefEngineer: [ 1, 1 ]
|
||||
StationEngineer: [ 3, 3 ]
|
||||
ChiefMedicalOfficer: [ 1, 1 ]
|
||||
MedicalDoctor: [ 3, 3 ]
|
||||
Chemist: [ 2, 2 ]
|
||||
ResearchDirector: [ 1, 1 ]
|
||||
Scientist: [ 3, 3 ]
|
||||
ResearchAssistant: [ 1, 1 ]
|
||||
HeadOfSecurity: [ 1, 1 ]
|
||||
SecurityOfficer: [ 3, 3 ]
|
||||
Chaplain: [ 1, 1 ]
|
||||
Warden: [ 1, 1 ]
|
||||
Librarian: [ 1, 1 ]
|
||||
Lawyer: [ 1, 1 ]
|
||||
Musician: [ 1, 1 ]
|
||||
AtmosphericTechnician: [ 2, 2 ]
|
||||
Detective: [ 1, 1 ]
|
||||
TechnicalAssistant: [ 1, 1 ]
|
||||
MedicalIntern: [ 1, 1 ]
|
||||
ServiceWorker: [ 1, 1 ]
|
||||
SecurityCadet: [ 1, 1 ]
|
||||
SalvageSpecialist: [ 2, 2 ]
|
||||
Quartermaster: [ 1, 1 ]
|
||||
stationProto: StandardNanotrasenStation
|
||||
components:
|
||||
- type: StationNameSetup
|
||||
mapNameTemplate: '{0} Omega Station {1}'
|
||||
nameGenerator:
|
||||
!type:NanotrasenNameGenerator
|
||||
prefixCreator: 'TG'
|
||||
- type: StationJobs
|
||||
overflowJobs:
|
||||
- Passenger
|
||||
availableJobs:
|
||||
CargoTechnician: [ 2, 2 ]
|
||||
Passenger: [ -1, -1 ]
|
||||
Bartender: [ 1, 1 ]
|
||||
Botanist: [ 2, 2 ]
|
||||
Chef: [ 1, 1 ]
|
||||
Clown: [ 1, 1 ]
|
||||
Janitor: [ 1, 1 ]
|
||||
Mime: [ 1, 1 ]
|
||||
Captain: [ 1, 1 ]
|
||||
HeadOfPersonnel: [ 1, 1 ]
|
||||
ChiefEngineer: [ 1, 1 ]
|
||||
StationEngineer: [ 3, 3 ]
|
||||
ChiefMedicalOfficer: [ 1, 1 ]
|
||||
MedicalDoctor: [ 3, 3 ]
|
||||
Chemist: [ 2, 2 ]
|
||||
ResearchDirector: [ 1, 1 ]
|
||||
Scientist: [ 3, 3 ]
|
||||
ResearchAssistant: [ 1, 1 ]
|
||||
HeadOfSecurity: [ 1, 1 ]
|
||||
SecurityOfficer: [ 3, 3 ]
|
||||
Chaplain: [ 1, 1 ]
|
||||
Warden: [ 1, 1 ]
|
||||
Librarian: [ 1, 1 ]
|
||||
Lawyer: [ 1, 1 ]
|
||||
Musician: [ 1, 1 ]
|
||||
AtmosphericTechnician: [ 2, 2 ]
|
||||
Detective: [ 1, 1 ]
|
||||
TechnicalAssistant: [ 1, 1 ]
|
||||
MedicalIntern: [ 1, 1 ]
|
||||
ServiceWorker: [ 1, 1 ]
|
||||
SecurityCadet: [ 1, 1 ]
|
||||
SalvageSpecialist: [ 2, 2 ]
|
||||
Quartermaster: [ 1, 1 ]
|
||||
|
||||
@@ -5,46 +5,51 @@
|
||||
minPlayers: 50
|
||||
stations:
|
||||
Origin:
|
||||
mapNameTemplate: '{0} Origin {1}'
|
||||
emergencyShuttlePath: /Maps/Shuttles/emergency_courser.yml
|
||||
nameGenerator:
|
||||
!type:NanotrasenNameGenerator
|
||||
prefixCreator: '14'
|
||||
overflowJobs:
|
||||
- Passenger
|
||||
availableJobs:
|
||||
CargoTechnician: [ 5, 5 ]
|
||||
Passenger: [ -1, -1 ]
|
||||
Bartender: [ 3, 3 ]
|
||||
Botanist: [ 3, 3 ]
|
||||
Chef: [ 3, 3 ]
|
||||
Clown: [ 1, 1 ]
|
||||
Janitor: [ 3, 3 ]
|
||||
Mime: [ 1, 1 ]
|
||||
Captain: [ 1, 1 ]
|
||||
HeadOfPersonnel: [ 1, 1 ]
|
||||
ChiefEngineer: [ 1, 1 ]
|
||||
StationEngineer: [ 5, 5 ]
|
||||
ChiefMedicalOfficer: [ 1, 1 ]
|
||||
MedicalDoctor: [ 5, 5 ]
|
||||
Chemist: [ 2, 3 ]
|
||||
ResearchDirector: [ 1, 1 ]
|
||||
Scientist: [ 5, 5 ]
|
||||
HeadOfSecurity: [ 1, 1 ]
|
||||
SecurityOfficer: [ 6, 6 ]
|
||||
Chaplain: [ 2, 2 ]
|
||||
Warden: [ 1, 1 ]
|
||||
Librarian: [ 2, 2 ]
|
||||
Lawyer: [ 2, 2 ]
|
||||
Quartermaster: [ 1, 1 ]
|
||||
SalvageSpecialist: [ 3, 3 ]
|
||||
Musician: [ 2, 2 ]
|
||||
AtmosphericTechnician: [ 3, 3 ]
|
||||
TechnicalAssistant: [ 2, 2 ]
|
||||
MedicalIntern: [ 2, 2 ]
|
||||
ServiceWorker: [ 4, 4 ]
|
||||
SecurityCadet: [ 3, 3 ]
|
||||
Detective: [ 1, 1 ]
|
||||
ResearchAssistant: [ 2, 2]
|
||||
Boxer: [ 1, 1]
|
||||
Paramedic: [ 1, 1]
|
||||
stationProto: StandardNanotrasenStation
|
||||
components:
|
||||
- type: StationNameSetup
|
||||
mapNameTemplate: '{0} Origin {1}'
|
||||
nameGenerator:
|
||||
!type:NanotrasenNameGenerator
|
||||
prefixCreator: '14'
|
||||
- type: StationEmergencyShuttle
|
||||
emergencyShuttlePath: /Maps/Shuttles/emergency_courser.yml
|
||||
- type: StationJobs
|
||||
overflowJobs:
|
||||
- Passenger
|
||||
availableJobs:
|
||||
CargoTechnician: [ 5, 5 ]
|
||||
Passenger: [ -1, -1 ]
|
||||
Bartender: [ 3, 3 ]
|
||||
Botanist: [ 3, 3 ]
|
||||
Chef: [ 3, 3 ]
|
||||
Clown: [ 1, 1 ]
|
||||
Janitor: [ 3, 3 ]
|
||||
Mime: [ 1, 1 ]
|
||||
Captain: [ 1, 1 ]
|
||||
HeadOfPersonnel: [ 1, 1 ]
|
||||
ChiefEngineer: [ 1, 1 ]
|
||||
StationEngineer: [ 5, 5 ]
|
||||
ChiefMedicalOfficer: [ 1, 1 ]
|
||||
MedicalDoctor: [ 5, 5 ]
|
||||
Chemist: [ 2, 3 ]
|
||||
ResearchDirector: [ 1, 1 ]
|
||||
Scientist: [ 5, 5 ]
|
||||
HeadOfSecurity: [ 1, 1 ]
|
||||
SecurityOfficer: [ 6, 6 ]
|
||||
Chaplain: [ 2, 2 ]
|
||||
Warden: [ 1, 1 ]
|
||||
Librarian: [ 2, 2 ]
|
||||
Lawyer: [ 2, 2 ]
|
||||
Quartermaster: [ 1, 1 ]
|
||||
SalvageSpecialist: [ 3, 3 ]
|
||||
Musician: [ 2, 2 ]
|
||||
AtmosphericTechnician: [ 3, 3 ]
|
||||
TechnicalAssistant: [ 2, 2 ]
|
||||
MedicalIntern: [ 2, 2 ]
|
||||
ServiceWorker: [ 4, 4 ]
|
||||
SecurityCadet: [ 3, 3 ]
|
||||
Detective: [ 1, 1 ]
|
||||
ResearchAssistant: [ 2, 2]
|
||||
Boxer: [ 1, 1]
|
||||
Paramedic: [ 1, 1]
|
||||
|
||||
@@ -7,42 +7,46 @@
|
||||
fallback: true
|
||||
stations:
|
||||
Saltern:
|
||||
mapNameTemplate: '{0} Saltern {1}'
|
||||
nameGenerator:
|
||||
!type:NanotrasenNameGenerator
|
||||
prefixCreator: '14'
|
||||
overflowJobs:
|
||||
- Passenger
|
||||
availableJobs:
|
||||
CargoTechnician: [ 2, 2 ]
|
||||
Passenger: [ -1, -1 ]
|
||||
Bartender: [ 1, 1 ]
|
||||
Botanist: [ 2, 2 ]
|
||||
Chef: [ 1, 1 ]
|
||||
Clown: [ 1, 1 ]
|
||||
Janitor: [ 1, 1 ]
|
||||
Mime: [ 1, 1 ]
|
||||
Captain: [ 1, 1 ]
|
||||
HeadOfPersonnel: [ 1, 1 ]
|
||||
ChiefEngineer: [ 1, 1 ]
|
||||
StationEngineer: [ 3, 3 ]
|
||||
AtmosphericTechnician: [ 2, 2 ]
|
||||
ChiefMedicalOfficer: [ 1, 1 ]
|
||||
MedicalDoctor: [ 2, 2 ]
|
||||
Chemist: [ 2, 2 ]
|
||||
ResearchDirector: [ 1, 1 ]
|
||||
Scientist: [ 3, 3 ]
|
||||
ResearchAssistant: [ 1, 1 ]
|
||||
HeadOfSecurity: [ 1, 1 ]
|
||||
SecurityOfficer: [ 3, 3 ]
|
||||
Chaplain: [ 1, 1 ]
|
||||
Librarian: [ 1, 1 ]
|
||||
Musician: [ 1, 1 ]
|
||||
Lawyer: [ 1, 1 ]
|
||||
SalvageSpecialist: [ 1, 3 ]
|
||||
Quartermaster: [ 1, 1 ]
|
||||
TechnicalAssistant: [ 2, 2 ]
|
||||
MedicalIntern: [ 2, 2 ]
|
||||
ServiceWorker: [ 2, 2 ]
|
||||
SecurityCadet: [ 2, 2 ]
|
||||
Warden: [ 1, 1 ]
|
||||
stationProto: StandardNanotrasenStation
|
||||
components:
|
||||
- type: StationNameSetup
|
||||
mapNameTemplate: '{0} Saltern {1}'
|
||||
nameGenerator:
|
||||
!type:NanotrasenNameGenerator
|
||||
prefixCreator: '14'
|
||||
- type: StationJobs
|
||||
overflowJobs:
|
||||
- Passenger
|
||||
availableJobs:
|
||||
CargoTechnician: [ 2, 2 ]
|
||||
Passenger: [ -1, -1 ]
|
||||
Bartender: [ 1, 1 ]
|
||||
Botanist: [ 2, 2 ]
|
||||
Chef: [ 1, 1 ]
|
||||
Clown: [ 1, 1 ]
|
||||
Janitor: [ 1, 1 ]
|
||||
Mime: [ 1, 1 ]
|
||||
Captain: [ 1, 1 ]
|
||||
HeadOfPersonnel: [ 1, 1 ]
|
||||
ChiefEngineer: [ 1, 1 ]
|
||||
StationEngineer: [ 3, 3 ]
|
||||
AtmosphericTechnician: [ 2, 2 ]
|
||||
ChiefMedicalOfficer: [ 1, 1 ]
|
||||
MedicalDoctor: [ 2, 2 ]
|
||||
Chemist: [ 2, 2 ]
|
||||
ResearchDirector: [ 1, 1 ]
|
||||
Scientist: [ 3, 3 ]
|
||||
ResearchAssistant: [ 1, 1 ]
|
||||
HeadOfSecurity: [ 1, 1 ]
|
||||
SecurityOfficer: [ 3, 3 ]
|
||||
Chaplain: [ 1, 1 ]
|
||||
Librarian: [ 1, 1 ]
|
||||
Musician: [ 1, 1 ]
|
||||
Lawyer: [ 1, 1 ]
|
||||
SalvageSpecialist: [ 1, 3 ]
|
||||
Quartermaster: [ 1, 1 ]
|
||||
TechnicalAssistant: [ 2, 2 ]
|
||||
MedicalIntern: [ 2, 2 ]
|
||||
ServiceWorker: [ 2, 2 ]
|
||||
SecurityCadet: [ 2, 2 ]
|
||||
Warden: [ 1, 1 ]
|
||||
|
||||
Submodule RobustToolbox updated: 57ddf81fc4...7836130bef
Reference in New Issue
Block a user