From 70a205f7efa06e52a97efc4e8ddab358a0d6f2fa Mon Sep 17 00:00:00 2001 From: Dvir <39403717+dvir001@users.noreply.github.com> Date: Sun, 22 Dec 2024 16:52:52 +0200 Subject: [PATCH] Multi gamemod support (#2541) --- Content.IntegrationTests/PoolSettings.cs | 4 +- .../Systems/ShipyardSystem.Consoles.cs | 1 - ...mponent.cs => NFAdventureRuleComponent.cs} | 7 +- .../_NF/GameRule/NfAdventureRuleSystem.cs | 261 +-------------- .../_NF/GameRule/PointOfInterestPrototype.cs | 17 +- .../_NF/GameRule/PointOfInterestSystem.cs | 299 ++++++++++++++++++ Content.Shared/CCVar/CCVars.cs | 2 +- .../Locale/en-US/_NF/adventure/adventure.ftl | 8 +- .../Prototypes/_NF/GameRules/roundstart.yml | 4 +- .../_NF/PointsOfInterest/anomalousgeode.yml | 1 + .../_NF/PointsOfInterest/anomalouslab.yml | 3 +- .../_NF/PointsOfInterest/bahamamamas.yml | 1 + .../_NF/PointsOfInterest/caseys.yml | 3 +- .../_NF/PointsOfInterest/courthouse.yml | 3 +- .../Prototypes/_NF/PointsOfInterest/cove.yml | 1 + .../_NF/PointsOfInterest/depots.yml | 3 +- .../_NF/PointsOfInterest/edison.yml | 9 +- .../_NF/PointsOfInterest/grifty.yml | 3 +- .../Prototypes/_NF/PointsOfInterest/lodge.yml | 1 + .../_NF/PointsOfInterest/lpbravo.yml | 5 +- .../_NF/PointsOfInterest/mchobo.yml | 3 +- .../Prototypes/_NF/PointsOfInterest/nfsd.yml | 1 + .../_NF/PointsOfInterest/northpole.yml | 5 +- .../_NF/PointsOfInterest/omnichurch.yml | 5 +- .../_NF/PointsOfInterest/thepit.yml | 1 + .../_NF/PointsOfInterest/tinniasrest.yml | 1 + .../Prototypes/_NF/PointsOfInterest/trade.yml | 1 + .../_NF/PointsOfInterest/trademall.yml | 1 + Resources/Prototypes/_NF/game_presets.yml | 28 +- Resources/Prototypes/game_presets.yml | 10 +- 30 files changed, 396 insertions(+), 296 deletions(-) rename Content.Server/_NF/GameRule/Components/{AdventureRuleComponent.cs => NFAdventureRuleComponent.cs} (58%) rename {Content.Shared => Content.Server}/_NF/GameRule/PointOfInterestPrototype.cs (83%) create mode 100644 Content.Server/_NF/GameRule/PointOfInterestSystem.cs diff --git a/Content.IntegrationTests/PoolSettings.cs b/Content.IntegrationTests/PoolSettings.cs index 187af4569f9..5cebda0bfa1 100644 --- a/Content.IntegrationTests/PoolSettings.cs +++ b/Content.IntegrationTests/PoolSettings.cs @@ -1,4 +1,4 @@ -#nullable enable +#nullable enable using Robust.Shared.Random; @@ -93,7 +93,7 @@ public sealed class PoolSettings /// /// Frontier: the preset to run the game in. /// Set to secret for upstream tests to mimic upstream behaviour. - /// If you need to check adventure game rule things, set this to Adventure. + /// If you need to check adventure game rule things, set this to nfadventure or nfpirate. /// public string GameLobbyDefaultPreset { get; set; } = "secret"; diff --git a/Content.Server/Shipyard/Systems/ShipyardSystem.Consoles.cs b/Content.Server/Shipyard/Systems/ShipyardSystem.Consoles.cs index 62d225badd7..923371f3b1e 100644 --- a/Content.Server/Shipyard/Systems/ShipyardSystem.Consoles.cs +++ b/Content.Server/Shipyard/Systems/ShipyardSystem.Consoles.cs @@ -3,7 +3,6 @@ using Content.Server.Radio.EntitySystems; using Content.Server._NF.Bank; using Content.Server.Shipyard.Components; -using Content.Shared._NF.GameRule; using Content.Shared.Bank.Components; using Content.Shared.Shipyard.Events; using Content.Shared.Shipyard.BUI; diff --git a/Content.Server/_NF/GameRule/Components/AdventureRuleComponent.cs b/Content.Server/_NF/GameRule/Components/NFAdventureRuleComponent.cs similarity index 58% rename from Content.Server/_NF/GameRule/Components/AdventureRuleComponent.cs rename to Content.Server/_NF/GameRule/Components/NFAdventureRuleComponent.cs index fc85a5209c6..2ea4339bb70 100644 --- a/Content.Server/_NF/GameRule/Components/AdventureRuleComponent.cs +++ b/Content.Server/_NF/GameRule/Components/NFAdventureRuleComponent.cs @@ -1,10 +1,7 @@ -using Content.Shared.Procedural; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List; - namespace Content.Server._NF.GameRule.Components; -[RegisterComponent, Access(typeof(NfAdventureRuleSystem))] -public sealed partial class AdventureRuleComponent : Component +[RegisterComponent, Access(typeof(NFAdventureRuleSystem))] +public sealed partial class NFAdventureRuleComponent : Component { public List NFPlayerMinds = new(); public List CargoDepots = new(); diff --git a/Content.Server/_NF/GameRule/NfAdventureRuleSystem.cs b/Content.Server/_NF/GameRule/NfAdventureRuleSystem.cs index 5ee7e6e8b7a..68062cdb598 100644 --- a/Content.Server/_NF/GameRule/NfAdventureRuleSystem.cs +++ b/Content.Server/_NF/GameRule/NfAdventureRuleSystem.cs @@ -1,24 +1,15 @@ using System.Linq; using System.Net.Http; -using System.Numerics; using System.Text; using System.Text.Json; using System.Text.Json.Serialization; using System.Threading.Tasks; -using Content.Shared._NF.GameRule; using Content.Server._NF.GameTicking.Events; -using Robust.Server.GameObjects; -using Robust.Server.Maps; using Content.Shared.GameTicking.Components; -using Robust.Shared.Map; using Robust.Shared.Prototypes; -using Robust.Shared.Random; -using Content.Server.Shuttles.Systems; using Content.Server.Cargo.Components; using Content.Server.GameTicking; using Content.Server.GameTicking.Rules; -using Content.Server.Maps; -using Content.Server.Station.Systems; using Content.Shared._NF.CCVar; // Frontier using Robust.Shared.Configuration; using Content.Shared._NF.Bank; @@ -29,26 +20,19 @@ using Content.Shared.GameTicking; using Robust.Shared.Enums; using Robust.Server.Player; -using Content.Server.Warps; namespace Content.Server._NF.GameRule; /// /// This handles the dungeon and trading post spawning, as well as round end capitalism summary /// -public sealed class NfAdventureRuleSystem : GameRuleSystem +public sealed class NFAdventureRuleSystem : GameRuleSystem { [Dependency] private readonly IPrototypeManager _prototypeManager = default!; - [Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly IConfigurationManager _configurationManager = default!; [Dependency] private readonly IPlayerManager _playerManager = default!; - [Dependency] private readonly MapLoaderSystem _map = default!; - [Dependency] private readonly MetaDataSystem _meta = default!; - [Dependency] private readonly StationSystem _station = default!; - [Dependency] private readonly ShuttleSystem _shuttle = default!; - [Dependency] private readonly PhysicsSystem _physics = default!; [Dependency] private readonly BankSystem _bank = default!; - [Dependency] private readonly StationRenameWarpsSystems _renameWarps = default!; + [Dependency] private readonly PointOfInterestSystem _poi = default!; private readonly HttpClient _httpClient = new(); @@ -77,11 +61,6 @@ public PlayerRoundBankInformation(int startBalance, string name, NetUserId userI [ViewVariables] private Dictionary _players = new(); - private float _distanceOffset = 1f; - private List _stationCoords = new(); - - private MapId _mapId; - /// public override void Initialize() { @@ -92,7 +71,7 @@ public override void Initialize() _playerManager.PlayerStatusChanged += PlayerManagerOnPlayerStatusChanged; } - protected override void AppendRoundEndText(EntityUid uid, AdventureRuleComponent component, GameRuleComponent gameRule, ref RoundEndTextAppendEvent ev) + protected override void AppendRoundEndText(EntityUid uid, NFAdventureRuleComponent component, GameRuleComponent gameRule, ref RoundEndTextAppendEvent ev) { ev.AddLine(Loc.GetString("adventure-list-start")); var allScore = new List>(); @@ -206,12 +185,9 @@ private void OnRoundRestart(RoundRestartCleanupEvent ev) _players.Clear(); } - protected override void Started(EntityUid uid, AdventureRuleComponent component, GameRuleComponent gameRule, GameRuleStartedEvent args) + protected override void Started(EntityUid uid, NFAdventureRuleComponent component, GameRuleComponent gameRule, GameRuleStartedEvent args) { - _mapId = GameTicker.DefaultMap; - - _distanceOffset = _configurationManager.GetCVar(NFCCVars.POIDistanceModifier); - _stationCoords = new List(); + var mapUid = GameTicker.DefaultMap; //First, we need to grab the list and sort it into its respective spawning logics List depotProtos = new(); @@ -237,11 +213,11 @@ protected override void Started(EntityUid uid, AdventureRuleComponent component, remainingUniqueProtosBySpawnGroup[location.SpawnGroup].Add(location); } } - GenerateDepots(depotProtos, out component.CargoDepots); - GenerateMarkets(marketProtos, out component.MarketStations); - GenerateRequireds(requiredProtos, out component.RequiredPois); - GenerateOptionals(optionalProtos, out component.OptionalPois); - GenerateUniques(remainingUniqueProtosBySpawnGroup, out component.UniquePois); + _poi.GenerateDepots(mapUid, depotProtos, out component.CargoDepots); + _poi.GenerateMarkets(mapUid, marketProtos, out component.MarketStations); + _poi.GenerateRequireds(mapUid, requiredProtos, out component.RequiredPois); + _poi.GenerateOptionals(mapUid, optionalProtos, out component.OptionalPois); + _poi.GenerateUniques(mapUid, remainingUniqueProtosBySpawnGroup, out component.UniquePois); base.Started(uid, component, gameRule, args); @@ -249,223 +225,6 @@ protected override void Started(EntityUid uid, AdventureRuleComponent component, RaiseLocalEvent(EntityUid.Invalid, new StationsGeneratedEvent(), broadcast: true); // TODO: attach this to a meaningful entity. } - private void GenerateDepots(List depotPrototypes, out List depotStations) - { - //For depots, we want them to fill a circular type dystance formula to try to keep them as far apart as possible - //Therefore, we will be taking our range properties and treating them as magnitudes of a direction vector divided - //by the number of depots set in our corresponding cvar - - depotStations = new List(); - var depotCount = _configurationManager.GetCVar(NFCCVars.CargoDepots); - var rotation = 2 * Math.PI / depotCount; - var rotationOffset = _random.NextAngle() / depotCount; - - for (int i = 0; i < depotCount && depotPrototypes.Count > 0; i++) - { - var proto = _random.Pick(depotPrototypes); - Vector2i offset = new Vector2i((int) (_random.Next(proto.MinimumDistance, proto.MaximumDistance) * _distanceOffset), 0); - offset = offset.Rotate(rotationOffset); - rotationOffset += rotation; - // Append letter to depot name. - - string overrideName = proto.Name; - if (i < 26) - overrideName += $" {(char) ('A' + i)}"; // " A" ... " Z" - else - overrideName += $" {i + 1}"; // " 27", " 28"... - if (TrySpawnPoiGrid(proto, offset, out var depotUid, overrideName: overrideName) && depotUid is { Valid: true } depot) - { - depotStations.Add(depot); - AddStationCoordsToSet(offset); // adjust list of actual station coords - } - } - } - - private void GenerateMarkets(List marketPrototypes, out List marketStations) - { - //For market stations, we are going to allow for a bit of randomness and a different offset configuration. We dont - //want copies of this one, since these can be more themed and duplicate names, for instance, can make for a less - //ideal world - - marketStations = new List(); - var marketCount = _configurationManager.GetCVar(NFCCVars.MarketStations); - _random.Shuffle(marketPrototypes); - int marketsAdded = 0; - foreach (var proto in marketPrototypes) - { - if (marketsAdded >= marketCount) - break; - - var offset = GetRandomPOICoord(proto.MinimumDistance, proto.MaximumDistance, true); - - if (TrySpawnPoiGrid(proto, offset, out var marketUid) && marketUid is { Valid: true } market) - { - marketStations.Add(market); - marketsAdded++; - AddStationCoordsToSet(offset); - } - } - } - - private void GenerateOptionals(List optionalPrototypes, out List optionalStations) - { - //Stations that do not have a defined grouping in their prototype get a default of "Optional" and get put into the - //generic random rotation of POIs. This should include traditional places like Tinnia's rest, the Science Lab, The Pit, - //and most RP places. This will essentially put them all into a pool to pull from, and still does not use the RNG function. - - optionalStations = new List(); - var optionalCount = _configurationManager.GetCVar(NFCCVars.OptionalStations); - _random.Shuffle(optionalPrototypes); - int optionalsAdded = 0; - foreach (var proto in optionalPrototypes) - { - if (optionalsAdded >= optionalCount) - break; - - var offset = GetRandomPOICoord(proto.MinimumDistance, proto.MaximumDistance, true); - - if (TrySpawnPoiGrid(proto, offset, out var optionalUid) && optionalUid is { Valid: true } uid) - { - optionalStations.Add(uid); - AddStationCoordsToSet(offset); - } - } - } - - private void GenerateRequireds(List requiredPrototypes, out List requiredStations) - { - //Stations are required are ones that are vital to function but otherwise still follow a generic random spawn logic - //Traditionally these would be stations like Expedition Lodge, NFSD station, Prison/Courthouse POI, etc. - //There are no limit to these, and any prototype marked alwaysSpawn = true will get pulled out of any list that isnt Markets/Depots - //And will always appear every time, and also will not be included in other optional/dynamic lists - - requiredStations = new List(); - foreach (var proto in requiredPrototypes) - { - var offset = GetRandomPOICoord(proto.MinimumDistance, proto.MaximumDistance, true); - - if (TrySpawnPoiGrid(proto, offset, out var requiredUid) && requiredUid is { Valid: true } uid) - { - requiredStations.Add(uid); - AddStationCoordsToSet(offset); - } - } - } - - private void GenerateUniques(Dictionary> uniquePrototypes, out List uniqueStations) - { - //Unique locations are semi-dynamic groupings of POIs that rely each independantly on the SpawnChance per POI prototype - //Since these are the remainder, and logically must have custom-designated groupings, we can then know to subdivide - //our random pool into these found groups. - //To do this with an equal distribution on a per-POI, per-round percentage basis, we are going to ensure a random - //pick order of which we analyze our weighted chances to spawn, and if successful, remove every entry of that group - //entirely. - - uniqueStations = new List(); - foreach (var prototypeList in uniquePrototypes.Values) - { - // Try to spawn - _random.Shuffle(prototypeList); - foreach (var proto in prototypeList) - { - var chance = _random.NextFloat(0, 1); - if (chance <= proto.SpawnChance) - { - var offset = GetRandomPOICoord(proto.MinimumDistance, proto.MaximumDistance, true); - - if (TrySpawnPoiGrid(proto, offset, out var optionalUid) && optionalUid is { Valid: true } uid) - { - uniqueStations.Add(uid); - AddStationCoordsToSet(offset); - break; - } - } - } - } - } - - private bool TrySpawnPoiGrid(PointOfInterestPrototype proto, Vector2 offset, out EntityUid? gridUid, string? overrideName = null) - { - gridUid = null; - if (_map.TryLoad(_mapId, proto.GridPath.ToString(), out var mapUids, - new MapLoadOptions - { - Offset = offset, - Rotation = _random.NextAngle() - })) - { - - string stationName = string.IsNullOrEmpty(overrideName) ? proto.Name : overrideName; - - EntityUid? stationUid = null; - if (_prototypeManager.TryIndex(proto.ID, out var stationProto)) - { - stationUid = _station.InitializeNewStation(stationProto.Stations[proto.ID], mapUids, stationName); - } - - foreach (var grid in mapUids) - { - var meta = EnsureComp(grid); - _meta.SetEntityName(grid, stationName, meta); - - EntityManager.AddComponents(grid, proto.AddComponents); - } - - // Rename warp points after set up if needed - if (proto.NameWarp) - { - bool? hideWarp = proto.HideWarp ? true : null; - if (stationUid != null) - _renameWarps.SyncWarpPointsToStation(stationUid.Value, forceAdminOnly: hideWarp); - else - _renameWarps.SyncWarpPointsToGrids(mapUids, forceAdminOnly: hideWarp); - } - - gridUid = mapUids[0]; - return true; - } - - return false; - } - - private Vector2 GetRandomPOICoord(float unscaledMinRange, float unscaledMaxRange, bool scaleRange) - { - int numRetries = int.Max(_configurationManager.GetCVar(NFCCVars.POIPlacementRetries), 0); - float minDistance = float.Max(_configurationManager.GetCVar(NFCCVars.MinPOIDistance), 0); // Constant at the end to avoid NaN weirdness - - Vector2 coords = _random.NextVector2(unscaledMinRange, unscaledMaxRange); - if (scaleRange) - coords *= _distanceOffset; - for (int i = 0; i < numRetries; i++) - { - bool positionIsValid = true; - foreach (var station in _stationCoords) - { - if (Vector2.Distance(station, coords) < minDistance) - { - positionIsValid = false; - break; - } - } - - // We have a valid position - if (positionIsValid) - break; - - // No vector yet, get next value. - coords = _random.NextVector2(unscaledMinRange, unscaledMaxRange); - if (scaleRange) - coords *= _distanceOffset; - } - - return coords; - } - - private void AddStationCoordsToSet(Vector2 coords) - { - _stationCoords.Add(coords); - } - private async Task ReportRound(string message, int color = 0x77DDE7) { Logger.InfoS("discord", message); diff --git a/Content.Shared/_NF/GameRule/PointOfInterestPrototype.cs b/Content.Server/_NF/GameRule/PointOfInterestPrototype.cs similarity index 83% rename from Content.Shared/_NF/GameRule/PointOfInterestPrototype.cs rename to Content.Server/_NF/GameRule/PointOfInterestPrototype.cs index b1b11cd5963..f29cf76474e 100644 --- a/Content.Shared/_NF/GameRule/PointOfInterestPrototype.cs +++ b/Content.Server/_NF/GameRule/PointOfInterestPrototype.cs @@ -1,8 +1,8 @@ +using Content.Server.GameTicking.Presets; using Robust.Shared.Prototypes; -using Robust.Shared.Serialization; using Robust.Shared.Utility; -namespace Content.Shared._NF.GameRule; +namespace Content.Server._NF.GameRule; /// /// Describes information for a single point of interest to be spawned in the world @@ -11,7 +11,6 @@ namespace Content.Shared._NF.GameRule; [Serializable] public sealed partial class PointOfInterestPrototype : IPrototype { - /// [IdDataField] public string ID { get; private set; } = default!; @@ -22,13 +21,13 @@ public sealed partial class PointOfInterestPrototype : IPrototype public string Name { get; private set; } = ""; /// - /// Should we set the warppoint name based on the grid name. + /// Should we set the warppoint name based on the grid name. /// [DataField] public bool NameWarp { get; set; } = true; /// - /// If true, makes the warp point admin-only (hiding it for players). + /// If true, makes the warp point admin-only (hiding it for players). /// [DataField] public bool HideWarp { get; set; } = false; @@ -46,11 +45,17 @@ public sealed partial class PointOfInterestPrototype : IPrototype public int MaximumDistance { get; private set; } = 10000; /// - /// Components to be added to any spawned grids. + /// Components to be added to any spawned grids. /// [DataField] public ComponentRegistry AddComponents { get; set; } = new(); + /// + /// What gamepresets ID this POI is allowed to spawn on. + /// + [DataField] + public ProtoId[] SpawnGamePreset { get; private set; } = []; + /// /// If the POI does not belong to a pre-defined group, it will default to the "unique" internal category and will /// use this float from 0-1 as a raw chance to spawn each round. diff --git a/Content.Server/_NF/GameRule/PointOfInterestSystem.cs b/Content.Server/_NF/GameRule/PointOfInterestSystem.cs new file mode 100644 index 00000000000..d58a70b924a --- /dev/null +++ b/Content.Server/_NF/GameRule/PointOfInterestSystem.cs @@ -0,0 +1,299 @@ +using System.Linq; +using System.Numerics; +using Robust.Server.GameObjects; +using Robust.Server.Maps; +using Robust.Shared.Configuration; +using Robust.Shared.Map; +using Robust.Shared.Prototypes; +using Robust.Shared.Random; +using Content.Server.Maps; +using Content.Server.Station.Systems; +using Content.Server.GameTicking; +using Content.Shared._NF.CCVar; +using Content.Shared.GameTicking; + +namespace Content.Server._NF.GameRule; + +/// +/// This handles the dungeon and trading post spawning, as well as round end capitalism summary +/// +//[Access(typeof(NfAdventureRuleSystem))] +public sealed class PointOfInterestSystem : EntitySystem +{ + [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly IConfigurationManager _configurationManager = default!; + [Dependency] private readonly MapLoaderSystem _map = default!; + [Dependency] private readonly MetaDataSystem _meta = default!; + [Dependency] private readonly StationSystem _station = default!; + [Dependency] private readonly StationRenameWarpsSystems _renameWarps = default!; + [Dependency] private readonly GameTicker _ticker = default!; + + private List _stationCoords = new(); + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnRoundRestart); + } + + private void OnRoundRestart(RoundRestartCleanupEvent ev) + { + _stationCoords.Clear(); + } + + private void AddStationCoordsToSet(Vector2 coords) + { + _stationCoords.Add(coords); + } + + public void GenerateDepots(MapId mapUid, List depotPrototypes, out List depotStations) + { + //For depots, we want them to fill a circular type dystance formula to try to keep them as far apart as possible + //Therefore, we will be taking our range properties and treating them as magnitudes of a direction vector divided + //by the number of depots set in our corresponding cvar + + depotStations = new List(); + var depotCount = _configurationManager.GetCVar(NFCCVars.CargoDepots); + var rotation = 2 * Math.PI / depotCount; + var rotationOffset = _random.NextAngle() / depotCount; + + if (_ticker.CurrentPreset is null) + return; + + var currentPreset = _ticker.CurrentPreset.ID; + + for (int i = 0; i < depotCount && depotPrototypes.Count > 0; i++) + { + var proto = _random.Pick(depotPrototypes); + + if (!proto.SpawnGamePreset.Contains(currentPreset)) + continue; + + Vector2i offset = new Vector2i((int) _random.Next(proto.MinimumDistance, proto.MaximumDistance), 0); + offset = offset.Rotate(rotationOffset); + rotationOffset += rotation; + // Append letter to depot name. + + string overrideName = proto.Name; + if (i < 26) + overrideName += $" {(char)('A' + i)}"; // " A" ... " Z" + else + overrideName += $" {i + 1}"; // " 27", " 28"... + if (TrySpawnPoiGrid(mapUid, proto, offset, out var depotUid, overrideName: overrideName) && depotUid is { Valid: true } depot) + { + depotStations.Add(depot); + AddStationCoordsToSet(offset); // adjust list of actual station coords + } + } + } + + public void GenerateMarkets(MapId mapUid, List marketPrototypes, out List marketStations) + { + //For market stations, we are going to allow for a bit of randomness and a different offset configuration. We dont + //want copies of this one, since these can be more themed and duplicate names, for instance, can make for a less + //ideal world + + marketStations = new List(); + var marketCount = _configurationManager.GetCVar(NFCCVars.MarketStations); + _random.Shuffle(marketPrototypes); + int marketsAdded = 0; + + if (_ticker.CurrentPreset is null) + return; + var currentPreset = _ticker.CurrentPreset.ID; + + foreach (var proto in marketPrototypes) + { + if (!proto.SpawnGamePreset.Contains(currentPreset)) + continue; + + if (marketsAdded >= marketCount) + break; + + var offset = GetRandomPOICoord(proto.MinimumDistance, proto.MaximumDistance); + + if (TrySpawnPoiGrid(mapUid, proto, offset, out var marketUid) && marketUid is { Valid: true } market) + { + marketStations.Add(market); + marketsAdded++; + AddStationCoordsToSet(offset); + } + } + } + + public void GenerateOptionals(MapId mapUid, List optionalPrototypes, out List optionalStations) + { + //Stations that do not have a defined grouping in their prototype get a default of "Optional" and get put into the + //generic random rotation of POIs. This should include traditional places like Tinnia's rest, the Science Lab, The Pit, + //and most RP places. This will essentially put them all into a pool to pull from, and still does not use the RNG function. + + optionalStations = new List(); + var optionalCount = _configurationManager.GetCVar(NFCCVars.OptionalStations); + _random.Shuffle(optionalPrototypes); + int optionalsAdded = 0; + + if (_ticker.CurrentPreset is null) + return; + var currentPreset = _ticker.CurrentPreset.ID; + + foreach (var proto in optionalPrototypes) + { + if (!proto.SpawnGamePreset.Contains(currentPreset)) + continue; + + if (optionalsAdded >= optionalCount) + break; + + var offset = GetRandomPOICoord(proto.MinimumDistance, proto.MaximumDistance); + + if (TrySpawnPoiGrid(mapUid, proto, offset, out var optionalUid) && optionalUid is { Valid: true } uid) + { + optionalStations.Add(uid); + AddStationCoordsToSet(offset); + } + } + } + + public void GenerateRequireds(MapId mapUid, List requiredPrototypes, out List requiredStations) + { + //Stations are required are ones that are vital to function but otherwise still follow a generic random spawn logic + //Traditionally these would be stations like Expedition Lodge, NFSD station, Prison/Courthouse POI, etc. + //There are no limit to these, and any prototype marked alwaysSpawn = true will get pulled out of any list that isnt Markets/Depots + //And will always appear every time, and also will not be included in other optional/dynamic lists + + requiredStations = new List(); + + if (_ticker.CurrentPreset is null) + return; + var currentPreset = _ticker.CurrentPreset!.ID; + + foreach (var proto in requiredPrototypes) + { + if (!proto.SpawnGamePreset.Contains(currentPreset)) + continue; + + var offset = GetRandomPOICoord(proto.MinimumDistance, proto.MaximumDistance); + + if (TrySpawnPoiGrid(mapUid, proto, offset, out var requiredUid) && requiredUid is { Valid: true } uid) + { + requiredStations.Add(uid); + AddStationCoordsToSet(offset); + } + } + } + + public void GenerateUniques(MapId mapUid, Dictionary> uniquePrototypes, out List uniqueStations) + { + //Unique locations are semi-dynamic groupings of POIs that rely each independantly on the SpawnChance per POI prototype + //Since these are the remainder, and logically must have custom-designated groupings, we can then know to subdivide + //our random pool into these found groups. + //To do this with an equal distribution on a per-POI, per-round percentage basis, we are going to ensure a random + //pick order of which we analyze our weighted chances to spawn, and if successful, remove every entry of that group + //entirely. + + uniqueStations = new List(); + + if (_ticker.CurrentPreset is null) + return; + var currentPreset = _ticker.CurrentPreset!.ID; + + foreach (var prototypeList in uniquePrototypes.Values) + { + // Try to spawn + _random.Shuffle(prototypeList); + foreach (var proto in prototypeList) + { + if (!proto.SpawnGamePreset.Contains(currentPreset)) + continue; + + var chance = _random.NextFloat(0, 1); + if (chance <= proto.SpawnChance) + { + var offset = GetRandomPOICoord(proto.MinimumDistance, proto.MaximumDistance); + + if (TrySpawnPoiGrid(mapUid, proto, offset, out var optionalUid) && optionalUid is { Valid: true } uid) + { + uniqueStations.Add(uid); + AddStationCoordsToSet(offset); + break; + } + } + } + } + } + + private bool TrySpawnPoiGrid(MapId mapUid, PointOfInterestPrototype proto, Vector2 offset, out EntityUid? gridUid, string? overrideName = null) + { + gridUid = null; + if (_map.TryLoad(mapUid, proto.GridPath.ToString(), out var mapUids, + new MapLoadOptions + { + Offset = offset, + Rotation = _random.NextAngle() + })) + { + + string stationName = string.IsNullOrEmpty(overrideName) ? proto.Name : overrideName; + + EntityUid? stationUid = null; + if (_prototypeManager.TryIndex(proto.ID, out var stationProto)) + { + stationUid = _station.InitializeNewStation(stationProto.Stations[proto.ID], mapUids, stationName); + } + + foreach (var grid in mapUids) + { + var meta = EnsureComp(grid); + _meta.SetEntityName(grid, stationName, meta); + + EntityManager.AddComponents(grid, proto.AddComponents); + } + + // Rename warp points after set up if needed + if (proto.NameWarp) + { + bool? hideWarp = proto.HideWarp ? true : null; + if (stationUid != null) + _renameWarps.SyncWarpPointsToStation(stationUid.Value, forceAdminOnly: hideWarp); + else + _renameWarps.SyncWarpPointsToGrids(mapUids, forceAdminOnly: hideWarp); + } + + gridUid = mapUids[0]; + return true; + } + + return false; + } + + private Vector2 GetRandomPOICoord(float unscaledMinRange, float unscaledMaxRange) + { + int numRetries = int.Max(_configurationManager.GetCVar(NFCCVars.POIPlacementRetries), 0); + float minDistance = float.Max(_configurationManager.GetCVar(NFCCVars.MinPOIDistance), 0); // Constant at the end to avoid NaN weirdness + + Vector2 coords = _random.NextVector2(unscaledMinRange, unscaledMaxRange); + for (int i = 0; i < numRetries; i++) + { + bool positionIsValid = true; + foreach (var station in _stationCoords) + { + if (Vector2.Distance(station, coords) < minDistance) + { + positionIsValid = false; + break; + } + } + + // We have a valid position + if (positionIsValid) + break; + + // No vector yet, get next value. + coords = _random.NextVector2(unscaledMinRange, unscaledMaxRange); + } + + return coords; + } +} diff --git a/Content.Shared/CCVar/CCVars.cs b/Content.Shared/CCVar/CCVars.cs index 6427dbbf734..790b77e1d11 100644 --- a/Content.Shared/CCVar/CCVars.cs +++ b/Content.Shared/CCVar/CCVars.cs @@ -163,7 +163,7 @@ public static readonly CVarDef /// Controls the default game preset. /// public static readonly CVarDef - GameLobbyDefaultPreset = CVarDef.Create("game.defaultpreset", "adventure", CVar.ARCHIVE); // Frontier: secret /// Controls if the game can force a different preset if the current preset's criteria are not met. diff --git a/Resources/Locale/en-US/_NF/adventure/adventure.ftl b/Resources/Locale/en-US/_NF/adventure/adventure.ftl index 3e1a1268163..9ee3991db5d 100644 --- a/Resources/Locale/en-US/_NF/adventure/adventure.ftl +++ b/Resources/Locale/en-US/_NF/adventure/adventure.ftl @@ -11,8 +11,12 @@ adventure-webhook-top-loss = lost a total of {$amount}. adventure-webhook-ledger-start = Ledger Summary -adventure-title = New Frontier Adventure Mode -adventure-description = Join a ship crew or buy your own and explore, research, salvage, or haul your way to riches! +nf-adventure-title = Adventure +nf-adventure-description = Join a ship crew or buy your own and explore, research, salvage, or haul your way to riches! + +nf-pirate-title = Pirates +nf-pirate-description = A gang of pirates is on the loose! Take care out in space and try not to get plundered! + currency = Spesos shipyard-rules-default1 = diff --git a/Resources/Prototypes/_NF/GameRules/roundstart.yml b/Resources/Prototypes/_NF/GameRules/roundstart.yml index 836fcc0a69b..a2214693626 100644 --- a/Resources/Prototypes/_NF/GameRules/roundstart.yml +++ b/Resources/Prototypes/_NF/GameRules/roundstart.yml @@ -1,9 +1,9 @@ - type: entity - id: Adventure + id: NFAdventure parent: BaseGameRule categories: [ HideSpawnMenu ] components: - - type: AdventureRule + - type: NFAdventureRule - type: entity id: BluespaceEventScheduler diff --git a/Resources/Prototypes/_NF/PointsOfInterest/anomalousgeode.yml b/Resources/Prototypes/_NF/PointsOfInterest/anomalousgeode.yml index b52fb814288..00644f0686e 100644 --- a/Resources/Prototypes/_NF/PointsOfInterest/anomalousgeode.yml +++ b/Resources/Prototypes/_NF/PointsOfInterest/anomalousgeode.yml @@ -13,6 +13,7 @@ name: 'Anomalous Geode' minimumDistance: 2100 maximumDistance: 3800 + spawnGamePreset: [ NFAdventure, NFPirate ] spawnGroup: ScienceLab gridPath: /Maps/_NF/POI/anomalousgeode.yml addComponents: diff --git a/Resources/Prototypes/_NF/PointsOfInterest/anomalouslab.yml b/Resources/Prototypes/_NF/PointsOfInterest/anomalouslab.yml index b3c705241ce..6d6a37e5db0 100644 --- a/Resources/Prototypes/_NF/PointsOfInterest/anomalouslab.yml +++ b/Resources/Prototypes/_NF/PointsOfInterest/anomalouslab.yml @@ -1,6 +1,6 @@ # Author Info # GitHub: RealIHANOfficial (??) -# Discord: +# Discord: # Maintainer Info # GitHub: ??? @@ -13,6 +13,7 @@ name: 'Anomalous Lab' minimumDistance: 2100 maximumDistance: 3800 + spawnGamePreset: [ NFAdventure, NFPirate ] spawnGroup: ScienceLab gridPath: /Maps/_NF/POI/anomalouslab.yml addComponents: diff --git a/Resources/Prototypes/_NF/PointsOfInterest/bahamamamas.yml b/Resources/Prototypes/_NF/PointsOfInterest/bahamamamas.yml index 9c89370ccc4..794d1c19e1f 100644 --- a/Resources/Prototypes/_NF/PointsOfInterest/bahamamamas.yml +++ b/Resources/Prototypes/_NF/PointsOfInterest/bahamamamas.yml @@ -13,6 +13,7 @@ name: "Bahama Mama's" minimumDistance: 1200 maximumDistance: 2900 + spawnGamePreset: [ NFAdventure, NFPirate ] spawnGroup: RestStop gridPath: /Maps/_NF/POI/bahama.yml addComponents: diff --git a/Resources/Prototypes/_NF/PointsOfInterest/caseys.yml b/Resources/Prototypes/_NF/PointsOfInterest/caseys.yml index e4ff899c439..bad9005947c 100644 --- a/Resources/Prototypes/_NF/PointsOfInterest/caseys.yml +++ b/Resources/Prototypes/_NF/PointsOfInterest/caseys.yml @@ -1,5 +1,5 @@ # Author Info -# GitHub: +# GitHub: # Discord: Terezi (??) # Maintainer Info @@ -13,6 +13,7 @@ name: "Crazy Casey's Casino" minimumDistance: 3250 maximumDistance: 5600 + spawnGamePreset: [ NFAdventure, NFPirate ] gridPath: /Maps/_NF/POI/caseyscasino.yml addComponents: - type: IFF diff --git a/Resources/Prototypes/_NF/PointsOfInterest/courthouse.yml b/Resources/Prototypes/_NF/PointsOfInterest/courthouse.yml index e56ca7a0ff5..a35d46d3eda 100644 --- a/Resources/Prototypes/_NF/PointsOfInterest/courthouse.yml +++ b/Resources/Prototypes/_NF/PointsOfInterest/courthouse.yml @@ -7,12 +7,13 @@ # Discord: ??? # Notes: -# +# - type: pointOfInterest id: Courthouse name: "Courthouse" minimumDistance: 1150 maximumDistance: 2050 + spawnGamePreset: [ NFAdventure, NFPirate ] spawnGroup: Required gridPath: /Maps/_NF/POI/courthouse.yml addComponents: diff --git a/Resources/Prototypes/_NF/PointsOfInterest/cove.yml b/Resources/Prototypes/_NF/PointsOfInterest/cove.yml index 3a6810a9a91..57bb4d1c336 100644 --- a/Resources/Prototypes/_NF/PointsOfInterest/cove.yml +++ b/Resources/Prototypes/_NF/PointsOfInterest/cove.yml @@ -13,6 +13,7 @@ name: Pirate Cove minimumDistance: 10000 maximumDistance: 15000 + spawnGamePreset: [ NFPirate ] spawnGroup: Required gridPath: /Maps/_NF/POI/cove.yml hideWarp: true diff --git a/Resources/Prototypes/_NF/PointsOfInterest/depots.yml b/Resources/Prototypes/_NF/PointsOfInterest/depots.yml index d46469c1348..0b8eae5b82c 100644 --- a/Resources/Prototypes/_NF/PointsOfInterest/depots.yml +++ b/Resources/Prototypes/_NF/PointsOfInterest/depots.yml @@ -13,6 +13,7 @@ name: Cargo Depot minimumDistance: 4500 maximumDistance: 6000 + spawnGamePreset: [ NFAdventure, NFPirate ] spawnGroup: CargoDepot gridPath: /Maps/_NF/POI/cargodepot.yml addComponents: @@ -64,4 +65,4 @@ stationProto: MarketFrontierOutpost components: - type: StationNameSetup - mapNameTemplate: 'Cargo Depot' # Has a letter appended in NfAdventureSystem \ No newline at end of file + mapNameTemplate: 'Cargo Depot' # Has a letter appended in NfAdventureSystem diff --git a/Resources/Prototypes/_NF/PointsOfInterest/edison.yml b/Resources/Prototypes/_NF/PointsOfInterest/edison.yml index c06777fa9bb..04bbf80b51d 100644 --- a/Resources/Prototypes/_NF/PointsOfInterest/edison.yml +++ b/Resources/Prototypes/_NF/PointsOfInterest/edison.yml @@ -1,5 +1,5 @@ # Author Info -# GitHub: +# GitHub: # Discord: Checkraze # Maintainer Info @@ -7,14 +7,15 @@ # Discord: ??? # Notes: -# +# # - type: pointOfInterest # id: Edison # name: 'Edison Power Plant' # minimumDistance: 3650 # maximumDistance: 6400 + # spawnGamePreset: [ NFAdventure, NFPirate ] # spawnGroup: Required - # gridPath: /Maps/_NF/POI/edison.yml + # gridPath: /Maps/_NF/POI/edison.yml # addComponents: # - type: IFF # color: "#3737C8" @@ -38,4 +39,4 @@ # availableJobs: # Pilot: [ 0, 0 ] # Mercenary: [ 0, 0 ] - # Contractor: [ 0, 0 ] \ No newline at end of file + # Contractor: [ 0, 0 ] diff --git a/Resources/Prototypes/_NF/PointsOfInterest/grifty.yml b/Resources/Prototypes/_NF/PointsOfInterest/grifty.yml index 4b9d434f497..cb5fce22f97 100644 --- a/Resources/Prototypes/_NF/PointsOfInterest/grifty.yml +++ b/Resources/Prototypes/_NF/PointsOfInterest/grifty.yml @@ -1,5 +1,5 @@ # Author Info -# GitHub: +# GitHub: # Discord: ??? # Maintainer Info @@ -13,6 +13,7 @@ name: "Grifty's Gas n Grub" minimumDistance: 3250 maximumDistance: 5600 + spawnGamePreset: [ NFAdventure, NFPirate ] spawnGroup: Scrapyard gridPath: /Maps/_NF/POI/grifty.yml addComponents: diff --git a/Resources/Prototypes/_NF/PointsOfInterest/lodge.yml b/Resources/Prototypes/_NF/PointsOfInterest/lodge.yml index b9d5ce3ebac..eb09273a2e4 100644 --- a/Resources/Prototypes/_NF/PointsOfInterest/lodge.yml +++ b/Resources/Prototypes/_NF/PointsOfInterest/lodge.yml @@ -13,6 +13,7 @@ name: 'Expeditionary Lodge' minimumDistance: 1650 maximumDistance: 3400 + spawnGamePreset: [ NFAdventure, NFPirate ] spawnGroup: Required gridPath: /Maps/_NF/POI/lodge.yml addComponents: diff --git a/Resources/Prototypes/_NF/PointsOfInterest/lpbravo.yml b/Resources/Prototypes/_NF/PointsOfInterest/lpbravo.yml index 478b777968f..7f135395d5b 100644 --- a/Resources/Prototypes/_NF/PointsOfInterest/lpbravo.yml +++ b/Resources/Prototypes/_NF/PointsOfInterest/lpbravo.yml @@ -1,5 +1,5 @@ # Author Info -# GitHub: +# GitHub: # Discord: Checkraze # Maintainer Info @@ -13,6 +13,7 @@ name: 'Listening Point Bravo' minimumDistance: 4000 maximumDistance: 6000 + spawnGamePreset: [ NFAdventure, NFPirate ] spawnGroup: SyndicateFOB gridPath: /Maps/_NF/POI/lpbravo.yml hideWarp: true @@ -39,4 +40,4 @@ mapNameTemplate: 'Listening Point Bravo' - type: StationJobs availableJobs: {} - - type: StationDeadDropHintExempt \ No newline at end of file + - type: StationDeadDropHintExempt diff --git a/Resources/Prototypes/_NF/PointsOfInterest/mchobo.yml b/Resources/Prototypes/_NF/PointsOfInterest/mchobo.yml index ef4b3ece947..aa6a3e70c2b 100644 --- a/Resources/Prototypes/_NF/PointsOfInterest/mchobo.yml +++ b/Resources/Prototypes/_NF/PointsOfInterest/mchobo.yml @@ -8,12 +8,13 @@ # Notes: # Dumping ground of broken dreams and broken ships. -# Based on the McCargo built by Dvir01 (https://github.com/dvir001) and ruined with drunken pride by Tych0. +# Based on the McCargo built by Dvir01 (https://github.com/dvir001) and ruined with drunken pride by Tych0. - type: pointOfInterest id: McHobo name: Derelict McCargo minimumDistance: 3250 maximumDistance: 5600 + spawnGamePreset: [ NFAdventure, NFPirate ] spawnGroup: Scrapyard gridPath: /Maps/_NF/POI/mchobo.yml addComponents: diff --git a/Resources/Prototypes/_NF/PointsOfInterest/nfsd.yml b/Resources/Prototypes/_NF/PointsOfInterest/nfsd.yml index 09336a02ce0..d993915f438 100644 --- a/Resources/Prototypes/_NF/PointsOfInterest/nfsd.yml +++ b/Resources/Prototypes/_NF/PointsOfInterest/nfsd.yml @@ -13,6 +13,7 @@ name: 'NFSD Outpost' minimumDistance: 750 maximumDistance: 1000 + spawnGamePreset: [ NFAdventure, NFPirate ] spawnGroup: Required gridPath: /Maps/_NF/POI/nfsd.yml addComponents: diff --git a/Resources/Prototypes/_NF/PointsOfInterest/northpole.yml b/Resources/Prototypes/_NF/PointsOfInterest/northpole.yml index 59324e7c148..47a9c84fc8b 100644 --- a/Resources/Prototypes/_NF/PointsOfInterest/northpole.yml +++ b/Resources/Prototypes/_NF/PointsOfInterest/northpole.yml @@ -1,5 +1,5 @@ # Author Info -# GitHub: +# GitHub: # Discord: Checkraze # Maintainer Info @@ -13,6 +13,7 @@ name: "The North Pole" minimumDistance: 2150 maximumDistance: 4850 + spawnGamePreset: [ NFAdventure, NFPirate ] spawnGroup: Christmas spawnChance: 0 gridPath: /Maps/_NF/POI/northpole.yml @@ -23,4 +24,4 @@ flags: [HideLabel] - type: Shuttle angularDamping: 999999 - linearDamping: 999999 \ No newline at end of file + linearDamping: 999999 diff --git a/Resources/Prototypes/_NF/PointsOfInterest/omnichurch.yml b/Resources/Prototypes/_NF/PointsOfInterest/omnichurch.yml index 43a8df90949..8a0861058c2 100644 --- a/Resources/Prototypes/_NF/PointsOfInterest/omnichurch.yml +++ b/Resources/Prototypes/_NF/PointsOfInterest/omnichurch.yml @@ -7,12 +7,13 @@ # Discord: ??? # Notes: -# +# - type: pointOfInterest id: Omnichurch name: "Omnichurch Beacon" minimumDistance: 2200 maximumDistance: 4900 + spawnGamePreset: [ NFAdventure, NFPirate ] gridPath: /Maps/_NF/POI/beacon.yml addComponents: - type: IFF @@ -20,4 +21,4 @@ readOnly: true - type: Shuttle angularDamping: 999999 - linearDamping: 999999 \ No newline at end of file + linearDamping: 999999 diff --git a/Resources/Prototypes/_NF/PointsOfInterest/thepit.yml b/Resources/Prototypes/_NF/PointsOfInterest/thepit.yml index 80ceac9e771..8a13ec26b97 100644 --- a/Resources/Prototypes/_NF/PointsOfInterest/thepit.yml +++ b/Resources/Prototypes/_NF/PointsOfInterest/thepit.yml @@ -13,6 +13,7 @@ name: "The Pit" minimumDistance: 2200 maximumDistance: 4200 + spawnGamePreset: [ NFAdventure, NFPirate ] spawnGroup: Arena gridPath: /Maps/_NF/POI/arena.yml addComponents: diff --git a/Resources/Prototypes/_NF/PointsOfInterest/tinniasrest.yml b/Resources/Prototypes/_NF/PointsOfInterest/tinniasrest.yml index 5ca2436ec0b..c7f48701a94 100644 --- a/Resources/Prototypes/_NF/PointsOfInterest/tinniasrest.yml +++ b/Resources/Prototypes/_NF/PointsOfInterest/tinniasrest.yml @@ -13,6 +13,7 @@ name: "Tinnia's Rest" minimumDistance: 1200 maximumDistance: 2900 + spawnGamePreset: [ NFAdventure, NFPirate ] spawnGroup: RestStop gridPath: /Maps/_NF/POI/tinnia.yml addComponents: diff --git a/Resources/Prototypes/_NF/PointsOfInterest/trade.yml b/Resources/Prototypes/_NF/PointsOfInterest/trade.yml index 475cd67bf6a..555f321139b 100644 --- a/Resources/Prototypes/_NF/PointsOfInterest/trade.yml +++ b/Resources/Prototypes/_NF/PointsOfInterest/trade.yml @@ -13,6 +13,7 @@ name: Trade Outpost minimumDistance: 1500 maximumDistance: 2500 + spawnGamePreset: [ NFAdventure, NFPirate ] spawnGroup: MarketStation gridPath: /Maps/_NF/POI/trade.yml addComponents: diff --git a/Resources/Prototypes/_NF/PointsOfInterest/trademall.yml b/Resources/Prototypes/_NF/PointsOfInterest/trademall.yml index 5c14ca2b5ae..9b7e75158fb 100644 --- a/Resources/Prototypes/_NF/PointsOfInterest/trademall.yml +++ b/Resources/Prototypes/_NF/PointsOfInterest/trademall.yml @@ -13,6 +13,7 @@ name: Trade Mall minimumDistance: 1500 maximumDistance: 2500 + spawnGamePreset: [ NFAdventure, NFPirate ] spawnGroup: MarketStation gridPath: /Maps/_NF/POI/trademall.yml addComponents: diff --git a/Resources/Prototypes/_NF/game_presets.yml b/Resources/Prototypes/_NF/game_presets.yml index b87244e0a7f..6c39e92fdb9 100644 --- a/Resources/Prototypes/_NF/game_presets.yml +++ b/Resources/Prototypes/_NF/game_presets.yml @@ -1,12 +1,30 @@ - type: gamePreset - id: Adventure + id: NFAdventure alias: + - nfadventure - adventure - name: adventure-title - description: adventure-description - showInVote: false + name: nf-adventure-title + description: nf-adventure-description + showInVote: true rules: - - Adventure + - NFAdventure + - BasicStationEventScheduler + - BluespaceEventScheduler + - BluespaceDungeonEventScheduler + - BluespaceSalvageEventScheduler + - SmugglingEventScheduler + - FrontierRoundstartVariation + +- type: gamePreset + id: NFPirate + alias: + - nfpirate + - pirate + name: nf-pirate-title + description: nf-pirate-description + showInVote: true + rules: + - NFAdventure - BasicStationEventScheduler - BluespaceEventScheduler - BluespaceDungeonEventScheduler diff --git a/Resources/Prototypes/game_presets.yml b/Resources/Prototypes/game_presets.yml index 945b4a8c83b..ad66624f7f5 100644 --- a/Resources/Prototypes/game_presets.yml +++ b/Resources/Prototypes/game_presets.yml @@ -91,7 +91,7 @@ showInVote: false #4boring4vote description: greenshift-description rules: - - SpaceTrafficControlFriendlyEventScheduler + - SpaceTrafficControlFriendlyEventScheduler - BasicRoundstartVariation - type: gamePreset @@ -100,7 +100,7 @@ - secret - sekrit name: secret-title - showInVote: true + showInVote: false # Frontier: true < false description: secret-description rules: - Secret @@ -126,7 +126,7 @@ showInVote: false #Admin Use description: secret-description rules: - - SpaceTrafficControlFriendlyEventScheduler + - SpaceTrafficControlFriendlyEventScheduler - BasicRoundstartVariation - type: gamePreset @@ -164,7 +164,7 @@ name: death-match-title description: death-match-description maxPlayers: 15 - showInVote: true + showInVote: false # Frontier: true < false supportedMaps: DeathMatchMapPool rules: - DeathMatch31 @@ -233,4 +233,4 @@ - BasicStationEventScheduler - KesslerSyndromeScheduler - SpaceTrafficControlEventScheduler - - BasicRoundstartVariation \ No newline at end of file + - BasicRoundstartVariation