diff --git a/Content.IntegrationTests/Tests/PostMapInitTest.cs b/Content.IntegrationTests/Tests/PostMapInitTest.cs index 05930eaf84..23b85b9959 100644 --- a/Content.IntegrationTests/Tests/PostMapInitTest.cs +++ b/Content.IntegrationTests/Tests/PostMapInitTest.cs @@ -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(targetGrid!.Value).Station; - var stationConfig = entManager.GetComponent(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(shuttle.Value), targetGrid.Value), $"Unable to dock {shuttlePath} to {mapProto}"); + if (entManager.TryGetComponent(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(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(station)) { - var lateSpawns = 0; - - foreach (var comp in entManager.EntityQuery(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(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(station).RoundStartJobList + .Where(x => x.Value != 0) + .Select(x => x.Key); + var spawnPoints = entManager.EntityQuery() + .Where(spawnpoint => spawnpoint.SpawnType == SpawnPointType.Job) + .Select(spawnpoint => spawnpoint.Job.ID) + .Distinct(); + List missingSpawnPoints = new(); + foreach (var spawnpoint in jobList.Except(spawnPoints)) + { + if (protoManager.Index(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(station).RoundStartJobList - .Where(x => x.Value != 0) - .Select(x => x.Key); - var spawnPoints = entManager.EntityQuery() - .Where(spawnpoint => spawnpoint.SpawnType == SpawnPointType.Job) - .Select(spawnpoint => spawnpoint.Job.ID) - .Distinct(); - List missingSpawnPoints = new(); - foreach (var spawnpoint in jobList.Except(spawnPoints)) - { - if (protoManager.Index(spawnpoint).SetPreference) - missingSpawnPoints.Add(spawnpoint); - } - Assert.That(missingSpawnPoints.Count() == 0, $"There is no spawnpoint for {String.Join(", ", missingSpawnPoints)} on {mapProto}."); try { diff --git a/Content.IntegrationTests/Tests/Station/StationJobsTest.cs b/Content.IntegrationTests/Tests/Station/StationJobsTest.cs index c47619d478..675a640945 100644 --- a/Content.IntegrationTests/Tests/Station/StationJobsTest.cs +++ b/Content.IntegrationTests/Tests/Station/StationJobsTest.cs @@ -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."); } diff --git a/Content.Server/Administration/Commands/Station/AdjustStationJobCommand.cs b/Content.Server/Administration/Commands/Station/AdjustStationJobCommand.cs index ceeffef430..cd221aafa6 100644 --- a/Content.Server/Administration/Commands/Station/AdjustStationJobCommand.cs +++ b/Content.Server/Administration/Commands/Station/AdjustStationJobCommand.cs @@ -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(); - var stationSystem = EntitySystem.Get(); - var stationJobs = EntitySystem.Get(); + var stationJobs = _entSysManager.GetEntitySystem(); - if (!int.TryParse(args[0], out var stationInt) || !stationSystem.Stations.Contains(new EntityUid(stationInt))) + if (!EntityUid.TryParse(args[0], out var station) || _entityManager.HasComponent(station)) { shell.WriteError(Loc.GetString("shell-argument-station-id-invalid", ("index", 1))); return; } - var station = new EntityUid(stationInt); - - if (!prototypeManager.TryIndex(args[1], out var job)) + if (!_prototypeManager.TryIndex(args[1], out var job)) { shell.WriteError(Loc.GetString("shell-argument-must-be-prototype", ("index", 2), ("prototypeName", nameof(JobPrototype)))); diff --git a/Content.Server/Administration/Commands/Station/ListStationJobsCommand.cs b/Content.Server/Administration/Commands/Station/ListStationJobsCommand.cs index 18d15d9e7c..1b00ac48d0 100644 --- a/Content.Server/Administration/Commands/Station/ListStationJobsCommand.cs +++ b/Content.Server/Administration/Commands/Station/ListStationJobsCommand.cs @@ -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(); - var stationJobs = EntitySystem.Get(); + var stationSystem = _entSysManager.GetEntitySystem(); + var stationJobs = _entSysManager.GetEntitySystem(); - if (!int.TryParse(args[0], out var station) || !stationSystem.Stations.Contains(new EntityUid(station))) + if (!EntityUid.TryParse(args[0], out var station) || !_entityManager.HasComponent(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}"); diff --git a/Content.Server/Administration/Commands/Station/ListStationsCommand.cs b/Content.Server/Administration/Commands/Station/ListStationsCommand.cs index b50bef2860..0877febe4d 100644 --- a/Content.Server/Administration/Commands/Station/ListStationsCommand.cs +++ b/Content.Server/Administration/Commands/Station/ListStationsCommand.cs @@ -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().Stations) + var query = _entityManager.EntityQueryEnumerator(); + + while (query.MoveNext(out var station, out _)) { var name = _entityManager.GetComponent(station).EntityName; shell.WriteLine($"{station, -10} | {name}"); diff --git a/Content.Server/Administration/Commands/Station/RenameStationCommand.cs b/Content.Server/Administration/Commands/Station/RenameStationCommand.cs index ec213b00af..78428841ea 100644 --- a/Content.Server/Administration/Commands/Station/RenameStationCommand.cs +++ b/Content.Server/Administration/Commands/Station/RenameStationCommand.cs @@ -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(); + var stationSystem = _entSysManager.GetEntitySystem(); - if (!int.TryParse(args[0], out var station) || !stationSystem.Stations.Contains(new EntityUid(station))) + if (!EntityUid.TryParse(args[0], out var station) || _entityManager.HasComponent(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]); } } diff --git a/Content.Server/AlertLevel/AlertLevelComponent.cs b/Content.Server/AlertLevel/AlertLevelComponent.cs index a597c87aeb..41664f91d4 100644 --- a/Content.Server/AlertLevel/AlertLevelComponent.cs +++ b/Content.Server/AlertLevel/AlertLevelComponent.cs @@ -1,3 +1,5 @@ +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; + namespace Content.Server.AlertLevel; /// @@ -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))] public string AlertLevelPrototype = default!; /// diff --git a/Content.Server/AlertLevel/AlertLevelSystem.cs b/Content.Server/AlertLevel/AlertLevelSystem.cs index 1c33394146..3d82259ad2 100644 --- a/Content.Server/AlertLevel/AlertLevelSystem.cs +++ b/Content.Server/AlertLevel/AlertLevelSystem.cs @@ -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(); + 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(args.Station); + if (!TryComp(args.Station, out var alertLevelComponent)) + return; - if (!_prototypeManager.TryIndex(DefaultAlertLevelSet, out AlertLevelPrototype? alerts)) + if (!_prototypeManager.TryIndex(alertLevelComponent.AlertLevelPrototype, out AlertLevelPrototype? alerts)) { return; } diff --git a/Content.Server/Cargo/Systems/CargoSystem.cs b/Content.Server/Cargo/Systems/CargoSystem.cs index 8cf85cef47..10ada53ccd 100644 --- a/Content.Server/Cargo/Systems/CargoSystem.cs +++ b/Content.Server/Cargo/Systems/CargoSystem.cs @@ -22,7 +22,6 @@ public sealed partial class CargoSystem : SharedCargoSystem InitializeConsole(); InitializeShuttle(); InitializeTelepad(); - SubscribeLocalEvent(OnStationInit); } public override void Shutdown() @@ -32,12 +31,6 @@ public sealed partial class CargoSystem : SharedCargoSystem CleanupShuttle(); } - private void OnStationInit(StationInitializedEvent ev) - { - EnsureComp(ev.Station); - EnsureComp(ev.Station); - } - public override void Update(float frameTime) { base.Update(frameTime); diff --git a/Content.Server/CrewManifest/CrewManifestSystem.cs b/Content.Server/CrewManifest/CrewManifestSystem.cs index fe037edcc3..7fffc33627 100644 --- a/Content.Server/CrewManifest/CrewManifestSystem.cs +++ b/Content.Server/CrewManifest/CrewManifestSystem.cs @@ -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() - .Stations - .Select(station => + .EntityQuery() + .Select(stationData => { - var meta = _entityManager.GetComponent(station); + var meta = _entityManager.GetComponent(stationData.Owner); - return new CompletionOption(station.ToString(), meta.EntityName); + return new CompletionOption(stationData.Owner.ToString(), meta.EntityName); }); return CompletionResult.FromHintOptions(stations, null); diff --git a/Content.Server/Dragon/DragonSystem.Rule.cs b/Content.Server/Dragon/DragonSystem.Rule.cs index 9f220bbd26..f3c8035f7d 100644 --- a/Content.Server/Dragon/DragonSystem.Rule.cs +++ b/Content.Server/Dragon/DragonSystem.Rule.cs @@ -31,10 +31,13 @@ public sealed partial class DragonSystem { base.Started(uid, component, gameRule, args); - if (!_station.Stations.Any()) + var eligible = EntityQuery().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(station)) is not { } grid) return; diff --git a/Content.Server/Entry/EntryPoint.cs b/Content.Server/Entry/EntryPoint.cs index b62c447244..147e0b4f94 100644 --- a/Content.Server/Entry/EntryPoint.cs +++ b/Content.Server/Entry/EntryPoint.cs @@ -174,7 +174,6 @@ namespace Content.Server.Entry protected override void Dispose(bool disposing) { _playTimeTracking?.Shutdown(); - _sysMan?.GetEntitySystemOrNull()?.OnServerDispose(); _dbManager?.Shutdown(); } diff --git a/Content.Server/GameTicking/GameTicker.Lobby.cs b/Content.Server/GameTicking/GameTicker.Lobby.cs index 18d481748a..05fd59e97e 100644 --- a/Content.Server/GameTicking/GameTicker.Lobby.cs +++ b/Content.Server/GameTicking/GameTicker.Lobby.cs @@ -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(); - 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")); } diff --git a/Content.Server/GameTicking/GameTicker.Spawning.cs b/Content.Server/GameTicking/GameTicker.Spawning.cs index 0826638a6f..2930430775 100644 --- a/Content.Server/GameTicking/GameTicker.Spawning.cs +++ b/Content.Server/GameTicking/GameTicker.Spawning.cs @@ -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().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().Select(x => x.Item1.Owner).ToList(); _robustRandom.Shuffle(stations); if (stations.Count == 0) station = EntityUid.Invalid; diff --git a/Content.Server/GameTicking/Rules/Components/NukeopsRuleComponent.cs b/Content.Server/GameTicking/Rules/Components/NukeopsRuleComponent.cs index 7c0bbbd6e3..a9a88efcd8 100644 --- a/Content.Server/GameTicking/Rules/Components/NukeopsRuleComponent.cs +++ b/Content.Server/GameTicking/Rules/Components/NukeopsRuleComponent.cs @@ -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 OperativePlayers = new(); + + [DataField("faction", customTypeSerializer: typeof(PrototypeIdSerializer), required: true)] + public string Faction = default!; } public enum WinType : byte diff --git a/Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs b/Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs index e7171c5627..c321c1c2aa 100644 --- a/Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs @@ -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 // 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() + .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(); diff --git a/Content.Server/GameTicking/Rules/PiratesRuleSystem.cs b/Content.Server/GameTicking/Rules/PiratesRuleSystem.cs index 6ff2429c2b..043ba255a5 100644 --- a/Content.Server/GameTicking/Rules/PiratesRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/PiratesRuleSystem.cs @@ -144,8 +144,8 @@ public sealed class PiratesRuleSystem : GameRuleSystem var map = "/Maps/Shuttles/pirate.yml"; var xformQuery = GetEntityQuery(); - var aabbs = _stationSystem.Stations.SelectMany(x => - Comp(x).Grids.Select(x => + var aabbs = EntityQuery().SelectMany(x => + x.Grids.Select(x => xformQuery.GetComponent(x).WorldMatrix.TransformBox(_mapManager.GetGridComp(x).LocalAABB))) .ToArray(); diff --git a/Content.Server/Jobs/AddComponentSpecial.cs b/Content.Server/Jobs/AddComponentSpecial.cs index f91cf43bf0..f618b163b4 100644 --- a/Content.Server/Jobs/AddComponentSpecial.cs +++ b/Content.Server/Jobs/AddComponentSpecial.cs @@ -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) { diff --git a/Content.Server/Magic/Events/ChangeComponentsSpellEvent.cs b/Content.Server/Magic/Events/ChangeComponentsSpellEvent.cs index aa197c46a5..2597a3eca9 100644 --- a/Content.Server/Magic/Events/ChangeComponentsSpellEvent.cs +++ b/Content.Server/Magic/Events/ChangeComponentsSpellEvent.cs @@ -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] diff --git a/Content.Server/NPC/Queries/Queries/ComponentQuery.cs b/Content.Server/NPC/Queries/Queries/ComponentQuery.cs index 9e101ec27a..f426fc4f40 100644 --- a/Content.Server/NPC/Queries/Queries/ComponentQuery.cs +++ b/Content.Server/NPC/Queries/Queries/ComponentQuery.cs @@ -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!; } diff --git a/Content.Server/NPC/Queries/Queries/NearbyComponentsQuery.cs b/Content.Server/NPC/Queries/Queries/NearbyComponentsQuery.cs index 7741c6beb5..c465f11fd2 100644 --- a/Content.Server/NPC/Queries/Queries/NearbyComponentsQuery.cs +++ b/Content.Server/NPC/Queries/Queries/NearbyComponentsQuery.cs @@ -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!; } diff --git a/Content.Server/NPC/Systems/FactionSystem.cs b/Content.Server/NPC/Systems/FactionSystem.cs index 9445c7d6ad..ed86a2cb63 100644 --- a/Content.Server/NPC/Systems/FactionSystem.cs +++ b/Content.Server/NPC/Systems/FactionSystem.cs @@ -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); + } + /// /// Makes the source faction friendly to the target faction, 1-way. /// diff --git a/Content.Server/NPC/Systems/NPCSteeringSystem.Context.cs b/Content.Server/NPC/Systems/NPCSteeringSystem.Context.cs index a99243180b..db87b2adc7 100644 --- a/Content.Server/NPC/Systems/NPCSteeringSystem.Context.cs +++ b/Content.Server/NPC/Systems/NPCSteeringSystem.Context.cs @@ -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) { diff --git a/Content.Server/Nuke/Commands/SendNukeCodesCommand.cs b/Content.Server/Nuke/Commands/SendNukeCodesCommand.cs index 83a0081389..fccfbe7c6b 100644 --- a/Content.Server/Nuke/Commands/SendNukeCodesCommand.cs +++ b/Content.Server/Nuke/Commands/SendNukeCodesCommand.cs @@ -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() - .Stations - .Select(station => + .EntityQuery() + .Select(stationData => { - var meta = _entityManager.GetComponent(station); + var meta = _entityManager.GetComponent(stationData.Owner); - return new CompletionOption(station.ToString(), meta.EntityName); + return new CompletionOption(stationData.Owner.ToString(), meta.EntityName); }); return CompletionResult.FromHintOptions(stations, null); diff --git a/Content.Server/Objectives/Conditions/EscapeShuttleCondition.cs b/Content.Server/Objectives/Conditions/EscapeShuttleCondition.cs index e5e8964f4e..ff475e706b 100644 --- a/Content.Server/Objectives/Conditions/EscapeShuttleCondition.cs +++ b/Content.Server/Objectives/Conditions/EscapeShuttleCondition.cs @@ -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()) + foreach (var stationData in entMan.EntityQuery()) { if (IsAgentOnShuttle(xform, stationData.EmergencyShuttle)) { shuttleContainsAgent = true; diff --git a/Content.Server/Salvage/SalvageSystem.Expeditions.cs b/Content.Server/Salvage/SalvageSystem.Expeditions.cs index 31a1c5fd63..0987dfe258 100644 --- a/Content.Server/Salvage/SalvageSystem.Expeditions.cs +++ b/Content.Server/Salvage/SalvageSystem.Expeditions.cs @@ -28,8 +28,6 @@ public sealed partial class SalvageSystem private void InitializeExpeditions() { - SubscribeLocalEvent(OnSalvageExpStationInit); - SubscribeLocalEvent(OnSalvageConsoleInit); SubscribeLocalEvent(OnSalvageConsoleParent); SubscribeLocalEvent(OnSalvageClaimMessage); @@ -115,11 +113,6 @@ public sealed partial class SalvageSystem component.EndTime += args.PausedTime; } - private void OnSalvageExpStationInit(StationInitializedEvent ev) - { - EnsureComp(ev.Station); - } - private void UpdateExpeditions() { var currentTime = _timing.CurTime; diff --git a/Content.Server/Shuttles/Components/StationEmergencyShuttleComponent.cs b/Content.Server/Shuttles/Components/StationEmergencyShuttleComponent.cs new file mode 100644 index 0000000000..4eaf139072 --- /dev/null +++ b/Content.Server/Shuttles/Components/StationEmergencyShuttleComponent.cs @@ -0,0 +1,24 @@ +using Content.Server.Shuttles.Systems; +using Robust.Shared.Serialization.TypeSerializers.Implementations; +using Robust.Shared.Utility; + +namespace Content.Server.Shuttles.Components; + +/// +/// This is used for controlling evacuation for a station. +/// +[RegisterComponent] +public sealed class StationEmergencyShuttleComponent : Component +{ + /// + /// The emergency shuttle assigned to this station. + /// + [ViewVariables, Access(typeof(ShuttleSystem), typeof(EmergencyShuttleSystem), Friend = AccessPermissions.ReadWrite)] + public EntityUid? EmergencyShuttle; + + /// + /// Emergency shuttle map path for this station. + /// + [DataField("emergencyShuttlePath", customTypeSerializer: typeof(ResPathSerializer))] + public ResPath EmergencyShuttlePath { get; set; } = new("/Maps/Shuttles/emergency.yml"); +} diff --git a/Content.Server/Shuttles/Systems/ArrivalsSystem.cs b/Content.Server/Shuttles/Systems/ArrivalsSystem.cs index 53dccef662..50b8d4f5b9 100644 --- a/Content.Server/Shuttles/Systems/ArrivalsSystem.cs +++ b/Content.Server/Shuttles/Systems/ArrivalsSystem.cs @@ -57,7 +57,6 @@ public sealed class ArrivalsSystem : EntitySystem SubscribeLocalEvent(OnShuttleUnpaused); SubscribeLocalEvent(OnShuttleTag); - SubscribeLocalEvent(OnStationInit); SubscribeLocalEvent(OnRoundStarting); SubscribeLocalEvent(OnArrivalsFTL); @@ -207,17 +206,15 @@ public sealed class ArrivalsSystem : EntitySystem } } - private void OnStationInit(StationInitializedEvent ev) - { - EnsureComp(ev.Station); - } - private void OnPlayerSpawn(PlayerSpawningEvent ev) { // Only works on latejoin even if enabled. if (!Enabled || _ticker.RunLevel != GameRunLevel.InRound) return; + if (!HasComp(ev.Station)) + return; + var points = EntityQuery().ToList(); _random.Shuffle(points); TryGetArrivals(out var arrivals); diff --git a/Content.Server/Shuttles/Systems/EmergencyShuttleSystem.Console.cs b/Content.Server/Shuttles/Systems/EmergencyShuttleSystem.Console.cs index 6e487ee7a3..c346546c46 100644 --- a/Content.Server/Shuttles/Systems/EmergencyShuttleSystem.Console.cs +++ b/Content.Server/Shuttles/Systems/EmergencyShuttleSystem.Console.cs @@ -156,7 +156,7 @@ public sealed partial class EmergencyShuttleSystem if (CentComMap != null) { - var dataQuery = AllEntityQuery(); + var dataQuery = AllEntityQuery(); while (dataQuery.MoveNext(out var comp)) { diff --git a/Content.Server/Shuttles/Systems/EmergencyShuttleSystem.cs b/Content.Server/Shuttles/Systems/EmergencyShuttleSystem.cs index 5f4983cf98..5e7b9225a6 100644 --- a/Content.Server/Shuttles/Systems/EmergencyShuttleSystem.cs +++ b/Content.Server/Shuttles/Systems/EmergencyShuttleSystem.cs @@ -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(OnRoundStart); - SubscribeLocalEvent(OnStationStartup); + SubscribeLocalEvent(OnStationStartup); SubscribeNetworkEvent(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(_station.GetOwningStation(player.Value), out var stationData) || - !HasComp(stationData.EmergencyShuttle)) + var station = _station.GetOwningStation(player.Value); + + if (!TryComp(station, out var stationShuttle) || + !HasComp(stationShuttle.EmergencyShuttle)) { return; } - var targetGrid = _station.GetLargestGrid(stationData); + var targetGrid = _station.GetLargestGrid(Comp(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 /// public void CallEmergencyShuttle(EntityUid? stationUid) { - if (!TryComp(stationUid, out var stationData) || - !TryComp(stationData.EmergencyShuttle, out var xform) || - !TryComp(stationData.EmergencyShuttle, out var shuttle)) + if (!TryComp(stationUid, out var stationShuttle) || + !TryComp(stationShuttle.EmergencyShuttle, out var xform) || + !TryComp(stationShuttle.EmergencyShuttle, out var shuttle)) { return; } - var targetGrid = _station.GetLargestGrid(stationData); + var targetGrid = _station.GetLargestGrid(Comp(stationUid.Value)); // UHH GOOD LUCK if (targetGrid == null) @@ -164,11 +167,11 @@ public sealed partial class EmergencyShuttleSystem : EntitySystem var xformQuery = GetEntityQuery(); - if (_shuttle.TryFTLDock(stationData.EmergencyShuttle.Value, shuttle, targetGrid.Value, DockTag)) + if (_shuttle.TryFTLDock(stationShuttle.EmergencyShuttle.Value, shuttle, targetGrid.Value, DockTag)) { if (TryComp(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(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(true)) + foreach (var comp in EntityQuery(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. diff --git a/Content.Server/Station/Components/PartOfStationComponent.cs b/Content.Server/Station/Components/PartOfStationComponent.cs deleted file mode 100644 index 69df581136..0000000000 --- a/Content.Server/Station/Components/PartOfStationComponent.cs +++ /dev/null @@ -1,15 +0,0 @@ -using Content.Server.GameTicking; - -namespace Content.Server.Station.Components; - -/// -/// 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. -/// -[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!; -} diff --git a/Content.Server/Station/Components/StationDataComponent.cs b/Content.Server/Station/Components/StationDataComponent.cs index 60d58d671f..6d33bcedab 100644 --- a/Content.Server/Station/Components/StationDataComponent.cs +++ b/Content.Server/Station/Components/StationDataComponent.cs @@ -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 /// /// List of all grids this station is part of. /// - /// - /// You should not mutate this yourself, go through StationSystem so the appropriate events get fired. - /// [DataField("grids")] public readonly HashSet Grids = new(); - - /// - /// The emergency shuttle assigned to this station. - /// - [ViewVariables, Access(typeof(ShuttleSystem), typeof(EmergencyShuttleSystem), Friend = AccessPermissions.ReadWrite)] - public EntityUid? EmergencyShuttle; } diff --git a/Content.Server/Station/Components/StationEventEligibleComponent.cs b/Content.Server/Station/Components/StationEventEligibleComponent.cs new file mode 100644 index 0000000000..0f3f6f85f7 --- /dev/null +++ b/Content.Server/Station/Components/StationEventEligibleComponent.cs @@ -0,0 +1,10 @@ +namespace Content.Server.Station.Components; + +/// +/// This is used for event eligibility. +/// +[RegisterComponent] +public sealed class StationEventEligibleComponent : Component +{ + +} diff --git a/Content.Server/Station/Components/StationJobsComponent.cs b/Content.Server/Station/Components/StationJobsComponent.cs index 42295fcca7..a717477f5a 100644 --- a/Content.Server/Station/Components/StationJobsComponent.cs +++ b/Content.Server/Station/Components/StationJobsComponent.cs @@ -32,6 +32,16 @@ public sealed class StationJobsComponent : Component /// [DataField("extendedAccess")] public bool ExtendedAccess; + /// + /// 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. + /// + /// + /// Set to -1 to disable extended access. + /// + [DataField("extendedAccessThreshold")] + public int ExtendedAccessThreshold { get; set; } = 15; + /// /// The percentage of jobs remaining. /// @@ -62,5 +72,10 @@ public sealed class StationJobsComponent : Component /// /// Overflow jobs that round-start can spawn infinitely many of. /// - [DataField("overflowJobs", customTypeSerializer: typeof(PrototypeIdHashSetSerializer))] public HashSet OverflowJobs = new(); + [DataField("overflowJobs", customTypeSerializer: typeof(PrototypeIdHashSetSerializer))] + public HashSet OverflowJobs = new(); + + [DataField("availableJobs", required: true, + customTypeSerializer: typeof(PrototypeIdDictionarySerializer, JobPrototype>))] + public readonly Dictionary> SetupAvailableJobs = default!; } diff --git a/Content.Server/Station/Components/StationNameSetupComponent.cs b/Content.Server/Station/Components/StationNameSetupComponent.cs new file mode 100644 index 0000000000..976434eb62 --- /dev/null +++ b/Content.Server/Station/Components/StationNameSetupComponent.cs @@ -0,0 +1,23 @@ +using Content.Server.Maps.NameGenerators; + +namespace Content.Server.Station.Components; + +/// +/// This is used for setting up a station's name. +/// +[RegisterComponent] +public sealed class StationNameSetupComponent : Component +{ + /// + /// The name template to use for the station. + /// If there's a name generator this should follow it's required format. + /// + [DataField("mapNameTemplate", required: true)] + public string StationNameTemplate { get; } = default!; + + /// + /// Name generator to use for the station, if any. + /// + [DataField("nameGenerator")] + public StationNameGenerator? NameGenerator { get; } +} diff --git a/Content.Server/Station/StationConfig.Jobs.cs b/Content.Server/Station/StationConfig.Jobs.cs deleted file mode 100644 index 4aeb79a967..0000000000 --- a/Content.Server/Station/StationConfig.Jobs.cs +++ /dev/null @@ -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))] - private readonly List _overflowJobs = default!; - - /// - /// 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! - /// - public IReadOnlyList OverflowJobs => _overflowJobs; - - - [DataField("availableJobs", required: true, - customTypeSerializer: typeof(PrototypeIdDictionarySerializer, JobPrototype>))] - private readonly Dictionary> _availableJobs = default!; - - /// - /// Index of all jobs available on the station, of form - /// job name: [round-start, mid-round] - /// - public IReadOnlyDictionary> AvailableJobs => _availableJobs; - - /// - /// 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. - /// - /// - /// Set to -1 to disable extended access. - /// - [DataField("extendedAccessThreshold")] - public int ExtendedAccessThreshold { get; set; } = 15; -} diff --git a/Content.Server/Station/StationConfig.Shuttles.cs b/Content.Server/Station/StationConfig.Shuttles.cs deleted file mode 100644 index 5b25abd4c5..0000000000 --- a/Content.Server/Station/StationConfig.Shuttles.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Robust.Shared.Utility; -using Robust.Shared.Serialization.TypeSerializers.Implementations; - -namespace Content.Server.Station; - -public sealed partial class StationConfig -{ - /// - /// Emergency shuttle map path for this station. - /// - [DataField("emergencyShuttlePath", customTypeSerializer: typeof(ResPathSerializer))] - public ResPath EmergencyShuttlePath { get; set; } = new("/Maps/Shuttles/emergency.yml"); -} diff --git a/Content.Server/Station/StationConfig.cs b/Content.Server/Station/StationConfig.cs index 5a4d875114..a5f998a016 100644 --- a/Content.Server/Station/StationConfig.cs +++ b/Content.Server/Station/StationConfig.cs @@ -1,30 +1,19 @@ using Content.Server.Maps.NameGenerators; using JetBrains.Annotations; +using Robust.Shared.Prototypes; namespace Content.Server.Station; /// -/// 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. /// -/// -/// 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. -/// [DataDefinition, PublicAPI] -public sealed partial class StationConfig +public sealed class StationConfig { - /// - /// The name template to use for the station. - /// If there's a name generator this should follow it's required format. - /// - [DataField("mapNameTemplate", required: true)] - public string StationNameTemplate { get; } = default!; + [DataField("stationProto", required: true)] + public string StationPrototype = default!; - /// - /// Name generator to use for the station, if any. - /// - [DataField("nameGenerator")] - public StationNameGenerator? NameGenerator { get; } + [DataField("components", required: true)] + public ComponentRegistry StationComponentOverrides = default!; } diff --git a/Content.Server/Station/Systems/StationJobsSystem.Roundstart.cs b/Content.Server/Station/Systems/StationJobsSystem.Roundstart.cs index a618e74c26..40411babff 100644 --- a/Content.Server/Station/Systems/StationJobsSystem.Roundstart.cs +++ b/Content.Server/Station/Systems/StationJobsSystem.Roundstart.cs @@ -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(station); - var data = Comp(station); - var thresh = data.StationConfig?.ExtendedAccessThreshold ?? -1; + var thresh = jobs.ExtendedAccessThreshold; jobs.ExtendedAccess = count <= thresh; diff --git a/Content.Server/Station/Systems/StationJobsSystem.cs b/Content.Server/Station/Systems/StationJobsSystem.cs index 268d50739d..3f52d6810b 100644 --- a/Content.Server/Station/Systems/StationJobsSystem.cs +++ b/Content.Server/Station/Systems/StationJobsSystem.cs @@ -53,30 +53,32 @@ public sealed partial class StationJobsSystem : EntitySystem private void OnStationInitialized(StationInitializedEvent msg) { - var stationJobs = AddComp(msg.Station); - var stationData = Comp(msg.Station); - - if (stationData.StationConfig == null) + if (!TryComp(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>(); var stationNames = new Dictionary(); - foreach (var station in _stationSystem.Stations) + var query = EntityQueryEnumerator(); + + while (query.MoveNext(out var station, out var comp)) { - var list = Comp(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)); } diff --git a/Content.Server/Station/Systems/StationNameSystem.cs b/Content.Server/Station/Systems/StationNameSystem.cs new file mode 100644 index 0000000000..fbbf690465 --- /dev/null +++ b/Content.Server/Station/Systems/StationNameSystem.cs @@ -0,0 +1,35 @@ +using Content.Server.Station.Components; + +namespace Content.Server.Station.Systems; + +/// +/// This handles naming stations. +/// +public sealed class StationNameSystem : EntitySystem +{ + [Dependency] private readonly StationSystem _station = default!; + + /// + public override void Initialize() + { + SubscribeLocalEvent(OnStationNameSetupInit); + } + + private void OnStationNameSetupInit(EntityUid uid, StationNameSetupComponent component, ComponentInit args) + { + if (!HasComp(uid)) + return; + + _station.RenameStation(uid, GenerateStationName(component), false); + } + + /// + /// Generates a station name from the given config. + /// + private static string GenerateStationName(StationNameSetupComponent config) + { + return config.NameGenerator is not null + ? config.NameGenerator.FormatName(config.StationNameTemplate) + : config.StationNameTemplate; + } +} diff --git a/Content.Server/Station/Systems/StationSpawningSystem.cs b/Content.Server/Station/Systems/StationSpawningSystem.cs index fcd61ed066..0e53a04d48 100644 --- a/Content.Server/Station/Systems/StationSpawningSystem.cs +++ b/Content.Server/Station/Systems/StationSpawningSystem.cs @@ -50,15 +50,9 @@ public sealed class StationSpawningSystem : EntitySystem /// public override void Initialize() { - SubscribeLocalEvent(OnStationInitialized); _configurationManager.OnValueChanged(CCVars.ICRandomCharacters, e => _randomizeCharacters = e, true); } - private void OnStationInitialized(StationInitializedEvent ev) - { - AddComp(ev.Station); - } - /// /// Attempts to spawn a player character onto the given station. /// @@ -95,16 +89,19 @@ public sealed class StationSpawningSystem : EntitySystem /// Job to assign to the character, if any. /// Appearance profile to use for the character. /// The station this player is being spawned on. + /// The entity to use, if one already exists. /// The spawned entity 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(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(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(entity).Content = profile.FlavorText; + AddComp(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) diff --git a/Content.Server/Station/Systems/StationSystem.cs b/Content.Server/Station/Systems/StationSystem.cs index 1828e53c6a..73fa592b40 100644 --- a/Content.Server/Station/Systems/StationSystem.cs +++ b/Content.Server/Station/Systems/StationSystem.cs @@ -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 _stations = new(); - - /// - /// All stations that currently exist. - /// - /// - /// 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. - /// - public IReadOnlySet Stations => _stations; - private bool _randomStationOffset; private bool _randomStationRotation; private float _maxRandomStationOffset; @@ -57,9 +48,8 @@ public sealed class StationSystem : EntitySystem SubscribeLocalEvent(OnRoundEnd); SubscribeLocalEvent(OnPreGameMapLoad); SubscribeLocalEvent(OnPostGameMapLoad); - SubscribeLocalEvent(OnStationAdd); + SubscribeLocalEvent(OnStationAdd); SubscribeLocalEvent(OnStationDeleted); - SubscribeLocalEvent(OnParentChanged); SubscribeLocalEvent(OnStationGridDeleted); SubscribeLocalEvent(OnStationSplitEvent); @@ -89,68 +79,34 @@ public sealed class StationSystem : EntitySystem _player.PlayerStatusChanged -= OnPlayerStatusChanged; } - /// - /// Called when the server shuts down or restarts to avoid uneccesarily logging mid-round station deletion errors. - /// - 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(grid); } - _stations.Remove(uid); - RaiseNetworkEvent(new StationsUpdatedEvent(_stations), Filter.Broadcast()); - } - - /// - /// If a station data entity is getting re-parented mid-round, this will log an error. - /// - /// - /// This doesn't really achieve anything, it just for debugging any future station data bugs. - /// - 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(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(); + while (query.MoveNext(out var station, out _)) { - DeleteStation(entity); + QueueDel(station); } } @@ -326,47 +278,26 @@ public sealed class StationSystem : EntitySystem return filter; } - /// - /// Generates a station name from the given config. - /// - public static string GenerateStationName(StationConfig config) - { - return config.NameGenerator is not null - ? config.NameGenerator.FormatName(config.StationNameTemplate) - : config.StationNameTemplate; - } - /// /// Initializes a new station with the given information. /// /// The game map prototype used, if any. /// All grids that should be added to the station. /// Optional override for the station name. + /// This is for ease of use, manually spawning the entity works just fine. /// The initialized station. - public EntityUid InitializeNewStation(StationConfig? stationConfig, IEnumerable? gridIds, string? name = null) + public EntityUid InitializeNewStation(StationConfig stationConfig, IEnumerable? 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(station); - var metaData = MetaData(station); - data.StationConfig = stationConfig; + DebugTools.Assert(HasComp(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(station); + name ??= MetaData(station).EntityName; foreach (var grid in gridIds ?? Array.Empty()) { @@ -397,11 +328,11 @@ public sealed class StationSystem : EntitySystem var stationMember = AddComp(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})"); } /// @@ -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(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})"); } /// @@ -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); } /// @@ -501,6 +430,16 @@ public sealed class StationSystem : EntitySystem return CompOrNull(xform.GridUid)?.Station; } + + public List GetStations() + { + return EntityQuery().Select(x => x.Owner).ToList(); + } + + public HashSet GetStationsSet() + { + return EntityQuery().Select(x => x.Owner).ToHashSet(); + } } /// diff --git a/Content.Server/StationEvents/Events/AnomalySpawnRule.cs b/Content.Server/StationEvents/Events/AnomalySpawnRule.cs index 8e7a860d2e..6ed2c0eb45 100644 --- a/Content.Server/StationEvents/Events/AnomalySpawnRule.cs +++ b/Content.Server/StationEvents/Events/AnomalySpawnRule.cs @@ -24,9 +24,9 @@ public sealed class AnomalySpawnRule : StationEventSystem(chosenStation, out var stationData)) return; diff --git a/Content.Server/StationEvents/Events/BreakerFlipRule.cs b/Content.Server/StationEvents/Events/BreakerFlipRule.cs index 2920ee331b..c53f3c5750 100644 --- a/Content.Server/StationEvents/Events/BreakerFlipRule.cs +++ b/Content.Server/StationEvents/Events/BreakerFlipRule.cs @@ -26,9 +26,8 @@ public sealed class BreakerFlipRule : StationEventSystem(); foreach (var (apc, transform) in EntityQuery()) diff --git a/Content.Server/StationEvents/Events/BureaucraticErrorRule.cs b/Content.Server/StationEvents/Events/BureaucraticErrorRule.cs index 0fbf72fd7d..b82546a55b 100644 --- a/Content.Server/StationEvents/Events/BureaucraticErrorRule.cs +++ b/Content.Server/StationEvents/Events/BureaucraticErrorRule.cs @@ -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)) + 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(true)) { diff --git a/Content.Server/StationEvents/Events/StationEventSystem.cs b/Content.Server/StationEvents/Events/StationEventSystem.cs index 2ff37824b4..e372c2eae8 100644 --- a/Content.Server/StationEvents/Events/StationEventSystem.cs +++ b/Content.Server/StationEvents/Events/StationEventSystem.cs @@ -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 : GameRuleSystem 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? 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(targetStation).Grids; + var possibleTargets = Comp(targetStation.Value).Grids; if (possibleTargets.Count == 0) { targetGrid = EntityUid.Invalid; diff --git a/Content.Server/StationEvents/Events/VentClogRule.cs b/Content.Server/StationEvents/Events/VentClogRule.cs index dd4a67d85e..5ef28304e7 100644 --- a/Content.Server/StationEvents/Events/VentClogRule.cs +++ b/Content.Server/StationEvents/Events/VentClogRule.cs @@ -22,9 +22,8 @@ public sealed class VentClogRule : StationEventSystem { 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() diff --git a/Content.Server/StationRecords/Systems/StationRecordsSystem.cs b/Content.Server/StationRecords/Systems/StationRecordsSystem.cs index 4b90e64193..17dfca4d0f 100644 --- a/Content.Server/StationRecords/Systems/StationRecordsSystem.cs +++ b/Content.Server/StationRecords/Systems/StationRecordsSystem.cs @@ -44,17 +44,14 @@ public sealed class StationRecordsSystem : EntitySystem { base.Initialize(); - SubscribeLocalEvent(OnStationInitialize); SubscribeLocalEvent(OnPlayerSpawn); } - private void OnStationInitialize(StationInitializedEvent args) - { - AddComp(args.Station); - } - private void OnPlayerSpawn(PlayerSpawnCompleteEvent args) { + if (!HasComp(args.Station)) + return; + CreateGeneralRecord(args.Station, args.Mob, args.Profile, args.JobId); } diff --git a/Content.Server/Worldgen/Prototypes/BiomePrototype.cs b/Content.Server/Worldgen/Prototypes/BiomePrototype.cs index b76d4547f6..3c83a5c711 100644 --- a/Content.Server/Worldgen/Prototypes/BiomePrototype.cs +++ b/Content.Server/Worldgen/Prototypes/BiomePrototype.cs @@ -41,7 +41,7 @@ public sealed class BiomePrototype : IPrototype, IInheritingPrototype /// [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. /// diff --git a/Content.Server/Worldgen/Prototypes/WorldgenConfigPrototype.cs b/Content.Server/Worldgen/Prototypes/WorldgenConfigPrototype.cs index b2c1230975..13408f5d94 100644 --- a/Content.Server/Worldgen/Prototypes/WorldgenConfigPrototype.cs +++ b/Content.Server/Worldgen/Prototypes/WorldgenConfigPrototype.cs @@ -18,7 +18,7 @@ public sealed class WorldgenConfigPrototype : IPrototype /// The components that get added to the target map. /// [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. /// diff --git a/Content.Shared/Humanoid/Prototypes/RandomHumanoidSettingsPrototype.cs b/Content.Shared/Humanoid/Prototypes/RandomHumanoidSettingsPrototype.cs index 2c2da188b3..367ff10748 100644 --- a/Content.Shared/Humanoid/Prototypes/RandomHumanoidSettingsPrototype.cs +++ b/Content.Shared/Humanoid/Prototypes/RandomHumanoidSettingsPrototype.cs @@ -33,5 +33,5 @@ public sealed class RandomHumanoidSettingsPrototype : IPrototype, IInheritingPro /// Extra components to add to this entity. /// [DataField("components")] - public EntityPrototype.ComponentRegistry? Components { get; } + public ComponentRegistry? Components { get; } } diff --git a/Content.Shared/Payload/Components/PayloadTriggerComponent.cs b/Content.Shared/Payload/Components/PayloadTriggerComponent.cs index c0dfb4db2a..e611a0d102 100644 --- a/Content.Shared/Payload/Components/PayloadTriggerComponent.cs +++ b/Content.Shared/Payload/Components/PayloadTriggerComponent.cs @@ -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. /// [DataField("components", serverOnly:true, readOnly: true)] - public readonly EntityPrototype.ComponentRegistry? Components = null; + public readonly ComponentRegistry? Components = null; /// /// Keeps track of what components this trigger has granted to the payload case. diff --git a/Content.Shared/Xenoarchaeology/XenoArtifacts/ArtifactEffectPrototype.cs b/Content.Shared/Xenoarchaeology/XenoArtifacts/ArtifactEffectPrototype.cs index 0fa62fdee0..1e47b9e443 100644 --- a/Content.Shared/Xenoarchaeology/XenoArtifacts/ArtifactEffectPrototype.cs +++ b/Content.Shared/Xenoarchaeology/XenoArtifacts/ArtifactEffectPrototype.cs @@ -21,13 +21,13 @@ public sealed class ArtifactEffectPrototype : IPrototype /// These are removed after the node is exited and the effect is changed. /// [DataField("components", serverOnly: true)] - public EntityPrototype.ComponentRegistry Components = new(); + public ComponentRegistry Components = new(); /// /// Components that are permanently added to an entity when the effect's node is entered. /// [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")] diff --git a/Content.Shared/Xenoarchaeology/XenoArtifacts/ArtifactTriggerPrototype.cs b/Content.Shared/Xenoarchaeology/XenoArtifacts/ArtifactTriggerPrototype.cs index ff34f6fafe..76f827b00f 100644 --- a/Content.Shared/Xenoarchaeology/XenoArtifacts/ArtifactTriggerPrototype.cs +++ b/Content.Shared/Xenoarchaeology/XenoArtifacts/ArtifactTriggerPrototype.cs @@ -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; diff --git a/Resources/Prototypes/Entities/Stations/base.yml b/Resources/Prototypes/Entities/Stations/base.yml new file mode 100644 index 0000000000..0a31b13394 --- /dev/null +++ b/Resources/Prototypes/Entities/Stations/base.yml @@ -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. diff --git a/Resources/Prototypes/Entities/Stations/nanotrasen.yml b/Resources/Prototypes/Entities/Stations/nanotrasen.yml new file mode 100644 index 0000000000..f7d4c39792 --- /dev/null +++ b/Resources/Prototypes/Entities/Stations/nanotrasen.yml @@ -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 diff --git a/Resources/Prototypes/GameRules/roundstart.yml b/Resources/Prototypes/GameRules/roundstart.yml index 0d493ba658..1346631af5 100644 --- a/Resources/Prototypes/GameRules/roundstart.yml +++ b/Resources/Prototypes/GameRules/roundstart.yml @@ -36,6 +36,7 @@ noSpawn: true components: - type: NukeopsRule + faction: Syndicate - type: entity id: Pirates diff --git a/Resources/Prototypes/Maps/aspid.yml b/Resources/Prototypes/Maps/aspid.yml index e457bb95d0..94e95f6d8e 100644 --- a/Resources/Prototypes/Maps/aspid.yml +++ b/Resources/Prototypes/Maps/aspid.yml @@ -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] diff --git a/Resources/Prototypes/Maps/bagel.yml b/Resources/Prototypes/Maps/bagel.yml index 68419c03df..521c34cd5a 100644 --- a/Resources/Prototypes/Maps/bagel.yml +++ b/Resources/Prototypes/Maps/bagel.yml @@ -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 ] diff --git a/Resources/Prototypes/Maps/barratry.yml b/Resources/Prototypes/Maps/barratry.yml index 2d9d3e2b57..7391c53eb2 100644 --- a/Resources/Prototypes/Maps/barratry.yml +++ b/Resources/Prototypes/Maps/barratry.yml @@ -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] diff --git a/Resources/Prototypes/Maps/box.yml b/Resources/Prototypes/Maps/box.yml index 5efbd3ade4..6c4caf01ad 100644 --- a/Resources/Prototypes/Maps/box.yml +++ b/Resources/Prototypes/Maps/box.yml @@ -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 ] diff --git a/Resources/Prototypes/Maps/centcomm.yml b/Resources/Prototypes/Maps/centcomm.yml index ebdb10f3e4..47dc5ca1f3 100644 --- a/Resources/Prototypes/Maps/centcomm.yml +++ b/Resources/Prototypes/Maps/centcomm.yml @@ -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' diff --git a/Resources/Prototypes/Maps/cluster.yml b/Resources/Prototypes/Maps/cluster.yml index 80072ddb13..9957fc33bf 100644 --- a/Resources/Prototypes/Maps/cluster.yml +++ b/Resources/Prototypes/Maps/cluster.yml @@ -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 ] diff --git a/Resources/Prototypes/Maps/debug.yml b/Resources/Prototypes/Maps/debug.yml index f3907791ba..be23cdac99 100644 --- a/Resources/Prototypes/Maps/debug.yml +++ b/Resources/Prototypes/Maps/debug.yml @@ -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 ] diff --git a/Resources/Prototypes/Maps/fland.yml b/Resources/Prototypes/Maps/fland.yml index 1e9a62c301..b42daf688b 100644 --- a/Resources/Prototypes/Maps/fland.yml +++ b/Resources/Prototypes/Maps/fland.yml @@ -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 ] diff --git a/Resources/Prototypes/Maps/infiltrator.yml b/Resources/Prototypes/Maps/infiltrator.yml deleted file mode 100644 index d0c45ddf69..0000000000 --- a/Resources/Prototypes/Maps/infiltrator.yml +++ /dev/null @@ -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 ] diff --git a/Resources/Prototypes/Maps/kettle.yml b/Resources/Prototypes/Maps/kettle.yml index 326e3b3a37..6c538e5108 100644 --- a/Resources/Prototypes/Maps/kettle.yml +++ b/Resources/Prototypes/Maps/kettle.yml @@ -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] diff --git a/Resources/Prototypes/Maps/marathon.yml b/Resources/Prototypes/Maps/marathon.yml index 1a14167697..24440e526f 100644 --- a/Resources/Prototypes/Maps/marathon.yml +++ b/Resources/Prototypes/Maps/marathon.yml @@ -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 ] diff --git a/Resources/Prototypes/Maps/meta.yml b/Resources/Prototypes/Maps/meta.yml index f86a1222bb..26c9328056 100644 --- a/Resources/Prototypes/Maps/meta.yml +++ b/Resources/Prototypes/Maps/meta.yml @@ -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 ] diff --git a/Resources/Prototypes/Maps/moose.yml b/Resources/Prototypes/Maps/moose.yml index ec49d41422..21d2a07cce 100644 --- a/Resources/Prototypes/Maps/moose.yml +++ b/Resources/Prototypes/Maps/moose.yml @@ -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 ] diff --git a/Resources/Prototypes/Maps/omega.yml b/Resources/Prototypes/Maps/omega.yml index c96a0f798f..f3f067079c 100644 --- a/Resources/Prototypes/Maps/omega.yml +++ b/Resources/Prototypes/Maps/omega.yml @@ -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 ] diff --git a/Resources/Prototypes/Maps/origin.yml b/Resources/Prototypes/Maps/origin.yml index 111d943135..6638c14951 100644 --- a/Resources/Prototypes/Maps/origin.yml +++ b/Resources/Prototypes/Maps/origin.yml @@ -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] diff --git a/Resources/Prototypes/Maps/saltern.yml b/Resources/Prototypes/Maps/saltern.yml index 7301c274a3..757c0667d0 100644 --- a/Resources/Prototypes/Maps/saltern.yml +++ b/Resources/Prototypes/Maps/saltern.yml @@ -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 ] diff --git a/RobustToolbox b/RobustToolbox index 57ddf81fc4..7836130bef 160000 --- a/RobustToolbox +++ b/RobustToolbox @@ -1 +1 @@ -Subproject commit 57ddf81fc4a46afccdb8d0a515be0afff31f29d5 +Subproject commit 7836130bef8126a7a4fce66dfc6d0050375455f7