diff --git a/Content.Client/Administration/Systems/AdminSystem.cs b/Content.Client/Administration/Systems/AdminSystem.cs index f7451d23047..db1b721343e 100644 --- a/Content.Client/Administration/Systems/AdminSystem.cs +++ b/Content.Client/Administration/Systems/AdminSystem.cs @@ -10,16 +10,9 @@ public sealed partial class AdminSystem : EntitySystem { public event Action>? PlayerListChanged; - private Dictionary? _playerList; - public IReadOnlyList PlayerList - { - get - { - if (_playerList != null) return _playerList.Values.ToList(); - - return new List(); - } - } + public Dictionary PlayerInfos = new(); + public IReadOnlyList PlayerList => + PlayerInfos != null ? PlayerInfos.Values.ToList() : new List(); public override void Initialize() { @@ -40,15 +33,15 @@ private void OnPlayerInfoChanged(PlayerInfoChangedEvent ev) { if(ev.PlayerInfo == null) return; - if (_playerList == null) _playerList = new(); + if (PlayerInfos == null) PlayerInfos = new(); - _playerList[ev.PlayerInfo.SessionId] = ev.PlayerInfo; - PlayerListChanged?.Invoke(_playerList.Values.ToList()); + PlayerInfos[ev.PlayerInfo.SessionId] = ev.PlayerInfo; + PlayerListChanged?.Invoke(PlayerInfos.Values.ToList()); } private void OnPlayerListChanged(FullPlayerListEvent msg) { - _playerList = msg.PlayersInfo.ToDictionary(x => x.SessionId, x => x); + PlayerInfos = msg.PlayersInfo.ToDictionary(x => x.SessionId, x => x); PlayerListChanged?.Invoke(msg.PlayersInfo); } } diff --git a/Content.Client/Administration/Systems/BwoinkSystem.cs b/Content.Client/Administration/Systems/BwoinkSystem.cs index 5166dc8416b..a3b295d6b6e 100644 --- a/Content.Client/Administration/Systems/BwoinkSystem.cs +++ b/Content.Client/Administration/Systems/BwoinkSystem.cs @@ -1,7 +1,10 @@ #nullable enable +using Content.Client.UserInterface.Systems.Bwoink; using Content.Shared.Administration; using JetBrains.Annotations; +using Robust.Client.Audio; using Robust.Shared.Network; +using Robust.Shared.Player; using Robust.Shared.Timing; namespace Content.Client.Administration.Systems @@ -10,6 +13,8 @@ namespace Content.Client.Administration.Systems public sealed class BwoinkSystem : SharedBwoinkSystem { [Dependency] private readonly IGameTiming _timing = default!; + [Dependency] private readonly AudioSystem _audio = default!; + [Dependency] private readonly AdminSystem _adminSystem = default!; public event EventHandler? OnBwoinkTextMessageRecieved; private (TimeSpan Timestamp, bool Typing) _lastTypingUpdateSent; @@ -21,6 +26,10 @@ protected override void OnBwoinkTextMessage(BwoinkTextMessage message, EntitySes public void Send(NetUserId channelId, string text, bool playSound) { + var info = _adminSystem.PlayerInfos.GetValueOrDefault(channelId)?.Connected ?? true; + _audio.PlayGlobal(info ? AHelpUIController.AHelpSendSound : AHelpUIController.AHelpErrorSound, + Filter.Local(), false); + // Reuse the channel ID as the 'true sender'. // Server will ignore this and if someone makes it not ignore this (which is bad, allows impersonation!!!), that will help. RaiseNetworkEvent(new BwoinkTextMessage(channelId, channelId, text, playSound: playSound)); @@ -31,9 +40,7 @@ public void SendInputTextUpdated(NetUserId channel, bool typing) { if (_lastTypingUpdateSent.Typing == typing && _lastTypingUpdateSent.Timestamp + TimeSpan.FromSeconds(1) > _timing.RealTime) - { return; - } _lastTypingUpdateSent = (_timing.RealTime, typing); RaiseNetworkEvent(new BwoinkClientTypingUpdated(channel, typing)); diff --git a/Content.Client/LateJoin/LateJoinGui.cs b/Content.Client/LateJoin/LateJoinGui.cs index ba9351d6746..92e1ee2aaf1 100644 --- a/Content.Client/LateJoin/LateJoinGui.cs +++ b/Content.Client/LateJoin/LateJoinGui.cs @@ -4,9 +4,13 @@ using Content.Client.GameTicking.Managers; using Content.Client.UserInterface.Controls; using Content.Client.Players.PlayTimeTracking; +using Content.Client.Preferences; using Content.Shared.CCVar; +using Content.Shared.Customization.Systems; +using Content.Shared.Preferences; using Content.Shared.Roles; using Content.Shared.StatusIcon; +using Microsoft.Win32.SafeHandles; using Robust.Client.Console; using Robust.Client.GameObjects; using Robust.Client.UserInterface; @@ -26,12 +30,15 @@ public sealed class LateJoinGui : DefaultWindow [Dependency] private readonly IConfigurationManager _configManager = default!; [Dependency] private readonly IEntitySystemManager _entitySystem = default!; [Dependency] private readonly JobRequirementsManager _jobRequirements = default!; + [Dependency] private readonly IEntityManager _entityManager = default!; + [Dependency] private readonly IClientPreferencesManager _prefs = default!; public event Action<(NetEntity, string)> SelectedId; private readonly ClientGameTicker _gameTicker; private readonly SpriteSystem _sprites; private readonly CrewManifestSystem _crewManifest; + private readonly CharacterRequirementsSystem _characterRequirements; private readonly Dictionary>> _jobButtons = new(); private readonly Dictionary> _jobCategories = new(); @@ -46,6 +53,7 @@ public LateJoinGui() _sprites = _entitySystem.GetEntitySystem(); _crewManifest = _entitySystem.GetEntitySystem(); _gameTicker = _entitySystem.GetEntitySystem(); + _characterRequirements = _entitySystem.GetEntitySystem(); Title = Loc.GetString("late-join-gui-title"); @@ -254,14 +262,24 @@ private void RebuildUI() jobButton.OnPressed += _ => SelectedId.Invoke((id, jobButton.JobId)); - if (!_jobRequirements.IsAllowed(prototype, out var reason)) + if (!_characterRequirements.CheckRequirementsValid( + prototype.Requirements ?? new(), + prototype, + (HumanoidCharacterProfile) (_prefs.Preferences?.SelectedCharacter + ?? HumanoidCharacterProfile.DefaultWithSpecies()), + _jobRequirements.GetRawPlayTimeTrackers(), + _jobRequirements.IsWhitelisted(), + _entityManager, + _prototypeManager, + _configManager, + out var reasons)) { jobButton.Disabled = true; - if (!reason.IsEmpty) + if (reasons.Count > 0) { var tooltip = new Tooltip(); - tooltip.SetMessage(reason); + tooltip.SetMessage(_characterRequirements.GetRequirementsText(reasons)); jobButton.TooltipSupplier = _ => tooltip; } diff --git a/Content.Client/Lobby/LobbyUIController.cs b/Content.Client/Lobby/LobbyUIController.cs index 36f43d6f4aa..47ab651c10e 100644 --- a/Content.Client/Lobby/LobbyUIController.cs +++ b/Content.Client/Lobby/LobbyUIController.cs @@ -2,6 +2,7 @@ using Content.Client.Humanoid; using Content.Client.Inventory; using Content.Client.Lobby.UI; +using Content.Client.Players.PlayTimeTracking; using Content.Client.Preferences; using Content.Client.Preferences.UI; using Content.Shared.Clothing.Loadouts.Systems; @@ -23,6 +24,7 @@ public sealed class LobbyUIController : UIController, IOnStateEntered diff --git a/Content.Client/Players/PlayTimeTracking/JobRequirementsManager.cs b/Content.Client/Players/PlayTimeTracking/JobRequirementsManager.cs index df73f5ff3f4..a2f8061d057 100644 --- a/Content.Client/Players/PlayTimeTracking/JobRequirementsManager.cs +++ b/Content.Client/Players/PlayTimeTracking/JobRequirementsManager.cs @@ -1,5 +1,6 @@ using System.Diagnostics.CodeAnalysis; using Content.Shared.CCVar; +using Content.Shared.Customization.Systems; using Content.Shared.Players; using Content.Shared.Players.PlayTimeTracking; using Content.Shared.Roles; @@ -17,9 +18,6 @@ public sealed partial class JobRequirementsManager : ISharedPlaytimeManager { [Dependency] private readonly IBaseClient _client = default!; [Dependency] private readonly IClientNetManager _net = default!; - [Dependency] private readonly IConfigurationManager _cfg = default!; - [Dependency] private readonly IEntityManager _entManager = default!; - [Dependency] private readonly IPlayerManager _playerManager = default!; [Dependency] private readonly IPrototypeManager _prototypes = default!; private readonly Dictionary _roles = new(); @@ -80,43 +78,6 @@ private void RxPlayTime(MsgPlayTime message) Updated?.Invoke(); } - public bool IsAllowed(JobPrototype job, [NotNullWhen(false)] out FormattedMessage? reason) - { - reason = null; - - if (_roleBans.Contains($"Job:{job.ID}")) - { - reason = FormattedMessage.FromUnformatted(Loc.GetString("role-ban")); - return false; - } - - var player = _playerManager.LocalSession; - if (player == null) - return true; - - return CheckRoleTime(job.Requirements, out reason); - } - - public bool CheckRoleTime(HashSet? requirements, [NotNullWhen(false)] out FormattedMessage? reason, string? localePrefix = "role-timer-") - { - reason = null; - - if (requirements == null || !_cfg.GetCVar(CCVars.GameRoleTimers)) - return true; - - var reasons = new List(); - foreach (var requirement in requirements) - { - if (JobRequirements.TryRequirementMet(requirement, _roles, out var jobReason, _entManager, _prototypes, _whitelisted, localePrefix)) - continue; - - reasons.Add(jobReason.ToMarkup()); - } - - reason = reasons.Count == 0 ? null : FormattedMessage.FromMarkup(string.Join('\n', reasons)); - return reason == null; - } - public TimeSpan FetchOverallPlaytime() { return _roles.TryGetValue("Overall", out var overallPlaytime) ? overallPlaytime : TimeSpan.Zero; @@ -137,12 +98,13 @@ public Dictionary FetchPlaytimeByRoles() public Dictionary GetPlayTimes() { - var dict = new Dictionary(); - + var dict = FetchPlaytimeByRoles(); dict.Add(PlayTimeTrackingShared.TrackerOverall, FetchOverallPlaytime()); - foreach (var role in FetchPlaytimeByRoles()) - dict.Add(role.Key, role.Value); - return dict; } + + public Dictionary GetRawPlayTimeTrackers() + { + return _roles; + } } diff --git a/Content.Client/Preferences/UI/AntagPreferenceSelector.cs b/Content.Client/Preferences/UI/AntagPreferenceSelector.cs index 06694f51168..4a339d3f659 100644 --- a/Content.Client/Preferences/UI/AntagPreferenceSelector.cs +++ b/Content.Client/Preferences/UI/AntagPreferenceSelector.cs @@ -1,5 +1,9 @@ using Content.Client.Players.PlayTimeTracking; +using Content.Shared.Customization.Systems; +using Content.Shared.Preferences; using Content.Shared.Roles; +using Robust.Shared.Configuration; +using Robust.Shared.Prototypes; namespace Content.Client.Preferences.UI; @@ -14,7 +18,7 @@ public bool Preference public event Action? PreferenceChanged; - public AntagPreferenceSelector(AntagPrototype proto) : base(proto) + public AntagPreferenceSelector(AntagPrototype proto, JobPrototype highJob) : base(proto, highJob) { Options.OnItemSelected += _ => PreferenceChanged?.Invoke(Preference); @@ -30,7 +34,23 @@ public AntagPreferenceSelector(AntagPrototype proto) : base(proto) // Immediately lock requirements if they aren't met. // Another function checks Disabled after creating the selector so this has to be done now var requirements = IoCManager.Resolve(); - if (proto.Requirements != null && !requirements.CheckRoleTime(proto.Requirements, out var reason)) - LockRequirements(reason); + var prefs = IoCManager.Resolve(); + var entMan = IoCManager.Resolve(); + var characterReqs = entMan.System(); + var protoMan = IoCManager.Resolve(); + var configMan = IoCManager.Resolve(); + + if (proto.Requirements != null + && !characterReqs.CheckRequirementsValid( + proto.Requirements, + highJob, + (HumanoidCharacterProfile) (prefs.Preferences?.SelectedCharacter ?? HumanoidCharacterProfile.DefaultWithSpecies()), + requirements.GetRawPlayTimeTrackers(), + requirements.IsWhitelisted(), + entMan, + protoMan, + configMan, + out var reasons)) + LockRequirements(characterReqs.GetRequirementsText(reasons)); } } diff --git a/Content.Client/Preferences/UI/HumanoidProfileEditor.xaml.cs b/Content.Client/Preferences/UI/HumanoidProfileEditor.xaml.cs index 771d928ebf9..954a705fceb 100644 --- a/Content.Client/Preferences/UI/HumanoidProfileEditor.xaml.cs +++ b/Content.Client/Preferences/UI/HumanoidProfileEditor.xaml.cs @@ -115,7 +115,7 @@ public HumanoidProfileEditor(IClientPreferencesManager preferencesManager, IProt _preferencesManager = preferencesManager; _configurationManager = configurationManager; _markingManager = IoCManager.Resolve(); - _characterRequirementsSystem = EntitySystem.Get(); + _characterRequirementsSystem = _entityManager.System(); _controller = UserInterfaceManager.GetUIController(); _controller.SetProfileEditor(this); @@ -642,7 +642,9 @@ private void UpdateAntagRequirements() if (!antag.SetPreference) continue; - var selector = new AntagPreferenceSelector(antag) + var selector = new AntagPreferenceSelector(antag, + _jobPriorities.FirstOrDefault(j => j.Priority == JobPriority.High)?.HighJob + ?? new()) { Margin = new Thickness(3f, 3f, 3f, 0f) }; _antagList.AddChild(selector); _antagPreferences.Add(selector); @@ -723,10 +725,17 @@ private void UpdateRoleRequirements() { var selector = new JobPrioritySelector(job, _prototypeManager); - if (!_requirements.IsAllowed(job, out var reason)) - { - selector.LockRequirements(reason); - } + if (!_characterRequirementsSystem.CheckRequirementsValid( + job.Requirements ?? new(), + job, + Profile ?? HumanoidCharacterProfile.DefaultWithSpecies(), + _requirements.GetRawPlayTimeTrackers(), + _requirements.IsWhitelisted(), + _entityManager, + _prototypeManager, + _configurationManager, + out var reasons)) + selector.LockRequirements(_characterRequirementsSystem.GetRequirementsText(reasons)); category.AddChild(selector); _jobPriorities.Add(selector); @@ -770,7 +779,17 @@ private void EnsureJobRequirementsValid() var changed = false; foreach (var selector in _jobPriorities) { - if (_requirements.IsAllowed(selector.Proto, out var _) || selector.Priority == JobPriority.Never) + if (selector.Priority == JobPriority.Never + || _characterRequirementsSystem.CheckRequirementsValid( + selector.Proto.Requirements ?? new(), + selector.Proto, + Profile ?? HumanoidCharacterProfile.DefaultWithSpecies(), + _requirements.GetRawPlayTimeTrackers(), + _requirements.IsWhitelisted(), + _entityManager, + _prototypeManager, + _configurationManager, + out _)) continue; selector.Priority = JobPriority.Never; @@ -1412,11 +1431,11 @@ private void UpdateTraits(bool showUnusable) var traits = enumeratedTraits.Where(trait => showUnusable || // Ignore everything if this is true _characterRequirementsSystem.CheckRequirementsValid( - trait, trait.Requirements, highJob?.Proto ?? new JobPrototype(), Profile ?? HumanoidCharacterProfile.DefaultWithSpecies(), - _requirements.GetPlayTimes(), + _requirements.GetRawPlayTimeTrackers(), + _requirements.IsWhitelisted(), _entityManager, _prototypeManager, _configurationManager, @@ -1427,11 +1446,11 @@ out _ // Traits to highlight red when showUnusable is true var traitsUnusable = enumeratedTraits.Where(trait => _characterRequirementsSystem.CheckRequirementsValid( - trait, trait.Requirements, highJob?.Proto ?? new JobPrototype(), Profile ?? HumanoidCharacterProfile.DefaultWithSpecies(), - _requirements.GetPlayTimes(), + _requirements.GetRawPlayTimeTrackers(), + _requirements.IsWhitelisted(), _entityManager, _prototypeManager, _configurationManager, @@ -1538,7 +1557,8 @@ out _ var selector = new TraitPreferenceSelector(trait, highJob?.Proto ?? new JobPrototype(), Profile ?? HumanoidCharacterProfile.DefaultWithSpecies(), traitsUnusable.Contains(trait) ? "" : "ButtonColorRed", - _entityManager, _prototypeManager, _configurationManager, _characterRequirementsSystem); + _entityManager, _prototypeManager, _configurationManager, _characterRequirementsSystem, + _requirements); // Look for an existing trait category BoxContainer? match = null; @@ -1570,7 +1590,8 @@ out _ { var selector = new TraitPreferenceSelector(trait, highJob?.Proto ?? new JobPrototype(), Profile ?? HumanoidCharacterProfile.DefaultWithSpecies(), "", - _entityManager, _prototypeManager, _configurationManager, _characterRequirementsSystem); + _entityManager, _prototypeManager, _configurationManager, _characterRequirementsSystem, + _requirements); AddSelector(selector, trait.Points, trait.ID); @@ -1578,7 +1599,7 @@ out _ // Hide Uncategorized tab if it's empty, other tabs already shouldn't exist if they're empty - _traitsTabs.SetTabVisible(0, uncategorized.Children.Any()); + _traitsTabs.SetTabVisible(0, uncategorized.Children.First().Children.First().Children.Any()); // Add fake tabs until tab container is happy for (var i = _traitsTabs.ChildCount - 1; i < _traitsTabs.CurrentTab; i++) @@ -1671,11 +1692,11 @@ private void UpdateLoadouts(bool showUnusable) var loadouts = enumeratedLoadouts.Where(loadout => showUnusable || // Ignore everything if this is true _characterRequirementsSystem.CheckRequirementsValid( - loadout, loadout.Requirements, highJob?.Proto ?? new JobPrototype(), Profile ?? HumanoidCharacterProfile.DefaultWithSpecies(), - _requirements.GetPlayTimes(), + _requirements.GetRawPlayTimeTrackers(), + _requirements.IsWhitelisted(), _entityManager, _prototypeManager, _configurationManager, @@ -1686,11 +1707,11 @@ out _ // Loadouts to highlight red when showUnusable is true var loadoutsUnusable = enumeratedLoadouts.Where(loadout => _characterRequirementsSystem.CheckRequirementsValid( - loadout, loadout.Requirements, highJob?.Proto ?? new JobPrototype(), Profile ?? HumanoidCharacterProfile.DefaultWithSpecies(), - _requirements.GetPlayTimes(), + _requirements.GetRawPlayTimeTrackers(), + _requirements.IsWhitelisted(), _entityManager, _prototypeManager, _configurationManager, @@ -1800,7 +1821,8 @@ out _ var selector = new LoadoutPreferenceSelector(loadout, highJob?.Proto ?? new JobPrototype(), Profile ?? HumanoidCharacterProfile.DefaultWithSpecies(), loadoutsUnusable.Contains(loadout) ? "" : "ButtonColorRed", - _entityManager, _prototypeManager, _configurationManager, _characterRequirementsSystem); + _entityManager, _prototypeManager, _configurationManager, _characterRequirementsSystem, + _requirements); // Look for an existing loadout category BoxContainer? match = null; @@ -1829,7 +1851,8 @@ out _ { var selector = new LoadoutPreferenceSelector(loadout, highJob?.Proto ?? new JobPrototype(), Profile ?? HumanoidCharacterProfile.DefaultWithSpecies(), "", - _entityManager, _prototypeManager, _configurationManager, _characterRequirementsSystem); + _entityManager, _prototypeManager, _configurationManager, _characterRequirementsSystem, + _requirements); AddSelector(selector, loadout.Cost, loadout.ID); @@ -1837,7 +1860,7 @@ out _ // Hide Uncategorized tab if it's empty, other tabs already shouldn't exist if they're empty - _loadoutsTabs.SetTabVisible(0, uncategorized.Children.Any()); + _loadoutsTabs.SetTabVisible(0, uncategorized.Children.First().Children.First().Children.Any()); // Add fake tabs until tab container is happy for (var i = _loadoutsTabs.ChildCount - 1; i < _loadoutsTabs.CurrentTab; i++) diff --git a/Content.Client/Preferences/UI/JobPrioritySelector.cs b/Content.Client/Preferences/UI/JobPrioritySelector.cs index 2e2c699c3ad..f66102d644f 100644 --- a/Content.Client/Preferences/UI/JobPrioritySelector.cs +++ b/Content.Client/Preferences/UI/JobPrioritySelector.cs @@ -4,6 +4,7 @@ using Content.Shared.StatusIcon; using Robust.Client.UserInterface.Controls; using Robust.Client.Utility; +using Robust.Shared.CPUJob.JobQueues; using Robust.Shared.Prototypes; namespace Content.Client.Preferences.UI; @@ -18,7 +19,7 @@ public JobPriority Priority public event Action? PriorityChanged; - public JobPrioritySelector(JobPrototype proto, IPrototypeManager protoMan) : base(proto) + public JobPrioritySelector(JobPrototype proto, IPrototypeManager protoMan) : base(proto, proto) { Options.OnItemSelected += _ => PriorityChanged?.Invoke(Priority); diff --git a/Content.Client/Preferences/UI/LoadoutPreferenceSelector.cs b/Content.Client/Preferences/UI/LoadoutPreferenceSelector.cs index a6839dee65f..82d8fd65b33 100644 --- a/Content.Client/Preferences/UI/LoadoutPreferenceSelector.cs +++ b/Content.Client/Preferences/UI/LoadoutPreferenceSelector.cs @@ -1,6 +1,7 @@ using System.Linq; using System.Numerics; using System.Text; +using Content.Client.Players.PlayTimeTracking; using Content.Client.Stylesheets; using Content.Shared.Clothing.Loadouts.Prototypes; using Content.Shared.Customization.Systems; @@ -32,7 +33,8 @@ public bool Preference public LoadoutPreferenceSelector(LoadoutPrototype loadout, JobPrototype highJob, HumanoidCharacterProfile profile, string style, IEntityManager entityManager, IPrototypeManager prototypeManager, - IConfigurationManager configManager, CharacterRequirementsSystem characterRequirementsSystem) + IConfigurationManager configManager, CharacterRequirementsSystem characterRequirementsSystem, + JobRequirementsManager jobRequirementsManager) { Loadout = loadout; @@ -94,8 +96,9 @@ public LoadoutPreferenceSelector(LoadoutPrototype loadout, JobPrototype highJob, // Get requirement reasons - characterRequirementsSystem.CheckRequirementsValid(loadout, loadout.Requirements, highJob, profile, - new Dictionary(), + characterRequirementsSystem.CheckRequirementsValid( + loadout.Requirements, highJob, profile, new Dictionary(), + jobRequirementsManager.IsWhitelisted(), entityManager, prototypeManager, configManager, out var reasons); diff --git a/Content.Client/Preferences/UI/RequirementsSelector.cs b/Content.Client/Preferences/UI/RequirementsSelector.cs index a4a25536d09..83b96952886 100644 --- a/Content.Client/Preferences/UI/RequirementsSelector.cs +++ b/Content.Client/Preferences/UI/RequirementsSelector.cs @@ -1,6 +1,7 @@ using System.Numerics; using Content.Client.Stylesheets; using Content.Client.UserInterface.Controls; +using Content.Shared.Roles; using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.CustomControls; using Robust.Shared.Prototypes; @@ -11,14 +12,16 @@ namespace Content.Client.Preferences.UI; public abstract class RequirementsSelector : BoxContainer where T : IPrototype { public T Proto { get; } + public JobPrototype HighJob { get; } public bool Disabled => _lockStripe.Visible; protected readonly RadioOptions Options; private readonly StripeBack _lockStripe; - protected RequirementsSelector(T proto) + protected RequirementsSelector(T proto, JobPrototype highJob) { Proto = proto; + HighJob = highJob; Options = new RadioOptions(RadioOptionsLayout.Horizontal) { diff --git a/Content.Client/Preferences/UI/TraitPreferenceSelector.cs b/Content.Client/Preferences/UI/TraitPreferenceSelector.cs index 0f843ca3a58..e9ce1a5e9be 100644 --- a/Content.Client/Preferences/UI/TraitPreferenceSelector.cs +++ b/Content.Client/Preferences/UI/TraitPreferenceSelector.cs @@ -1,4 +1,5 @@ using System.Text; +using Content.Client.Players.PlayTimeTracking; using Content.Client.Stylesheets; using Content.Shared.Customization.Systems; using Content.Shared.Preferences; @@ -30,7 +31,8 @@ public bool Preference public TraitPreferenceSelector(TraitPrototype trait, JobPrototype highJob, HumanoidCharacterProfile profile, string style, IEntityManager entityManager, IPrototypeManager prototypeManager, - IConfigurationManager configManager, CharacterRequirementsSystem characterRequirementsSystem) + IConfigurationManager configManager, CharacterRequirementsSystem characterRequirementsSystem, + JobRequirementsManager jobRequirementsManager) { Trait = trait; @@ -71,8 +73,9 @@ public TraitPreferenceSelector(TraitPrototype trait, JobPrototype highJob, // Get requirement reasons - characterRequirementsSystem.CheckRequirementsValid(trait, trait.Requirements, highJob, profile, - new Dictionary(), + characterRequirementsSystem.CheckRequirementsValid( + trait.Requirements, highJob, profile, new Dictionary(), + jobRequirementsManager.IsWhitelisted(), entityManager, prototypeManager, configManager, out var reasons); diff --git a/Content.Client/UserInterface/Systems/Bwoink/AHelpUIController.cs b/Content.Client/UserInterface/Systems/Bwoink/AHelpUIController.cs index 2c913a2d580..2d2be1babca 100644 --- a/Content.Client/UserInterface/Systems/Bwoink/AHelpUIController.cs +++ b/Content.Client/UserInterface/Systems/Bwoink/AHelpUIController.cs @@ -33,7 +33,6 @@ namespace Content.Client.UserInterface.Systems.Bwoink; public sealed class AHelpUIController: UIController, IOnSystemChanged, IOnStateChanged, IOnStateChanged { [Dependency] private readonly IClientAdminManager _adminManager = default!; - [Dependency] private readonly IConfigurationManager _config = default!; [Dependency] private readonly IPlayerManager _playerManager = default!; [Dependency] private readonly IClyde _clyde = default!; [Dependency] private readonly IUserInterfaceManager _uiManager = default!; @@ -43,9 +42,14 @@ public sealed class AHelpUIController: UIController, IOnSystemChanged UIManager.GetActiveUIWidgetOrNull()?.AHelpButton; private Button? LobbyAHelpButton => (UIManager.ActiveScreen as LobbyGui)?.AHelpButton; public IAHelpUIHandler? UIHelper; + private bool _discordRelayActive; private bool _hasUnreadAHelp; - private string? _aHelpSound; + + public const string AHelpErrorSound = "/Audio/Admin/ahelp_error.ogg"; + public const string AHelpReceiveSound = "/Audio/Admin/ahelp_receive.ogg"; + public const string AHelpSendSound = "/Audio/Admin/ahelp_send.ogg"; + public override void Initialize() { @@ -55,9 +59,9 @@ public override void Initialize() SubscribeNetworkEvent(PeopleTypingUpdated); _adminManager.AdminStatusUpdated += OnAdminStatusUpdated; - _config.OnValueChanged(CCVars.AHelpSound, v => _aHelpSound = v, true); } + public void UnloadButton() { if (GameAHelpButton != null) @@ -112,14 +116,10 @@ public void OnSystemUnloaded(BwoinkSystem system) private void SetAHelpPressed(bool pressed) { if (GameAHelpButton != null) - { GameAHelpButton.Pressed = pressed; - } if (LobbyAHelpButton != null) - { LobbyAHelpButton.Pressed = pressed; - } UIManager.ClickSound(); UnreadAHelpRead(); @@ -130,22 +130,18 @@ private void ReceivedBwoink(object? sender, SharedBwoinkSystem.BwoinkTextMessage Logger.InfoS("c.s.go.es.bwoink", $"@{message.UserId}: {message.Text}"); var localPlayer = _playerManager.LocalSession; if (localPlayer == null) - { return; - } - if (message.PlaySound && localPlayer.UserId != message.TrueSender) + + EnsureUIHelper(); + + if (message.PlaySound && localPlayer.UserId != message.TrueSender && !UIHelper!.IsOpen) { - if (_aHelpSound != null) - _audio.PlayGlobal(_aHelpSound, Filter.Local(), false); + _audio.PlayGlobal(AHelpReceiveSound, Filter.Local(), false); _clyde.RequestWindowAttention(); } - EnsureUIHelper(); - if (!UIHelper!.IsOpen) - { UnreadAHelpReceived(); - } UIHelper!.Receive(message); } diff --git a/Content.Client/UserInterface/Systems/Ghost/Controls/Roles/GhostRolesEui.cs b/Content.Client/UserInterface/Systems/Ghost/Controls/Roles/GhostRolesEui.cs index 8e72eafd97c..f03289782ae 100644 --- a/Content.Client/UserInterface/Systems/Ghost/Controls/Roles/GhostRolesEui.cs +++ b/Content.Client/UserInterface/Systems/Ghost/Controls/Roles/GhostRolesEui.cs @@ -1,10 +1,15 @@ using System.Linq; using Content.Client.Eui; using Content.Client.Players.PlayTimeTracking; +using Content.Client.Preferences; +using Content.Shared.Customization.Systems; using Content.Shared.Eui; using Content.Shared.Ghost.Roles; +using Content.Shared.Preferences; using JetBrains.Annotations; using Robust.Client.GameObjects; +using Robust.Shared.Configuration; +using Robust.Shared.Prototypes; using Robust.Shared.Utility; namespace Content.Client.UserInterface.Systems.Ghost.Controls.Roles @@ -71,6 +76,10 @@ public override void HandleState(EuiStateBase state) var sysManager = entityManager.EntitySysManager; var spriteSystem = sysManager.GetEntitySystem(); var requirementsManager = IoCManager.Resolve(); + var characterReqs = entityManager.System(); + var prefs = IoCManager.Resolve(); + var protoMan = IoCManager.Resolve(); + var configManager = IoCManager.Resolve(); var groupedRoles = ghostState.GhostRoles.GroupBy( role => (role.Name, role.Description, role.Requirements)); @@ -78,15 +87,22 @@ public override void HandleState(EuiStateBase state) { var name = group.Key.Name; var description = group.Key.Description; - bool hasAccess = true; - FormattedMessage? reason; + // ReSharper disable once ReplaceWithSingleAssignment.True + var hasAccess = true; - if (!requirementsManager.CheckRoleTime(group.Key.Requirements, out reason)) - { + if (!characterReqs.CheckRequirementsValid( + group.Key.Requirements ?? new(), + new(), + (HumanoidCharacterProfile) (prefs.Preferences?.SelectedCharacter ?? HumanoidCharacterProfile.DefaultWithSpecies()), + requirementsManager.GetRawPlayTimeTrackers(), + requirementsManager.IsWhitelisted(), + entityManager, + protoMan, + configManager, + out var reasons)) hasAccess = false; - } - _window.AddEntry(name, description, hasAccess, reason, group, spriteSystem); + _window.AddEntry(name, description, hasAccess, characterReqs.GetRequirementsText(reasons), group, spriteSystem); } var closeRulesWindow = ghostState.GhostRoles.All(role => role.Identifier != _windowRulesId); diff --git a/Content.IntegrationTests/Tests/Nyanotrasen/Oracle/OracleTest.cs b/Content.IntegrationTests/Tests/Nyanotrasen/Oracle/OracleTest.cs deleted file mode 100644 index c925db3ba21..00000000000 --- a/Content.IntegrationTests/Tests/Nyanotrasen/Oracle/OracleTest.cs +++ /dev/null @@ -1,72 +0,0 @@ -#nullable enable -using NUnit.Framework; -using System.Threading.Tasks; -using Content.Shared.Item; -using Content.Shared.Mobs.Components; -using Content.Server.Research.Oracle; -using Content.Shared.Chemistry.Components; -using Robust.Shared.GameObjects; -using Robust.Shared.Map; -using Robust.Shared.Prototypes; - - -/// -/// The oracle's request pool is huge. -/// We need to test everything that the oracle could request can be turned in. -/// -namespace Content.IntegrationTests.Tests.Oracle -{ - [TestFixture] - [TestOf(typeof(OracleSystem))] - public sealed class OracleTest - { - [Test] - public async Task AllOracleItemsCanBeTurnedIn() - { - await using var pairTracker = await PoolManager.GetServerClient(); - var server = pairTracker.Server; - // Per RobustIntegrationTest.cs, wait until state is settled to access it. - await server.WaitIdleAsync(); - - var mapManager = server.ResolveDependency(); - var prototypeManager = server.ResolveDependency(); - var entityManager = server.ResolveDependency(); - var entitySystemManager = server.ResolveDependency(); - - var oracleSystem = entitySystemManager.GetEntitySystem(); - var oracleComponent = new OracleComponent(); - - var testMap = await pairTracker.CreateTestMap(); - - await server.WaitAssertion(() => - { - var allProtos = oracleSystem.GetAllProtos(oracleComponent); - var coordinates = testMap.GridCoords; - - Assert.That((allProtos.Count > 0), "Oracle has no valid prototypes!"); - - foreach (var proto in allProtos) - { - var spawned = entityManager.SpawnEntity(proto, coordinates); - - Assert.That(entityManager.HasComponent(spawned), - $"Oracle can request non-item {proto}"); - - Assert.That(!entityManager.HasComponent(spawned), - $"Oracle can request reagent container {proto} that will conflict with the fountain"); - - Assert.That(!entityManager.HasComponent(spawned), - $"Oracle can request mob {proto} that could potentially have a player-set name."); - } - - // Because Server/Client pairs can be re-used between Tests, we - // need to clean up anything that might affect other tests, - // otherwise this pair cannot be considered clean, and the - // CleanReturnAsync call would need to be removed. - mapManager.DeleteMap(testMap.MapId); - }); - - await pairTracker.CleanReturnAsync(); - } - } -} diff --git a/Content.IntegrationTests/Tests/Slipping/SlippingTest.cs b/Content.IntegrationTests/Tests/Slipping/SlippingTest.cs index 7f77146f455..511a720ed07 100644 --- a/Content.IntegrationTests/Tests/Slipping/SlippingTest.cs +++ b/Content.IntegrationTests/Tests/Slipping/SlippingTest.cs @@ -1,11 +1,14 @@ #nullable enable using System.Collections.Generic; using Content.IntegrationTests.Tests.Interaction; +using Content.Shared.CCVar; using Content.Shared.Movement.Components; using Content.Shared.Slippery; using Content.Shared.Stunnable; +using Robust.Shared.Configuration; using Robust.Shared.GameObjects; using Robust.Shared.Input; +using Robust.Shared.IoC; using Robust.Shared.Maths; namespace Content.IntegrationTests.Tests.Slipping; @@ -14,6 +17,7 @@ public sealed class SlippingTest : MovementTest { public sealed class SlipTestSystem : EntitySystem { + [Dependency] public readonly IConfigurationManager Config = default!; public HashSet Slipped = new(); public override void Initialize() { @@ -30,6 +34,7 @@ private void OnSlip(EntityUid uid, SlipperyComponent component, ref SlipEvent ar public async Task BananaSlipTest() { var sys = SEntMan.System(); + var sprintWalks = sys.Config.GetCVar(CCVars.GamePressToSprint); await SpawnTarget("TrashBananaPeel"); var modifier = Comp(Player).SprintSpeedModifier; @@ -42,7 +47,7 @@ public async Task BananaSlipTest() #pragma warning restore NUnit2045 // Walking over the banana slowly does not trigger a slip. - await SetKey(EngineKeyFunctions.Walk, BoundKeyState.Down); + await SetKey(EngineKeyFunctions.Walk, sprintWalks ? BoundKeyState.Up : BoundKeyState.Down); await Move(DirectionFlag.East, 1f); #pragma warning disable NUnit2045 Assert.That(Delta(), Is.LessThan(0.5f)); @@ -51,10 +56,9 @@ public async Task BananaSlipTest() AssertComp(false, Player); // Moving at normal speeds does trigger a slip. - await SetKey(EngineKeyFunctions.Walk, BoundKeyState.Up); + await SetKey(EngineKeyFunctions.Walk, sprintWalks ? BoundKeyState.Down : BoundKeyState.Up); await Move(DirectionFlag.West, 1f); Assert.That(sys.Slipped, Does.Contain(SEntMan.GetEntity(Player))); AssertComp(true, Player); } } - diff --git a/Content.Server/Administration/Managers/AdminManager.cs b/Content.Server/Administration/Managers/AdminManager.cs index 19c56282937..ec284fcadce 100644 --- a/Content.Server/Administration/Managers/AdminManager.cs +++ b/Content.Server/Administration/Managers/AdminManager.cs @@ -279,7 +279,13 @@ public void Initialize() _commandPermissions.LoadPermissionsFromStream(efs); } - if (_res.TryContentFileRead(new ResPath("/toolshedEngineCommandPerms.yml"), out var toolshedPerms)) + var toolshedPermsPath = new ResPath("/toolshedEngineCommandPerms.yml"); + if (_res.TryContentFileRead(toolshedPermsPath, out var toolshedPerms)) + { + _commandPermissions.LoadPermissionsFromStream(toolshedPerms); + } + // This may or may not be necessary. We read the same file again and load the same permissions into a different manager. + if (_res.TryContentFileRead(toolshedPermsPath, out toolshedPerms)) { _toolshedCommandPermissions.LoadPermissionsFromStream(toolshedPerms); } diff --git a/Content.Server/AlertLevel/AlertLevelSystem.cs b/Content.Server/AlertLevel/AlertLevelSystem.cs index d856fab9da7..b290d95a5c1 100644 --- a/Content.Server/AlertLevel/AlertLevelSystem.cs +++ b/Content.Server/AlertLevel/AlertLevelSystem.cs @@ -150,7 +150,7 @@ public void SetLevel(EntityUid station, string level, bool playSound, bool annou if (Loc.TryGetString(detail.Announcement, out var locAnnouncement)) announcement = locAnnouncement; - var alert = _announcer.GetAnnouncementId($"Alert{level}"); + var alert = $"alert{char.ToUpperInvariant(level[0]) + level[1..]}"; if (playSound) _announcer.SendAnnouncementAudio(alert, _stationSystem.GetInOwningStation(station)); if (announce) diff --git a/Content.Server/Atmos/EntitySystems/BarotraumaSystem.cs b/Content.Server/Atmos/EntitySystems/BarotraumaSystem.cs index fc77a1c8d94..d55ef355f02 100644 --- a/Content.Server/Atmos/EntitySystems/BarotraumaSystem.cs +++ b/Content.Server/Atmos/EntitySystems/BarotraumaSystem.cs @@ -153,9 +153,6 @@ public float GetFeltLowPressure(EntityUid uid, BarotraumaComponent barotrauma, f return Math.Min(modified, Atmospherics.OneAtmosphere); } - /// - /// Returns adjusted pressure after having applied resistances from equipment and innate (if any), to check against a high pressure hazard threshold - /// public float GetFeltHighPressure(EntityUid uid, BarotraumaComponent barotrauma, float environmentPressure) { if (barotrauma.HasImmunity) @@ -226,69 +223,59 @@ public override void Update(float frameTime) pressure = MathF.Max(mixture.Pressure, 1f); } - switch (pressure) + pressure = pressure switch { - // Low pressure. - case <= Atmospherics.WarningLowPressure: - pressure = GetFeltLowPressure(uid, barotrauma, pressure); - - if (pressure > Atmospherics.WarningLowPressure) - goto default; + // Adjust pressure based on equipment. Works differently depending on if it's "high" or "low". + <= Atmospherics.WarningLowPressure => GetFeltLowPressure(uid, barotrauma, pressure), + >= Atmospherics.WarningHighPressure => GetFeltHighPressure(uid, barotrauma, pressure), + _ => pressure + }; + if (pressure <= Atmospherics.HazardLowPressure) + { + // Deal damage and ignore resistances. Resistance to pressure damage should be done via pressure protection gear. + _damageableSystem.TryChangeDamage(uid, barotrauma.Damage * Atmospherics.LowPressureDamage, true, false); + if (!barotrauma.TakingDamage) + { + barotrauma.TakingDamage = true; + _adminLogger.Add(LogType.Barotrauma, $"{ToPrettyString(uid):entity} started taking low pressure damage"); + } - // Deal damage and ignore resistances. Resistance to pressure damage should be done via pressure protection gear. - _damageableSystem.TryChangeDamage(uid, barotrauma.Damage * Atmospherics.LowPressureDamage, true, false); + _alertsSystem.ShowAlert(uid, AlertType.LowPressure, 2); + } + else if (pressure >= Atmospherics.HazardHighPressure) + { + var damageScale = MathF.Min(((pressure / Atmospherics.HazardHighPressure) - 1) * Atmospherics.PressureDamageCoefficient, Atmospherics.MaxHighPressureDamage); - if (!barotrauma.TakingDamage) - { - barotrauma.TakingDamage = true; - _adminLogger.Add(LogType.Barotrauma, $"{ToPrettyString(uid):entity} started taking low pressure damage"); - } + _damageableSystem.TryChangeDamage(uid, barotrauma.Damage * damageScale, true, false); - if (pressure <= Atmospherics.HazardLowPressure) - { - _alertsSystem.ShowAlert(uid, AlertType.LowPressure, 2); + _alertsSystem.ShowAlert(uid, AlertType.HighPressure, 2); + } + else + { + // Within safe pressure limits + if (barotrauma.TakingDamage) + { + barotrauma.TakingDamage = false; + _adminLogger.Add(LogType.Barotrauma, $"{ToPrettyString(uid):entity} stopped taking pressure damage"); + } + if (!barotrauma.TakingDamage) + { + barotrauma.TakingDamage = true; + _adminLogger.Add(LogType.Barotrauma, $"{ToPrettyString(uid):entity} started taking high pressure damage"); + } + // Set correct alert. + switch (pressure) + { + case <= Atmospherics.WarningLowPressure: + _alertsSystem.ShowAlert(uid, AlertType.LowPressure, 1); break; - } - - _alertsSystem.ShowAlert(uid, AlertType.LowPressure, 1); - break; - - // High pressure. - case >= Atmospherics.WarningHighPressure: - pressure = GetFeltHighPressure(uid, barotrauma, pressure); - - if (pressure < Atmospherics.WarningHighPressure) - goto default; - - var damageScale = MathF.Min((pressure / Atmospherics.HazardHighPressure) * Atmospherics.PressureDamageCoefficient, Atmospherics.MaxHighPressureDamage); - - // Deal damage and ignore resistances. Resistance to pressure damage should be done via pressure protection gear. - _damageableSystem.TryChangeDamage(uid, barotrauma.Damage * damageScale, true, false); - - if (!barotrauma.TakingDamage) - { - barotrauma.TakingDamage = true; - _adminLogger.Add(LogType.Barotrauma, $"{ToPrettyString(uid):entity} started taking high pressure damage"); - } - - if (pressure >= Atmospherics.HazardHighPressure) - { - _alertsSystem.ShowAlert(uid, AlertType.HighPressure, 2); + case >= Atmospherics.WarningHighPressure: + _alertsSystem.ShowAlert(uid, AlertType.HighPressure, 1); break; - } - - _alertsSystem.ShowAlert(uid, AlertType.HighPressure, 1); - break; - - // Normal pressure. - default: - if (barotrauma.TakingDamage) - { - barotrauma.TakingDamage = false; - _adminLogger.Add(LogType.Barotrauma, $"{ToPrettyString(uid):entity} stopped taking pressure damage"); - } - _alertsSystem.ClearAlertCategory(uid, AlertCategory.Pressure); - break; + default: + _alertsSystem.ClearAlertCategory(uid, AlertCategory.Pressure); + break; + } } } } diff --git a/Content.Server/Nyanotrasen/Carrying/BeingCarriedComponent.cs b/Content.Server/Carrying/BeingCarriedComponent.cs similarity index 100% rename from Content.Server/Nyanotrasen/Carrying/BeingCarriedComponent.cs rename to Content.Server/Carrying/BeingCarriedComponent.cs diff --git a/Content.Server/Nyanotrasen/Carrying/CarriableComponent.cs b/Content.Server/Carrying/CarriableComponent.cs similarity index 58% rename from Content.Server/Nyanotrasen/Carrying/CarriableComponent.cs rename to Content.Server/Carrying/CarriableComponent.cs index f4fd1fa6d56..eb12dbc904e 100644 --- a/Content.Server/Nyanotrasen/Carrying/CarriableComponent.cs +++ b/Content.Server/Carrying/CarriableComponent.cs @@ -9,9 +9,16 @@ public sealed partial class CarriableComponent : Component /// Number of free hands required /// to carry the entity /// - [DataField("freeHandsRequired")] + [DataField] public int FreeHandsRequired = 2; public CancellationTokenSource? CancelToken; + + /// + /// The base duration (In Seconds) of how long it should take to pick up this entity + /// before Contests are considered. + /// + [DataField] + public float PickupDuration = 3; } } diff --git a/Content.Server/Nyanotrasen/Carrying/CarryingComponent.cs b/Content.Server/Carrying/CarryingComponent.cs similarity index 100% rename from Content.Server/Nyanotrasen/Carrying/CarryingComponent.cs rename to Content.Server/Carrying/CarryingComponent.cs diff --git a/Content.Server/Nyanotrasen/Carrying/CarryingSystem.cs b/Content.Server/Carrying/CarryingSystem.cs similarity index 73% rename from Content.Server/Nyanotrasen/Carrying/CarryingSystem.cs rename to Content.Server/Carrying/CarryingSystem.cs index ff4c097080c..13338ea2b7b 100644 --- a/Content.Server/Nyanotrasen/Carrying/CarryingSystem.cs +++ b/Content.Server/Carrying/CarryingSystem.cs @@ -1,7 +1,6 @@ using System.Numerics; using System.Threading; using Content.Server.DoAfter; -using Content.Server.Body.Systems; using Content.Server.Resist; using Content.Server.Popups; using Content.Server.Inventory; @@ -14,8 +13,9 @@ using Content.Shared.Stunnable; using Content.Shared.Interaction.Events; using Content.Shared.Verbs; -using Content.Shared.Climbing.Events; // Added this. +using Content.Shared.Climbing.Events; using Content.Shared.Carrying; +using Content.Shared.Contests; using Content.Shared.Movement.Events; using Content.Shared.Movement.Systems; using Content.Shared.Standing; @@ -31,6 +31,7 @@ using Content.Shared.Storage; using Robust.Shared.Map.Components; using Robust.Shared.Physics.Components; +using Robust.Server.GameObjects; namespace Content.Server.Carrying { @@ -47,6 +48,8 @@ public sealed class CarryingSystem : EntitySystem [Dependency] private readonly PopupSystem _popupSystem = default!; [Dependency] private readonly MovementSpeedModifierSystem _movementSpeed = default!; [Dependency] private readonly PseudoItemSystem _pseudoItem = default!; + [Dependency] private readonly ContestsSystem _contests = default!; + [Dependency] private readonly TransformSystem _transform = default!; public override void Initialize() { @@ -70,22 +73,11 @@ public override void Initialize() private void AddCarryVerb(EntityUid uid, CarriableComponent component, GetVerbsEvent args) { - if (!args.CanInteract || !args.CanAccess) - return; - - if (!CanCarry(args.User, uid, component)) - return; - - if (HasComp(args.User)) // yeah not dealing with that - return; - - if (HasComp(args.User) || HasComp(args.Target)) - return; - - if (!_mobStateSystem.IsAlive(args.User)) - return; - - if (args.User == args.Target) + if (!args.CanInteract || !args.CanAccess || !_mobStateSystem.IsAlive(args.User) + || !CanCarry(args.User, uid, component) + || HasComp(args.User) + || HasComp(args.User) || HasComp(args.Target) + || args.User == args.Target) return; AlternativeVerb verb = new() @@ -105,13 +97,10 @@ private void AddInsertCarriedVerb(EntityUid uid, CarryingComponent component, Ge // If the person is carrying someone, and the carried person is a pseudo-item, and the target entity is a storage, // then add an action to insert the carried entity into the target var toInsert = args.Using; - if (toInsert is not { Valid: true } || !args.CanAccess || !TryComp(toInsert, out var pseudoItem)) - return; - - if (!TryComp(args.Target, out var storageComp)) - return; - - if (!_pseudoItem.CheckItemFits((toInsert.Value, pseudoItem), (args.Target, storageComp))) + if (toInsert is not { Valid: true } || !args.CanAccess + || !TryComp(toInsert, out var pseudoItem) + || !TryComp(args.Target, out var storageComp) + || !_pseudoItem.CheckItemFits((toInsert.Value, pseudoItem), (args.Target, storageComp))) return; InnateVerb verb = new() @@ -142,25 +131,22 @@ private void OnVirtualItemDeleted(EntityUid uid, CarryingComponent component, Vi /// Basically using virtual item passthrough to throw the carried person. A new age! /// Maybe other things besides throwing should use virt items like this... /// - private void OnThrow(EntityUid uid, CarryingComponent component, BeforeThrowEvent args) + private void OnThrow(EntityUid uid, CarryingComponent component, ref BeforeThrowEvent args) { - if (!TryComp(args.ItemUid, out var virtItem) || !HasComp(virtItem.BlockingEntity)) + if (!TryComp(args.ItemUid, out var virtItem) + || !HasComp(virtItem.BlockingEntity)) return; args.ItemUid = virtItem.BlockingEntity; - var multiplier = MassContest(uid, virtItem.BlockingEntity); - args.ThrowStrength = 5f * multiplier; + args.ThrowStrength *= _contests.MassContest(uid, virtItem.BlockingEntity, false, 2f) + * _contests.StaminaContest(uid, virtItem.BlockingEntity); } private void OnParentChanged(EntityUid uid, CarryingComponent component, ref EntParentChangedMessage args) { var xform = Transform(uid); - if (xform.MapID != args.OldMapId) - return; - - // Do not drop the carried entity if the new parent is a grid - if (xform.ParentUid == xform.GridUid) + if (xform.MapID != args.OldMapId || xform.ParentUid == xform.GridUid) return; DropCarried(uid, component.Carried); @@ -190,17 +176,14 @@ private void OnInteractionAttempt(EntityUid uid, BeingCarriedComponent component /// private void OnMoveInput(EntityUid uid, BeingCarriedComponent component, ref MoveInputEvent args) { - if (!TryComp(uid, out var escape)) - return; - - if (!args.HasDirectionalMovement) + if (!TryComp(uid, out var escape) + || !args.HasDirectionalMovement) return; + // Check if the victim is in any way incapacitated, and if not make an escape attempt. + // Escape time scales with the inverse of a mass contest. Being lighter makes escape harder. if (_actionBlockerSystem.CanInteract(uid, component.Carrier)) - { - // Note: the mass contest is inverted because weaker entities are supposed to take longer to escape - _escapeInventorySystem.AttemptEscape(uid, component.Carrier, escape, MassContest(component.Carrier, uid)); - } + _escapeInventorySystem.AttemptEscape(uid, component.Carrier, escape, _contests.MassContest(uid, component.Carrier, false, 2f)); } private void OnMoveAttempt(EntityUid uid, BeingCarriedComponent component, UpdateCanMoveEvent args) @@ -237,10 +220,8 @@ private void OnBuckleChange(EntityUid uid, BeingCarriedComponent component, ref private void OnDoAfter(EntityUid uid, CarriableComponent component, CarryDoAfterEvent args) { component.CancelToken = null; - if (args.Handled || args.Cancelled) - return; - - if (!CanCarry(args.Args.User, uid, component)) + if (args.Handled || args.Cancelled + || !CanCarry(args.Args.User, uid, component)) return; Carry(args.Args.User, uid); @@ -248,16 +229,18 @@ private void OnDoAfter(EntityUid uid, CarriableComponent component, CarryDoAfter } private void StartCarryDoAfter(EntityUid carrier, EntityUid carried, CarriableComponent component) { - TimeSpan length = GetPickupDuration(carrier, carried); - - if (length >= TimeSpan.FromSeconds(9)) + if (!TryComp(carrier, out var carrierPhysics) + || !TryComp(carried, out var carriedPhysics) + || carriedPhysics.Mass > carrierPhysics.Mass * 2f) { _popupSystem.PopupEntity(Loc.GetString("carry-too-heavy"), carried, carrier, Shared.Popups.PopupType.SmallCaution); return; } - if (!HasComp(carried)) - length *= 2f; + var length = TimeSpan.FromSeconds(component.PickupDuration + * _contests.MassContest(carriedPhysics, carrierPhysics, false, 4f) + * _contests.StaminaContest(carrier, carried) + * (_standingState.IsDown(carried) ? 0.5f : 1)); component.CancelToken = new CancellationTokenSource(); @@ -280,10 +263,10 @@ private void Carry(EntityUid carrier, EntityUid carried) if (TryComp(carried, out var pullable)) _pullingSystem.TryStopPull(carried, pullable); - Transform(carrier).AttachToGridOrMap(); - Transform(carried).AttachToGridOrMap(); - Transform(carried).Coordinates = Transform(carrier).Coordinates; - Transform(carried).AttachParent(Transform(carrier)); + _transform.AttachToGridOrMap(carrier); + _transform.AttachToGridOrMap(carried); + _transform.SetCoordinates(carried, Transform(carrier).Coordinates); + _transform.SetParent(carried, carrier); _virtualItemSystem.TrySpawnVirtualItemInHand(carried, carrier); _virtualItemSystem.TrySpawnVirtualItemInHand(carried, carrier); var carryingComp = EnsureComp(carrier); @@ -299,17 +282,13 @@ private void Carry(EntityUid carrier, EntityUid carried) public bool TryCarry(EntityUid carrier, EntityUid toCarry, CarriableComponent? carriedComp = null) { - if (!Resolve(toCarry, ref carriedComp, false)) - return false; - - if (!CanCarry(carrier, toCarry, carriedComp)) - return false; - - // The second one means that carrier is a pseudo-item and is inside a bag. - if (HasComp(carrier) || HasComp(carrier)) - return false; - - if (GetPickupDuration(carrier, toCarry) > TimeSpan.FromSeconds(9)) + if (!Resolve(toCarry, ref carriedComp, false) + || !CanCarry(carrier, toCarry, carriedComp) + || HasComp(carrier) + || HasComp(carrier) + || TryComp(carrier, out var carrierPhysics) + && TryComp(toCarry, out var toCarryPhysics) + && carrierPhysics.Mass < toCarryPhysics.Mass * 2f) return false; Carry(carrier, toCarry); @@ -319,79 +298,41 @@ public bool TryCarry(EntityUid carrier, EntityUid toCarry, CarriableComponent? c public void DropCarried(EntityUid carrier, EntityUid carried) { - RemComp(carrier); // get rid of this first so we don't recusrively fire that event + RemComp(carrier); // get rid of this first so we don't recursively fire that event RemComp(carrier); RemComp(carried); RemComp(carried); _actionBlockerSystem.UpdateCanMove(carried); _virtualItemSystem.DeleteInHandsMatching(carrier, carried); - Transform(carried).AttachToGridOrMap(); + _transform.AttachToGridOrMap(carried); _standingState.Stand(carried); _movementSpeed.RefreshMovementSpeedModifiers(carrier); } private void ApplyCarrySlowdown(EntityUid carrier, EntityUid carried) { - var massRatio = MassContest(carrier, carried); - - if (massRatio == 0) - massRatio = 1; + var massRatio = _contests.MassContest(carrier, carried, true); + var massRatioSq = MathF.Pow(massRatio, 2); + var modifier = 1 - 0.15f / massRatioSq; + modifier = Math.Max(0.1f, modifier); - var massRatioSq = Math.Pow(massRatio, 2); - var modifier = (1 - (0.15 / massRatioSq)); - modifier = Math.Max(0.1, modifier); var slowdownComp = EnsureComp(carrier); - _slowdown.SetModifier(carrier, (float) modifier, (float) modifier, slowdownComp); + _slowdown.SetModifier(carrier, modifier, modifier, slowdownComp); } public bool CanCarry(EntityUid carrier, EntityUid carried, CarriableComponent? carriedComp = null) { - if (!Resolve(carried, ref carriedComp, false)) - return false; - - if (carriedComp.CancelToken != null) - return false; - - if (!HasComp(Transform(carrier).ParentUid)) - return false; - - if (HasComp(carrier) || HasComp(carried)) - return false; - - // if (_respirator.IsReceivingCPR(carried)) - // return false; - - if (!TryComp(carrier, out var hands)) + if (!Resolve(carried, ref carriedComp, false) + || carriedComp.CancelToken != null + || !HasComp(Transform(carrier).ParentUid) + || HasComp(carrier) + || HasComp(carried) + || !TryComp(carrier, out var hands) + || hands.CountFreeHands() < carriedComp.FreeHandsRequired) return false; - - if (hands.CountFreeHands() < carriedComp.FreeHandsRequired) - return false; - return true; } - private float MassContest(EntityUid roller, EntityUid target, PhysicsComponent? rollerPhysics = null, PhysicsComponent? targetPhysics = null) - { - if (!Resolve(roller, ref rollerPhysics, false) || !Resolve(target, ref targetPhysics, false)) - return 1f; - - if (targetPhysics.FixturesMass == 0) - return 1f; - - return rollerPhysics.FixturesMass / targetPhysics.FixturesMass; - } - - private TimeSpan GetPickupDuration(EntityUid carrier, EntityUid carried) - { - var length = TimeSpan.FromSeconds(3); - - var mod = MassContest(carrier, carried); - if (mod != 0) - length /= mod; - - return length; - } - public override void Update(float frameTime) { var query = EntityQueryEnumerator(); diff --git a/Content.Server/Chat/Systems/ChatSystem.cs b/Content.Server/Chat/Systems/ChatSystem.cs index b0591f49892..450a35f438c 100644 --- a/Content.Server/Chat/Systems/ChatSystem.cs +++ b/Content.Server/Chat/Systems/ChatSystem.cs @@ -78,6 +78,7 @@ public sealed partial class ChatSystem : SharedChatSystem public const int WhisperMuffledRange = 5; // how far whisper goes at all, in world units public const string DefaultAnnouncementSound = "/Audio/Announcements/announce.ogg"; public const float DefaultObfuscationFactor = 0.2f; // Percentage of symbols in a whispered message that can be seen even by "far" listeners + public readonly Color DefaultSpeakColor = Color.White; private bool _loocEnabled = true; private bool _deadLoocEnabled; @@ -532,7 +533,7 @@ private void SendEntityWhisper( } else if (_interactionSystem.InRangeUnobstructed(source, listener, WhisperMuffledRange, Shared.Physics.CollisionGroup.Opaque)) { - // Scenerio 2: if the listener is too far, they only hear fragments of the message + // Scenario 2: if the listener is too far, they only hear fragments of the message result = ObfuscateMessageReadability(perceivedMessage); wrappedMessage = WrapWhisperMessage(source, "chat-manager-entity-whisper-wrap-message", nameIdentity, result, language); } @@ -546,10 +547,7 @@ private void SendEntityWhisper( _chatManager.ChatMessageToOne(ChatChannel.Whisper, result, wrappedMessage, source, false, session.Channel); } - var replayWrap = Loc.GetString("chat-manager-entity-whisper-wrap-message", - ("color", language.SpeechOverride.Color), - ("entityName", name), - ("message", FormattedMessage.EscapeText(message))); + var replayWrap = WrapWhisperMessage(source, "chat-manager-entity-whisper-wrap-message", name, FormattedMessage.EscapeText(message), language); _replay.RecordServerMessage(new ChatMessage(ChatChannel.Whisper, message, replayWrap, GetNetEntity(source), null, MessageRangeHideChatForReplay(range))); var ev = new EntitySpokeEvent(source, message, channel, true, language); @@ -925,9 +923,12 @@ public string WrapMessage(LocId wrapId, InGameICChatType chatType, EntityUid sou var verbId = language.SpeechOverride.SpeechVerbOverrides is { } verbsOverride ? _random.Pick(verbsOverride).ToString() : _random.Pick(speech.SpeechVerbStrings); + var color = DefaultSpeakColor; + if (language.SpeechOverride.Color is { } colorOverride) + color = Color.InterpolateBetween(color, colorOverride, colorOverride.A); return Loc.GetString(wrapId, - ("color", language.SpeechOverride.Color), + ("color", color), ("entityName", entityName), ("verb", Loc.GetString(verbId)), ("fontType", language.SpeechOverride.FontId ?? speech.FontId), diff --git a/Content.Server/Clothing/Systems/LoadoutSystem.cs b/Content.Server/Clothing/Systems/LoadoutSystem.cs index c22f7afb598..73d5ae387ab 100644 --- a/Content.Server/Clothing/Systems/LoadoutSystem.cs +++ b/Content.Server/Clothing/Systems/LoadoutSystem.cs @@ -3,6 +3,7 @@ using Content.Shared.CCVar; using Content.Shared.Inventory; using Content.Shared.Item; +using Content.Shared.Players; using Content.Shared.Storage; using Content.Shared.Storage.EntitySystems; using Robust.Shared.Configuration; @@ -31,7 +32,8 @@ private void OnPlayerSpawnComplete(PlayerSpawnCompleteEvent ev) return; // Spawn the loadout, get a list of items that failed to equip - var failedLoadouts = _loadout.ApplyCharacterLoadout(ev.Mob, ev.JobId, ev.Profile, _playTimeTracking.GetTrackerTimes(ev.Player)); + var failedLoadouts = _loadout.ApplyCharacterLoadout(ev.Mob, ev.JobId, ev.Profile, + _playTimeTracking.GetTrackerTimes(ev.Player), ev.Player.ContentData()?.Whitelisted ?? false); // Try to find back-mounted storage apparatus if (!_inventory.TryGetSlotEntity(ev.Mob, "back", out var item) || diff --git a/Content.Server/GameTicking/Rules/ZombieRuleSystem.cs b/Content.Server/GameTicking/Rules/ZombieRuleSystem.cs index e8dc37dc1eb..5714337d4db 100644 --- a/Content.Server/GameTicking/Rules/ZombieRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/ZombieRuleSystem.cs @@ -43,6 +43,7 @@ public sealed class ZombieRuleSystem : GameRuleSystem [Dependency] private readonly AntagSelectionSystem _antagSelection = default!; [Dependency] private readonly IGameTiming _timing = default!; [Dependency] private readonly AnnouncerSystem _announcer = default!; + [Dependency] private readonly GameTicker _gameTicker = default!; public override void Initialize() { @@ -89,7 +90,7 @@ private void OnRoundEndText(RoundEndTextAppendEvent ev) ("username", player.Value))); } - var healthy = GetHealthyHumans(); + var healthy = GetHealthyHumans(true); // Gets a bunch of the living players and displays them if they're under a threshold. // InitialInfected is used for the threshold because it scales with the player count well. if (healthy.Count <= 0 || healthy.Count > 2 * zombie.InitialInfectedNames.Count) @@ -185,7 +186,7 @@ private void OnZombifySelf(EntityUid uid, PendingZombieComponent component, Zomb /// Include healthy players that are not on the station grid /// Should dead zombies be included in the count /// - private float GetInfectedFraction(bool includeOffStation = true, bool includeDead = false) + private float GetInfectedFraction(bool includeOffStation = false, bool includeDead = true) { var players = GetHealthyHumans(includeOffStation); var zombieCount = 0; @@ -205,14 +206,14 @@ private float GetInfectedFraction(bool includeOffStation = true, bool includeDea /// Flying off via a shuttle disqualifies you. /// /// - private List GetHealthyHumans(bool includeOffStation = true) + private List GetHealthyHumans(bool includeOffStation = false) { var healthy = new List(); var stationGrids = new HashSet(); if (!includeOffStation) { - foreach (var station in _station.GetStationsSet()) + foreach (var station in _gameTicker.GetSpawnableStations()) { if (TryComp(station, out var data) && _station.GetLargestGrid(data) is { } grid) stationGrids.Add(grid); @@ -223,13 +224,11 @@ private List GetHealthyHumans(bool includeOffStation = true) var zombers = GetEntityQuery(); while (players.MoveNext(out var uid, out _, out _, out var mob, out var xform)) { - if (!_mobState.IsAlive(uid, mob)) - continue; - - if (zombers.HasComponent(uid)) - continue; - - if (!includeOffStation && !stationGrids.Contains(xform.GridUid ?? EntityUid.Invalid)) + if (!_mobState.IsAlive(uid, mob) + || HasComp(uid) //Do not include infected players in the "Healthy players" list. + || HasComp(uid) + || zombers.HasComponent(uid) + || !includeOffStation && !stationGrids.Contains(xform.GridUid ?? EntityUid.Invalid)) continue; healthy.Add(uid); diff --git a/Content.Server/Ghost/Roles/Components/GhostRoleComponent.cs b/Content.Server/Ghost/Roles/Components/GhostRoleComponent.cs index abb26a8c8bc..997961ae675 100644 --- a/Content.Server/Ghost/Roles/Components/GhostRoleComponent.cs +++ b/Content.Server/Ghost/Roles/Components/GhostRoleComponent.cs @@ -1,4 +1,5 @@ using Content.Server.Mind.Commands; +using Content.Shared.Customization.Systems; using Content.Shared.Roles; namespace Content.Server.Ghost.Roles.Components @@ -14,7 +15,7 @@ public sealed partial class GhostRoleComponent : Component [DataField("rules")] private string _roleRules = "ghost-role-component-default-rules"; [DataField("requirements")] - public HashSet? Requirements; + public List? Requirements; /// /// Whether the should run on the mob. diff --git a/Content.Server/Language/TranslatorSystem.cs b/Content.Server/Language/TranslatorSystem.cs index adbfe2d681f..24f4cb17298 100644 --- a/Content.Server/Language/TranslatorSystem.cs +++ b/Content.Server/Language/TranslatorSystem.cs @@ -4,6 +4,7 @@ using Content.Shared.Interaction; using Content.Shared.Interaction.Events; using Content.Shared.Language; +using Content.Shared.Language.Components; using Content.Shared.Language.Systems; using Content.Shared.PowerCell; using Content.Shared.Language.Components.Translators; @@ -173,11 +174,13 @@ private void UpdateBoundIntrinsicComp(HandheldTranslatorComponent comp, HoldsTra { intrinsic.SpokenLanguages = [..comp.SpokenLanguages]; intrinsic.UnderstoodLanguages = [..comp.UnderstoodLanguages]; + intrinsic.RequiredLanguages = [..comp.RequiredLanguages]; } else { intrinsic.SpokenLanguages.Clear(); intrinsic.UnderstoodLanguages.Clear(); + intrinsic.RequiredLanguages.Clear(); } intrinsic.Enabled = isEnabled; diff --git a/Content.Server/Nutrition/EntitySystems/DrinkSystem.cs b/Content.Server/Nutrition/EntitySystems/DrinkSystem.cs index 47e7fa6802c..2249926baab 100644 --- a/Content.Server/Nutrition/EntitySystems/DrinkSystem.cs +++ b/Content.Server/Nutrition/EntitySystems/DrinkSystem.cs @@ -7,6 +7,7 @@ using Content.Server.Inventory; using Content.Server.Nutrition.Components; using Content.Server.Popups; +using Content.Server.Traits.Assorted.Components; using Content.Shared.Administration.Logs; using Content.Shared.Body.Components; using Content.Shared.CCVar; @@ -279,9 +280,13 @@ private bool TryDrink(EntityUid user, EntityUid target, DrinkComponent drink, En var flavors = _flavorProfile.GetLocalizedFlavorsMessage(user, drinkSolution); + var drinkDelay = drink.Delay; + if (TryComp(target, out var delayModifier)) + drinkDelay *= delayModifier.DrinkDelayMultiplier; + var doAfterEventArgs = new DoAfterArgs(EntityManager, user, - forceDrink ? drink.ForceFeedDelay : drink.Delay, + forceDrink ? drink.ForceFeedDelay : drinkDelay, new ConsumeDoAfterEvent(drink.Solution, flavors), eventTarget: item, target: target, diff --git a/Content.Server/Nutrition/EntitySystems/FoodSystem.cs b/Content.Server/Nutrition/EntitySystems/FoodSystem.cs index 06d1c4b42d3..84355f03c16 100644 --- a/Content.Server/Nutrition/EntitySystems/FoodSystem.cs +++ b/Content.Server/Nutrition/EntitySystems/FoodSystem.cs @@ -6,6 +6,7 @@ using Content.Shared.Nutrition.Components; using Content.Server.Popups; using Content.Server.Stack; +using Content.Server.Traits.Assorted.Components; using Content.Shared.Administration.Logs; using Content.Shared.Body.Components; using Content.Shared.Body.Organ; @@ -176,9 +177,13 @@ private void OnFeedFood(Entity entity, ref AfterInteractEvent arg _adminLogger.Add(LogType.Ingestion, LogImpact.Low, $"{ToPrettyString(target):target} is eating {ToPrettyString(food):food} {SolutionContainerSystem.ToPrettyString(foodSolution)}"); } + var foodDelay = foodComp.Delay; + if (TryComp(target, out var delayModifier)) + foodDelay *= delayModifier.FoodDelayMultiplier; + var doAfterArgs = new DoAfterArgs(EntityManager, user, - forceFeed ? foodComp.ForceFeedDelay : foodComp.Delay, + forceFeed ? foodComp.ForceFeedDelay : foodDelay, new ConsumeDoAfterEvent(foodComp.Solution, flavors), eventTarget: food, target: target, diff --git a/Content.Server/Nyanotrasen/Research/Oracle/OracleComponent.cs b/Content.Server/Nyanotrasen/Research/Oracle/OracleComponent.cs deleted file mode 100644 index e238d5c7a18..00000000000 --- a/Content.Server/Nyanotrasen/Research/Oracle/OracleComponent.cs +++ /dev/null @@ -1,87 +0,0 @@ -using Content.Shared.Chemistry.Reagent; -using Robust.Shared.Prototypes; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List; - -namespace Content.Server.Research.Oracle; - -[RegisterComponent] -public sealed partial class OracleComponent : Component -{ - public const string SolutionName = "fountain"; - - [ViewVariables] - [DataField("accumulator")] - public float Accumulator; - - [ViewVariables] - [DataField("resetTime")] - public TimeSpan ResetTime = TimeSpan.FromMinutes(10); - - [DataField("barkAccumulator")] - public float BarkAccumulator; - - [DataField("barkTime")] - public TimeSpan BarkTime = TimeSpan.FromMinutes(1); - - [DataField("rejectAccumulator")] - public float RejectAccumulator; - - [DataField("rejectTime")] - public TimeSpan RejectTime = TimeSpan.FromSeconds(5); - - [ViewVariables(VVAccess.ReadWrite)] - public EntityPrototype DesiredPrototype = default!; - - [ViewVariables(VVAccess.ReadWrite)] - public EntityPrototype? LastDesiredPrototype = default!; - - [DataField("rewardReagents", customTypeSerializer: typeof(PrototypeIdListSerializer))] - public IReadOnlyList RewardReagents = new[] - { - "LotophagoiOil", "LotophagoiOil", "LotophagoiOil", "LotophagoiOil", "LotophagoiOil", "Wine", "Blood", "Ichor" - }; - - [DataField("demandMessages")] - public IReadOnlyList DemandMessages = new[] - { - "oracle-demand-1", - "oracle-demand-2", - "oracle-demand-3", - "oracle-demand-4", - "oracle-demand-5", - "oracle-demand-6", - "oracle-demand-7", - "oracle-demand-8", - "oracle-demand-9", - "oracle-demand-10", - "oracle-demand-11", - "oracle-demand-12" - }; - - [DataField("rejectMessages")] - public IReadOnlyList RejectMessages = new[] - { - "ἄγνοια", - "υλικό", - "ἀγνωσία", - "γήινος", - "σάκλας" - }; - - [DataField("blacklistedPrototypes")] - [ViewVariables(VVAccess.ReadOnly)] - public IReadOnlyList BlacklistedPrototypes = new[] - { - "Drone", - "QSI", - "HandTeleporter", - "BluespaceBeaker", - "ClothingBackpackHolding", - "ClothingBackpackSatchelHolding", - "ClothingBackpackDuffelHolding", - "TrashBagOfHolding", - "BluespaceCrystal", - "InsulativeHeadcage", - "CrystalNormality", - }; -} diff --git a/Content.Server/Nyanotrasen/Research/Oracle/OracleSystem.cs b/Content.Server/Nyanotrasen/Research/Oracle/OracleSystem.cs deleted file mode 100644 index c3eced61da9..00000000000 --- a/Content.Server/Nyanotrasen/Research/Oracle/OracleSystem.cs +++ /dev/null @@ -1,256 +0,0 @@ -using System.Linq; -using Content.Server.Botany; -using Content.Server.Chat.Managers; -using Content.Server.Chat.Systems; -using Content.Server.Chemistry.Containers.EntitySystems; -using Content.Server.Fluids.EntitySystems; -using Content.Server.Psionics; -using Content.Shared.Psionics.Abilities; -using Content.Shared.Chat; -using Content.Shared.Chemistry.Components; -using Content.Shared.Chemistry.Reagent; -using Content.Shared.Interaction; -using Content.Shared.Mobs.Components; -using Content.Shared.Psionics.Glimmer; -using Content.Shared.Research.Prototypes; -using Robust.Shared.Player; -using Robust.Shared.Prototypes; -using Robust.Shared.Random; - -namespace Content.Server.Research.Oracle; - -public sealed class OracleSystem : EntitySystem -{ - [Dependency] private readonly IPrototypeManager _prototypeManager = default!; - [Dependency] private readonly IRobustRandom _random = default!; - [Dependency] private readonly ChatSystem _chat = default!; - [Dependency] private readonly IChatManager _chatManager = default!; - [Dependency] private readonly SolutionContainerSystem _solutionSystem = default!; - [Dependency] private readonly GlimmerSystem _glimmerSystem = default!; - [Dependency] private readonly PuddleSystem _puddleSystem = default!; - - public override void Update(float frameTime) - { - base.Update(frameTime); - foreach (var oracle in EntityQuery()) - { - oracle.Accumulator += frameTime; - oracle.BarkAccumulator += frameTime; - oracle.RejectAccumulator += frameTime; - if (oracle.BarkAccumulator >= oracle.BarkTime.TotalSeconds) - { - oracle.BarkAccumulator = 0; - var message = Loc.GetString(_random.Pick(oracle.DemandMessages), ("item", oracle.DesiredPrototype.Name)) - .ToUpper(); - _chat.TrySendInGameICMessage(oracle.Owner, message, InGameICChatType.Speak, false); - } - - if (oracle.Accumulator >= oracle.ResetTime.TotalSeconds) - { - oracle.LastDesiredPrototype = oracle.DesiredPrototype; - NextItem(oracle); - } - } - } - - public override void Initialize() - { - base.Initialize(); - SubscribeLocalEvent(OnInit); - SubscribeLocalEvent(OnInteractHand); - SubscribeLocalEvent(OnInteractUsing); - } - - private void OnInit(EntityUid uid, OracleComponent component, ComponentInit args) - { - NextItem(component); - } - - private void OnInteractHand(EntityUid uid, OracleComponent component, InteractHandEvent args) - { - if (!HasComp(args.User) || HasComp(args.User)) - return; - - if (!TryComp(args.User, out var actor)) - return; - - var message = Loc.GetString("oracle-current-item", ("item", component.DesiredPrototype.Name)); - - var messageWrap = Loc.GetString("chat-manager-send-telepathic-chat-wrap-message", - ("telepathicChannelName", Loc.GetString("chat-manager-telepathic-channel-name")), ("message", message)); - - _chatManager.ChatMessageToOne(ChatChannel.Telepathic, - message, messageWrap, uid, false, actor.PlayerSession.ConnectedClient, Color.PaleVioletRed); - - if (component.LastDesiredPrototype != null) - { - var message2 = Loc.GetString("oracle-previous-item", ("item", component.LastDesiredPrototype.Name)); - var messageWrap2 = Loc.GetString("chat-manager-send-telepathic-chat-wrap-message", - ("telepathicChannelName", Loc.GetString("chat-manager-telepathic-channel-name")), - ("message", message2)); - - _chatManager.ChatMessageToOne(ChatChannel.Telepathic, - message2, messageWrap2, uid, false, actor.PlayerSession.ConnectedClient, Color.PaleVioletRed); - } - } - - private void OnInteractUsing(EntityUid uid, OracleComponent component, InteractUsingEvent args) - { - if (HasComp(args.Used)) - return; - - if (!TryComp(args.Used, out var meta)) - return; - - if (meta.EntityPrototype == null) - return; - - var validItem = CheckValidity(meta.EntityPrototype, component.DesiredPrototype); - - var nextItem = true; - - if (component.LastDesiredPrototype != null && - CheckValidity(meta.EntityPrototype, component.LastDesiredPrototype)) - { - nextItem = false; - validItem = true; - component.LastDesiredPrototype = null; - } - - if (!validItem) - { - if (!HasComp(args.Used) && - component.RejectAccumulator >= component.RejectTime.TotalSeconds) - { - component.RejectAccumulator = 0; - _chat.TrySendInGameICMessage(uid, _random.Pick(component.RejectMessages), InGameICChatType.Speak, true); - } - return; - } - - EntityManager.QueueDeleteEntity(args.Used); - - EntityManager.SpawnEntity("ResearchDisk5000", Transform(args.User).Coordinates); - - DispenseLiquidReward(uid, component); - - var i = _random.Next(1, 4); - - while (i != 0) - { - EntityManager.SpawnEntity("MaterialBluespace1", Transform(args.User).Coordinates); - i--; - } - - if (nextItem) - NextItem(component); - } - - private bool CheckValidity(EntityPrototype given, EntityPrototype target) - { - // 1: directly compare Names - // name instead of ID because the oracle asks for them by name - // this could potentially lead to like, labeller exploits maybe but so far only mob names can be fully player-set. - if (given.Name == target.Name) - return true; - - return false; - } - - private void DispenseLiquidReward(EntityUid uid, OracleComponent component) - { - if (!_solutionSystem.TryGetSolution(uid, OracleComponent.SolutionName, out var fountainSol)) - return; - - var allReagents = _prototypeManager.EnumeratePrototypes() - .Where(x => !x.Abstract) - .Select(x => x.ID).ToList(); - - var amount = 20 + _random.Next(1, 30) + _glimmerSystem.GlimmerOutput / 10f; - amount = (float) Math.Round(amount); - - var sol = new Solution(); - var reagent = ""; - - if (_random.Prob(0.2f)) - reagent = _random.Pick(allReagents); - else - reagent = _random.Pick(component.RewardReagents); - - sol.AddReagent(reagent, amount); - - _solutionSystem.TryMixAndOverflow(fountainSol.Value, sol, fountainSol.Value.Comp.Solution.MaxVolume, out var overflowing); - - if (overflowing != null && overflowing.Volume > 0) - _puddleSystem.TrySpillAt(uid, overflowing, out var _); - } - - private void NextItem(OracleComponent component) - { - component.Accumulator = 0; - component.BarkAccumulator = 0; - component.RejectAccumulator = 0; - var protoString = GetDesiredItem(component); - if (_prototypeManager.TryIndex(protoString, out var proto)) - component.DesiredPrototype = proto; - else - Logger.Error("Oracle can't index prototype " + protoString); - } - - private string GetDesiredItem(OracleComponent component) - { - return _random.Pick(GetAllProtos(component)); - } - - - public List GetAllProtos(OracleComponent component) - { - var allTechs = _prototypeManager.EnumeratePrototypes(); - var allRecipes = new List(); - - foreach (var tech in allTechs) - { - foreach (var recipe in tech.RecipeUnlocks) - { - var recipeProto = _prototypeManager.Index(recipe); - allRecipes.Add(recipeProto.Result); - } - } - - var allPlants = _prototypeManager.EnumeratePrototypes().Select(x => x.ProductPrototypes[0]) - .ToList(); - var allProtos = allRecipes.Concat(allPlants).ToList(); - var blacklist = component.BlacklistedPrototypes.ToList(); - - foreach (var proto in allProtos) - { - if (!_prototypeManager.TryIndex(proto, out var entityProto)) - { - blacklist.Add(proto); - continue; - } - - if (!entityProto.Components.ContainsKey("Item")) - { - blacklist.Add(proto); - continue; - } - - if (entityProto.Components.ContainsKey("SolutionTransfer")) - { - blacklist.Add(proto); - continue; - } - - if (entityProto.Components.ContainsKey("MobState")) - blacklist.Add(proto); - } - - foreach (var proto in blacklist) - { - allProtos.Remove(proto); - } - - return allProtos; - } -} diff --git a/Content.Server/Players/PlayTimeTracking/PlayTimeTrackingSystem.cs b/Content.Server/Players/PlayTimeTracking/PlayTimeTrackingSystem.cs index 57c6466ebbb..8368388d81e 100644 --- a/Content.Server/Players/PlayTimeTracking/PlayTimeTrackingSystem.cs +++ b/Content.Server/Players/PlayTimeTracking/PlayTimeTrackingSystem.cs @@ -3,12 +3,15 @@ using Content.Server.Afk.Events; using Content.Server.GameTicking; using Content.Server.Mind; +using Content.Server.Preferences.Managers; using Content.Shared.CCVar; +using Content.Shared.Customization.Systems; using Content.Shared.GameTicking; using Content.Shared.Mobs; using Content.Shared.Mobs.Components; using Content.Shared.Players; using Content.Shared.Players.PlayTimeTracking; +using Content.Shared.Preferences; using Content.Shared.Roles; using Robust.Server.GameObjects; using Robust.Server.Player; @@ -31,6 +34,10 @@ public sealed class PlayTimeTrackingSystem : EntitySystem [Dependency] private readonly IConfigurationManager _cfg = default!; [Dependency] private readonly MindSystem _minds = default!; [Dependency] private readonly PlayTimeTrackingManager _tracking = default!; + [Dependency] private readonly CharacterRequirementsSystem _characterRequirements = default!; + [Dependency] private readonly IServerPreferencesManager _prefs = default!; + [Dependency] private readonly IConfigurationManager _config = default!; + public override void Initialize() { @@ -173,7 +180,16 @@ public bool IsAllowed(ICommonSession player, string role) var isWhitelisted = player.ContentData()?.Whitelisted ?? false; // DeltaV - Whitelist requirement - return JobRequirements.TryRequirementsMet(job, playTimes, out _, EntityManager, _prototypes, isWhitelisted); + return _characterRequirements.CheckRequirementsValid( + job.Requirements, + job, + (HumanoidCharacterProfile) _prefs.GetPreferences(player.UserId).SelectedCharacter, + playTimes, + isWhitelisted, + EntityManager, + _prototypes, + _config, + out _); } public HashSet GetDisallowedJobs(ICommonSession player) @@ -194,13 +210,19 @@ public HashSet GetDisallowedJobs(ICommonSession player) { if (job.Requirements != null) { - foreach (var requirement in job.Requirements) - { - if (JobRequirements.TryRequirementMet(requirement, playTimes, out _, EntityManager, _prototypes, isWhitelisted)) - continue; + if (_characterRequirements.CheckRequirementsValid( + job.Requirements, + job, + (HumanoidCharacterProfile) _prefs.GetPreferences(player.UserId).SelectedCharacter, + playTimes, + isWhitelisted, + EntityManager, + _prototypes, + _config, + out _)) + continue; - goto NoRole; - } + goto NoRole; } roles.Add(job.ID); @@ -234,14 +256,19 @@ public void RemoveDisallowedJobs(NetUserId userId, ref List jobs) jobber.Requirements.Count == 0) continue; - foreach (var requirement in jobber.Requirements) + if (!_characterRequirements.CheckRequirementsValid( + jobber.Requirements, + jobber, + (HumanoidCharacterProfile) _prefs.GetPreferences(userId).SelectedCharacter, + _tracking.GetPlayTimes(_playerManager.GetSessionById(userId)), + _playerManager.GetSessionById(userId).ContentData()?.Whitelisted ?? false, + EntityManager, + _prototypes, + _config, + out _)) { - if (JobRequirements.TryRequirementMet(requirement, playTimes, out _, EntityManager, _prototypes, isWhitelisted)) - continue; - jobs.RemoveSwap(i); i--; - break; } } } diff --git a/Content.Server/Radio/EntitySystems/RadioSystem.cs b/Content.Server/Radio/EntitySystems/RadioSystem.cs index 7232a23d2c8..5fce6f770a2 100644 --- a/Content.Server/Radio/EntitySystems/RadioSystem.cs +++ b/Content.Server/Radio/EntitySystems/RadioSystem.cs @@ -178,9 +178,11 @@ public void SendRadioMessage(EntityUid messageSource, string message, RadioChann private string WrapRadioMessage(EntityUid source, RadioChannelPrototype channel, string name, string message, LanguagePrototype language) { + // TODO: code duplication with ChatSystem.WrapMessage var speech = _chat.GetSpeechVerb(source, message); - // TODO this is done just to preserve the old look of radio, perhaps we can change it as well? - var languageColor = language.SpeechOverride.Color == Color.White ? channel.Color : language.SpeechOverride.Color; + var languageColor = channel.Color; + if (language.SpeechOverride.Color is { } colorOverride) + languageColor = Color.InterpolateBetween(languageColor, colorOverride, colorOverride.A); return Loc.GetString(speech.Bold ? "chat-radio-message-wrap-bold" : "chat-radio-message-wrap", ("color", channel.Color), diff --git a/Content.Server/Remotes/DoorRemoteSystem.cs b/Content.Server/Remotes/DoorRemoteSystem.cs index e42bc700912..31fcacdaf80 100644 --- a/Content.Server/Remotes/DoorRemoteSystem.cs +++ b/Content.Server/Remotes/DoorRemoteSystem.cs @@ -50,8 +50,10 @@ private void OnBeforeInteract(Entity entity, ref BeforeRang return; } + // Holding the door remote grants you access to the relevant doors IN ADDITION to what ever access you had. + // This access is enforced in _doorSystem.HasAccess when it calls _accessReaderSystem.IsAllowed if (TryComp(args.Target, out var accessComponent) - && !_doorSystem.HasAccess(args.Target.Value, args.Used, doorComp, accessComponent)) + && !_doorSystem.HasAccess(args.Target.Value, args.User, doorComp, accessComponent)) { _doorSystem.Deny(args.Target.Value, doorComp, args.User); Popup.PopupEntity(Loc.GetString("door-remote-denied"), args.User, args.User); @@ -61,7 +63,10 @@ private void OnBeforeInteract(Entity entity, ref BeforeRang switch (entity.Comp.Mode) { case OperatingMode.OpenClose: - if (_doorSystem.TryToggleDoor(args.Target.Value, doorComp, args.Used)) + // Note we provide args.User here to TryToggleDoor as the "user" + // This means that the door will look at all access items carried by the player for access, including + // this remote, but also including anything else they are carrying such as a PDA or ID card. + if (_doorSystem.TryToggleDoor(args.Target.Value, doorComp, args.User)) _adminLogger.Add(LogType.Action, LogImpact.Medium, $"{ToPrettyString(args.User):player} used {ToPrettyString(args.Used)} on {ToPrettyString(args.Target.Value)}: {doorComp.State}"); break; case OperatingMode.ToggleBolts: @@ -69,7 +74,7 @@ private void OnBeforeInteract(Entity entity, ref BeforeRang { if (!boltsComp.BoltWireCut) { - _doorSystem.SetBoltsDown((args.Target.Value, boltsComp), !boltsComp.BoltsDown, args.Used); + _doorSystem.SetBoltsDown((args.Target.Value, boltsComp), !boltsComp.BoltsDown, args.User); _adminLogger.Add(LogType.Action, LogImpact.Medium, $"{ToPrettyString(args.User):player} used {ToPrettyString(args.Used)} on {ToPrettyString(args.Target.Value)} to {(boltsComp.BoltsDown ? "" : "un")}bolt it"); } } diff --git a/Content.Server/Research/Oracle/OracleComponent.cs b/Content.Server/Research/Oracle/OracleComponent.cs new file mode 100644 index 00000000000..6196ce95060 --- /dev/null +++ b/Content.Server/Research/Oracle/OracleComponent.cs @@ -0,0 +1,73 @@ +using Content.Shared.Random; +using Robust.Shared.Prototypes; + +namespace Content.Server.Research.Oracle; + +[RegisterComponent] +public sealed partial class OracleComponent : Component +{ + public const string SolutionName = "fountain"; + + [DataField(required: true)] + public ProtoId DemandTypes; + + [DataField] + public List> BlacklistedDemands = new(); + + [DataField(required: true)] + public List> RewardEntities; + + [DataField(required: true)] + public ProtoId RewardReagents; + + /// + /// The chance to dispense a completely random chemical instead of what's listed in + /// + [DataField] + public float AbnormalReagentChance = 0.2f; + + [DataField] + public TimeSpan + NextDemandTime = TimeSpan.Zero, + NextBarkTime = TimeSpan.Zero, + NextRejectTime = TimeSpan.Zero; + + [DataField] + public TimeSpan + DemandDelay = TimeSpan.FromMinutes(10), + BarkDelay = TimeSpan.FromMinutes(2), + RejectDelay = TimeSpan.FromSeconds(10); + + [ViewVariables(VVAccess.ReadWrite)] + public EntityPrototype DesiredPrototype = default!; + + [ViewVariables(VVAccess.ReadWrite)] + public EntityPrototype? LastDesiredPrototype = default!; + + [DataField("demandMessages")] + public IReadOnlyList DemandMessages = new[] + { + "oracle-demand-1", + "oracle-demand-2", + "oracle-demand-3", + "oracle-demand-4", + "oracle-demand-5", + "oracle-demand-6", + "oracle-demand-7", + "oracle-demand-8", + "oracle-demand-9", + "oracle-demand-10", + "oracle-demand-11", + "oracle-demand-12" + }; + + [DataField("rejectMessages")] + public IReadOnlyList RejectMessages = new[] + { + "ἄγνοια", + "υλικό", + "ἀγνωσία", + "γήινος", + "σάκλας" + }; +} diff --git a/Content.Server/Research/Oracle/OracleSystem.cs b/Content.Server/Research/Oracle/OracleSystem.cs new file mode 100644 index 00000000000..c9b050a246d --- /dev/null +++ b/Content.Server/Research/Oracle/OracleSystem.cs @@ -0,0 +1,288 @@ +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using Content.Server.Botany; +using Content.Server.Chat.Managers; +using Content.Server.Chat.Systems; +using Content.Server.Chemistry.Containers.EntitySystems; +using Content.Server.Fluids.EntitySystems; +using Content.Server.Psionics; +using Content.Server.Research.Systems; +using Content.Shared.Psionics.Abilities; +using Content.Shared.Chat; +using Content.Shared.Chemistry.Components; +using Content.Shared.Chemistry.Reagent; +using Content.Shared.Interaction; +using Content.Shared.Mobs.Components; +using Content.Shared.Psionics.Glimmer; +using Content.Shared.Random.Helpers; +using Content.Shared.Research.Components; +using Content.Shared.Research.Prototypes; +using Content.Shared.Throwing; +using Robust.Shared.Map; +using Robust.Shared.Network; +using Robust.Shared.Player; +using Robust.Shared.Prototypes; +using Robust.Shared.Random; +using Robust.Shared.Timing; + +namespace Content.Server.Research.Oracle; + +public sealed class OracleSystem : EntitySystem +{ + [Dependency] private readonly ChatSystem _chat = default!; + [Dependency] private readonly IChatManager _chatMan = default!; + [Dependency] private readonly GlimmerSystem _glimmer = default!; + [Dependency] private readonly IPrototypeManager _protoMan = default!; + [Dependency] private readonly PuddleSystem _puddles = default!; + [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly ResearchSystem _research = default!; + [Dependency] private readonly SolutionContainerSystem _solutions = default!; + [Dependency] private readonly ThrowingSystem _throwing = default!; + [Dependency] private readonly IGameTiming _timing = default!; + + public override void Update(float frameTime) + { + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var uid, out var comp)) + { + if (_timing.CurTime >= comp.NextDemandTime) + { + // Might be null if this is the first tick. In that case this will simply initialize it. + var last = (EntityPrototype?) comp.DesiredPrototype; + if (NextItem((uid, comp))) + comp.LastDesiredPrototype = last; + } + + if (_timing.CurTime >= comp.NextBarkTime) + { + comp.NextBarkTime = _timing.CurTime + comp.BarkDelay; + + var message = Loc.GetString(_random.Pick(comp.DemandMessages), ("item", comp.DesiredPrototype.Name)).ToUpper(); + _chat.TrySendInGameICMessage(uid, message, InGameICChatType.Speak, false); + } + } + + query.Dispose(); + } + + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnInteractHand); + SubscribeLocalEvent(OnInteractUsing); + } + + private void OnInteractHand(Entity oracle, ref InteractHandEvent args) + { + if (!HasComp(args.User) || HasComp(args.User) + || !TryComp(args.User, out var actor)) + return; + + SendTelepathicInfo(oracle, actor.PlayerSession.Channel, + Loc.GetString("oracle-current-item", ("item", oracle.Comp.DesiredPrototype.Name))); + + if (oracle.Comp.LastDesiredPrototype != null) + SendTelepathicInfo(oracle, actor.PlayerSession.Channel, + Loc.GetString("oracle-previous-item", ("item", oracle.Comp.LastDesiredPrototype.Name))); + } + + private void OnInteractUsing(Entity oracle, ref InteractUsingEvent args) + { + if (args.Handled) + return; + + if (HasComp(args.Used) || !TryComp(args.Used, out var meta) || meta.EntityPrototype == null) + return; + + var requestValid = IsCorrectItem(meta.EntityPrototype, oracle.Comp.DesiredPrototype); + var updateRequest = true; + + if (oracle.Comp.LastDesiredPrototype != null && + IsCorrectItem(meta.EntityPrototype, oracle.Comp.LastDesiredPrototype)) + { + updateRequest = false; + requestValid = true; + oracle.Comp.LastDesiredPrototype = null; + } + + if (!requestValid) + { + if (!HasComp(args.Used) && + _timing.CurTime >= oracle.Comp.NextRejectTime) + { + oracle.Comp.NextRejectTime = _timing.CurTime + oracle.Comp.RejectDelay; + _chat.TrySendInGameICMessage(oracle, _random.Pick(oracle.Comp.RejectMessages), InGameICChatType.Speak, true); + } + + return; + } + + DispenseRewards(oracle, Transform(args.User).Coordinates); + QueueDel(args.Used); + + if (updateRequest) + NextItem(oracle); + } + + private void SendTelepathicInfo(Entity oracle, INetChannel client, string message) + { + var messageWrap = Loc.GetString("chat-manager-send-telepathic-chat-wrap-message", + ("telepathicChannelName", Loc.GetString("chat-manager-telepathic-channel-name")), + ("message", message)); + + _chatMan.ChatMessageToOne(ChatChannel.Telepathic, + message, messageWrap, oracle, false, client, Color.PaleVioletRed); + } + + private bool IsCorrectItem(EntityPrototype given, EntityPrototype target) + { + // Nyano, what is this shit? + // Why are we comparing by name instead of prototype id? + // Why is this ever necessary? + // What were you trying to accomplish?! + if (given.Name == target.Name) + return true; + + return false; + } + + private void DispenseRewards(Entity oracle, EntityCoordinates throwTarget) + { + foreach (var rewardRandom in oracle.Comp.RewardEntities) + { + // Spawn each reward next to oracle and throw towards the target + var rewardProto = _protoMan.Index(rewardRandom).Pick(_random); + var reward = EntityManager.SpawnNextToOrDrop(rewardProto, oracle); + _throwing.TryThrow(reward, throwTarget, recoil: false); + } + + DispenseLiquidReward(oracle); + } + + private void DispenseLiquidReward(Entity oracle) + { + if (!_solutions.TryGetSolution(oracle.Owner, OracleComponent.SolutionName, out var fountainSol)) + return; + + // Why is this hardcoded? + var amount = MathF.Round(20 + _random.Next(1, 30) + _glimmer.GlimmerOutput / 10f); + var temporarySol = new Solution(); + var reagent = _protoMan.Index(oracle.Comp.RewardReagents).Pick(_random); + + if (_random.Prob(oracle.Comp.AbnormalReagentChance)) + { + var allReagents = _protoMan.EnumeratePrototypes() + .Where(x => !x.Abstract) + .Select(x => x.ID).ToList(); + + reagent = _random.Pick(allReagents); + } + + temporarySol.AddReagent(reagent, amount); + _solutions.TryMixAndOverflow(fountainSol.Value, temporarySol, fountainSol.Value.Comp.Solution.MaxVolume, out var overflowing); + + if (overflowing != null && overflowing.Volume > 0) + _puddles.TrySpillAt(oracle, overflowing, out var _); + } + + private bool NextItem(Entity oracle) + { + oracle.Comp.NextBarkTime = oracle.Comp.NextRejectTime = TimeSpan.Zero; + oracle.Comp.NextDemandTime = _timing.CurTime + oracle.Comp.DemandDelay; + + var protoId = GetDesiredItem(oracle); + if (protoId != null && _protoMan.TryIndex(protoId, out var proto)) + { + oracle.Comp.DesiredPrototype = proto; + return true; + } + + return false; + } + + // TODO: find a way to not just use string literals here (weighted random doesn't support enums) + private string? GetDesiredItem(Entity oracle) + { + var demand = _protoMan.Index(oracle.Comp.DemandTypes).Pick(_random); + + string? proto; + if (demand == "tech" && GetRandomTechProto(oracle, out proto)) + return proto; + + // This is also a fallback for when there's no research server to form an oracle tech request. + if (demand is "plant" or "tech" && GetRandomPlantProto(oracle, out proto)) + return proto; + + return null; + } + + private bool GetRandomTechProto(Entity oracle, [NotNullWhen(true)] out string? proto) + { + // Try to find the most advanced server. + var database = _research.GetServerIds() + .Select(x => _research.TryGetServerById(x, out var serverUid, out _) ? serverUid : null) + .Where(x => x != null && Transform(x.Value).GridUid == Transform(oracle).GridUid) + .Select(x => + { + TryComp(x!.Value, out var comp); + return new Entity(x.Value, comp); + }) + .Where(x => x.Comp != null) + .OrderByDescending(x => + _research.GetDisciplineTiers(x.Comp!).Select(pair => pair.Value).Max()) + .FirstOrDefault(EntityUid.Invalid); + + if (database.Owner == EntityUid.Invalid) + { + Log.Warning($"Cannot find an applicable server on grid {Transform(oracle).GridUid} to form an oracle request."); + proto = null; + return false; + } + + // Select a technology that's either already unlocked, or can be unlocked from current research + var techs = _protoMan.EnumeratePrototypes() + .Where(x => !x.Hidden) + .Where(x => + _research.IsTechnologyUnlocked(database.Owner, x, database.Comp) + || _research.IsTechnologyAvailable(database.Comp!, x)) + .SelectMany(x => x.RecipeUnlocks) + .Select(x => _protoMan.Index(x).Result) + .Where(x => IsDemandValid(oracle, x)) + .ToList(); + + // Unlikely. + if (techs.Count == 0) + { + proto = null; + return false; + } + + proto = _random.Pick(techs); + return true; + } + + private bool GetRandomPlantProto(Entity oracle, [NotNullWhen(true)] out string? proto) + { + var allPlants = _protoMan.EnumeratePrototypes() + .Select(x => x.ProductPrototypes.FirstOrDefault()) + .Where(x => IsDemandValid(oracle, x)) + .ToList(); + + if (allPlants.Count == 0) + { + proto = null; + return false; + } + + proto = _random.Pick(allPlants)!; + return true; + } + + private bool IsDemandValid(Entity oracle, ProtoId? id) + { + if (id == null || oracle.Comp.BlacklistedDemands.Contains(id.Value)) + return false; + + return _protoMan.TryIndex(id, out var proto) && proto.Components.ContainsKey("Item"); + } +} \ No newline at end of file diff --git a/Content.Server/StationEvents/Components/RampingStationEventSchedulerComponent.cs b/Content.Server/StationEvents/Components/RampingStationEventSchedulerComponent.cs index 673c82b20f6..282ee5b612a 100644 --- a/Content.Server/StationEvents/Components/RampingStationEventSchedulerComponent.cs +++ b/Content.Server/StationEvents/Components/RampingStationEventSchedulerComponent.cs @@ -4,50 +4,38 @@ public sealed partial class RampingStationEventSchedulerComponent : Component { /// - /// Multiplies the End Time of the Ramping Event curve. Lower this number for shorter, hectic shifts, increase this number for longer shifts. + /// The maximum number by which the event rate will be multiplied when shift time reaches the end time. /// [DataField] - public float ShiftChaosModifier = 1f; + public float ChaosModifier = 3f; /// - /// The number by which all event delays will be multiplied. Unlike chaos, remains constant throughout the shift. + /// The minimum number by which the event rate will be multiplied when the shift has just begun. /// [DataField] - public float EventDelayModifier = 1f; - + public float StartingChaosRatio = 0.1f; /// - /// Shift Length(in Minutes) is directly reduced by this value. - /// - [DataField] - public float ShiftLengthOffset = 0f; - - /// - /// Minimum time between events is decreased by this value. + /// The number by which all event delays will be multiplied. Unlike chaos, remains constant throughout the shift. /// [DataField] - public float MinimumEventTimeOffset = 0f; + public float EventDelayModifier = 1f; /// - /// Maximum time between events is decreased by this value. + /// The number by which average expected shift length is multiplied. Higher values lead to slower chaos growth. /// - - [DataField] - public float MaximumEventTimeOffset = 0f; - - [DataField] - public bool IgnoreMinimumTimes = false; + public float ShiftLengthModifier = 1f; // Everything below is overridden in the RampingStationEventSchedulerSystem based on CVars - [DataField] + [DataField("endTime"), ViewVariables(VVAccess.ReadWrite)] public float EndTime; - [DataField] + [DataField("maxChaos"), ViewVariables(VVAccess.ReadWrite)] public float MaxChaos; - [DataField] + [DataField("startingChaos"), ViewVariables(VVAccess.ReadWrite)] public float StartingChaos; - [DataField] + [DataField("timeUntilNextEvent"), ViewVariables(VVAccess.ReadWrite)] public float TimeUntilNextEvent; } diff --git a/Content.Server/StationEvents/EventManagerSystem.cs b/Content.Server/StationEvents/EventManagerSystem.cs index d33a373b377..c6e9beeaca1 100644 --- a/Content.Server/StationEvents/EventManagerSystem.cs +++ b/Content.Server/StationEvents/EventManagerSystem.cs @@ -162,7 +162,7 @@ public TimeSpan TimeSinceLastEvent(EntityPrototype stationEvent) private bool CanRun(EntityPrototype prototype, StationEventComponent stationEvent, int playerCount, TimeSpan currentTime) { - if (GameTicker.IsGameRuleActive(prototype.ID)) + if (GameTicker.IsGameRuleAdded(prototype.ID)) return false; if (stationEvent.MaxOccurrences.HasValue && GetOccurrences(prototype) >= stationEvent.MaxOccurrences.Value) diff --git a/Content.Server/StationEvents/RampingStationEventSchedulerSystem.cs b/Content.Server/StationEvents/RampingStationEventSchedulerSystem.cs index e24578fdac9..aa0c9b214b4 100644 --- a/Content.Server/StationEvents/RampingStationEventSchedulerSystem.cs +++ b/Content.Server/StationEvents/RampingStationEventSchedulerSystem.cs @@ -2,10 +2,10 @@ using Content.Server.GameTicking.Rules; using Content.Server.GameTicking.Rules.Components; using Content.Server.StationEvents.Components; +using Content.Server.StationEvents.Events; using Content.Shared.CCVar; using Robust.Shared.Configuration; using Robust.Shared.Random; -using Robust.Shared.Utility; namespace Content.Server.StationEvents; @@ -16,35 +16,30 @@ public sealed class RampingStationEventSchedulerSystem : GameRuleSystem - /// A logistic curve equation used to smooth out the transition between event times at shift start, vs. shift end. - /// Depending on the settings used, the end time might not necessarily be the point at which timers hit the floor. - /// It is after all, an asymptote. - /// - /// - /// - /// - /// - public float RampingEventTimeEquation(RampingStationEventSchedulerComponent component, float startTime, float endTimeOffset = 0) + public float GetChaosModifier(EntityUid uid, RampingStationEventSchedulerComponent component) { - var endTime = Math.Clamp(endTimeOffset, 0.1f, startTime - 1); - var shiftLength = Math.Max(1, _cfg.GetCVar(CCVars.EventsRampingAverageEndTime) - component.ShiftLengthOffset); - return 2 * endTime - / (1 - + MathF.Exp(_cfg.GetCVar(CCVars.EventsRampingAverageChaos) - * component.ShiftChaosModifier - / shiftLength - * endTime - * (float) _gameTicker.RoundDuration().TotalSeconds - / 60)) - + (startTime - endTime); + var roundTime = (float) _gameTicker.RoundDuration().TotalSeconds; + if (roundTime > component.EndTime) + return component.MaxChaos; + + return component.MaxChaos / component.EndTime * roundTime + component.StartingChaos; } protected override void Started(EntityUid uid, RampingStationEventSchedulerComponent component, GameRuleComponent gameRule, GameRuleStartedEvent args) { base.Started(uid, component, gameRule, args); - PickNextEventTime(component); + var avgChaos = _cfg.GetCVar(CCVars.EventsRampingAverageChaos) * component.ChaosModifier; + var avgTime = _cfg.GetCVar(CCVars.EventsRampingAverageEndTime) * component.ShiftLengthModifier; + + // Worlds shittiest probability distribution + // Got a complaint? Send them to + component.MaxChaos = avgChaos * _random.NextFloat(0.75f, 1.25f); + // This is in minutes, so *60 for seconds (for the chaos calc) + component.EndTime = avgTime * _random.NextFloat(0.75f, 1.25f) * 60f; + component.StartingChaos = component.MaxChaos * component.StartingChaosRatio; + + PickNextEventTime(uid, component); } public override void Update(float frameTime) @@ -66,31 +61,17 @@ public override void Update(float frameTime) return; } - PickNextEventTime(scheduler); + PickNextEventTime(uid, scheduler); _event.RunRandomEvent(); } } - private void PickNextEventTime(RampingStationEventSchedulerComponent component) + private void PickNextEventTime(EntityUid uid, RampingStationEventSchedulerComponent component) { - // In case of server hosts being silly and setting maximum time to be lower than minimum time, sanity check the scheduler inputs and sort them by Min/Max - var minimumTime = MathF.Min(_cfg.GetCVar(CCVars.GameEventsRampingMinimumTime) - - _cfg.GetCVar(CCVars.GameEventsRampingMinimumTimeOffset) - - component.MinimumEventTimeOffset, _cfg.GetCVar(CCVars.GameEventsRampingMaximumTime) - - _cfg.GetCVar(CCVars.GameEventsRampingMaximumTimeOffset) - - component.MaximumEventTimeOffset); - - var maximumTime = MathF.Max(_cfg.GetCVar(CCVars.GameEventsRampingMinimumTime) - - _cfg.GetCVar(CCVars.GameEventsRampingMinimumTimeOffset) - - component.MinimumEventTimeOffset, _cfg.GetCVar(CCVars.GameEventsRampingMaximumTime) - - _cfg.GetCVar(CCVars.GameEventsRampingMaximumTimeOffset) - - component.MaximumEventTimeOffset); - - // Just in case someone messed up their math, set it to between 6 and 12 seconds. This absolutely isn't ideal component.TimeUntilNextEvent = _random.NextFloat( - RampingEventTimeEquation(component, MathF.Max(0.1f, minimumTime)), - RampingEventTimeEquation(component, MathF.Max(0.2f, maximumTime))); + _cfg.GetCVar(CCVars.GameEventsRampingMinimumTime), + _cfg.GetCVar(CCVars.GameEventsRampingMaximumTime)); - component.TimeUntilNextEvent *= component.EventDelayModifier; + component.TimeUntilNextEvent *= component.EventDelayModifier / GetChaosModifier(uid, component); } } diff --git a/Content.Server/Supermatter/Systems/SupermatterSystem.Processing.cs b/Content.Server/Supermatter/Systems/SupermatterSystem.Processing.cs new file mode 100644 index 00000000000..7a62eba6f7d --- /dev/null +++ b/Content.Server/Supermatter/Systems/SupermatterSystem.Processing.cs @@ -0,0 +1,412 @@ +using Content.Shared.Atmos; +using Content.Shared.Radiation.Components; +using Content.Shared.Supermatter.Components; +using System.Text; +using Content.Shared.Chat; +using System.Linq; +using Content.Shared.Audio; +using Content.Shared.CCVar; + +namespace Content.Server.Supermatter.Systems; + +public sealed partial class SupermatterSystem +{ + /// + /// Handle power and radiation output depending on atmospheric things. + /// + private void ProcessAtmos(EntityUid uid, SupermatterComponent sm) + { + var mix = _atmosphere.GetContainingMixture(uid, true, true); + + if (mix is not { }) + return; + + var absorbedGas = mix.Remove(sm.GasEfficiency * mix.TotalMoles); + var moles = absorbedGas.TotalMoles; + + if (!(moles > 0f)) + return; + + var gases = sm.GasStorage; + var facts = sm.GasDataFields; + + // Lets get the proportions of the gasses in the mix for scaling stuff later + // They range between 0 and 1 + gases = gases.ToDictionary( + gas => gas.Key, + gas => Math.Clamp(absorbedGas.GetMoles(gas.Key) / moles, 0, 1) + ); + + // No less then zero, and no greater then one, we use this to do explosions and heat to power transfer. + var powerRatio = gases.Sum(gas => gases[gas.Key] * facts[gas.Key].PowerMixRatio); + + // Minimum value of -10, maximum value of 23. Affects plasma, o2 and heat output. + var heatModifier = gases.Sum(gas => gases[gas.Key] * facts[gas.Key].HeatPenalty); + + // Minimum value of -10, maximum value of 23. Affects plasma, o2 and heat output. + var transmissionBonus = gases.Sum(gas => gases[gas.Key] * facts[gas.Key].TransmitModifier); + + var h2OBonus = 1 - gases[Gas.WaterVapor] * 0.25f; + + powerRatio = Math.Clamp(powerRatio, 0, 1); + heatModifier = Math.Max(heatModifier, 0.5f); + transmissionBonus *= h2OBonus; + + // Effects the damage heat does to the crystal + sm.DynamicHeatResistance = 1f; + + // More moles of gases are harder to heat than fewer, so let's scale heat damage around them + sm.MoleHeatPenaltyThreshold = (float) Math.Max(moles * sm.MoleHeatPenalty, 0.25); + + // Ramps up or down in increments of 0.02 up to the proportion of CO2 + // Given infinite time, powerloss_dynamic_scaling = co2comp + // Some value from 0-1 + if (moles > sm.PowerlossInhibitionMoleThreshold && gases[Gas.CarbonDioxide] > sm.PowerlossInhibitionGasThreshold) + { + var co2powerloss = Math.Clamp(gases[Gas.CarbonDioxide] - sm.PowerlossDynamicScaling, -0.02f, 0.02f); + sm.PowerlossDynamicScaling = Math.Clamp(sm.PowerlossDynamicScaling + co2powerloss, 0f, 1f); + } + else + sm.PowerlossDynamicScaling = Math.Clamp(sm.PowerlossDynamicScaling - 0.05f, 0f, 1f); + + // Ranges from 0~1(1 - (0~1 * 1~(1.5 * (mol / 500)))) + // We take the mol count, and scale it to be our inhibitor + var powerlossInhibitor = + Math.Clamp( + 1 + - sm.PowerlossDynamicScaling + * Math.Clamp( + moles / sm.PowerlossInhibitionMoleBoostThreshold, + 1f, 1.5f), + 0f, 1f); + + if (sm.MatterPower != 0) // We base our removed power off 1/10 the matter_power. + { + var removedMatter = Math.Max(sm.MatterPower / sm.MatterPowerConversion, 40); + // Adds at least 40 power + sm.Power = Math.Max(sm.Power + removedMatter, 0); + // Removes at least 40 matter power + sm.MatterPower = Math.Max(sm.MatterPower - removedMatter, 0); + } + + // Based on gas mix, makes the power more based on heat or less effected by heat + var tempFactor = powerRatio > 0.8 ? 50f : 30f; + + // If there is more pluox and N2 then anything else, we receive no power increase from heat + sm.Power = Math.Max(absorbedGas.Temperature * tempFactor / Atmospherics.T0C * powerRatio + sm.Power, 0); + + // Irradiate stuff + if (TryComp(uid, out var rad)) + rad.Intensity = + sm.Power + * Math.Max(0, 1f + transmissionBonus / 10f) + * 0.003f + * _config.GetCVar(CCVars.SupermatterRadsModifier); + + // Power * 0.55 * 0.8~1 + var energy = sm.Power * sm.ReactionPowerModifier; + + // Keep in mind we are only adding this temperature to (efficiency)% of the one tile the rock is on. + // An increase of 4°C at 25% efficiency here results in an increase of 1°C / (#tilesincore) overall. + // Power * 0.55 * 1.5~23 / 5 + absorbedGas.Temperature += energy * heatModifier * sm.ThermalReleaseModifier; + absorbedGas.Temperature = Math.Max(0, + Math.Min(absorbedGas.Temperature, sm.HeatThreshold * heatModifier)); + + // Release the waste + absorbedGas.AdjustMoles(Gas.Plasma, Math.Max(energy * heatModifier * sm.PlasmaReleaseModifier, 0f)); + absorbedGas.AdjustMoles(Gas.Oxygen, Math.Max((energy + absorbedGas.Temperature * heatModifier - Atmospherics.T0C) * sm.OxygenReleaseEfficiencyModifier, 0f)); + + _atmosphere.Merge(mix, absorbedGas); + + var powerReduction = (float) Math.Pow(sm.Power / 500, 3); + + // After this point power is lowered + // This wraps around to the begining of the function + sm.Power = Math.Max(sm.Power - Math.Min(powerReduction * powerlossInhibitor, sm.Power * 0.83f * powerlossInhibitor), 0f); + } + + /// + /// Shoot lightning bolts depensing on accumulated power. + /// + private void SupermatterZap(EntityUid uid, SupermatterComponent sm) + { + // Divide power by its' threshold to get a value from 0-1, then multiply by the amount of possible lightnings + var zapPower = sm.Power / sm.PowerPenaltyThreshold * sm.LightningPrototypes.Length; + var zapPowerNorm = (int) Math.Clamp(zapPower, 0, sm.LightningPrototypes.Length - 1); + _lightning.ShootRandomLightnings(uid, 3.5f, sm.Power > sm.PowerPenaltyThreshold ? 3 : 1, sm.LightningPrototypes[zapPowerNorm]); + } + + /// + /// Handles environmental damage. + /// + private void HandleDamage(EntityUid uid, SupermatterComponent sm) + { + var xform = Transform(uid); + var indices = _xform.GetGridOrMapTilePosition(uid, xform); + + sm.DamageArchived = sm.Damage; + + var mix = _atmosphere.GetContainingMixture(uid, true, true); + + // We're in space or there is no gas to process + if (!xform.GridUid.HasValue || mix is not { } || mix.TotalMoles == 0f) + { + sm.Damage += Math.Max(sm.Power / 1000 * sm.DamageIncreaseMultiplier, 0.1f); + return; + } + + // Absorbed gas from surrounding area + var absorbedGas = mix.Remove(sm.GasEfficiency * mix.TotalMoles); + var moles = absorbedGas.TotalMoles; + + var totalDamage = 0f; + + var tempThreshold = Atmospherics.T0C + sm.HeatPenaltyThreshold; + + // Temperature start to have a positive effect on damage after 350 + var tempDamage = + Math.Max( + Math.Clamp(moles / 200f, .5f, 1f) + * absorbedGas.Temperature + - tempThreshold + * sm.DynamicHeatResistance, + 0f) + * sm.MoleHeatThreshold + / 150f + * sm.DamageIncreaseMultiplier; + totalDamage += tempDamage; + + // Power only starts affecting damage when it is above 5000 + var powerDamage = Math.Max(sm.Power - sm.PowerPenaltyThreshold, 0f) / 500f * sm.DamageIncreaseMultiplier; + totalDamage += powerDamage; + + // Mol count only starts affecting damage when it is above 1800 + var moleDamage = Math.Max(moles - sm.MolePenaltyThreshold, 0) / 80 * sm.DamageIncreaseMultiplier; + totalDamage += moleDamage; + + // Healing damage + if (moles < sm.MolePenaltyThreshold) + { + // There's a very small float so that it doesn't divide by 0 + var healHeatDamage = Math.Min(absorbedGas.Temperature - tempThreshold, 0.001f) / 150; + totalDamage += healHeatDamage; + } + + // Check for space tiles next to SM + //TODO: Change moles out for checking if adjacent tiles exist + var enumerator = _atmosphere.GetAdjacentTileMixtures(xform.GridUid.Value, indices, false, false); + while (enumerator.MoveNext(out var ind)) + { + if (ind.TotalMoles != 0) + continue; + + var integrity = GetIntegrity(sm); + + var factor = integrity switch + { + < 10 => 0.0005f, + < 25 => 0.0009f, + < 45 => 0.005f, + < 75 => 0.002f, + _ => 0f + }; + + totalDamage += Math.Clamp(sm.Power * factor * sm.DamageIncreaseMultiplier, 0, sm.MaxSpaceExposureDamage); + + break; + } + + var damage = Math.Min(sm.DamageArchived + sm.DamageHardcap * sm.DamageDelaminationPoint, totalDamage); + + // Prevent it from going negative + sm.Damage = Math.Clamp(damage, 0, float.PositiveInfinity); + } + + /// + /// Handles core damage announcements + /// + private void AnnounceCoreDamage(EntityUid uid, SupermatterComponent sm) + { + var message = string.Empty; + var global = false; + + var integrity = GetIntegrity(sm).ToString("0.00"); + + // Special cases + if (sm.Damage < sm.DamageDelaminationPoint && sm.Delamming) + { + message = Loc.GetString("supermatter-delam-cancel", ("integrity", integrity)); + sm.DelamAnnounced = false; + global = true; + } + + if (sm.Delamming && !sm.DelamAnnounced) + { + var sb = new StringBuilder(); + var loc = string.Empty; + + switch (sm.PreferredDelamType) + { + case DelamType.Cascade: loc = "supermatter-delam-cascade"; break; + case DelamType.Singulo: loc = "supermatter-delam-overmass"; break; + case DelamType.Tesla: loc = "supermatter-delam-tesla"; break; + default: loc = "supermatter-delam-explosion"; break; + } + + var station = _station.GetOwningStation(uid); + if (station != null) + _alert.SetLevel((EntityUid) station, sm.AlertCodeDeltaId, true, true, true, false); + + sb.AppendLine(Loc.GetString(loc)); + sb.AppendLine(Loc.GetString("supermatter-seconds-before-delam", ("seconds", sm.DelamTimer))); + + message = sb.ToString(); + global = true; + sm.DelamAnnounced = true; + + SendSupermatterAnnouncement(uid, message, global); + return; + } + + // Ignore the 0% integrity alarm + if (sm.Delamming) + return; + + // We are not taking consistent damage, Engineers aren't needed + if (sm.Damage <= sm.DamageArchived) + return; + + if (sm.Damage >= sm.DamageWarningThreshold) + { + message = Loc.GetString("supermatter-warning", ("integrity", integrity)); + if (sm.Damage >= sm.DamageEmergencyThreshold) + { + message = Loc.GetString("supermatter-emergency", ("integrity", integrity)); + global = true; + } + } + + SendSupermatterAnnouncement(uid, message, global); + } + + /// If true, sends a station announcement + /// Localisation string for a custom announcer name + public void SendSupermatterAnnouncement(EntityUid uid, string message, bool global = false, string? customSender = null) + { + if (global) + { + var sender = Loc.GetString(customSender != null ? customSender : "supermatter-announcer"); + _chat.DispatchStationAnnouncement(uid, message, sender, colorOverride: Color.Yellow); + return; + } + + _chat.TrySendInGameICMessage(uid, message, InGameICChatType.Speak, hideChat: false, checkRadioPrefix: true); + } + + /// + /// Returns the integrity rounded to hundreds, e.g. 100.00% + /// + public float GetIntegrity(SupermatterComponent sm) + { + var integrity = sm.Damage / sm.DamageDelaminationPoint; + integrity = (float) Math.Round(100 - integrity * 100, 2); + integrity = integrity < 0 ? 0 : integrity; + return integrity; + } + + /// + /// Decide on how to delaminate. + /// + public DelamType ChooseDelamType(EntityUid uid, SupermatterComponent sm) + { + if (_config.GetCVar(CCVars.SupermatterDoForceDelam)) + return _config.GetCVar(CCVars.SupermatterForcedDelamType); + + var mix = _atmosphere.GetContainingMixture(uid, true, true); + + if (mix is { }) + { + var absorbedGas = mix.Remove(sm.GasEfficiency * mix.TotalMoles); + var moles = absorbedGas.TotalMoles; + + if (_config.GetCVar(CCVars.SupermatterDoSingulooseDelam) + && moles >= sm.MolePenaltyThreshold * _config.GetCVar(CCVars.SupermatterSingulooseMolesModifier)) + return DelamType.Singulo; + } + + if (_config.GetCVar(CCVars.SupermatterDoTeslooseDelam) + && sm.Power >= sm.PowerPenaltyThreshold * _config.GetCVar(CCVars.SupermatterTesloosePowerModifier)) + return DelamType.Tesla; + + //TODO: Add resonance cascade when there's crazy conditions or a destabilizing crystal + + return DelamType.Explosion; + } + + /// + /// Handle the end of the station. + /// + private void HandleDelamination(EntityUid uid, SupermatterComponent sm) + { + var xform = Transform(uid); + + sm.PreferredDelamType = ChooseDelamType(uid, sm); + + if (!sm.Delamming) + { + sm.Delamming = true; + AnnounceCoreDamage(uid, sm); + } + + if (sm.Damage < sm.DamageDelaminationPoint && sm.Delamming) + { + sm.Delamming = false; + AnnounceCoreDamage(uid, sm); + } + + sm.DelamTimerAccumulator++; + + if (sm.DelamTimerAccumulator < sm.DelamTimer) + return; + + switch (sm.PreferredDelamType) + { + case DelamType.Cascade: + Spawn(sm.KudzuSpawnPrototype, xform.Coordinates); + break; + + case DelamType.Singulo: + Spawn(sm.SingularitySpawnPrototype, xform.Coordinates); + break; + + case DelamType.Tesla: + Spawn(sm.TeslaSpawnPrototype, xform.Coordinates); + break; + + default: + _explosion.TriggerExplosive(uid); + break; + } + } + + /// + /// Swaps out ambience sounds when the SM is delamming or not. + /// + private void HandleSoundLoop(EntityUid uid, SupermatterComponent sm) + { + var ambient = Comp(uid); + + if (ambient == null) + return; + + if (sm.Delamming && sm.CurrentSoundLoop != sm.DelamSound) + sm.CurrentSoundLoop = sm.DelamSound; + + else if (!sm.Delamming && sm.CurrentSoundLoop != sm.CalmSound) + sm.CurrentSoundLoop = sm.CalmSound; + + if (ambient.Sound != sm.CurrentSoundLoop) + _ambient.SetSound(uid, sm.CurrentSoundLoop, ambient); + } +} \ No newline at end of file diff --git a/Content.Server/Supermatter/Systems/SupermatterSystem.cs b/Content.Server/Supermatter/Systems/SupermatterSystem.cs new file mode 100644 index 00000000000..3d86f57fb84 --- /dev/null +++ b/Content.Server/Supermatter/Systems/SupermatterSystem.cs @@ -0,0 +1,212 @@ +using Robust.Shared.Audio.Systems; +using Robust.Shared.Configuration; +using Robust.Shared.Containers; +using Robust.Shared.Physics; +using Robust.Shared.Physics.Events; +using Robust.Server.GameObjects; +using Content.Shared.Atmos; +using Content.Shared.Interaction; +using Content.Shared.Projectiles; +using Content.Shared.Mobs.Components; +using Content.Server.Atmos.EntitySystems; +using Content.Server.Chat.Systems; +using Content.Server.Explosion.EntitySystems; +using Content.Shared.Supermatter.Components; +using Content.Server.Lightning; +using Content.Server.AlertLevel; +using Content.Server.Station.Systems; +using Content.Server.Kitchen.Components; +using Content.Shared.DoAfter; +using Content.Shared.Examine; +using Content.Server.DoAfter; +using Content.Server.Popups; +using Content.Shared.Audio; + +namespace Content.Server.Supermatter.Systems; + +public sealed partial class SupermatterSystem : EntitySystem +{ + [Dependency] private readonly AtmosphereSystem _atmosphere = default!; + [Dependency] private readonly ChatSystem _chat = default!; + [Dependency] private readonly SharedContainerSystem _container = default!; + [Dependency] private readonly ExplosionSystem _explosion = default!; + [Dependency] private readonly TransformSystem _xform = default!; + [Dependency] private readonly SharedAudioSystem _audio = default!; + [Dependency] private readonly SharedAmbientSoundSystem _ambient = default!; + [Dependency] private readonly LightningSystem _lightning = default!; + [Dependency] private readonly AlertLevelSystem _alert = default!; + [Dependency] private readonly StationSystem _station = default!; + [Dependency] private readonly DoAfterSystem _doAfter = default!; + [Dependency] private readonly SharedTransformSystem _transform = default!; + [Dependency] private readonly PopupSystem _popup = default!; + [Dependency] private readonly IConfigurationManager _config = default!; + + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnMapInit); + + SubscribeLocalEvent(OnCollideEvent); + SubscribeLocalEvent(OnHandInteract); + SubscribeLocalEvent(OnItemInteract); + SubscribeLocalEvent(OnExamine); + SubscribeLocalEvent(OnGetSliver); + } + + + public override void Update(float frameTime) + { + base.Update(frameTime); + + foreach (var sm in EntityManager.EntityQuery()) + { + if (!sm.Activated) + return; + + var uid = sm.Owner; + sm.UpdateAccumulator += frameTime; + + if (sm.UpdateAccumulator >= sm.UpdateTimer) + { + sm.UpdateAccumulator -= sm.UpdateTimer; + Cycle(uid, sm); + } + } + } + + + public void Cycle(EntityUid uid, SupermatterComponent sm) + { + sm.ZapAccumulator++; + sm.YellAccumulator++; + + ProcessAtmos(uid, sm); + HandleDamage(uid, sm); + + if (sm.Damage >= sm.DamageDelaminationPoint || sm.Delamming) + HandleDelamination(uid, sm); + + HandleSoundLoop(uid, sm); + + if (sm.ZapAccumulator >= sm.ZapTimer) + { + sm.ZapAccumulator -= sm.ZapTimer; + SupermatterZap(uid, sm); + } + + if (sm.YellAccumulator >= sm.YellTimer) + { + sm.YellAccumulator -= sm.YellTimer; + AnnounceCoreDamage(uid, sm); + } + } + + private void OnMapInit(EntityUid uid, SupermatterComponent sm, MapInitEvent args) + { + // Set the Sound + _ambient.SetAmbience(uid, true); + + // Add Air to the initialized SM in the Map so it doesn't delam on its' own + var mix = _atmosphere.GetContainingMixture(uid, true, true); + mix?.AdjustMoles(Gas.Oxygen, Atmospherics.OxygenMolesStandard); + mix?.AdjustMoles(Gas.Nitrogen, Atmospherics.NitrogenMolesStandard); + } + + private void OnCollideEvent(EntityUid uid, SupermatterComponent sm, ref StartCollideEvent args) + { + if (!sm.Activated) + sm.Activated = true; + + var target = args.OtherEntity; + if (args.OtherBody.BodyType == BodyType.Static + || HasComp(target) + || _container.IsEntityInContainer(uid)) + return; + + if (!HasComp(target)) + { + EntityManager.SpawnEntity(sm.CollisionResultPrototype, Transform(target).Coordinates); + _audio.PlayPvs(sm.DustSound, uid); + sm.Power += args.OtherBody.Mass; + } + + EntityManager.QueueDeleteEntity(target); + + if (TryComp(target, out var food)) + sm.Power += food.Energy; + else if (TryComp(target, out var projectile)) + sm.Power += (float) projectile.Damage.GetTotal(); + else + sm.Power++; + + sm.MatterPower += HasComp(target) ? 200 : 0; + } + + private void OnHandInteract(EntityUid uid, SupermatterComponent sm, ref InteractHandEvent args) + { + if (!sm.Activated) + sm.Activated = true; + + var target = args.User; + + if (HasComp(target)) + return; + + sm.MatterPower += 200; + + EntityManager.SpawnEntity(sm.CollisionResultPrototype, Transform(target).Coordinates); + _audio.PlayPvs(sm.DustSound, uid); + EntityManager.QueueDeleteEntity(target); + } + + private void OnItemInteract(EntityUid uid, SupermatterComponent sm, ref InteractUsingEvent args) + { + if (!sm.Activated) + sm.Activated = true; + + if (sm.SliverRemoved) + return; + + if (!HasComp(args.Used)) + return; + + var dae = new DoAfterArgs(EntityManager, args.User, 30f, new SupermatterDoAfterEvent(), args.Target) + { + BreakOnDamage = true, + BreakOnHandChange = false, + BreakOnTargetMove = true, + BreakOnUserMove = true, + BreakOnWeightlessMove = false, + NeedHand = true, + RequireCanInteract = true, + }; + + _doAfter.TryStartDoAfter(dae); + _popup.PopupClient(Loc.GetString("supermatter-tamper-begin"), uid, args.User); + } + + private void OnGetSliver(EntityUid uid, SupermatterComponent sm, ref SupermatterDoAfterEvent args) + { + if (args.Cancelled) + return; + + // Your criminal actions will not go unnoticed + sm.Damage += sm.DamageDelaminationPoint / 10; + + var integrity = GetIntegrity(sm).ToString("0.00"); + SendSupermatterAnnouncement(uid, Loc.GetString("supermatter-announcement-cc-tamper", ("integrity", integrity)), true, "Central Command"); + + Spawn(sm.SliverPrototype, _transform.GetMapCoordinates(args.User)); + _popup.PopupClient(Loc.GetString("supermatter-tamper-end"), uid, args.User); + + sm.DelamTimer /= 2; + } + + private void OnExamine(EntityUid uid, SupermatterComponent sm, ref ExaminedEvent args) + { + if (args.IsInDetailsRange) + args.PushMarkup(Loc.GetString("supermatter-examine-integrity", ("integrity", GetIntegrity(sm).ToString("0.00")))); + } +} diff --git a/Content.Server/Traits/Assorted/ConsumeDelayModifierComponent.cs b/Content.Server/Traits/Assorted/ConsumeDelayModifierComponent.cs new file mode 100644 index 00000000000..aa551a79f76 --- /dev/null +++ b/Content.Server/Traits/Assorted/ConsumeDelayModifierComponent.cs @@ -0,0 +1,22 @@ +using Robust.Shared.GameStates; + +namespace Content.Server.Traits.Assorted.Components; + +/// +/// This is used for any trait that modifies how fast an entity consumes food and drinks. +/// +[RegisterComponent] +public sealed partial class ConsumeDelayModifierComponent : Component +{ + /// + /// What to multiply the eating delay by. + /// + [DataField] + public float FoodDelayMultiplier { get; set; } = 1f; + + /// + /// What to multiply the drinking delay by. + /// + [DataField] + public float DrinkDelayMultiplier { get; set; } = 1f; +} diff --git a/Content.Server/Traits/Assorted/LanguageKnowledgeModifierComponent.cs b/Content.Server/Traits/Assorted/LanguageKnowledgeModifierComponent.cs new file mode 100644 index 00000000000..170dae40fa6 --- /dev/null +++ b/Content.Server/Traits/Assorted/LanguageKnowledgeModifierComponent.cs @@ -0,0 +1,23 @@ +using Content.Shared.Language; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List; + +namespace Content.Server.Traits.Assorted; + +/// +/// Used for traits that modify entities' language knowledge. +/// +[RegisterComponent] +public sealed partial class LanguageKnowledgeModifierComponent : Component +{ + /// + /// List of languages this entity will learn to speak. + /// + [DataField("speaks")] + public List NewSpokenLanguages = new(); + + /// + /// List of languages this entity will learn to understand. + /// + [DataField("understands")] + public List NewUnderstoodLanguages = new(); +} diff --git a/Content.Server/Traits/Assorted/LanguageKnowledgeModifierSystem.cs b/Content.Server/Traits/Assorted/LanguageKnowledgeModifierSystem.cs new file mode 100644 index 00000000000..9053c9404fe --- /dev/null +++ b/Content.Server/Traits/Assorted/LanguageKnowledgeModifierSystem.cs @@ -0,0 +1,35 @@ +using System.Linq; +using Content.Server.Language; +using Content.Shared.Language.Components; + +namespace Content.Server.Traits.Assorted; + +public sealed class LanguageKnowledgeModifierSystem : EntitySystem +{ + [Dependency] private readonly LanguageSystem _languages = default!; + + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnStartup); + } + + private void OnStartup(Entity entity, ref ComponentInit args) + { + if (!TryComp(entity, out var knowledge)) + { + Log.Warning($"Entity {entity.Owner} does not have a LanguageKnowledge but has a LanguageKnowledgeModifier!"); + return; + } + + foreach (var spokenLanguage in entity.Comp.NewSpokenLanguages) + { + _languages.AddLanguage(entity, spokenLanguage, true, false, knowledge); + } + + foreach (var understoodLanguage in entity.Comp.NewUnderstoodLanguages) + { + _languages.AddLanguage(entity, understoodLanguage, false, true, knowledge); + } + } +} diff --git a/Content.Server/Traits/TraitSystem.cs b/Content.Server/Traits/TraitSystem.cs index be2c3c05039..628cb43b8d2 100644 --- a/Content.Server/Traits/TraitSystem.cs +++ b/Content.Server/Traits/TraitSystem.cs @@ -4,6 +4,7 @@ using Content.Shared.Customization.Systems; using Content.Shared.Hands.Components; using Content.Shared.Hands.EntitySystems; +using Content.Shared.Players; using Content.Shared.Roles; using Content.Shared.Traits; using Pidgin.Configuration; @@ -40,9 +41,10 @@ private void OnPlayerSpawnComplete(PlayerSpawnCompleteEvent args) return; } - if (!_characterRequirements.CheckRequirementsValid(traitPrototype, traitPrototype.Requirements, + if (!_characterRequirements.CheckRequirementsValid( + traitPrototype.Requirements, _prototype.Index(args.JobId ?? _prototype.EnumeratePrototypes().First().ID), - args.Profile, _playTimeTracking.GetTrackerTimes(args.Player), + args.Profile, _playTimeTracking.GetTrackerTimes(args.Player), args.Player.ContentData()?.Whitelisted ?? false, EntityManager, _prototype, _configuration, out _)) continue; diff --git a/Content.Server/Wagging/WaggingSystem.cs b/Content.Server/Wagging/WaggingSystem.cs index 7ccc19e20c6..ed2747da198 100644 --- a/Content.Server/Wagging/WaggingSystem.cs +++ b/Content.Server/Wagging/WaggingSystem.cs @@ -65,6 +65,8 @@ public bool TryToggleWagging(EntityUid uid, WaggingComponent? wagging = null, Hu wagging.Wagging = !wagging.Wagging; + _actions.SetToggled(wagging.ActionEntity, wagging.Wagging); + for (var idx = 0; idx < markings.Count; idx++) // Animate all possible tails { var currentMarkingId = markings[idx].MarkingId; diff --git a/Content.Shared/Atmos/Atmospherics.cs b/Content.Shared/Atmos/Atmospherics.cs index 6a8587ca239..78b692d52de 100644 --- a/Content.Shared/Atmos/Atmospherics.cs +++ b/Content.Shared/Atmos/Atmospherics.cs @@ -271,7 +271,7 @@ public static class Atmospherics public const float HazardLowPressure = 20f; /// - /// The amount of pressure damage someone takes is equal to (pressure / HAZARD_HIGH_PRESSURE)*PRESSURE_DAMAGE_COEFFICIENT, + /// /// The amount of pressure damage someone takes is equal to ((pressure / HAZARD_HIGH_PRESSURE) - 1)*PRESSURE_DAMAGE_COEFFICIENT /// with the maximum of MaxHighPressureDamage. /// public const float PressureDamageCoefficient = 4; diff --git a/Content.Shared/CCVar/CCVars.cs b/Content.Shared/CCVar/CCVars.cs index 5bd2a77b1f2..4938e75e5d1 100644 --- a/Content.Shared/CCVar/CCVars.cs +++ b/Content.Shared/CCVar/CCVars.cs @@ -1,3 +1,4 @@ +using Content.Shared.Supermatter.Components; using Robust.Shared; using Robust.Shared.Configuration; @@ -119,7 +120,7 @@ public static readonly CVarDef /// Max chaos chosen for a round will deviate from this /// public static readonly CVarDef - EventsRampingAverageChaos = CVarDef.Create("events.ramping_average_chaos", 0.8f, CVar.ARCHIVE | CVar.SERVERONLY); + EventsRampingAverageChaos = CVarDef.Create("events.ramping_average_chaos", 6f, CVar.ARCHIVE | CVar.SERVERONLY); /* * Game @@ -186,29 +187,16 @@ public static readonly CVarDef // 25 Minutes GameEventsBasicMaximumTime = CVarDef.Create("game.events_basic_maximum_time", 1500, CVar.SERVERONLY); /// - /// Minimum time between Ramping station events in minutes + /// Minimum time between Ramping station events in seconds /// - public static readonly CVarDef // 8 Minutes - GameEventsRampingMinimumTime = CVarDef.Create("game.events_ramping_minimum_time", 8f, CVar.SERVERONLY); + public static readonly CVarDef // 4 Minutes + GameEventsRampingMinimumTime = CVarDef.Create("game.events_ramping_minimum_time", 240, CVar.SERVERONLY); /// - /// After the shift's desired "Endpoint" is reached, the minimum time between events is RampingMinimumTime - Offset. + /// Maximum time between Ramping station events in seconds /// - - public static readonly CVarDef - GameEventsRampingMinimumTimeOffset = CVarDef.Create("game.events_ramping_minimum_time_offset", 6f, CVar.SERVERONLY); - - /// - /// Maximum time between Ramping station events in minutes - /// - public static readonly CVarDef // 16 Minutes - GameEventsRampingMaximumTime = CVarDef.Create("game.events_ramping_maximum_time", 16f, CVar.SERVERONLY); - - /// - /// After the shift's desired "Endpoint" is reached, the maximum time between events is RampingMaximumTime - Offset. - /// - public static readonly CVarDef - GameEventsRampingMaximumTimeOffset = CVarDef.Create("game.events_ramping_maximum_time_offset", 10f, CVar.SERVERONLY); + public static readonly CVarDef // 12 Minutes + GameEventsRampingMaximumTime = CVarDef.Create("game.events_ramping_maximum_time", 720, CVar.SERVERONLY); /// /// @@ -407,6 +395,13 @@ public static readonly CVarDef public static readonly CVarDef GameAutoEatDrinks = CVarDef.Create("game.auto_eat_drinks", false, CVar.REPLICATED); + + /// + /// When true, you have to press the change speed button to sprint. + /// + public static readonly CVarDef GamePressToSprint = + CVarDef.Create("game.press_to_sprint", true, CVar.REPLICATED); + #if EXCEPTION_TOLERANCE /// /// Amount of times round start must fail before the server is shut down. @@ -831,8 +826,6 @@ public static readonly CVarDef CVarDef.Create("audio.admin_chat_sound_path", "/Audio/Items/pop.ogg", CVar.ARCHIVE | CVar.CLIENT | CVar.REPLICATED); public static readonly CVarDef AdminChatSoundVolume = CVarDef.Create("audio.admin_chat_sound_volume", -5f, CVar.ARCHIVE | CVar.CLIENT | CVar.REPLICATED); - public static readonly CVarDef AHelpSound = - CVarDef.Create("audio.ahelp_sound", "/Audio/Effects/adminhelp.ogg", CVar.ARCHIVE | CVar.CLIENTONLY); /* * HUD @@ -1432,7 +1425,7 @@ public static readonly CVarDef /// Controls whether the server will deny any players that are not whitelisted in the DB. /// public static readonly CVarDef WhitelistEnabled = - CVarDef.Create("whitelist.enabled", false, CVar.SERVERONLY); + CVarDef.Create("whitelist.enabled", false, CVar.REPLICATED); /// /// The loc string to display as a disconnect reason when someone is not whitelisted. @@ -2353,5 +2346,54 @@ public static readonly CVarDef CVarDef.Create("consent.freetext_max_length", 1000, CVar.REPLICATED | CVar.SERVER); #endregion + + #region Supermatter System + + /// + /// With completely default supermatter values, Singuloose delamination will occur if engineers inject at least 900 moles of coolant per tile + /// in the crystal chamber. For reference, a gas canister contains 1800 moles of air. This Cvar directly multiplies the amount of moles required to singuloose. + /// + public static readonly CVarDef SupermatterSingulooseMolesModifier = + CVarDef.Create("supermatter.singuloose_moles_modifier", 1f, CVar.SERVER); + + /// + /// Toggles whether or not Singuloose delaminations can occur. If both Singuloose and Tesloose are disabled, it will always delam into a Nuke. + /// + public static readonly CVarDef SupermatterDoSingulooseDelam = + CVarDef.Create("supermatter.do_singuloose", true, CVar.SERVER); + + /// + /// By default, Supermatter will "Tesloose" if the conditions for Singuloose are not met, and the core's power is at least 4000. + /// The actual reasons for being at least this amount vary by how the core was screwed up, but traditionally it's caused by "The core is on fire". + /// This Cvar multiplies said power threshold for the purpose of determining if the delam is a Tesloose. + /// + public static readonly CVarDef SupermatterTesloosePowerModifier = + CVarDef.Create("supermatter.tesloose_power_modifier", 1f, CVar.SERVER); + + /// + /// Toggles whether or not Tesloose delaminations can occur. If both Singuloose and Tesloose are disabled, it will always delam into a Nuke. + /// + public static readonly CVarDef SupermatterDoTeslooseDelam = + CVarDef.Create("supermatter.do_tesloose", true, CVar.SERVER); + + /// + /// When true, bypass the normal checks to determine delam type, and instead use the type chosen by supermatter.forced_delam_type + /// + public static readonly CVarDef SupermatterDoForceDelam = + CVarDef.Create("supermatter.do_force_delam", false, CVar.SERVER); + + /// + /// If supermatter.do_force_delam is true, this determines the delamination type, bypassing the normal checks. + /// + public static readonly CVarDef SupermatterForcedDelamType = + CVarDef.Create("supermatter.forced_delam_type", DelamType.Singulo, CVar.SERVER); + + /// + /// Directly multiplies the amount of rads put out by the supermatter. Be VERY conservative with this. + /// + public static readonly CVarDef SupermatterRadsModifier = + CVarDef.Create("supermatter.rads_modifier", 1f, CVar.SERVER); + + #endregion } } diff --git a/Content.Shared/Nyanotrasen/Carrying/CarryingDoAfterEvent.cs b/Content.Shared/Carrying/CarryingDoAfterEvent.cs similarity index 91% rename from Content.Shared/Nyanotrasen/Carrying/CarryingDoAfterEvent.cs rename to Content.Shared/Carrying/CarryingDoAfterEvent.cs index 6acd6b775f3..fb7225461cb 100644 --- a/Content.Shared/Nyanotrasen/Carrying/CarryingDoAfterEvent.cs +++ b/Content.Shared/Carrying/CarryingDoAfterEvent.cs @@ -4,7 +4,5 @@ namespace Content.Shared.Carrying { [Serializable, NetSerializable] - public sealed partial class CarryDoAfterEvent : SimpleDoAfterEvent - { - } + public sealed partial class CarryDoAfterEvent : SimpleDoAfterEvent { } } diff --git a/Content.Shared/Nyanotrasen/Carrying/CarryingSlowdownComponent.cs b/Content.Shared/Carrying/CarryingSlowdownComponent.cs similarity index 80% rename from Content.Shared/Nyanotrasen/Carrying/CarryingSlowdownComponent.cs rename to Content.Shared/Carrying/CarryingSlowdownComponent.cs index aabde66af0d..597edc2a795 100644 --- a/Content.Shared/Nyanotrasen/Carrying/CarryingSlowdownComponent.cs +++ b/Content.Shared/Carrying/CarryingSlowdownComponent.cs @@ -7,10 +7,10 @@ namespace Content.Shared.Carrying public sealed partial class CarryingSlowdownComponent : Component { - [DataField("walkModifier", required: true)] [ViewVariables(VVAccess.ReadWrite)] + [DataField(required: true)] public float WalkModifier = 1.0f; - [DataField("sprintModifier", required: true)] [ViewVariables(VVAccess.ReadWrite)] + [DataField(required: true)] public float SprintModifier = 1.0f; } diff --git a/Content.Shared/Nyanotrasen/Carrying/CarryingSlowdownSystem.cs b/Content.Shared/Carrying/CarryingSlowdownSystem.cs similarity index 85% rename from Content.Shared/Nyanotrasen/Carrying/CarryingSlowdownSystem.cs rename to Content.Shared/Carrying/CarryingSlowdownSystem.cs index 9b9c8cec10f..04b714fdd78 100644 --- a/Content.Shared/Nyanotrasen/Carrying/CarryingSlowdownSystem.cs +++ b/Content.Shared/Carrying/CarryingSlowdownSystem.cs @@ -31,13 +31,12 @@ private void OnGetState(EntityUid uid, CarryingSlowdownComponent component, ref private void OnHandleState(EntityUid uid, CarryingSlowdownComponent component, ref ComponentHandleState args) { - if (args.Current is CarryingSlowdownComponentState state) - { - component.WalkModifier = state.WalkModifier; - component.SprintModifier = state.SprintModifier; + if (args.Current is not CarryingSlowdownComponentState state) + return; - _movementSpeed.RefreshMovementSpeedModifiers(uid); - } + component.WalkModifier = state.WalkModifier; + component.SprintModifier = state.SprintModifier; + _movementSpeed.RefreshMovementSpeedModifiers(uid); } private void OnRefreshMoveSpeed(EntityUid uid, CarryingSlowdownComponent component, RefreshMovementSpeedModifiersEvent args) { diff --git a/Content.Shared/Clothing/Loadouts/Systems/LoadoutSystem.cs b/Content.Shared/Clothing/Loadouts/Systems/LoadoutSystem.cs index 09e3db3793f..e7a0eef80ee 100644 --- a/Content.Shared/Clothing/Loadouts/Systems/LoadoutSystem.cs +++ b/Content.Shared/Clothing/Loadouts/Systems/LoadoutSystem.cs @@ -38,12 +38,11 @@ private void OnMapInit(EntityUid uid, LoadoutComponent component, MapInitEvent a } - /// - public List ApplyCharacterLoadout(EntityUid uid, string job, HumanoidCharacterProfile profile, - Dictionary? playTimes = null) + public List ApplyCharacterLoadout(EntityUid uid, ProtoId job, HumanoidCharacterProfile profile, + Dictionary playTimes, bool whitelisted) { - var jobPrototype = _prototype.Index(job); - return ApplyCharacterLoadout(uid, jobPrototype, profile, playTimes); + var jobPrototype = _prototype.Index(job); + return ApplyCharacterLoadout(uid, jobPrototype, profile, playTimes, whitelisted); } /// @@ -53,9 +52,10 @@ public List ApplyCharacterLoadout(EntityUid uid, string job, Humanoid /// The job to use for loadout whitelist/blacklist (should be the job of the entity) /// The profile to get loadout items from (should be the entity's, or at least have the same species as the entity) /// Playtime for the player for use with playtime requirements + /// If the player is whitelisted /// A list of loadout items that couldn't be equipped but passed checks public List ApplyCharacterLoadout(EntityUid uid, JobPrototype job, HumanoidCharacterProfile profile, - Dictionary? playTimes = null) + Dictionary playTimes, bool whitelisted) { var failedLoadouts = new List(); @@ -68,8 +68,8 @@ public List ApplyCharacterLoadout(EntityUid uid, JobPrototype job, Hu continue; - if (!_characterRequirements.CheckRequirementsValid(loadoutProto, loadoutProto.Requirements, job, profile, - playTimes ?? new Dictionary(), + if (!_characterRequirements.CheckRequirementsValid( + loadoutProto.Requirements, job, profile, playTimes, whitelisted, EntityManager, _prototype, _configuration, out _)) continue; diff --git a/Content.Shared/Customization/Systems/CharacterRequirements.Job.cs b/Content.Shared/Customization/Systems/CharacterRequirements.Job.cs new file mode 100644 index 00000000000..fe44f2ccc06 --- /dev/null +++ b/Content.Shared/Customization/Systems/CharacterRequirements.Job.cs @@ -0,0 +1,299 @@ +using System.Linq; +using Content.Shared.CCVar; +using Content.Shared.Players.PlayTimeTracking; +using Content.Shared.Preferences; +using Content.Shared.Roles; +using Content.Shared.Roles.Jobs; +using JetBrains.Annotations; +using Robust.Shared.Configuration; +using Robust.Shared.Prototypes; +using Robust.Shared.Serialization; +using Robust.Shared.Utility; + +namespace Content.Shared.Customization.Systems; + + +/// +/// Requires the selected job to be one of the specified jobs +/// +[UsedImplicitly] +[Serializable, NetSerializable] +public sealed partial class CharacterJobRequirement : CharacterRequirement +{ + [DataField(required: true)] + public List> Jobs; + + public override bool IsValid(JobPrototype job, HumanoidCharacterProfile profile, + Dictionary playTimes, bool whitelisted, + IEntityManager entityManager, IPrototypeManager prototypeManager, IConfigurationManager configManager, + out FormattedMessage? reason) + { + var jobs = new List(); + + // Get the job names and department colors + foreach (var j in Jobs) + { + var jobProto = prototypeManager.Index(j); + var color = Color.LightBlue; + + foreach (var dept in prototypeManager.EnumeratePrototypes() + .OrderBy(d => Loc.GetString($"department-{d.ID}"))) + { + if (!dept.Roles.Contains(j)) + continue; + + color = dept.Color; + break; + } + + jobs.Add(FormattedMessage.FromMarkup($"[color={color.ToHex()}]{Loc.GetString(jobProto.Name)}[/color]")); + } + + // Join the job names + var jobsList = string.Join(", ", jobs.Select(j => j.ToMarkup())); + var jobsString = Loc.GetString("character-job-requirement", + ("inverted", Inverted), ("jobs", jobsList)); + + reason = FormattedMessage.FromMarkup(jobsString); + return Jobs.Contains(job.ID); + } +} + +/// +/// Requires the selected job to be in one of the specified departments +/// +[UsedImplicitly] +[Serializable, NetSerializable] +public sealed partial class CharacterDepartmentRequirement : CharacterRequirement +{ + [DataField(required: true)] + public List> Departments; + + public override bool IsValid(JobPrototype job, HumanoidCharacterProfile profile, + Dictionary playTimes, bool whitelisted, + IEntityManager entityManager, IPrototypeManager prototypeManager, IConfigurationManager configManager, + out FormattedMessage? reason) + { + var departments = new List(); + + // Get the department names and colors + foreach (var d in Departments) + { + var deptProto = prototypeManager.Index(d); + var color = deptProto.Color; + + departments.Add(FormattedMessage.FromMarkup($"[color={color.ToHex()}]{Loc.GetString($"department-{deptProto.ID}")}[/color]")); + } + + // Join the department names + var departmentsList = string.Join(", ", departments.Select(d => d.ToMarkup())); + var departmentsString = Loc.GetString("character-department-requirement", + ("inverted", Inverted), ("departments", departmentsList)); + + reason = FormattedMessage.FromMarkup(departmentsString); + return Departments.Any(d => prototypeManager.Index(d).Roles.Contains(job.ID)); + } +} + +/// +/// Requires the playtime for a department to be within a certain range +/// +[UsedImplicitly] +[Serializable, NetSerializable] +public sealed partial class CharacterDepartmentTimeRequirement : CharacterRequirement +{ + [DataField] + public TimeSpan Min = TimeSpan.MinValue; + + [DataField] + public TimeSpan Max = TimeSpan.MaxValue; + + [DataField(required: true)] + public ProtoId Department; + + public override bool IsValid(JobPrototype job, HumanoidCharacterProfile profile, + Dictionary playTimes, bool whitelisted, + IEntityManager entityManager, IPrototypeManager prototypeManager, IConfigurationManager configManager, + out FormattedMessage? reason) + { + // Disable the requirement if the role timers are disabled + if (!configManager.GetCVar(CCVars.GameRoleTimers)) + { + reason = null; + return !Inverted; + } + + var department = prototypeManager.Index(Department); + + // Combine all of this department's job playtimes + var playtime = TimeSpan.Zero; + foreach (var other in department.Roles) + { + var proto = prototypeManager.Index(other).PlayTimeTracker; + + playTimes.TryGetValue(proto, out var otherTime); + playtime += otherTime; + } + + if (playtime > Max) + { + // Show the reason if invalid + reason = Inverted + ? null + : FormattedMessage.FromMarkup(Loc.GetString("character-timer-department-too-high", + ("time", playtime.TotalMinutes - Max.TotalMinutes), + ("department", Loc.GetString($"department-{department.ID}")), + ("departmentColor", department.Color))); + return false; + } + + if (playtime < Min) + { + // Show the reason if invalid + reason = Inverted + ? null + : FormattedMessage.FromMarkup(Loc.GetString("character-timer-department-insufficient", + ("time", Min.TotalMinutes - playtime.TotalMinutes), + ("department", Loc.GetString($"department-{department.ID}")), + ("departmentColor", department.Color))); + return false; + } + + reason = null; + return true; + } +} + +/// +/// Requires the player to have a certain amount of overall job time +/// +[UsedImplicitly] +[Serializable, NetSerializable] +public sealed partial class CharacterOverallTimeRequirement : CharacterRequirement +{ + [DataField] + public TimeSpan Min = TimeSpan.MinValue; + + [DataField] + public TimeSpan Max = TimeSpan.MaxValue; + + public override bool IsValid(JobPrototype job, HumanoidCharacterProfile profile, + Dictionary playTimes, bool whitelisted, + IEntityManager entityManager, IPrototypeManager prototypeManager, IConfigurationManager configManager, + out FormattedMessage? reason) + { + // Disable the requirement if the role timers are disabled + if (!configManager.GetCVar(CCVars.GameRoleTimers)) + { + reason = null; + return !Inverted; + } + + // Get the overall time + var overallTime = playTimes.GetValueOrDefault(PlayTimeTrackingShared.TrackerOverall); + + if (overallTime > Max) + { + // Show the reason if invalid + reason = Inverted + ? null + : FormattedMessage.FromMarkup(Loc.GetString("character-timer-overall-too-high", + ("time", overallTime.TotalMinutes - Max.TotalMinutes))); + return false; + } + + if (overallTime < Min) + { + // Show the reason if invalid + reason = Inverted + ? null + : FormattedMessage.FromMarkup(Loc.GetString("character-timer-overall-insufficient", + ("time", Min.TotalMinutes - overallTime.TotalMinutes))); + return false; + } + + reason = null; + return true; + } +} + +/// +/// Requires the playtime for a tracker to be within a certain range +/// +[UsedImplicitly] +[Serializable, NetSerializable] +public sealed partial class CharacterPlaytimeRequirement : CharacterRequirement +{ + [DataField] + public TimeSpan Min = TimeSpan.MinValue; + + [DataField] + public TimeSpan Max = TimeSpan.MaxValue; + + [DataField(required: true)] + public ProtoId Tracker; + + public override bool IsValid(JobPrototype job, HumanoidCharacterProfile profile, + Dictionary playTimes, bool whitelisted, + IEntityManager entityManager, IPrototypeManager prototypeManager, IConfigurationManager configManager, + out FormattedMessage? reason) + { + // Disable the requirement if the role timers are disabled + if (!configManager.GetCVar(CCVars.GameRoleTimers)) + { + reason = null; + return !Inverted; + } + + // Get SharedJobSystem + if (!entityManager.EntitySysManager.TryGetEntitySystem(out SharedJobSystem? jobSystem)) + { + DebugTools.Assert("CharacterRequirements: SharedJobSystem not found"); + reason = null; + return false; + } + + // Get the JobPrototype of the Tracker + var trackerJob = jobSystem.GetJobPrototype(Tracker); + var jobStr = prototypeManager.Index(trackerJob).LocalizedName; + + // Get the primary department of the Tracker + if (!jobSystem.TryGetPrimaryDepartment(trackerJob, out var department) && + !jobSystem.TryGetDepartment(trackerJob, out department)) + { + DebugTools.Assert($"CharacterRequirements: Department not found for job {trackerJob}"); + reason = null; + return false; + } + + // Get the time for the tracker + var time = playTimes.GetValueOrDefault(Tracker); + reason = null; + + if (time > Max) + { + // Show the reason if invalid + reason = Inverted + ? null + : FormattedMessage.FromMarkup(Loc.GetString("character-timer-role-too-high", + ("time", time.TotalMinutes - Max.TotalMinutes), + ("job", jobStr), + ("departmentColor", department.Color))); + return false; + } + + if (time < Min) + { + // Show the reason if invalid + reason = Inverted + ? null + : FormattedMessage.FromMarkup(Loc.GetString("character-timer-role-insufficient", + ("time", Min.TotalMinutes - time.TotalMinutes), + ("job", jobStr), + ("departmentColor", department.Color))); + return false; + } + + return true; + } +} diff --git a/Content.Shared/Customization/Systems/CharacterRequirements.Profile.cs b/Content.Shared/Customization/Systems/CharacterRequirements.Profile.cs new file mode 100644 index 00000000000..aaeae107b9e --- /dev/null +++ b/Content.Shared/Customization/Systems/CharacterRequirements.Profile.cs @@ -0,0 +1,157 @@ +using System.Linq; +using Content.Shared.Clothing.Loadouts.Prototypes; +using Content.Shared.Humanoid.Prototypes; +using Content.Shared.Preferences; +using Content.Shared.Roles; +using Content.Shared.Traits; +using JetBrains.Annotations; +using Robust.Shared.Configuration; +using Robust.Shared.Prototypes; +using Robust.Shared.Serialization; +using Robust.Shared.Utility; + +namespace Content.Shared.Customization.Systems; + + +/// +/// Requires the profile to be within an age range +/// +[UsedImplicitly] +[Serializable, NetSerializable] +public sealed partial class CharacterAgeRequirement : CharacterRequirement +{ + [DataField(required: true)] + public int Min; + + [DataField(required: true)] + public int Max; + + public override bool IsValid(JobPrototype job, HumanoidCharacterProfile profile, + Dictionary playTimes, bool whitelisted, + IEntityManager entityManager, IPrototypeManager prototypeManager, IConfigurationManager configManager, + out FormattedMessage? reason) + { + reason = FormattedMessage.FromMarkup(Loc.GetString("character-age-requirement", + ("inverted", Inverted), ("min", Min), ("max", Max))); + return profile.Age >= Min && profile.Age <= Max; + } +} + +/// +/// Requires the profile to use either a Backpack, Satchel, or Duffelbag +/// +[UsedImplicitly] +[Serializable, NetSerializable] +public sealed partial class CharacterBackpackTypeRequirement : CharacterRequirement +{ + [DataField(required: true)] + public BackpackPreference Preference; + + public override bool IsValid(JobPrototype job, HumanoidCharacterProfile profile, + Dictionary playTimes, bool whitelisted, + IEntityManager entityManager, IPrototypeManager prototypeManager, IConfigurationManager configManager, + out FormattedMessage? reason) + { + reason = FormattedMessage.FromMarkup(Loc.GetString("character-backpack-type-requirement", + ("inverted", Inverted), + ("type", Loc.GetString($"humanoid-profile-editor-preference-{Preference.ToString().ToLower()}")))); + return profile.Backpack == Preference; + } +} + +/// +/// Requires the profile to use either Jumpsuits or Jumpskirts +/// +[UsedImplicitly] +[Serializable, NetSerializable] +public sealed partial class CharacterClothingPreferenceRequirement : CharacterRequirement +{ + [DataField(required: true)] + public ClothingPreference Preference; + + public override bool IsValid(JobPrototype job, HumanoidCharacterProfile profile, + Dictionary playTimes, bool whitelisted, + IEntityManager entityManager, IPrototypeManager prototypeManager, IConfigurationManager configManager, + out FormattedMessage? reason) + { + reason = FormattedMessage.FromMarkup(Loc.GetString("character-clothing-preference-requirement", + ("inverted", Inverted), + ("preference", Loc.GetString($"humanoid-profile-editor-preference-{Preference.ToString().ToLower()}")))); + return profile.Clothing == Preference; + } +} + +/// +/// Requires the profile to be a certain species +/// +[UsedImplicitly] +[Serializable, NetSerializable] +public sealed partial class CharacterSpeciesRequirement : CharacterRequirement +{ + [DataField(required: true)] + public List> Species; + + public override bool IsValid(JobPrototype job, HumanoidCharacterProfile profile, + Dictionary playTimes, bool whitelisted, + IEntityManager entityManager, IPrototypeManager prototypeManager, IConfigurationManager configManager, + out FormattedMessage? reason) + { + const string color = "green"; + reason = FormattedMessage.FromMarkup(Loc.GetString("character-species-requirement", + ("inverted", Inverted), + ("species", $"[color={color}]{string.Join($"[/color], [color={color}]", + Species.Select(s => Loc.GetString(prototypeManager.Index(s).Name)))}[/color]"))); + + return Species.Contains(profile.Species); + } +} + +/// +/// Requires the profile to have one of the specified traits +/// +[UsedImplicitly] +[Serializable, NetSerializable] +public sealed partial class CharacterTraitRequirement : CharacterRequirement +{ + [DataField(required: true)] + public List> Traits; + + public override bool IsValid(JobPrototype job, HumanoidCharacterProfile profile, + Dictionary playTimes, bool whitelisted, + IEntityManager entityManager, IPrototypeManager prototypeManager, IConfigurationManager configManager, + out FormattedMessage? reason) + { + const string color = "lightblue"; + reason = FormattedMessage.FromMarkup(Loc.GetString("character-trait-requirement", + ("inverted", Inverted), + ("traits", $"[color={color}]{string.Join($"[/color], [color={color}]", + Traits.Select(t => Loc.GetString($"trait-name-{t}")))}[/color]"))); + + return Traits.Any(t => profile.TraitPreferences.Contains(t.ToString())); + } +} + +/// +/// Requires the profile to have one of the specified loadouts +/// +[UsedImplicitly] +[Serializable, NetSerializable] +public sealed partial class CharacterLoadoutRequirement : CharacterRequirement +{ + [DataField(required: true)] + public List> Loadouts; + + public override bool IsValid(JobPrototype job, HumanoidCharacterProfile profile, + Dictionary playTimes, bool whitelisted, + IEntityManager entityManager, IPrototypeManager prototypeManager, IConfigurationManager configManager, + out FormattedMessage? reason) + { + const string color = "lightblue"; + reason = FormattedMessage.FromMarkup(Loc.GetString("character-loadout-requirement", + ("inverted", Inverted), + ("loadouts", $"[color={color}]{string.Join($"[/color], [color={color}]", + Loadouts.Select(l => Loc.GetString($"loadout-name-{l}")))}[/color]"))); + + return Loadouts.Any(l => profile.LoadoutPreferences.Contains(l.ToString())); + } +} diff --git a/Content.Shared/Customization/Systems/CharacterRequirements.Whitelist.cs b/Content.Shared/Customization/Systems/CharacterRequirements.Whitelist.cs new file mode 100644 index 00000000000..56465251cdd --- /dev/null +++ b/Content.Shared/Customization/Systems/CharacterRequirements.Whitelist.cs @@ -0,0 +1,28 @@ +using Content.Shared.CCVar; +using Content.Shared.Preferences; +using Content.Shared.Roles; +using JetBrains.Annotations; +using Robust.Shared.Configuration; +using Robust.Shared.Prototypes; +using Robust.Shared.Serialization; +using Robust.Shared.Utility; + +namespace Content.Shared.Customization.Systems; + + +/// +/// Requires the player to be whitelisted if whitelists are enabled +/// +[UsedImplicitly] +[Serializable, NetSerializable] +public sealed partial class CharacterWhitelistRequirement : CharacterRequirement +{ + public override bool IsValid(JobPrototype job, HumanoidCharacterProfile profile, + Dictionary playTimes, bool whitelisted, + IEntityManager entityManager, IPrototypeManager prototypeManager, IConfigurationManager configManager, + out FormattedMessage? reason) + { + reason = FormattedMessage.FromMarkup(Loc.GetString("character-whitelist-requirement", ("inverted", Inverted))); + return !configManager.GetCVar(CCVars.WhitelistEnabled) || whitelisted; + } +} diff --git a/Content.Shared/Customization/Systems/CharacterRequirements.cs b/Content.Shared/Customization/Systems/CharacterRequirements.cs index 4e862aa69e3..b347c9787af 100644 --- a/Content.Shared/Customization/Systems/CharacterRequirements.cs +++ b/Content.Shared/Customization/Systems/CharacterRequirements.cs @@ -1,12 +1,5 @@ -using System.Linq; -using Content.Shared.CCVar; -using Content.Shared.Clothing.Loadouts.Prototypes; -using Content.Shared.Humanoid.Prototypes; -using Content.Shared.Players.PlayTimeTracking; using Content.Shared.Preferences; using Content.Shared.Roles; -using Content.Shared.Roles.Jobs; -using Content.Shared.Traits; using JetBrains.Annotations; using Robust.Shared.Configuration; using Robust.Shared.Prototypes; @@ -22,459 +15,25 @@ public abstract partial class CharacterRequirement { /// /// If true valid requirements will be treated as invalid and vice versa + /// This inversion is done by other systems like , not this one /// [DataField] public bool Inverted; /// /// Checks if this character requirement is valid for the given parameters + ///
+ /// You should probably not be calling this directly, use ///
/// Description for the requirement, shown when not null public abstract bool IsValid( - IPrototype prototype, JobPrototype job, HumanoidCharacterProfile profile, Dictionary playTimes, + bool whitelisted, IEntityManager entityManager, IPrototypeManager prototypeManager, IConfigurationManager configManager, out FormattedMessage? reason ); } - - -#region HumanoidCharacterProfile - -/// -/// Requires the profile to be within an age range -/// -[UsedImplicitly] -[Serializable, NetSerializable] -public sealed partial class CharacterAgeRequirement : CharacterRequirement -{ - [DataField(required: true)] - public int Min; - - [DataField(required: true)] - public int Max; - - public override bool IsValid(IPrototype prototype, JobPrototype job, HumanoidCharacterProfile profile, - Dictionary playTimes, - IEntityManager entityManager, IPrototypeManager prototypeManager, IConfigurationManager configManager, - out FormattedMessage? reason) - { - reason = FormattedMessage.FromMarkup(Loc.GetString("character-age-requirement", - ("inverted", Inverted), ("min", Min), ("max", Max))); - return profile.Age >= Min && profile.Age <= Max; - } -} - -/// -/// Requires the profile to use either a Backpack, Satchel, or Duffelbag -/// -[UsedImplicitly] -[Serializable, NetSerializable] -public sealed partial class CharacterBackpackTypeRequirement : CharacterRequirement -{ - [DataField(required: true)] - public BackpackPreference Preference; - - public override bool IsValid(IPrototype prototype, JobPrototype job, HumanoidCharacterProfile profile, - Dictionary playTimes, - IEntityManager entityManager, IPrototypeManager prototypeManager, IConfigurationManager configManager, - out FormattedMessage? reason) - { - reason = FormattedMessage.FromMarkup(Loc.GetString("character-backpack-type-requirement", - ("inverted", Inverted), - ("type", Loc.GetString($"humanoid-profile-editor-preference-{Preference.ToString().ToLower()}")))); - return profile.Backpack == Preference; - } -} - -/// -/// Requires the profile to use either Jumpsuits or Jumpskirts -/// -[UsedImplicitly] -[Serializable, NetSerializable] -public sealed partial class CharacterClothingPreferenceRequirement : CharacterRequirement -{ - [DataField(required: true)] - public ClothingPreference Preference; - - public override bool IsValid(IPrototype prototype, JobPrototype job, HumanoidCharacterProfile profile, - Dictionary playTimes, - IEntityManager entityManager, IPrototypeManager prototypeManager, IConfigurationManager configManager, - out FormattedMessage? reason) - { - reason = FormattedMessage.FromMarkup(Loc.GetString("character-clothing-preference-requirement", - ("inverted", Inverted), - ("preference", Loc.GetString($"humanoid-profile-editor-preference-{Preference.ToString().ToLower()}")))); - return profile.Clothing == Preference; - } -} - -/// -/// Requires the profile to be a certain species -/// -[UsedImplicitly] -[Serializable, NetSerializable] -public sealed partial class CharacterSpeciesRequirement : CharacterRequirement -{ - [DataField(required: true)] - public List> Species; - - public override bool IsValid(IPrototype prototype, JobPrototype job, HumanoidCharacterProfile profile, - Dictionary playTimes, - IEntityManager entityManager, IPrototypeManager prototypeManager, IConfigurationManager configManager, - out FormattedMessage? reason) - { - const string color = "green"; - reason = FormattedMessage.FromMarkup(Loc.GetString("character-species-requirement", - ("inverted", Inverted), - ("species", $"[color={color}]{string.Join($"[/color], [color={color}]", - Species.Select(s => Loc.GetString(prototypeManager.Index(s).Name)))}[/color]"))); - - return Species.Contains(profile.Species); - } -} - -/// -/// Requires the profile to have one of the specified traits -/// -[UsedImplicitly] -[Serializable, NetSerializable] -public sealed partial class CharacterTraitRequirement : CharacterRequirement -{ - [DataField(required: true)] - public List> Traits; - - public override bool IsValid(IPrototype prototype, JobPrototype job, HumanoidCharacterProfile profile, - Dictionary playTimes, - IEntityManager entityManager, IPrototypeManager prototypeManager, IConfigurationManager configManager, - out FormattedMessage? reason) - { - const string color = "lightblue"; - reason = FormattedMessage.FromMarkup(Loc.GetString("character-trait-requirement", - ("inverted", Inverted), - ("traits", $"[color={color}]{string.Join($"[/color], [color={color}]", - Traits.Select(t => Loc.GetString($"trait-name-{t}")))}[/color]"))); - - return Traits.Any(t => profile.TraitPreferences.Contains(t.ToString())); - } -} - -/// -/// Requires the profile to have one of the specified loadouts -/// -[UsedImplicitly] -[Serializable, NetSerializable] -public sealed partial class CharacterLoadoutRequirement : CharacterRequirement -{ - [DataField(required: true)] - public List> Loadouts; - - public override bool IsValid(IPrototype prototype, JobPrototype job, HumanoidCharacterProfile profile, - Dictionary playTimes, - IEntityManager entityManager, IPrototypeManager prototypeManager, IConfigurationManager configManager, - out FormattedMessage? reason) - { - const string color = "lightblue"; - reason = FormattedMessage.FromMarkup(Loc.GetString("character-loadout-requirement", - ("inverted", Inverted), - ("loadouts", $"[color={color}]{string.Join($"[/color], [color={color}]", - Loadouts.Select(l => Loc.GetString($"loadout-name-{l}")))}[/color]"))); - - return Loadouts.Any(l => profile.LoadoutPreferences.Contains(l.ToString())); - } -} - -#endregion - -#region Jobs - -/// -/// Requires the selected job to be one of the specified jobs -/// -[UsedImplicitly] -[Serializable, NetSerializable] -public sealed partial class CharacterJobRequirement : CharacterRequirement -{ - [DataField(required: true)] - public List> Jobs; - - public override bool IsValid(IPrototype prototype, JobPrototype job, HumanoidCharacterProfile profile, - Dictionary playTimes, - IEntityManager entityManager, IPrototypeManager prototypeManager, IConfigurationManager configManager, - out FormattedMessage? reason) - { - var jobs = new List(); - - // Get the job names and department colors - foreach (var j in Jobs) - { - var jobProto = prototypeManager.Index(j); - var color = Color.LightBlue; - - foreach (var dept in prototypeManager.EnumeratePrototypes() - .OrderBy(d => Loc.GetString($"department-{d.ID}"))) - { - if (!dept.Roles.Contains(j)) - continue; - - color = dept.Color; - break; - } - - jobs.Add(FormattedMessage.FromMarkup($"[color={color.ToHex()}]{Loc.GetString(jobProto.Name)}[/color]")); - } - - // Join the job names - var jobsList = string.Join(", ", jobs.Select(j => j.ToMarkup())); - var jobsString = Loc.GetString("character-job-requirement", - ("inverted", Inverted), ("jobs", jobsList)); - - reason = FormattedMessage.FromMarkup(jobsString); - return Jobs.Contains(job.ID); - } -} - -/// -/// Requires the selected job to be in one of the specified departments -/// -[UsedImplicitly] -[Serializable, NetSerializable] -public sealed partial class CharacterDepartmentRequirement : CharacterRequirement -{ - [DataField(required: true)] - public List> Departments; - - public override bool IsValid(IPrototype prototype, JobPrototype job, HumanoidCharacterProfile profile, - Dictionary playTimes, - IEntityManager entityManager, IPrototypeManager prototypeManager, IConfigurationManager configManager, - out FormattedMessage? reason) - { - var departments = new List(); - - // Get the department names and colors - foreach (var d in Departments) - { - var deptProto = prototypeManager.Index(d); - var color = deptProto.Color; - - departments.Add(FormattedMessage.FromMarkup($"[color={color.ToHex()}]{Loc.GetString($"department-{deptProto.ID}")}[/color]")); - } - - // Join the department names - var departmentsList = string.Join(", ", departments.Select(d => d.ToMarkup())); - var departmentsString = Loc.GetString("character-department-requirement", - ("inverted", Inverted), ("departments", departmentsList)); - - reason = FormattedMessage.FromMarkup(departmentsString); - return Departments.Any(d => prototypeManager.Index(d).Roles.Contains(job.ID)); - } -} - -/// -/// Requires the playtime for a department to be within a certain range -/// -[UsedImplicitly] -[Serializable, NetSerializable] -public sealed partial class CharacterDepartmentTimeRequirement : CharacterRequirement -{ - [DataField] - public TimeSpan Min = TimeSpan.MinValue; - - [DataField] - public TimeSpan Max = TimeSpan.MaxValue; - - [DataField(required: true)] - public ProtoId Department; - - public override bool IsValid(IPrototype prototype, JobPrototype job, HumanoidCharacterProfile profile, - Dictionary playTimes, - IEntityManager entityManager, IPrototypeManager prototypeManager, IConfigurationManager configManager, - out FormattedMessage? reason) - { - // Disable the requirement if the role timers are disabled - if (!configManager.GetCVar(CCVars.GameRoleTimers)) - { - reason = null; - return !Inverted; - } - - var department = prototypeManager.Index(Department); - - // Combine all of this department's job playtimes - var playtime = TimeSpan.Zero; - foreach (var other in department.Roles) - { - var proto = prototypeManager.Index(other).PlayTimeTracker; - - playTimes.TryGetValue(proto, out var otherTime); - playtime += otherTime; - } - - if (playtime > Max) - { - // Show the reason if invalid - reason = Inverted - ? null - : FormattedMessage.FromMarkup(Loc.GetString("character-timer-department-too-high", - ("time", playtime.TotalMinutes - Max.TotalMinutes), - ("department", Loc.GetString($"department-{department.ID}")), - ("departmentColor", department.Color))); - return false; - } - - if (playtime < Min) - { - // Show the reason if invalid - reason = Inverted - ? null - : FormattedMessage.FromMarkup(Loc.GetString("character-timer-department-insufficient", - ("time", Min.TotalMinutes - playtime.TotalMinutes), - ("department", Loc.GetString($"department-{department.ID}")), - ("departmentColor", department.Color))); - return false; - } - - reason = null; - return true; - } -} - -/// -/// Requires the player to have a certain amount of overall job time -/// -[UsedImplicitly] -[Serializable, NetSerializable] -public sealed partial class CharacterOverallTimeRequirement : CharacterRequirement -{ - [DataField] - public TimeSpan Min = TimeSpan.MinValue; - - [DataField] - public TimeSpan Max = TimeSpan.MaxValue; - - public override bool IsValid(IPrototype prototype, JobPrototype job, HumanoidCharacterProfile profile, - Dictionary playTimes, - IEntityManager entityManager, IPrototypeManager prototypeManager, IConfigurationManager configManager, - out FormattedMessage? reason) - { - // Disable the requirement if the role timers are disabled - if (!configManager.GetCVar(CCVars.GameRoleTimers)) - { - reason = null; - return !Inverted; - } - - // Get the overall time - var overallTime = playTimes.GetValueOrDefault(PlayTimeTrackingShared.TrackerOverall); - - if (overallTime > Max) - { - // Show the reason if invalid - reason = Inverted - ? null - : FormattedMessage.FromMarkup(Loc.GetString("character-timer-overall-too-high", - ("time", overallTime.TotalMinutes - Max.TotalMinutes))); - return false; - } - - if (overallTime < Min) - { - // Show the reason if invalid - reason = Inverted - ? null - : FormattedMessage.FromMarkup(Loc.GetString("character-timer-overall-insufficient", - ("time", Min.TotalMinutes - overallTime.TotalMinutes))); - return false; - } - - reason = null; - return true; - } -} - -/// -/// Requires the playtime for a tracker to be within a certain range -/// -[UsedImplicitly] -[Serializable, NetSerializable] -public sealed partial class CharacterPlaytimeRequirement : CharacterRequirement -{ - [DataField] - public TimeSpan Min = TimeSpan.MinValue; - - [DataField] - public TimeSpan Max = TimeSpan.MaxValue; - - [DataField(required: true)] - public ProtoId Tracker; - - public override bool IsValid(IPrototype prototype, JobPrototype job, HumanoidCharacterProfile profile, - Dictionary playTimes, - IEntityManager entityManager, IPrototypeManager prototypeManager, IConfigurationManager configManager, - out FormattedMessage? reason) - { - // Disable the requirement if the role timers are disabled - if (!configManager.GetCVar(CCVars.GameRoleTimers)) - { - reason = null; - return !Inverted; - } - - // Get SharedJobSystem - if (!entityManager.EntitySysManager.TryGetEntitySystem(out SharedJobSystem? jobSystem)) - { - DebugTools.Assert("CharacterRequirements: SharedJobSystem not found"); - reason = null; - return false; - } - - // Get the JobPrototype of the Tracker - var trackerJob = jobSystem.GetJobPrototype(Tracker); - var jobStr = prototypeManager.Index(trackerJob).LocalizedName; - - // Get the primary department of the Tracker - if (!jobSystem.TryGetPrimaryDepartment(trackerJob, out var department) && - !jobSystem.TryGetDepartment(trackerJob, out department)) - { - DebugTools.Assert($"CharacterRequirements: Department not found for job {trackerJob}"); - reason = null; - return false; - } - - // Get the time for the tracker - var time = playTimes.GetValueOrDefault(Tracker); - reason = null; - - if (time > Max) - { - // Show the reason if invalid - reason = Inverted - ? null - : FormattedMessage.FromMarkup(Loc.GetString("character-timer-role-too-high", - ("time", time.TotalMinutes - Max.TotalMinutes), - ("job", jobStr), - ("departmentColor", department.Color))); - return false; - } - - if (time < Min) - { - // Show the reason if invalid - reason = Inverted - ? null - : FormattedMessage.FromMarkup(Loc.GetString("character-timer-role-insufficient", - ("time", Min.TotalMinutes - time.TotalMinutes), - ("job", jobStr), - ("departmentColor", department.Color))); - return false; - } - - return true; - } -} - -#endregion diff --git a/Content.Shared/Customization/Systems/CharacterRequirementsSystem.cs b/Content.Shared/Customization/Systems/CharacterRequirementsSystem.cs index f21971b5e68..521c4f186a2 100644 --- a/Content.Shared/Customization/Systems/CharacterRequirementsSystem.cs +++ b/Content.Shared/Customization/Systems/CharacterRequirementsSystem.cs @@ -1,3 +1,4 @@ +using System.Text; using Content.Shared.Preferences; using Content.Shared.Roles; using Robust.Shared.Configuration; @@ -9,8 +10,8 @@ namespace Content.Shared.Customization.Systems; public sealed class CharacterRequirementsSystem : EntitySystem { - public bool CheckRequirementsValid(IPrototype prototype, List requirements, JobPrototype job, - HumanoidCharacterProfile profile, Dictionary playTimes, + public bool CheckRequirementsValid(List requirements, JobPrototype job, + HumanoidCharacterProfile profile, Dictionary playTimes, bool whitelisted, IEntityManager entityManager, IPrototypeManager prototypeManager, IConfigurationManager configManager, out List reasons) { @@ -21,7 +22,7 @@ public bool CheckRequirementsValid(IPrototype prototype, List + /// Gets the reason text from as a . + ///
+ public FormattedMessage GetRequirementsText(List reasons) + { + var text = new StringBuilder(); + foreach (var reason in reasons) + text.Append($"\n{reason.ToMarkup()}"); + + return FormattedMessage.FromMarkup(text.ToString().Trim()); + } + + /// + /// Gets the reason text from as a markup string. + /// + public string GetRequirementsMarkup(List reasons) + { + var text = new StringBuilder(); + foreach (var reason in reasons) + text.Append($"\n{reason.ToMarkup()}"); + + return text.ToString().Trim(); + } } diff --git a/Content.Shared/DeltaV/Roles/JobRequirements.Whitelist.cs b/Content.Shared/DeltaV/Roles/JobRequirements.Whitelist.cs deleted file mode 100644 index a6e352991e9..00000000000 --- a/Content.Shared/DeltaV/Roles/JobRequirements.Whitelist.cs +++ /dev/null @@ -1,11 +0,0 @@ -using JetBrains.Annotations; -using Robust.Shared.Serialization; - -namespace Content.Shared.Roles -{ - [UsedImplicitly] - [Serializable, NetSerializable] - public sealed partial class WhitelistRequirement : JobRequirement - { - } -} diff --git a/Content.Shared/DoAfter/SharedDoAfterSystem.cs b/Content.Shared/DoAfter/SharedDoAfterSystem.cs index 9e81c91550f..3b0ba58f55a 100644 --- a/Content.Shared/DoAfter/SharedDoAfterSystem.cs +++ b/Content.Shared/DoAfter/SharedDoAfterSystem.cs @@ -65,7 +65,8 @@ private void OnDamage(EntityUid uid, DoAfterComponent component, DamageChangedEv { // If we're applying state then let the server state handle the do_after prediction. // This is to avoid scenarios where a do_after is erroneously cancelled on the final tick. - if (!args.InterruptsDoAfters || !args.DamageIncreased || args.DamageDelta == null || GameTiming.ApplyingState) + if (!args.InterruptsDoAfters || !args.DamageIncreased || args.DamageDelta == null || GameTiming.ApplyingState + || args.DamageDelta.DamageDict.ContainsKey("Radiation")) //Sanity check so people can crowbar doors open to flee from Lord Singuloth return; var delta = args.DamageDelta.GetTotal(); diff --git a/Content.Shared/Ghost/Roles/GhostRolesEuiMessages.cs b/Content.Shared/Ghost/Roles/GhostRolesEuiMessages.cs index 8fbb931ca95..74af1e89ecc 100644 --- a/Content.Shared/Ghost/Roles/GhostRolesEuiMessages.cs +++ b/Content.Shared/Ghost/Roles/GhostRolesEuiMessages.cs @@ -1,3 +1,4 @@ +using Content.Shared.Customization.Systems; using Content.Shared.Eui; using Content.Shared.Roles; using Robust.Shared.Serialization; @@ -11,7 +12,7 @@ public struct GhostRoleInfo public string Name { get; set; } public string Description { get; set; } public string Rules { get; set; } - public HashSet? Requirements { get; set; } + public List? Requirements { get; set; } } [NetSerializable, Serializable] diff --git a/Content.Shared/Language/LanguagePrototype.cs b/Content.Shared/Language/LanguagePrototype.cs index d3a977202be..d40a7b40681 100644 --- a/Content.Shared/Language/LanguagePrototype.cs +++ b/Content.Shared/Language/LanguagePrototype.cs @@ -37,8 +37,12 @@ public sealed class LanguagePrototype : IPrototype [DataDefinition] public sealed partial class SpeechOverrideInfo { + /// + /// Color which text in this language will be blended with. + /// Alpha blending is used, which means the alpha component of the color controls the intensity of this color. + /// [DataField] - public Color Color = Color.White; + public Color? Color = null; [DataField] public string? FontId; diff --git a/Content.Shared/Movement/Components/CanWalkComponent.cs b/Content.Shared/Movement/Components/CanWalkComponent.cs deleted file mode 100644 index fab851595c7..00000000000 --- a/Content.Shared/Movement/Components/CanWalkComponent.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Robust.Shared.GameStates; - -namespace Content.Shared.Movement.Components; - -/// -/// Indicates if the entity can toggle walking or not. -/// -[NetworkedComponent, RegisterComponent] -public sealed partial class CanWalkComponent : Component -{ -} diff --git a/Content.Shared/Movement/Components/InputMoverComponent.cs b/Content.Shared/Movement/Components/InputMoverComponent.cs index 263190d46fd..916ecc90af1 100644 --- a/Content.Shared/Movement/Components/InputMoverComponent.cs +++ b/Content.Shared/Movement/Components/InputMoverComponent.cs @@ -1,6 +1,8 @@ using System.Numerics; using Content.Shared.Alert; +using Content.Shared.CCVar; using Content.Shared.Movement.Systems; +using Robust.Shared.Configuration; using Robust.Shared.GameStates; using Robust.Shared.Serialization; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; @@ -72,7 +74,10 @@ public sealed partial class InputMoverComponent : Component public const float LerpTime = 1.0f; - public bool Sprinting => (HeldMoveButtons & MoveButtons.Walk) == 0x0; + //NOTE I don't think I'm supposed to do this + public bool Sprinting => IoCManager.Resolve().GetCVar(CCVars.GamePressToSprint) + ? (HeldMoveButtons & MoveButtons.Walk) != 0x0 + : (HeldMoveButtons & MoveButtons.Walk) == 0x0; [ViewVariables(VVAccess.ReadWrite)] public bool CanMove = true; diff --git a/Content.Shared/Movement/Components/MovementSpeedModifierComponent.cs b/Content.Shared/Movement/Components/MovementSpeedModifierComponent.cs index 813a18f974c..0f404f45b97 100644 --- a/Content.Shared/Movement/Components/MovementSpeedModifierComponent.cs +++ b/Content.Shared/Movement/Components/MovementSpeedModifierComponent.cs @@ -22,8 +22,8 @@ public sealed partial class MovementSpeedModifierComponent : Component public const float DefaultFriction = 20f; public const float DefaultFrictionNoInput = 20f; - public const float DefaultBaseWalkSpeed = 2.5f; - public const float DefaultBaseSprintSpeed = 4.5f; + public const float DefaultBaseWalkSpeed = 3f; + public const float DefaultBaseSprintSpeed = 5f; [AutoNetworkedField, ViewVariables] public float WalkSpeedModifier = 1.0f; diff --git a/Content.Shared/Movement/Systems/SharedMoverController.Input.cs b/Content.Shared/Movement/Systems/SharedMoverController.Input.cs index 891bd518b1c..50cffa6ffea 100644 --- a/Content.Shared/Movement/Systems/SharedMoverController.Input.cs +++ b/Content.Shared/Movement/Systems/SharedMoverController.Input.cs @@ -620,7 +620,7 @@ public enum MoveButtons : byte Down = 2, Left = 4, Right = 8, - Walk = 16, + Walk = 16, // This may be either a sprint button or a walk button, depending on server config AnyDirection = Up | Down | Left | Right, } diff --git a/Content.Shared/Movement/Systems/SharedMoverController.cs b/Content.Shared/Movement/Systems/SharedMoverController.cs index 4c2c91db6a1..3cc35e7bc67 100644 --- a/Content.Shared/Movement/Systems/SharedMoverController.cs +++ b/Content.Shared/Movement/Systems/SharedMoverController.cs @@ -12,6 +12,7 @@ using Content.Shared.Movement.Events; using Content.Shared.StepTrigger.Components; using Content.Shared.Tag; +using Content.Shared.Traits.Assorted.Components; using Robust.Shared.Audio; using Robust.Shared.Audio.Systems; using Robust.Shared.Configuration; @@ -261,9 +262,17 @@ protected void HandleMobMovement( TryGetSound(weightless, uid, mover, mobMover, xform, out var sound, tileDef: tileDef)) { var soundModifier = mover.Sprinting ? 3.5f : 1.5f; + var volume = sound.Params.Volume + soundModifier; + + if (_entities.TryGetComponent(uid, out FootstepVolumeModifierComponent? volumeModifier)) + { + volume += mover.Sprinting + ? volumeModifier.SprintVolumeModifier + : volumeModifier.WalkVolumeModifier; + } var audioParams = sound.Params - .WithVolume(sound.Params.Volume + soundModifier) + .WithVolume(volume) .WithVariation(sound.Params.Variation ?? FootstepVariation); // If we're a relay target then predict the sound for all relays. @@ -289,12 +298,10 @@ protected void HandleMobMovement( PhysicsSystem.SetAngularVelocity(physicsUid, 0, body: physicsComponent); } - public void WalkingAlert(EntityUid player, bool walking) + private void WalkingAlert(EntityUid player, bool walking) { - if (HasComp(player)) - { - _alerts.ShowAlert(player, AlertType.Walking, walking ? (short) 0 : (short) 1); - } + walking = _configManager.GetCVar(CCVars.GamePressToSprint) ? !walking : walking; + _alerts.ShowAlert(player, AlertType.Walking, walking ? (short) 0 : (short) 1); } public void LerpRotation(EntityUid uid, InputMoverComponent mover, float frameTime) diff --git a/Content.Shared/Roles/AntagPrototype.cs b/Content.Shared/Roles/AntagPrototype.cs index c6acb9b7575..824ea4be4e5 100644 --- a/Content.Shared/Roles/AntagPrototype.cs +++ b/Content.Shared/Roles/AntagPrototype.cs @@ -1,3 +1,4 @@ +using Content.Shared.Customization.Systems; using Robust.Shared.Prototypes; using Robust.Shared.Serialization; @@ -42,5 +43,5 @@ public sealed partial class AntagPrototype : IPrototype /// Requirements that must be met to opt in to this antag role. ///
[DataField("requirements")] - public HashSet? Requirements; + public List? Requirements; } diff --git a/Content.Shared/Roles/JobPrototype.cs b/Content.Shared/Roles/JobPrototype.cs index 9f158a79e08..15f8233aab8 100644 --- a/Content.Shared/Roles/JobPrototype.cs +++ b/Content.Shared/Roles/JobPrototype.cs @@ -1,4 +1,5 @@ using Content.Shared.Access; +using Content.Shared.Customization.Systems; using Content.Shared.Players.PlayTimeTracking; using Content.Shared.Roles; using Content.Shared.StatusIcon; @@ -43,7 +44,7 @@ public sealed partial class JobPrototype : IPrototype public string? LocalizedDescription => Description is null ? null : Loc.GetString(Description); [DataField("requirements")] - public HashSet? Requirements; + public List? Requirements; [DataField("joinNotifyCrew")] public bool JoinNotifyCrew { get; private set; } = false; diff --git a/Content.Shared/Roles/JobRequirements.cs b/Content.Shared/Roles/JobRequirements.cs deleted file mode 100644 index 44607fc44d9..00000000000 --- a/Content.Shared/Roles/JobRequirements.cs +++ /dev/null @@ -1,232 +0,0 @@ -using System.Diagnostics.CodeAnalysis; -using Content.Shared.Players.PlayTimeTracking; -using Content.Shared.Roles.Jobs; -using JetBrains.Annotations; -using Robust.Shared.Prototypes; -using Robust.Shared.Serialization; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; -using Robust.Shared.Utility; - -namespace Content.Shared.Roles -{ - /// - /// Abstract class for playtime and other requirements for role gates. - /// - [ImplicitDataDefinitionForInheritors] - [Serializable, NetSerializable] - public abstract partial class JobRequirement{} - - [UsedImplicitly] - [Serializable, NetSerializable] - public sealed partial class DepartmentTimeRequirement : JobRequirement - { - /// - /// Which department needs the required amount of time. - /// - [DataField("department", customTypeSerializer: typeof(PrototypeIdSerializer))] - public string Department = default!; - - /// - /// How long (in seconds) this requirement is. - /// - [DataField("time")] public TimeSpan Time; - - /// - /// If true, requirement will return false if playtime above the specified time. - /// - /// - /// False by default.
- /// True for invert general requirement - ///
- [DataField("inverted")] public bool Inverted; - } - - [UsedImplicitly] - [Serializable, NetSerializable] - public sealed partial class RoleTimeRequirement : JobRequirement - { - /// - /// What particular role they need the time requirement with. - /// - [DataField("role", customTypeSerializer: typeof(PrototypeIdSerializer))] - public string Role = default!; - - /// - [DataField("time")] public TimeSpan Time; - - /// - [DataField("inverted")] public bool Inverted; - } - - [UsedImplicitly] - [Serializable, NetSerializable] - public sealed partial class OverallPlaytimeRequirement : JobRequirement - { - /// - [DataField("time")] public TimeSpan Time; - - /// - [DataField("inverted")] public bool Inverted; - } - - public static class JobRequirements - { - public static bool TryRequirementsMet( - JobPrototype job, - IReadOnlyDictionary playTimes, - [NotNullWhen(false)] out FormattedMessage? reason, - IEntityManager entManager, - IPrototypeManager prototypes, - bool isWhitelisted) - { - reason = null; - if (job.Requirements == null) - return true; - - foreach (var requirement in job.Requirements) - { - if (!TryRequirementMet(requirement, playTimes, out reason, entManager, prototypes, isWhitelisted)) - return false; - } - - return true; - } - - /// - /// Returns a string with the reason why a particular requirement may not be met. - /// - public static bool TryRequirementMet( - JobRequirement requirement, - IReadOnlyDictionary playTimes, - [NotNullWhen(false)] out FormattedMessage? reason, - IEntityManager entManager, - IPrototypeManager prototypes, - bool isWhitelisted, - string? localePrefix = "role-timer-") - { - reason = null; - - switch (requirement) - { - case DepartmentTimeRequirement deptRequirement: - var playtime = TimeSpan.Zero; - - // Check all jobs' departments - var department = prototypes.Index(deptRequirement.Department); - var jobs = department.Roles; - string proto; - - // Check all jobs' playtime - foreach (var other in jobs) - { - // The schema is stored on the Job role but we want to explode if the timer isn't found anyway. - proto = prototypes.Index(other).PlayTimeTracker; - - playTimes.TryGetValue(proto, out var otherTime); - playtime += otherTime; - } - - var deptDiff = deptRequirement.Time.TotalMinutes - playtime.TotalMinutes; - - if (!deptRequirement.Inverted) - { - if (deptDiff <= 0) - return true; - - reason = FormattedMessage.FromMarkup(Loc.GetString( - $"{localePrefix}department-insufficient", - ("time", Math.Ceiling(deptDiff)), - ("department", Loc.GetString(deptRequirement.Department)), - ("departmentColor", department.Color.ToHex()))); - return false; - } - - if (deptDiff <= 0) - { - reason = FormattedMessage.FromMarkup(Loc.GetString( - $"{localePrefix}department-too-high", - ("time", -deptDiff), - ("department", Loc.GetString(deptRequirement.Department)), - ("departmentColor", department.Color.ToHex()))); - return false; - } - - return true; - - case OverallPlaytimeRequirement overallRequirement: - var overallTime = playTimes.GetValueOrDefault(PlayTimeTrackingShared.TrackerOverall); - var overallDiff = overallRequirement.Time.TotalMinutes - overallTime.TotalMinutes; - - if (!overallRequirement.Inverted) - { - if (overallDiff <= 0 || overallTime >= overallRequirement.Time) - return true; - - reason = FormattedMessage.FromMarkup(Loc.GetString( - $"{localePrefix}overall-insufficient", - ("time", Math.Ceiling(overallDiff)))); - return false; - } - - if (overallDiff <= 0 || overallTime >= overallRequirement.Time) - { - reason = FormattedMessage.FromMarkup(Loc.GetString($"{localePrefix}overall-too-high", ("time", -overallDiff))); - return false; - } - - return true; - - case RoleTimeRequirement roleRequirement: - proto = roleRequirement.Role; - - playTimes.TryGetValue(proto, out var roleTime); - var roleDiff = roleRequirement.Time.TotalMinutes - roleTime.TotalMinutes; - var departmentColor = Color.Yellow; - - if (entManager.EntitySysManager.TryGetEntitySystem(out SharedJobSystem? jobSystem)) - { - var jobProto = jobSystem.GetJobPrototype(proto); - - if (jobSystem.TryGetDepartment(jobProto, out var departmentProto)) - departmentColor = departmentProto.Color; - } - - if (!roleRequirement.Inverted) - { - if (roleDiff <= 0) - return true; - - reason = FormattedMessage.FromMarkup(Loc.GetString( - $"{localePrefix}role-insufficient", - ("time", Math.Ceiling(roleDiff)), - ("job", Loc.GetString(proto)), - ("departmentColor", departmentColor.ToHex()))); - return false; - } - - if (roleDiff <= 0) - { - reason = FormattedMessage.FromMarkup(Loc.GetString( - $"{localePrefix}role-too-high", - ("time", -roleDiff), - ("job", Loc.GetString(proto)), - ("departmentColor", departmentColor.ToHex()))); - return false; - } - - return true; - case WhitelistRequirement _: // DeltaV - Whitelist requirement - if (isWhitelisted == null) - throw new ArgumentNullException(nameof(isWhitelisted), "isWhitelisted cannot be null."); - - if (isWhitelisted) - return true; - - reason = FormattedMessage.FromMarkup(Loc.GetString("playtime-deny-reason-not-whitelisted")); - return false; - default: - throw new NotImplementedException(); - } - } - } -} diff --git a/Content.Shared/Supermatter/Components/SupermatterComponent.cs b/Content.Shared/Supermatter/Components/SupermatterComponent.cs new file mode 100644 index 00000000000..ad7604f5ba6 --- /dev/null +++ b/Content.Shared/Supermatter/Components/SupermatterComponent.cs @@ -0,0 +1,390 @@ +using Robust.Shared.GameStates; +using Robust.Shared.Audio; +using Content.Shared.Atmos; +using Content.Shared.Whitelist; +using Content.Shared.DoAfter; +using Robust.Shared.Serialization; + +namespace Content.Shared.Supermatter.Components; + +[RegisterComponent, NetworkedComponent] +public sealed partial class SupermatterComponent : Component +{ + #region Base + + /// + /// The SM will only cycle if activated. + /// + [DataField] + public bool Activated = false; + + [DataField] + public string SliverPrototype = "SupermatterSliver"; + + /// + /// Affects delamination timer. + /// If removed - delamination timer is divided by 2. + /// + [DataField] + public bool SliverRemoved = false; + + public string[] LightningPrototypes = + { + "Lightning", + "ChargedLightning", + "SuperchargedLightning", + "HyperchargedLightning" + }; + + [DataField] + public string SingularitySpawnPrototype = "Singularity"; + + [DataField] + public string TeslaSpawnPrototype = "TeslaEnergyBall"; + + [DataField] + public string KudzuSpawnPrototype = "SupermatterKudzu"; + + /// + /// What spawns in the place of an unfortunate entity that got removed by the SM. + /// + [DataField] + public string CollisionResultPrototype = "Ash"; + + [DataField] + public SoundSpecifier DustSound = new SoundPathSpecifier("/Audio/Effects/Grenades/Supermatter/supermatter_start.ogg"); + + [DataField] + public SoundSpecifier CalmSound = new SoundPathSpecifier("/Audio/Supermatter/calm.ogg"); + + [DataField] + public SoundSpecifier DelamSound = new SoundPathSpecifier("/Audio/Supermatter/delamming.ogg"); + + [DataField] + public SoundSpecifier CurrentSoundLoop = new SoundPathSpecifier("/Audio/Supermatter/calm.ogg"); + + #endregion + + #region Processing + + [DataField] + public float Power; + + [DataField] + public float MatterPower; + + [DataField] + public float MatterPowerConversion = 10f; + + /// + /// The portion of the gasmix we're on + /// + [DataField] + public float GasEfficiency = 0.15f; + + /// + /// Based on CO2 percentage, this slowly moves between 0 and 1. + /// We use it to calculate the powerloss_inhibitor. + /// + [DataField] + public float PowerlossDynamicScaling; + + /// + /// Affects the amount of damage and minimum point at which the SM takes heat damage + /// + [DataField] + public float DynamicHeatResistance = 1; + + /// + /// Multiplier on damage the core takes from absorbing hot gas. + /// Default is ~1/350. + /// + [DataField] + public float MoleHeatPenalty = 0.00286f; + + /// + /// Inverse of + /// + [DataField] + public float MoleHeatThreshold = 350f; + + /// + /// Multiplier on power generated by nuclear reactions + /// + [DataField] + public float ReactionPowerModifier = 0.55f; + + /// + /// Acts as a multiplier on the amount that nuclear reactions increase the supermatter core temperature + /// + [DataField] + public float ThermalReleaseModifier = 0.2f; + + /// + /// Multiplier on how much plasma is released during supermatter reactions + /// Default is ~1/750 + /// + [DataField] + public float PlasmaReleaseModifier = 0.001333f; + + /// + /// Multiplier on how much oxygen is released during supermatter reactions. + /// Default is ~1/325 + /// + [DataField] + public float OxygenReleaseEfficiencyModifier = 0.0031f; + + #endregion + + #region Timing + + /// + /// We yell if over 50 damage every YellTimer Seconds + /// + [DataField] + public float YellTimer = 60f; + + /// + /// Set to YellTimer at first so it doesnt yell a minute after being hit + /// + [DataField] + public float YellAccumulator = 60f; + + /// + /// Timer for delam + /// + [DataField] + public float DelamTimerAccumulator; + + /// + /// Time until delam + /// + [DataField] + public float DelamTimer = 120f; + + /// + /// The message timer + /// + [DataField] + public float SpeakAccumulator = 60f; + + [DataField] + public float UpdateAccumulator = 0f; + + [DataField] + public float UpdateTimer = 1f; + + [DataField] + public float ZapAccumulator = 0f; + + [DataField] + public float ZapTimer = 10f; + + #endregion + + #region Thresholds + + /// + /// The heat threshold in Kelvin, after which the supermatter begins taking damage. + /// + [DataField] + public float HeatThreshold = 2500f; + + /// + /// Percentage of inhibitor gas needed before the charge inertia chain reaction effect starts. + /// + [DataField] + public float PowerlossInhibitionGasThreshold = 0.20f; + + /// + /// Moles of the gas needed before the charge inertia chain reaction effect starts. + /// Scales powerloss inhibition down until this amount of moles is reached. + /// + [DataField] + public float PowerlossInhibitionMoleThreshold = 20f; + + /// + /// Bonus powerloss inhibition boost if this amount of moles is reached + /// + [DataField] + public float PowerlossInhibitionMoleBoostThreshold = 500f; + + /// + /// Above this value we can get lord singulo and independent mol damage, below it we can heal damage + /// + [DataField] + public float MolePenaltyThreshold = 900f; + + /// + /// More moles of gases are harder to heat than fewer, so let's scale heat damage around them + /// + [DataField] + public float MoleHeatPenaltyThreshold; + + /// + /// The cutoff on power properly doing damage, pulling shit around, + /// and delamming into a tesla. Low chance of pyro anomalies, +2 bolts of electricity + /// + [DataField] + public float PowerPenaltyThreshold = 4000f; + + /// + /// Maximum safe operational temperature in degrees Celsius. + /// Supermatter begins taking damage above this temperature. + /// + [DataField] + public float HeatPenaltyThreshold = 40f; + + #endregion + + #region Damage + + /// + /// The amount of damage taken + /// + [DataField] + public float Damage = 0f; + + /// + /// The damage from before this cycle. + /// Used to limit the damage we can take each cycle, and for safe alert. + /// + [DataField] + public float DamageArchived = 0f; + + /// + /// Is multiplied by ExplosionPoint to cap evironmental damage per cycle + /// + [DataField] + public float DamageHardcap = 0.002f; + + /// + /// Environmental damage is scaled by this + /// + [DataField] + public float DamageIncreaseMultiplier = 0.25f; + + /// + /// Max space damage the SM will take per cycle + /// + [DataField] + public float MaxSpaceExposureDamage = 2; + + /// + /// The point at which we should start sending radio messages about the damage. + /// + [DataField] + public float DamageWarningThreshold = 50; + + /// + /// The point at which we start sending station announcements about the damage. + /// + [DataField] + public float DamageEmergencyThreshold = 500; + + /// + /// The point at which the SM begins delaminating. + /// + [DataField] + public int DamageDelaminationPoint = 900; + + [DataField] + public bool Delamming = false; + + [DataField] + public DelamType PreferredDelamType = DelamType.Explosion; + + #endregion + + #region Announcements + + [DataField] + public string AlertCodeYellowId = "yellow"; + + [DataField] + public string AlertCodeDeltaId = "delta"; + + [DataField] + public bool DelamAnnounced = false; + + #endregion + + #region Gases + + /// + /// How much gas is in the SM + /// + [DataField] + public Dictionary GasStorage = new Dictionary() + { + { Gas.Oxygen, 0f }, + { Gas.Nitrogen, 0f }, + { Gas.CarbonDioxide, 0f }, + { Gas.Plasma, 0f }, + { Gas.Tritium, 0f }, + { Gas.WaterVapor, 0f }, + { Gas.Frezon, 0f }, + { Gas.Ammonia, 0f }, + { Gas.NitrousOxide, 0f }, + }; + + /// + /// Stores information about how every gas interacts with the SM + /// + //TODO: Replace this with serializable GasFact array something + public readonly Dictionary GasDataFields = new() + { + { Gas.Oxygen, (1.5f, 1f, 1f) }, + { Gas.Nitrogen, (0f, -1.5f, -1f) }, + { Gas.CarbonDioxide, (0f, 0.1f, 1f) }, + { Gas.Plasma, (4f, 15f, 1f) }, + { Gas.Tritium, (30f, 10f, 1f) }, + { Gas.WaterVapor, (2f, 12f, 1f) }, + { Gas.Frezon, (3f, -10f, -1f) }, + { Gas.Ammonia, (0f, .5f, 1f) }, + { Gas.NitrousOxide, (0f, -5f, -1f) }, + }; + + #endregion +} + + +public enum SupermatterSound : sbyte +{ + Aggressive = 0, + Delam = 1 +} + +public enum DelamType : int +{ + Explosion = 0, + Singulo = 1, + Tesla = 2, + Cascade = 3 +} + +[Serializable, DataDefinition] +public sealed partial class GasFact +{ + [DataField] + public float TransmitModifier; + + [DataField] + public float HeatPenalty; + + [DataField] + public float PowerMixRatio; + + public GasFact(float transmitModifier, float heatPenalty, float powerMixRatio) + { + TransmitModifier = transmitModifier; + HeatPenalty = heatPenalty; + PowerMixRatio = powerMixRatio; + } +} + +[Serializable, NetSerializable] +public sealed partial class SupermatterDoAfterEvent : SimpleDoAfterEvent +{ + +} diff --git a/Content.Shared/Supermatter/Components/SupermatterFoodComponent.cs b/Content.Shared/Supermatter/Components/SupermatterFoodComponent.cs new file mode 100644 index 00000000000..9d235a4b4d3 --- /dev/null +++ b/Content.Shared/Supermatter/Components/SupermatterFoodComponent.cs @@ -0,0 +1,8 @@ +namespace Content.Shared.Supermatter.Components; + +[RegisterComponent] +public sealed partial class SupermatterFoodComponent : Component +{ + [DataField] + public int Energy { get; set; } = 1; +} diff --git a/Content.Shared/Supermatter/Components/SupermatterImmuneComponent.cs b/Content.Shared/Supermatter/Components/SupermatterImmuneComponent.cs new file mode 100644 index 00000000000..b517115eca7 --- /dev/null +++ b/Content.Shared/Supermatter/Components/SupermatterImmuneComponent.cs @@ -0,0 +1,9 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared.Supermatter.Components; + +[RegisterComponent, NetworkedComponent] +public sealed partial class SupermatterImmuneComponent : Component +{ + +} diff --git a/Content.Shared/Traits/Assorted/Components/FootstepVolumeModifierComponent.cs b/Content.Shared/Traits/Assorted/Components/FootstepVolumeModifierComponent.cs new file mode 100644 index 00000000000..8c7e763692c --- /dev/null +++ b/Content.Shared/Traits/Assorted/Components/FootstepVolumeModifierComponent.cs @@ -0,0 +1,22 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared.Traits.Assorted.Components; + +/// +/// This is used for any trait that modifies footstep volumes. +/// +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +public sealed partial class FootstepVolumeModifierComponent : Component +{ + /// + /// What to add to the volume of sprinting, in terms of decibels. + /// + [DataField, AutoNetworkedField] + public float SprintVolumeModifier; + + /// + /// What to add to the volume of walking, in terms of decibels. + /// + [DataField, AutoNetworkedField] + public float WalkVolumeModifier; +} diff --git a/Content.Shared/Weapons/Ranged/Components/GunComponent.cs b/Content.Shared/Weapons/Ranged/Components/GunComponent.cs index ada99801f01..8d7ecae1a81 100644 --- a/Content.Shared/Weapons/Ranged/Components/GunComponent.cs +++ b/Content.Shared/Weapons/Ranged/Components/GunComponent.cs @@ -241,6 +241,12 @@ public sealed partial class GunComponent : Component ///
[DataField] public float FireOnDropChance = 0.1f; + + /// + /// Whether or not this gun is truly Recoilless, such as Lasers, and therefore shouldn't move the user. + /// + [DataField] + public bool DoRecoil = true; } [Flags] diff --git a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs index 1dfdede1afa..3c5e5c79846 100644 --- a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs +++ b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs @@ -362,11 +362,11 @@ private void AttemptShoot(EntityUid user, EntityUid gunUid, GunComponent gun) var shotEv = new GunShotEvent(user, ev.Ammo); RaiseLocalEvent(gunUid, ref shotEv); - if (userImpulse && TryComp(user, out var userPhysics)) - { - if (_gravity.IsWeightless(user, userPhysics)) - CauseImpulse(fromCoordinates, toCoordinates.Value, user, userPhysics); - } + if (gun.DoRecoil + && userImpulse + && TryComp(user, out var userPhysics) + && _gravity.IsWeightless(user, userPhysics)) + CauseImpulse(fromCoordinates, toCoordinates.Value, user, userPhysics); Dirty(gunUid, gun); } diff --git a/Resources/Audio/Admin/ahelp_error.ogg b/Resources/Audio/Admin/ahelp_error.ogg new file mode 100755 index 00000000000..bcdb3267900 Binary files /dev/null and b/Resources/Audio/Admin/ahelp_error.ogg differ diff --git a/Resources/Audio/Admin/ahelp_receive.ogg b/Resources/Audio/Admin/ahelp_receive.ogg new file mode 100755 index 00000000000..eb31b3a8ab3 Binary files /dev/null and b/Resources/Audio/Admin/ahelp_receive.ogg differ diff --git a/Resources/Audio/Admin/ahelp_send.ogg b/Resources/Audio/Admin/ahelp_send.ogg new file mode 100755 index 00000000000..427605cfb80 Binary files /dev/null and b/Resources/Audio/Admin/ahelp_send.ogg differ diff --git a/Resources/Audio/Admin/attributions.yml b/Resources/Audio/Admin/attributions.yml new file mode 100644 index 00000000000..8df7e38c578 --- /dev/null +++ b/Resources/Audio/Admin/attributions.yml @@ -0,0 +1,9 @@ +- files: [ "ahelp_error" ] + license: "CC-BY-NC-SA-3.0" + copyright: "CM-SS13" + source: "https://github.com/cmss13-devs/cmss13/commit/497204fb1660977fb6bf1fe8de153c65c8299d7d" + +- files: [ "ahelp_receive", "ahelp_send" ] + license: "CC-BY-NC-SA-3.0" + copyright: "CM-SS13" + source: "https://github.com/cmss13-devs/cmss13/commit/21e6447cc08aea502f671c819fdbcecbb85e6028" diff --git a/Resources/Audio/Announcers/NEIL/alerts/code_blue.ogg b/Resources/Audio/Announcers/NEIL/alerts/blue.ogg similarity index 100% rename from Resources/Audio/Announcers/NEIL/alerts/code_blue.ogg rename to Resources/Audio/Announcers/NEIL/alerts/blue.ogg diff --git a/Resources/Audio/Announcers/NEIL/alerts/code_delta.ogg b/Resources/Audio/Announcers/NEIL/alerts/delta.ogg similarity index 100% rename from Resources/Audio/Announcers/NEIL/alerts/code_delta.ogg rename to Resources/Audio/Announcers/NEIL/alerts/delta.ogg diff --git a/Resources/Audio/Announcers/NEIL/alerts/code_epsilon.ogg b/Resources/Audio/Announcers/NEIL/alerts/epsilon.ogg similarity index 100% rename from Resources/Audio/Announcers/NEIL/alerts/code_epsilon.ogg rename to Resources/Audio/Announcers/NEIL/alerts/epsilon.ogg diff --git a/Resources/Audio/Announcers/NEIL/alerts/code_gamma.ogg b/Resources/Audio/Announcers/NEIL/alerts/gamma.ogg similarity index 100% rename from Resources/Audio/Announcers/NEIL/alerts/code_gamma.ogg rename to Resources/Audio/Announcers/NEIL/alerts/gamma.ogg diff --git a/Resources/Audio/Announcers/NEIL/alerts/code_green.ogg b/Resources/Audio/Announcers/NEIL/alerts/green.ogg similarity index 100% rename from Resources/Audio/Announcers/NEIL/alerts/code_green.ogg rename to Resources/Audio/Announcers/NEIL/alerts/green.ogg diff --git a/Resources/Audio/Announcers/NEIL/alerts/code_red.ogg b/Resources/Audio/Announcers/NEIL/alerts/red.ogg similarity index 100% rename from Resources/Audio/Announcers/NEIL/alerts/code_red.ogg rename to Resources/Audio/Announcers/NEIL/alerts/red.ogg diff --git a/Resources/Audio/Announcers/NEIL/alerts/code_violet.ogg b/Resources/Audio/Announcers/NEIL/alerts/violet.ogg similarity index 100% rename from Resources/Audio/Announcers/NEIL/alerts/code_violet.ogg rename to Resources/Audio/Announcers/NEIL/alerts/violet.ogg diff --git a/Resources/Audio/Announcers/NEIL/alerts/code_white.ogg b/Resources/Audio/Announcers/NEIL/alerts/white.ogg similarity index 100% rename from Resources/Audio/Announcers/NEIL/alerts/code_white.ogg rename to Resources/Audio/Announcers/NEIL/alerts/white.ogg diff --git a/Resources/Audio/Announcers/NEIL/alerts/code_yellow.ogg b/Resources/Audio/Announcers/NEIL/alerts/yellow.ogg similarity index 100% rename from Resources/Audio/Announcers/NEIL/alerts/code_yellow.ogg rename to Resources/Audio/Announcers/NEIL/alerts/yellow.ogg diff --git a/Resources/Audio/Effects/adminhelp.ogg b/Resources/Audio/Effects/adminhelp.ogg deleted file mode 100644 index 704c0fd6d20..00000000000 Binary files a/Resources/Audio/Effects/adminhelp.ogg and /dev/null differ diff --git a/Resources/Audio/Supermatter/calm.ogg b/Resources/Audio/Supermatter/calm.ogg new file mode 100644 index 00000000000..dc3102e5786 Binary files /dev/null and b/Resources/Audio/Supermatter/calm.ogg differ diff --git a/Resources/Audio/Supermatter/delamming.ogg b/Resources/Audio/Supermatter/delamming.ogg new file mode 100644 index 00000000000..a48878ec42f Binary files /dev/null and b/Resources/Audio/Supermatter/delamming.ogg differ diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index fa12b491b85..9709714067f 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -4658,3 +4658,279 @@ Entries: message: Long Survival has been added as a new Game mode. id: 6185 time: '2024-07-27T06:00:24.0000000+00:00' +- author: CilliePaint + changes: + - type: Tweak + message: New Box Textures! + id: 6186 + time: '2024-07-29T05:50:43.0000000+00:00' +- author: Mnemotechnician + changes: + - type: Fix + message: >- + Fixed toolshed command permissions. This will mostly affect admins who + don't have full host access. + id: 6187 + time: '2024-07-29T05:54:01.0000000+00:00' +- author: VMSolidus + changes: + - type: Fix + message: Radiation damage no longer interrupts DoAfters. + id: 6188 + time: '2024-07-29T06:00:26.0000000+00:00' +- author: Skubman + changes: + - type: Add + message: >- + Added cybernetic limb markings from Hesphiastos Industries and Bishop + Cybernetics. + id: 6189 + time: '2024-07-30T21:33:23.0000000+00:00' +- author: Skubman + changes: + - type: Add + message: >- + Makeup is finally here: lips, blush, and nail polish! Sashay over to + Character Setup in the Markings section, then look at Head/Overlay to + give makeovers to your characters! + id: 6190 + time: '2024-07-30T21:34:37.0000000+00:00' +- author: VMSolidus + changes: + - type: Fix + message: >- + Fixed Tools, Drink Containers, Lockers, and all base items having + inconsistent sound settings. + id: 6191 + time: '2024-07-31T22:47:01.0000000+00:00' +- author: VMSolidus + changes: + - type: Fix + message: 'Lasers no longer function as jetpacks in space. ' + id: 6192 + time: '2024-07-31T22:57:33.0000000+00:00' +- author: DEATHB4DEFEAT + changes: + - type: Fix + message: Fixed the Uncategorized category not being hidden when empty + id: 6193 + time: '2024-07-31T23:32:52.0000000+00:00' +- author: Mnemotechnician + changes: + - type: Fix + message: Whisper can no longer be heard clearly outside the intended range. + - type: Fix + message: >- + Translators can no longer be used without knowing the languages they + require. + - type: Fix + message: >- + Computers (primarily RnD console) now speak GC by default instead of + Universal. + - type: Tweak + message: Readjusted colors of all languages to make them easier to read. + id: 6194 + time: '2024-07-31T23:57:25.0000000+00:00' +- author: Skubman + changes: + - type: Add + message: >- + Added dozens of new clothes and items to Loadouts, including the new + Mask category. Have fun dressing up your characters! + - type: Tweak + message: Restrict Command Loadouts from selecting uniforms outside of their job. + - type: Tweak + message: >- + Limit the selection in Security Loadouts of non-sec uniforms, hats, and + masks to those that maintain the Security aesthetic. + - type: Tweak + message: >- + Made all types of colored jumpsuits in Loadouts available to Civilian + roles (excluding HoP), and suitable jumpsuits to Epistemics, + Engineering, and Medical. + - type: Fix + message: Prevent dionas and harpies from selecting shoes in Loadouts. + id: 6195 + time: '2024-08-01T02:37:45.0000000+00:00' +- author: DEATHB4DEFEAT + changes: + - type: Tweak + message: >- + The station's crew hivemind has decided to slow down their movement and + enjoy The Park instead of sprinting everywhere + id: 6196 + time: '2024-08-01T08:30:47.0000000+00:00' +- author: VMSolidus + changes: + - type: Add + message: 'Survival Boxes have been added to loadouts. ' + id: 6197 + time: '2024-08-01T21:12:49.0000000+00:00' +- author: VMSolidus + changes: + - type: Add + message: >- + Boxes(Cardboard, Medkits, Lunchboxes) now contain slightly more + inventory slots than they occupy. + id: 6198 + time: '2024-08-01T21:55:09.0000000+00:00' +- author: VMSolidus + changes: + - type: Tweak + message: >- + Ultraviolet Vision, Deuteranopia, and Trichromat Modification are all + now 0 point Neutral traits. They still occupy one of your trait + selections. + id: 6199 + time: '2024-08-01T22:41:24.0000000+00:00' +- author: Skubman + changes: + - type: Add + message: 'Added new clothes in Loadouts: slim trench coat, and Mafia-style suits.' + - type: Add + message: >- + Added new useful items in Loadouts: lunchbox, more survival gear, + paperwork, and medkits. + id: 6200 + time: '2024-08-01T22:45:13.0000000+00:00' +- author: FoxxoTrystan + changes: + - type: Add + message: Vulpkanins can wag their tails now + id: 6201 + time: '2024-08-01T23:06:24.0000000+00:00' +- author: angelofallars + changes: + - type: Add + message: >- + Added the combat knife to the SecTech, and the ability to manufacture + combat knives in the SecLathe and emagged autolathes. + - type: Add + message: >- + Added a 1-point combat knife to Loadouts for Felinid/Harpy security + jobs. + - type: Tweak + message: Made the security belt and security webbing able to hold combat knives. + - type: Tweak + message: 'Prison Guards now start with combat boots with a combat knife. ' + id: 6202 + time: '2024-08-02T07:08:07.0000000+00:00' +- author: rosieposieeee + changes: + - type: Add + message: >- + Added breaching charges to the SecTech vendor for Security, to break + through walls. + id: 6203 + time: '2024-08-02T07:09:44.0000000+00:00' +- author: DEATHB4DEFEAT + changes: + - type: Tweak + message: >- + The AdminHelp sound has changed to three that play under different + circumstances + id: 6204 + time: '2024-08-02T07:14:01.0000000+00:00' +- author: Mnemotechnician + changes: + - type: Fix + message: >- + Reverted the station event scheduler rework due to it absolutely + breaking the game. + id: 6205 + time: '2024-08-02T22:52:41.0000000+00:00' +- author: VMSolidus + changes: + - type: Add + message: 'Supermatter Engines have been implemented. ' + id: 6206 + time: '2024-08-03T00:41:54.0000000+00:00' +- author: Tilkku + changes: + - type: Tweak + message: Rouny Sprite Changed + id: 6207 + time: '2024-08-03T11:04:01.0000000+00:00' +- author: VMSolidus + changes: + - type: Tweak + message: >- + Due to budget cuts, Nanotrasen has ceased stocking Clothesmate vendors + with more clothing than the average cargo tech can afford. Civilians are + advised to bring their own clothes to the station if they wish to wear + anything other than grey. + id: 6208 + time: '2024-08-04T00:23:53.0000000+00:00' +- author: VMSolidus + changes: + - type: Add + message: >- + SweatMAX, "hot foods", Mars Mart, and Nippon-tan vendors have all been + added to vendor spawners. + id: 6209 + time: '2024-08-04T06:26:34.0000000+00:00' +- author: Skubman + changes: + - type: Add + message: >- + Add the Voracious trait, a 1-point trait that makes you eat and drink + twice as fast. + id: 6210 + time: '2024-08-04T09:30:31.0000000+00:00' +- author: VMSolidus + changes: + - type: Fix + message: >- + Zombie events have had their Anti-Stalling mechanic improved. Dead + (Player) Zombies, Infected Players, and Initial Infected are all counted + as zombies for the purpose of determine if the shuttle should be called. + Additionally, any player who leaves the station is no longer counted as + a healthy crewman for the automatic shuttle call. + id: 6211 + time: '2024-08-04T14:14:12.0000000+00:00' +- author: Skubman + changes: + - type: Tweak + message: Rename the trait "Heavyweight Drunk" into "Alcohol Tolerance". + id: 6212 + time: '2024-08-05T03:30:41.0000000+00:00' +- author: Skubman + changes: + - type: Add + message: >- + Add the Light Step trait, a 1-point trait that makes your footsteps + quieter. + id: 6213 + time: '2024-08-05T15:29:07.0000000+00:00' +- author: Skubman + changes: + - type: Add + message: >- + Add a new 1-point trait called Sign Language, a trait that allows you to + communicate in Galactic Sign Language. + id: 6214 + time: '2024-08-05T16:55:31.0000000+00:00' +- author: Mnemotechnician + changes: + - type: Tweak + message: >- + Oracle requests are now more likely to be aligned with the current + research. + id: 6215 + time: '2024-08-05T17:10:42.0000000+00:00' +- author: VMSolidus + changes: + - type: Tweak + message: >- + The Carrying system has been reworked as a means of better supporting + having extremely large species and characters. 10kg Harpies should no + longer be oppressed by 2000kg Lamia with infinitely short carry + attempts. + id: 6216 + time: '2024-08-05T17:11:37.0000000+00:00' +- author: Rane + changes: + - type: Add + message: Lamiae should now be rendered much better. + id: 6217 + time: '2024-08-05T17:15:51.0000000+00:00' diff --git a/Resources/Credits/GitHub.txt b/Resources/Credits/GitHub.txt index 276f44a01f0..6e47a71e43f 100644 --- a/Resources/Credits/GitHub.txt +++ b/Resources/Credits/GitHub.txt @@ -1 +1 @@ -0x6273, 2013HORSEMEATSCANDAL, 20kdc, 21Melkuu, 4dplanner, 612git, 778b, Ablankmann, Acruid, actioninja, adamsong, Admiral-Obvious-001, Adrian16199, Aerocrux, Aexxie, africalimedrop, Agoichi, Ahion, AJCM-git, AjexRose, Alekshhh, AlexMorgan3817, AlmondFlour, AlphaQwerty, Altoids1, amylizzle, ancientpower, ArchPigeon, Arendian, arimah, Arteben, AruMoon, as334, AsikKEsel, asperger-sind, aspiringLich, avghdev, AzzyIsNotHere, BananaFlambe, BasedUser, beck-thompson, BGare, BingoJohnson-zz, BismarckShuffle, Bixkitts, Blackern5000, Blazeror, Boaz1111, BobdaBiscuit, brainfood1183, BramvanZijp, Brandon-Huu, Bribrooo, Bright0, brndd, BubblegumBlue, BYONDFuckery, c4llv07e, CaasGit, CakeQ, CaptainSqrBeard, Carbonhell, Carolyn3114, CatTheSystem, Centronias, chairbender, Charlese2, Cheackraze, cheesePizza2, Chief-Engineer, chromiumboy, Chronophylos, clement-or, Clyybber, CodedCrow, ColdAutumnRain, Colin-Tel, collinlunn, ComicIronic, coolmankid12345, corentt, crazybrain23, creadth, CrigCrag, Crotalus, CrudeWax, CrzyPotato, Cyberboss, d34d10cc, Daemon, daerSeebaer, dahnte, dakamakat, dakimasu, DamianX, DangerRevolution, daniel-cr, Darkenson, DawBla, dch-GH, Deahaka, DEATHB4DEFEAT, DeathCamel58, deathride58, DebugOk, Decappi, deepdarkdepths, Delete69, deltanedas, DeltaV-Bot, DerbyX, DoctorBeard, DogZeroX, dontbetank, Doru991, DoubleRiceEddiedd, DrMelon, DrSmugleaf, drteaspoon420, DTanxxx, DubiousDoggo, Duddino, Dutch-VanDerLinde, Easypoller, eclips_e, EdenTheLiznerd, EEASAS, Efruit, ElectroSR, elthundercloud, Emisse, EmoGarbage404, Endecc, enumerate0, eoineoineoin, ERORR404V1, Errant-4, estacaoespacialpirata, exincore, exp111, Fahasor, FairlySadPanda, ficcialfaint, Fildrance, FillerVK, Fishfish458, Flareguy, FluffiestFloof, FluidRock, FoLoKe, fooberticus, Fortune117, FoxxoTrystan, freeman2651, Froffy025, Fromoriss, FungiFellow, GalacticChimp, gbasood, Geekyhobo, Genkail, geraeumig, Ghagliiarghii, Git-Nivrak, github-actions[bot], gituhabu, GNF54, Golinth, GoodWheatley, Gotimanga, graevy, GreyMario, Guess-My-Name, gusxyz, h3half, Hanzdegloker, Hardly3D, harikattar, Hebiman, Henry12116, HerCoyote23, Hmeister-real, HoofedEar, hord-brayden, hubismal, Hugal31, Huxellberger, Hyenh, iacore, IamVelcroboy, icekot8, igorsaux, ike709, Illiux, Ilya246, IlyaElDunaev, Injazz, Insineer, IntegerTempest, Interrobang01, IProduceWidgets, ItsMeThom, Jackal298, Jackrost, jamessimo, janekvap, JerryImMouse, Jessetriesagain, jessicamaybe, Jezithyr, jicksaw, JiimBob, JoeHammad1844, JohnGinnane, johnku1, joshepvodka, jproads, Jrpl, juliangiebel, JustArt1m, JustCone14, JustinTrotter, KaiShibaa, kalane15, kalanosh, Kelrak, kerisargit, keronshb, KIBORG04, Killerqu00, KingFroozy, kira-er, Kit0vras, KittenColony, Ko4ergaPunk, komunre, koteq, Krunklehorn, kxvvv, Lamrr, LankLTE, lapatison, Leander-0, leonardo-dabepis, LetterN, Level10Cybermancer, lever1209, liltenhead, LittleBuilderJane, Lomcastar, LordCarve, LordEclipse, LovelyLophi, Lukasz825700516, lunarcomets, luringens, lvvova1, lzimann, lzk228, MACMAN2003, Macoron, MagnusCrowe, ManelNavola, Matz05, MehimoNemo, MeltedPixel, MemeProof, Menshin, Mervill, metalgearsloth, mhamsterr, MilenVolf, Minty642, Mirino97, mirrorcult, misandrie, MishaUnity, MisterMecky, Mith-randalf, Mnemotechnician, Moneyl, Moomoobeef, moony, Morb0, Mr0maks, musicmanvr, Myakot, Myctai, N3X15, Nairodian, Naive817, namespace-Memory, NickPowers43, nikthechampiongr, Nimfar11, Nirnael, nmajask, nok-ko, notafet, notquitehadouken, noudoit, noverd, nuke-haus, NULL882, OCOtheOmega, OctoRocket, OldDanceJacket, onoira, osjarw, Owai-Seek, pali6, Pangogie, patrikturi, PaulRitter, Peptide90, peptron1, Phantom-Lily, PHCodes, PixelTheKermit, PJB3005, Plykiya, pofitlo, pointer-to-null, PolterTzi, PoorMansDreams, potato1234x, ProfanedBane, PrPleGoo, ps3moira, Pspritechologist, Psychpsyo, psykzz, PuroSlavKing, quatre, QuietlyWhisper, qwerltaz, Radosvik, Radrark, Rainbeon, Rainfey, Rane, ravage123321, rbertoche, Redict, RedlineTriad, RednoWCirabrab, RemberBM, RemieRichards, RemTim, rene-descartes2021, RiceMar1244, RieBi, Rinkashikachi, Rockdtben, rolfero, rosieposieeee, Saakra, Samsterious, SaphireLattice, ScalyChimp, scrato, Scribbles0, Serkket, SethLafuente, ShadowCommander, Shadowtheprotogen546, SignalWalker, SimpleStation14, Simyon264, Sirionaut, siyengar04, Skarletto, Skrauz, Skyedra, SlamBamActionman, slarticodefast, Slava0135, Snowni, snowsignal, SonicHDC, SoulSloth, SpaceManiac, SpeltIncorrectyl, spoogemonster, ssdaniel24, Stealthbomber16, stellar-novas, StrawberryMoses, superjj18, SweptWasTaken, Szunti, TadJohnson00, takemysoult, TaralGit, Tayrtahn, tday93, TekuNut, TemporalOroboros, tentekal, tgrkzus, thatrandomcanadianguy, TheArturZh, theashtronaut, thedraccx, themias, Theomund, theOperand, TheShuEd, TimrodDX, Titian3, tkdrg, tmtmtl30, TokenStyle, tom-leys, tomasalves8, Tomeno, Tornado-Technology, tosatur, Tryded, TsjipTsjip, Tunguso4ka, TurboTrackerss14, Tyler-IN, Tyzemol, UbaserB, UKNOWH, UnicornOnLSD, Uriende, UristMcDorf, Vaaankas, Varen, VasilisThePikachu, veliebm, Veritius, Vermidia, Verslebas, VigersRay, Visne, VMSolidus, volundr-, Voomra, Vordenburg, vulppine, wafehling, WarMechanic, waylon531, weaversam8, Willhelm53, wixoaGit, WlarusFromDaSpace, wrexbe, xRiriq, yathxyz, Ygg01, YotaXP, YuriyKiss, zach-hill, Zandario, Zap527, Zealith-Gamer, ZelteHonor, zerorulez, zionnBE, zlodo, ZNixian, ZoldorfTheWizard, Zumorica, Zymem +0x6273, 2013HORSEMEATSCANDAL, 20kdc, 21Melkuu, 4dplanner, 612git, 778b, Ablankmann, Acruid, actioninja, adamsong, Admiral-Obvious-001, Adrian16199, Aerocrux, Aexxie, africalimedrop, Agoichi, Ahion, AJCM-git, AjexRose, Alekshhh, AlexMorgan3817, AlmondFlour, AlphaQwerty, Altoids1, amylizzle, ancientpower, angelofallars, ArchPigeon, Arendian, arimah, Arteben, AruMoon, as334, AsikKEsel, asperger-sind, aspiringLich, avghdev, AzzyIsNotHere, BananaFlambe, BasedUser, beck-thompson, BGare, BingoJohnson-zz, BismarckShuffle, Bixkitts, Blackern5000, Blazeror, Boaz1111, BobdaBiscuit, brainfood1183, BramvanZijp, Brandon-Huu, Bribrooo, Bright0, brndd, BubblegumBlue, BYONDFuckery, c4llv07e, CaasGit, CakeQ, CaptainSqrBeard, Carbonhell, Carolyn3114, CatTheSystem, Centronias, chairbender, Charlese2, Cheackraze, cheesePizza2, Chief-Engineer, chromiumboy, Chronophylos, clement-or, Clyybber, CodedCrow, ColdAutumnRain, Colin-Tel, collinlunn, ComicIronic, coolmankid12345, corentt, crazybrain23, creadth, CrigCrag, Crotalus, CrudeWax, CrzyPotato, Cyberboss, d34d10cc, Daemon, daerSeebaer, dahnte, dakamakat, dakimasu, DamianX, DangerRevolution, daniel-cr, Darkenson, DawBla, dch-GH, Deahaka, DEATHB4DEFEAT, DeathCamel58, deathride58, DebugOk, Decappi, Deeeeja, deepdarkdepths, Delete69, deltanedas, DeltaV-Bot, DerbyX, DoctorBeard, DogZeroX, dontbetank, Doru991, DoubleRiceEddiedd, DrMelon, DrSmugleaf, drteaspoon420, DTanxxx, DubiousDoggo, Duddino, Dutch-VanDerLinde, Easypoller, eclips_e, EdenTheLiznerd, EEASAS, Efruit, ElectroSR, elthundercloud, Emisse, EmoGarbage404, Endecc, enumerate0, eoineoineoin, ERORR404V1, Errant-4, estacaoespacialpirata, exincore, exp111, Fahasor, FairlySadPanda, ficcialfaint, Fildrance, FillerVK, Fishfish458, Flareguy, FluffiestFloof, FluidRock, FoLoKe, fooberticus, Fortune117, FoxxoTrystan, freeman2651, Froffy025, Fromoriss, FungiFellow, GalacticChimp, gbasood, Geekyhobo, Genkail, geraeumig, Ghagliiarghii, Git-Nivrak, github-actions[bot], gituhabu, GNF54, Golinth, GoodWheatley, graevy, GreyMario, Guess-My-Name, gusxyz, h3half, Hanzdegloker, Hardly3D, harikattar, Hebiman, Henry12116, HerCoyote23, Hmeister-real, HoofedEar, Hoolny, hord-brayden, hubismal, Hugal31, Huxellberger, Hyenh, iacore, IamVelcroboy, icekot8, igorsaux, ike709, Illiux, Ilya246, IlyaElDunaev, Injazz, Insineer, Interrobang01, IProduceWidgets, ItsMeThom, Jackal298, Jackrost, jamessimo, janekvap, JerryImMouse, Jessetriesagain, jessicamaybe, Jezithyr, jicksaw, JiimBob, JoeHammad1844, JohnGinnane, johnku1, joshepvodka, jproads, Jrpl, juliangiebel, JustArt1m, JustCone14, JustinTrotter, KaiShibaa, kalane15, kalanosh, Kelrak, kerisargit, keronshb, KIBORG04, Killerqu00, KingFroozy, kira-er, Kit0vras, KittenColony, Ko4ergaPunk, komunre, koteq, Krunklehorn, kxvvv, Lamrr, LankLTE, lapatison, Leander-0, leonardo-dabepis, LetterN, Level10Cybermancer, lever1209, liltenhead, LittleBuilderJane, Lomcastar, LordCarve, LordEclipse, LovelyLophi, Lukasz825700516, lunarcomets, luringens, lvvova1, lzimann, lzk228, MACMAN2003, Macoron, MagnusCrowe, ManelNavola, Matz05, MehimoNemo, MeltedPixel, MemeProof, Menshin, Mervill, metalgearsloth, mhamsterr, MilenVolf, Minty642, Mirino97, mirrorcult, misandrie, MishaUnity, MisterMecky, Mith-randalf, Mnemotechnician, Moneyl, Moomoobeef, moony, Morb0, Mr0maks, musicmanvr, Myakot, Myctai, N3X15, Nairodian, Naive817, namespace-Memory, NickPowers43, nikthechampiongr, Nimfar11, Nirnael, nmajask, nok-ko, notafet, notquitehadouken, noudoit, noverd, nuke-haus, NULL882, OCOtheOmega, OctoRocket, OldDanceJacket, onoira, osjarw, Owai-Seek, pali6, Pangogie, patrikturi, PaulRitter, Peptide90, peptron1, Phantom-Lily, PHCodes, PixelTheKermit, PJB3005, Plykiya, pofitlo, pointer-to-null, PolterTzi, PoorMansDreams, potato1234x, ProfanedBane, PrPleGoo, ps3moira, Pspritechologist, Psychpsyo, psykzz, PuroSlavKing, quatre, QuietlyWhisper, qwerltaz, Radosvik, Radrark, Rainbeon, Rainfey, Rane, ravage123321, rbertoche, Redict, RedlineTriad, RednoWCirabrab, RemberBM, RemieRichards, RemTim, rene-descartes2021, RiceMar1244, RieBi, Rinkashikachi, Rockdtben, rolfero, rosieposieeee, Saakra, Samsterious, SaphireLattice, ScalyChimp, scrato, Scribbles0, Serkket, ShadowCommander, Shadowtheprotogen546, SignalWalker, SimpleStation14, Simyon264, Sirionaut, siyengar04, Skarletto, Skrauz, Skyedra, SlamBamActionman, slarticodefast, Slava0135, Snowni, snowsignal, SonicHDC, SoulSloth, SpaceManiac, SpeltIncorrectyl, spoogemonster, ssdaniel24, stalengd, Stealthbomber16, stellar-novas, StrawberryMoses, superjj18, SweptWasTaken, Szunti, TadJohnson00, takemysoult, TaralGit, Tayrtahn, tday93, TekuNut, TemporalOroboros, tentekal, tgrkzus, thatrandomcanadianguy, TheArturZh, theashtronaut, thedraccx, themias, Theomund, theOperand, TheShuEd, TimrodDX, Titian3, tkdrg, Tmanzxd, tmtmtl30, TokenStyle, tom-leys, tomasalves8, Tomeno, Tornado-Technology, tosatur, Tryded, TsjipTsjip, Tunguso4ka, TurboTrackerss14, Tyler-IN, Tyzemol, UbaserB, UKNOWH, UnicornOnLSD, Uriende, UristMcDorf, Vaaankas, Varen, VasilisThePikachu, veliebm, Veritius, Vermidia, Verslebas, VigersRay, Visne, VMSolidus, volundr-, Voomra, Vordenburg, vulppine, wafehling, WarMechanic, waylon531, weaversam8, Willhelm53, wixoaGit, WlarusFromDaSpace, wrexbe, xRiriq, yathxyz, Ygg01, YotaXP, YuriyKiss, zach-hill, Zandario, Zap527, Zealith-Gamer, ZelteHonor, zerorulez, zionnBE, zlodo, ZNixian, ZoldorfTheWizard, Zumorica, Zymem diff --git a/Resources/Locale/en-US/customization/character-requirements.ftl b/Resources/Locale/en-US/customization/character-requirements.ftl index d0eeb8f9c85..a3f00dea872 100644 --- a/Resources/Locale/en-US/customization/character-requirements.ftl +++ b/Resources/Locale/en-US/customization/character-requirements.ftl @@ -1,3 +1,22 @@ +# Job +character-job-requirement = You must {$inverted -> + [true] not be + *[other] be +} one of these jobs: {$jobs} +character-department-requirement = You must {$inverted -> + [true] not be + *[other] be +} in one of these departments: {$departments} + +character-timer-department-insufficient = You require [color=yellow]{TOSTRING($time, "0")}[/color] more minutes of [color={$departmentColor}]{$department}[/color] department playtime +character-timer-department-too-high = You require [color=yellow]{TOSTRING($time, "0")}[/color] fewer minutes in [color={$departmentColor}]{$department}[/color] department +character-timer-overall-insufficient = You require [color=yellow]{TOSTRING($time, "0")}[/color] more minutes of playtime +character-timer-overall-too-high = You require [color=yellow]{TOSTRING($time, "0")}[/color] fewer minutes of playtime +character-timer-role-insufficient = You require [color=yellow]{TOSTRING($time, "0")}[/color] more minutes with [color={$departmentColor}]{$job}[/color] +character-timer-role-too-high = You require[color=yellow] {TOSTRING($time, "0")}[/color] fewer minutes with [color={$departmentColor}]{$job}[/color] + + +# Profile character-age-requirement = You must {$inverted -> [true] not be *[other] be @@ -23,18 +42,9 @@ character-clothing-preference-requirement = You must {$inverted -> *[other] wear } a [color=white]{$type}[/color] -character-job-requirement = You must {$inverted -> - [true] not be - *[other] be -} one of these jobs: {$jobs} -character-department-requirement = You must {$inverted -> + +# Whitelist +character-whitelist-requirement = You must {$inverted -> [true] not be *[other] be -} in one of these departments: {$departments} - -character-timer-department-insufficient = You require [color=yellow]{TOSTRING($time, "0")}[/color] more minutes of [color={$departmentColor}]{$department}[/color] department playtime -character-timer-department-too-high = You require [color=yellow]{TOSTRING($time, "0")}[/color] fewer minutes in [color={$departmentColor}]{$department}[/color] department -character-timer-overall-insufficient = You require [color=yellow]{TOSTRING($time, "0")}[/color] more minutes of playtime -character-timer-overall-too-high = You require [color=yellow]{TOSTRING($time, "0")}[/color] fewer minutes of playtime -character-timer-role-insufficient = You require [color=yellow]{TOSTRING($time, "0")}[/color] more minutes with [color={$departmentColor}]{$job}[/color] -character-timer-role-too-high = You require[color=yellow] {TOSTRING($time, "0")}[/color] fewer minutes with [color={$departmentColor}]{$job}[/color] +} whitelisted diff --git a/Resources/Locale/en-US/deltav/markings/vulpkanin.ftl b/Resources/Locale/en-US/deltav/markings/vulpkanin.ftl index 857cc711570..d23dd4d346a 100644 --- a/Resources/Locale/en-US/deltav/markings/vulpkanin.ftl +++ b/Resources/Locale/en-US/deltav/markings/vulpkanin.ftl @@ -102,14 +102,6 @@ marking-VulpTailTip-vulp = Vulpkanin tail (base) marking-VulpTailTip-vulp-tip = Vulpkanin tail (tip) marking-VulpTailTip = Vulpkanin (tip) -marking-VulpTailWag-vulp_wag = Vulpkanin tail (base) -marking-VulpTailWag-vulp_wag-fade = Vulpkanin tail (fade) -marking-VulpTailWag = Vulpkanin (wag) - -marking-VulpTailWagTip-vulp_wag = Vulpkanin tail (base) -marking-VulpTailWagTip-vulp_wag-tip = Vulpkanin tail (tip) -marking-VulpTailWagTip = Vulpkanin (wag, tip) - marking-VulpTailAlt-vulp_alt = Vulpkanin tail (base) marking-VulpTailAlt-vulp_alt-fade = Vulpkanin tail (fade) marking-VulpTailAlt = Vulpkanin (alt) @@ -130,29 +122,12 @@ marking-VulpTailFoxTip-fox = Fox tail (base) marking-VulpTailFoxTip-fox-tip = Fox tail (fade) marking-VulpTailFoxTip = Vulpkanin Fox (tip) -marking-VulpTailFoxWag-fox_wag = Fox tail (base) -marking-VulpTailFoxWag-fox_wag-fade = Fox tail (fade) -marking-VulpTailFoxWag = Vulpkanin Fox (wag) - -marking-VulpTailFoxWagTip-fox_wag = Fox tail (base) -marking-VulpTailFoxWagTip-fox_wag-tip = Fox tail (tip) -marking-VulpTailFoxWagTip = Vulpkanin Fox (wag, tip) - marking-VulpTailBushy-bushfluff = Bush tail marking-VulpTailBushy = Vulpkanin Bush -marking-VulpTailBushyWag-bushfluff_wag = Bush tail -marking-VulpTailBushyWag = Vulpkanin Bush (wag) - marking-VulpTailCoyote-coyote = Coyote tail marking-VulpTailCoyote = Vulpkanin Coyote -marking-VulpTailCoyoteWag-coyote_wag = Coyote tail -marking-VulpTailCoyoteWag = Vulpkanin Coyote (wag) - -marking-VulpTailCorgiWag-corgi_wag = Crogi tail -marking-VulpTailCorgiWag = Vulpkanin Corgi (wag) - marking-VulpTailHusky-husky-inner = Husky tail (inner) marking-VulpTailHusky-husky-outer = Husky tail (outer) marking-VulpTailHusky = Vulpkanin Husky @@ -176,8 +151,11 @@ marking-VulpTailOtie = Vulpkanin Otie marking-VulpTailFluffy-fluffy = Fluffy tail marking-VulpTailFluffy = Vulpkanin Fluffy -marking-VulpTailDalmatianWag-dalmatian_wag = Dalmatian tail -marking-VulpTailDalmatianWag = Vulpkanin Dalmatian (wag) +marking-VulpTailCorgi-corgi = Crogi tail +marking-VulpTailCorgi = Vulpkanin Corgi + +marking-VulpTailDalmatian-dalmatian = Dalmatian tail +marking-VulpTailDalmatian = Vulpkanin Dalmatian marking-VulpBellyCrest-belly_crest = Belly diff --git a/Resources/Locale/en-US/escape-menu/ui/options-menu.ftl b/Resources/Locale/en-US/escape-menu/ui/options-menu.ftl index 8c6cf575d54..7b25b616b24 100644 --- a/Resources/Locale/en-US/escape-menu/ui/options-menu.ftl +++ b/Resources/Locale/en-US/escape-menu/ui/options-menu.ftl @@ -112,13 +112,13 @@ ui-options-header-dev = Development ui-options-header-general = General ui-options-hotkey-keymap = Use US QWERTY Keys -ui-options-hotkey-toggle-walk = Toggle Walk +ui-options-hotkey-toggle-walk = Toggle Speed ui-options-function-move-up = Move Up ui-options-function-move-left = Move Left ui-options-function-move-down = Move Down ui-options-function-move-right = Move Right -ui-options-function-walk = Walk +ui-options-function-walk = Change Speed ui-options-function-camera-rotate-left = Rotate left ui-options-function-camera-rotate-right = Rotate right diff --git a/Resources/Locale/en-US/game-ticking/game-presets/preset-survival.ftl b/Resources/Locale/en-US/game-ticking/game-presets/preset-survival.ftl index 10e6a4a24f2..0b8fa83ae8b 100644 --- a/Resources/Locale/en-US/game-ticking/game-presets/preset-survival.ftl +++ b/Resources/Locale/en-US/game-ticking/game-presets/preset-survival.ftl @@ -3,6 +3,3 @@ survival-description = No internal threats, but how long can the station survive hellshift-title = Hellshift hellshift-description = The station rolled a "one" in a luck check. Can the crew make it to the end? - -longsurvival-title = Long Survival -longsurvival-description = Survival, but two hours longer. Event growth is stretched over a vastly greater length of time. diff --git a/Resources/Locale/en-US/language/languages.ftl b/Resources/Locale/en-US/language/languages.ftl index 4e84afe55eb..d44b6648397 100644 --- a/Resources/Locale/en-US/language/languages.ftl +++ b/Resources/Locale/en-US/language/languages.ftl @@ -31,6 +31,9 @@ language-Moffic-description = The language of the mothpeople borders on complete language-RobotTalk-name = RobotTalk language-RobotTalk-description = A language consisting of harsh binary chirps, whistles, hisses, and whines. Organic tongues cannot speak it without aid from special translators. +language-Sign-name = Galactic Sign Language +language-Sign-description = GSL for short, this sign language is prevalent among mute and deaf people. + language-Cat-name = Cat language-Cat-description = Meow @@ -73,8 +76,8 @@ language-Crab-description = Click! language-Kobold-name = Kobold language-Kobold-description = Hiss! -language-Sign-name = Sign Language -language-Sign-description = The standard Galactic sign language, used by those that are unable to speak Galactic Common or at all. +language-Hissing-name = Hissing +language-Hissing-description = Hiss! language-ScugSign-name = ScugSign language-ScugSign-description = Wawa! The secret ScugSign making you able to understand your fellows scug! \ No newline at end of file diff --git a/Resources/Locale/en-US/loadouts/items.ftl b/Resources/Locale/en-US/loadouts/items.ftl index b92f56bc7cb..c2ec9a1c847 100644 --- a/Resources/Locale/en-US/loadouts/items.ftl +++ b/Resources/Locale/en-US/loadouts/items.ftl @@ -13,3 +13,25 @@ loadout-description-LoadoutItemPlushieSharkGrey = Introducing the Grey Shark Plu loadout-description-LoadoutItemPlushieCarp = Brace for extraterrestrial antics with the Purple Space Carp Plushie! A fishy invader from the cosmic deep, this plushie brings a splash of humor to zero-gravity escapades. From hostile waters to interstellar giggles, it's a cuddly contradiction that's out of this world loadout-description-LoadoutSolCommonTranslator = The most common of all translators, such that it can be purchased in any civilized station. This device translates Sol Common speech into Galactic Common. +loadout-name-LoadoutItemPapers = papers (x4) +loadout-description-LoadoutItemPapers = four pieces of paper, good for filling out tedious paperwork and silent communication. +loadout-description-LoadoutItemBoxFolderGrey = A folder to store papers and top secret documents. +loadout-description-LoadoutBookRandom = A notebook with a random cover. Can be used as a diary, or for writing fanfiction drafts for SpacePad. +loadout-description-LoadoutPen = An extra pen, just in case your pen from your PDA gets robbed by skeletal space pirates. +loadout-description-LoadoutItemLunchboxGenericFilledRandom = Packed with love. + This is only useful when the chefs are either a.) nonexistent or b.) not doing their job. + In conclusion, this lunchbox is useful most of the time. +loadout-description-LoadoutHandLabeler = A hand labeler, used to label items and objects. + It's not really recommended to use this to label a fuel tank with "SOLUTION TO CLOWN PROBLEM". +loadout-description-LoadoutEmergencyMedipen = A rapid and safe way to stabilize patients in critical condition for personnel without advanced medical knowledge. + WARNING: injecting two emergency medipens at once will cause an epinephrine overdose. +loadout-description-LoadoutSpaceMedipen = Contains a mix of chemicals that protect you from the deadly effects of space. + Also known as the "poor man's hardsuit". + WARNING: injecting two space medipens at once will cause a barozine overdose. + +loadout-name-LoadoutItemBoxSurvival = survival box (standard) +loadout-name-LoadoutItemBoxSurvivalEngineering = extended-capacity survival box (engineering) +loadout-name-LoadoutItemBoxSurvivalSecurity = survival box (security) +loadout-name-LoadoutItemBoxSurvivalBrigmedic = survival box (corpsman) +loadout-name-LoadoutItemBoxSurvivalMedical = survival box (medical) +loadout-name-LoadoutItemBoxHug = box of hugs (clown) diff --git a/Resources/Locale/en-US/markings/makeup.ftl b/Resources/Locale/en-US/markings/makeup.ftl new file mode 100644 index 00000000000..24ca3a10b7d --- /dev/null +++ b/Resources/Locale/en-US/markings/makeup.ftl @@ -0,0 +1,17 @@ +marking-MakeupLips-lips = Lips +marking-MakeupLips = Lips + +marking-MakeupBlush-blush = Blush +marking-MakeupBlush = Blush + +marking-MakeupNailPolishLeft-nail_polish_l = Nail Polish (Left) +marking-MakeupNailPolishLeft = Nail Polish (Left) + +marking-MakeupNailPolishRight-nail_polish_r = Nail Polish (Right) +marking-MakeupNailPolishRight = Nail Polish (Right) + +marking-MakeupMothBlush-moth_blush = Moth Blush +marking-MakeupMothBlush = Moth Blush + +marking-MakeupMothLips-moth_lips = Moth Lipstick +marking-MakeupMothLips = Moth Lipstick diff --git a/Resources/Locale/en-US/objectives/conditions/steal.ftl b/Resources/Locale/en-US/objectives/conditions/steal.ftl index 00c8e0fdaf9..0709bf6e5e6 100644 --- a/Resources/Locale/en-US/objectives/conditions/steal.ftl +++ b/Resources/Locale/en-US/objectives/conditions/steal.ftl @@ -9,3 +9,6 @@ objective-condition-steal-Ian = head of personnel's corgi objective-condition-thief-description = The {$itemName} would be a great addition to my collection! objective-condition-thief-animal-description = The {$itemName} would be a great addition to my collection! Most importantly, alive. objective-condition-thief-multiply-description = I need to get {$count} {MAKEPLURAL($itemName)} and take them with me. + +objective-condition-steal-smsliver-title = Cut off a sliver from the supermatter crystal. +objective-condition-steal-smsliver-description = Use any cutting tool that comes in handy. A scalpel is more recommended. Also, don't die of radiation poisoning. diff --git a/Resources/Locale/en-US/silicons/cyberlimbs.ftl b/Resources/Locale/en-US/silicons/cyberlimbs.ftl new file mode 100644 index 00000000000..b7686b0a2dc --- /dev/null +++ b/Resources/Locale/en-US/silicons/cyberlimbs.ftl @@ -0,0 +1,77 @@ +marking-MobIPCHeadDefault = Standard Operational Monitor +marking-MobIPCTorsoDefault = Standard Robotic Chassis +marking-MobIPCTorsoFemaleDefault = Standard Robotic Chassis +marking-MobIPCLArmDefault = Standard Left Robotic Arm +marking-MobIPCLHandDefault = Standard Left Robotic Hand +marking-MobIPCLLegDefault = Standard Left Robotic Leg +marking-MobIPCLFootDefault = Standard Left Robotic Foot +marking-MobIPCRArmDefault = Standard Right Robotic Arm +marking-MobIPCRHandDefault = Standard Right Robotic Hand +marking-MobIPCRLegDefault = Standard Right Robotic Leg +marking-MobIPCRFootDefault = Standard Right Robotic Foot + +marking-CyberLimbsMarkingBishopHead = Operational Monitor from Bishop Cybernetics +marking-CyberLimbsMarkingBishopChest = Robotic Chassis from Bishop Cybernetics +marking-CyberLimbsMarkingBishopLArm = Left Robotic Arm from Bishop Cybernetics +marking-CyberLimbsMarkingBishopLHand = Left Robotic Hand from Bishop Cybernetics +marking-CyberLimbsMarkingBishopLLeg = Left Robotic Leg from Bishop Cybernetics +marking-CyberLimbsMarkingBishopLFoot = Left Robotic Foot from Bishop Cybernetics +marking-CyberLimbsMarkingBishopRArm = Right Robotic Arm from Bishop Cybernetics +marking-CyberLimbsMarkingBishopRHand = Right Robotic Hand from Bishop Cybernetics +marking-CyberLimbsMarkingBishopRLeg = Right Robotic Leg from Bishop Cybernetics +marking-CyberLimbsMarkingBishopRFoot = Right Robotic Foot from Bishop Cybernetics + +marking-CyberLimbsMarkingHesphiastosHead = Operational Monitor from Hesphiastos Industries +marking-CyberLimbsMarkingHesphiastosChest = Robotic Chassis from Hesphiastos Industries +marking-CyberLimbsMarkingHesphiastosLArm = Left Robotic Arm from Hesphiastos Industries +marking-CyberLimbsMarkingHesphiastosLHand = Left Robotic Hand from Hesphiastos Industries +marking-CyberLimbsMarkingHesphiastosLLeg = Left Robotic Leg from Hesphiastos Industries +marking-CyberLimbsMarkingHesphiastosLFoot = Left Robotic Foot from Hesphiastos Industries +marking-CyberLimbsMarkingHesphiastosRArm = Right Robotic Arm from Hesphiastos Industries +marking-CyberLimbsMarkingHesphiastosRHand = Right Robotic Hand from Hesphiastos Industries +marking-CyberLimbsMarkingHesphiastosRLeg = Right Robotic Leg from Hesphiastos Industries +marking-CyberLimbsMarkingHesphiastosRFoot = Right Robotic Foot from Hesphiastos Industries + +marking-CyberLimbsMarkingWardtakahashiHead = Operational Monitor from Ward-Takahashi +marking-CyberLimbsMarkingWardtakahashiChest = Robotic Chassis from Ward-Takahashi +marking-CyberLimbsMarkingWardtakahashiLArm = Left Robotic Arm from Ward-Takahashi +marking-CyberLimbsMarkingWardtakahashiLHand = Left Robotic Hand from Ward-Takahashi +marking-CyberLimbsMarkingWardtakahashiLLeg = Left Robotic Leg from Ward-Takahashi +marking-CyberLimbsMarkingWardtakahashiLFoot = Left Robotic Foot from Ward-Takahashi +marking-CyberLimbsMarkingWardtakahashiRArm = Right Robotic Arm from Ward-Takahashi +marking-CyberLimbsMarkingWardtakahashiRHand = Right Robotic Hand from Ward-Takahashi +marking-CyberLimbsMarkingWardtakahashiRLeg = Right Robotic Leg from Ward-Takahashi +marking-CyberLimbsMarkingWardtakahashiRFoot = Right Robotic Foot from Ward-Takahashi + +marking-CyberLimbsMarkingXionHead = Operational Monitor from Xion Manufacturing Group +marking-CyberLimbsMarkingXionChest = Robotic Chassis from Xion Manufacturing Group +marking-CyberLimbsMarkingXionLArm = Left Robotic Arm from Xion Manufacturing Group +marking-CyberLimbsMarkingXionLHand = Left Robotic Hand from Xion Manufacturing Group +marking-CyberLimbsMarkingXionLLeg = Left Robotic Leg from Xion Manufacturing Group +marking-CyberLimbsMarkingXionLFoot = Left Robotic Foot from Xion Manufacturing Group +marking-CyberLimbsMarkingXionRArm = Right Robotic Arm from Xion Manufacturing Group +marking-CyberLimbsMarkingXionRHand = Right Robotic Hand from Xion Manufacturing Group +marking-CyberLimbsMarkingXionRLeg = Right Robotic Leg from Xion Manufacturing Group +marking-CyberLimbsMarkingXionRFoot = Right Robotic Foot from Xion Manufacturing Group + +marking-CyberLimbsMarkingShellguardHead = Operational Monitor from Shellguard Munitions +marking-CyberLimbsMarkingShellguardChest = Robotic Chassis from Shellguard Munitions +marking-CyberLimbsMarkingShellguardLArm = Left Robotic Arm from Shellguard Munitions +marking-CyberLimbsMarkingShellguardLHand = Left Robotic Hand from Shellguard Munitions +marking-CyberLimbsMarkingShellguardLLeg = Left Robotic Leg from Shellguard Munitions +marking-CyberLimbsMarkingShellguardLFoot = Left Robotic Foot from Shellguard Munitions +marking-CyberLimbsMarkingShellguardRArm = Right Robotic Arm from Shellguard Munitions +marking-CyberLimbsMarkingShellguardRHand = Right Robotic Hand from Shellguard Munitions +marking-CyberLimbsMarkingShellguardRLeg = Right Robotic Leg from Shellguard Munitions +marking-CyberLimbsMarkingShellguardRFoot = Right Robotic Foot from Shellguard Munitions + +marking-CyberLimbsMarkingMorpheusHead = Operational Monitor from Morpheus Cyberkinetics +marking-CyberLimbsMarkingMorpheusChest = Robotic Chassis from Morpheus Cyberkinetics +marking-CyberLimbsMarkingMorpheusLArm = Left Robotic Arm from Morpheus Cyberkinetics +marking-CyberLimbsMarkingMorpheusLHand = Left Robotic Hand from Morpheus Cyberkinetics +marking-CyberLimbsMarkingMorpheusLLeg = Left Robotic Leg from Morpheus Cyberkinetics +marking-CyberLimbsMarkingMorpheusLFoot = Left Robotic Foot from Morpheus Cyberkinetics +marking-CyberLimbsMarkingMorpheusRArm = Right Robotic Arm from Morpheus Cyberkinetics +marking-CyberLimbsMarkingMorpheusRHand = Right Robotic Hand from Morpheus Cyberkinetics +marking-CyberLimbsMarkingMorpheusRLeg = Right Robotic Leg from Morpheus Cyberkinetics +marking-CyberLimbsMarkingMorpheusRFoot = Right Robotic Foot from Morpheus Cyberkinetics diff --git a/Resources/Locale/en-US/station-events/events/anomaly-spawn.ftl b/Resources/Locale/en-US/station-events/events/anomaly-spawn.ftl index 543bef949aa..30fe4971eb8 100644 --- a/Resources/Locale/en-US/station-events/events/anomaly-spawn.ftl +++ b/Resources/Locale/en-US/station-events/events/anomaly-spawn.ftl @@ -1,4 +1,4 @@ -station-event-anomaly-spawn-announcement = Our readings have detected a dangerous interspacial anomaly. Please inform the research team of { $sighting }. +anomaly-spawn-event-announcement = Our readings have detected a dangerous interspacial anomaly. Please inform the research team of { $sighting }. anomaly-spawn-sighting-1 = low pulsating sounds heard throughout the station anomaly-spawn-sighting-2 = strange sources of light diff --git a/Resources/Locale/en-US/supermatter/supermatter.ftl b/Resources/Locale/en-US/supermatter/supermatter.ftl new file mode 100644 index 00000000000..52593f5524e --- /dev/null +++ b/Resources/Locale/en-US/supermatter/supermatter.ftl @@ -0,0 +1,26 @@ +supermatter-announcer = Automatic Supermatter Engine +supermatter-examine-integrity = + Its' integrity is [color=yellow]{$integrity}%[/color]. +supermatter-announcement-warning = + Warning! Crystal hyperstructure integrity faltering! Integrity: {$integrity}%. +supermatter-announcement-emergency = + DANGER! Crystal hyperstructure integrity reaching critical levels! Integrity: {$integrity}%. +supermatter-announcement-delam-explosion = + CRYSTAL DELAMINATION IMMINENT! The crystal has reached critical integrity failure! Emergency causality destabilization field has been engaged. +supermatter-announcement-delam-overmass = + CRYSTAL DELAMINATION IMMINENT! Crystal hyperstructure integrity has reached critical mass failure! Singularity formation imminent! +supermatter-announcement-delam-tesla = + CRYSTAL DELAMINATION IMMINENT! Crystal hyperstructure integrity has reached critical power surge failure! Energy ball formation imminent! +supermatter-announcement-delam-cascade = + CRYSTAL DELAMINATION IMMINENT! Harmonic frequency limits exceeded, casualty destabilization field could not be engaged! +supermatter-announcement-delam-cancel = + Crystalline hyperstructure returning to safe operating parameters. Failsafe has been Disengaged. Integrity: {$integrity}%. +supermatter-seconds-before-delam = + Estimated time before delamination: {$seconds} seconds. +supermatter-tamper-begin = + You begin carefully cutting a piece off the supermatter crystal... +supermatter-tamper-end = + You feel the power of a thousand suns laying on your palms. Or is it all the radiation? +supermatter-announcement-cc-tamper = + Our automatic casualty system has detected that the supermatter crystal structural integrity was compromised by an external force. + Engineering department, report to the supermatter engine immediately. diff --git a/Resources/Locale/en-US/traits/traits.ftl b/Resources/Locale/en-US/traits/traits.ftl index 93b46867692..9bc453f50a0 100644 --- a/Resources/Locale/en-US/traits/traits.ftl +++ b/Resources/Locale/en-US/traits/traits.ftl @@ -11,8 +11,8 @@ trait-description-Pacifist = You cannot attack or hurt any living beings. trait-name-LightweightDrunk = Lightweight Drunk trait-description-LightweightDrunk = Alcohol has a stronger effect on you -trait-name-HeavyweightDrunk = Heavyweight Drunk -trait-description-HeavyweightDrunk = Alcohols are afraid of you +trait-name-HeavyweightDrunk = Alcohol Tolerance +trait-description-HeavyweightDrunk = Alcohol is afraid of you. trait-name-Muted = Muted trait-description-Muted = You can't speak @@ -76,6 +76,20 @@ trait-description-Foreigner = For one reason or another you do not speak this station's primary language. Instead, you have a translator issued to you that only you can use. +trait-name-SignLanguage = Sign Language +trait-description-SignLanguage = + You can understand and use Galactic Sign Language (GSL). + If you are mute for any reason, you can still communicate with sign language. + +trait-name-Voracious = Voracious +trait-description-Voracious = + Nothing gets between you and your food. + Your endless consumption of food and drinks is twice as fast. + +trait-name-LightStep = Light Step +trait-description-LightStep = + You move with a gentle step, making your footsteps quieter. + trait-name-CumProducer = Cock trait-description-CumProducer = You have a schlong between your legs. diff --git a/Resources/Prototypes/Actions/types.yml b/Resources/Prototypes/Actions/types.yml index f55f59daaa8..f5dff1f453a 100644 --- a/Resources/Prototypes/Actions/types.yml +++ b/Resources/Prototypes/Actions/types.yml @@ -345,8 +345,8 @@ noSpawn: true components: - type: InstantAction - icon: { sprite: Mobs/Customization/reptilian_parts.rsi, state: tail_smooth_behind } - iconOn: { sprite: Mobs/Customization/reptilian_parts.rsi, state: tail_smooth_behind } + icon: { sprite: Interface/Actions/wagging.rsi, state: icon } + iconOn: { sprite: Interface/Actions/wagging.rsi, state: icon-on } itemIconStyle: NoItem useDelay: 1 # emote spam event: !type:ToggleActionEvent diff --git a/Resources/Prototypes/Announcers/michael.yml b/Resources/Prototypes/Announcers/michael.yml index adeb4f3b853..39a535b2161 100644 --- a/Resources/Prototypes/Announcers/michael.yml +++ b/Resources/Prototypes/Announcers/michael.yml @@ -37,9 +37,9 @@ path: alerts/red.ogg - id: alertgamma # There is a massive immediate threat to the station, listen to Central Command path: alerts/gamma.ogg - - id: alertdelta # The station is being or about to be massively destroyed, run for your life + - id: alertDelta # The station is being or about to be massively destroyed, run for your life path: alerts/delta.ogg - - id: alertepsilon # The station has been terminated, good luck survivors! + - id: alertEpsilon # The station has been terminated, good luck survivors! path: alerts/epsilon.ogg audioParams: volume: -3 diff --git a/Resources/Prototypes/Atmospherics/thresholds.yml b/Resources/Prototypes/Atmospherics/thresholds.yml index 9b09d64a10c..22ca42869ed 100644 --- a/Resources/Prototypes/Atmospherics/thresholds.yml +++ b/Resources/Prototypes/Atmospherics/thresholds.yml @@ -12,13 +12,14 @@ - type: alarmThreshold id: stationPressure upperBound: !type:AlarmThresholdSetting - threshold: 550 # as defined in Atmospherics.cs + threshold: 550 # HazardHighPressure from Atmospherics.cs lowerBound: !type:AlarmThresholdSetting - threshold: 20 # as defined in Atmospherics.cs + # Actual low pressure damage threshold is at 20 kPa, but below ~85 kPa you can't breathe due to lack of oxygen. + threshold: 20 upperWarnAround: !type:AlarmThresholdSetting - threshold: 0.7 + threshold: 0.7 # 385 kPa, WarningHighPressure from Atmospherics.cs lowerWarnAround: !type:AlarmThresholdSetting - threshold: 2.5 + threshold: 1.05 # ~90 kPa # a reminder that all of these are percentages (where 1 is 100%), # so 0.01 is 1%, diff --git a/Resources/Prototypes/Catalog/Cargo/cargo_cargo.yml b/Resources/Prototypes/Catalog/Cargo/cargo_cargo.yml index fb3b2da41a8..409670636fb 100644 --- a/Resources/Prototypes/Catalog/Cargo/cargo_cargo.yml +++ b/Resources/Prototypes/Catalog/Cargo/cargo_cargo.yml @@ -1,13 +1,3 @@ -- type: cargoProduct - id: CargoPallet - icon: - sprite: Structures/catwalk.rsi - state: catwalk_preview - product: CargoPallet - cost: 250 - category: Logistics # DeltaV - Logistics Department replacing Cargo - group: market - - type: cargoProduct id: CargoOreBox icon: diff --git a/Resources/Prototypes/Catalog/Cargo/cargo_vending.yml b/Resources/Prototypes/Catalog/Cargo/cargo_vending.yml index 93c60e4caa0..7062b2eb155 100644 --- a/Resources/Prototypes/Catalog/Cargo/cargo_vending.yml +++ b/Resources/Prototypes/Catalog/Cargo/cargo_vending.yml @@ -33,7 +33,7 @@ sprite: Objects/Specific/Service/vending_machine_restock.rsi state: base product: CrateVendingMachineRestockClothesFilled - cost: 4500 + cost: 1500 category: cargoproduct-category-name-service group: market diff --git a/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/backpack.yml b/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/backpack.yml index 2e09906b13e..4d33ec98a90 100644 --- a/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/backpack.yml +++ b/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/backpack.yml @@ -2,10 +2,6 @@ parent: ClothingBackpack id: ClothingBackpackFilled noSpawn: true - components: - - type: StorageFill - contents: - - id: BoxSurvival - type: entity noSpawn: true @@ -25,7 +21,6 @@ components: - type: StorageFill contents: - - id: BoxSurvivalSecurity - id: Flash # - id: MagazinePistol # DeltaV - Security doesn't get an extra mag @@ -36,7 +31,6 @@ components: - type: StorageFill contents: - - id: BoxSurvivalSecurity - id: Flash - id: ForensicPad - id: ForensicScanner @@ -45,10 +39,6 @@ noSpawn: true parent: ClothingBackpackMedical id: ClothingBackpackMedicalFilled - components: - - type: StorageFill - contents: - - id: BoxSurvivalMedical - type: entity noSpawn: true @@ -57,7 +47,6 @@ components: - type: StorageFill contents: - - id: BoxSurvivalMedical - id: EmergencyRollerBedSpawnFolded - type: entity @@ -67,7 +56,6 @@ components: - type: StorageFill contents: - - id: BoxSurvival - id: Flash #- name: StationCharter #- name: TelescopicBaton @@ -78,7 +66,6 @@ components: - type: StorageFill contents: - - id: BoxSurvivalEngineering - id: Flash #- id: TelescopicBaton @@ -89,7 +76,6 @@ components: - type: StorageFill contents: - - id: BoxSurvival - id: Flash #- id: TelescopicBaton @@ -100,7 +86,6 @@ components: - type: StorageFill contents: - - id: BoxSurvival - id: Flash #- id: TelescopicBaton @@ -111,7 +96,6 @@ components: - type: StorageFill contents: - - id: BoxSurvivalMedical - id: Flash #- id: TelescopicBaton @@ -122,7 +106,6 @@ components: - type: StorageFill contents: - - id: BoxSurvival - id: Flash #- id: TelescopicBaton @@ -133,7 +116,6 @@ components: - type: StorageFill contents: - - id: BoxSurvivalSecurity - id: Flash - id: MagazinePistol @@ -141,37 +123,21 @@ noSpawn: true parent: ClothingBackpackEngineering id: ClothingBackpackEngineeringFilled - components: - - type: StorageFill - contents: - - id: BoxSurvivalEngineering - type: entity noSpawn: true parent: ClothingBackpackAtmospherics id: ClothingBackpackAtmosphericsFilled - components: - - type: StorageFill - contents: - - id: BoxSurvivalEngineering - type: entity noSpawn: true parent: ClothingBackpackScience id: ClothingBackpackScienceFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - type: entity noSpawn: true parent: ClothingBackpackHydroponics id: ClothingBackpackHydroponicsFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - type: entity noSpawn: true @@ -180,17 +146,12 @@ components: - type: StorageFill contents: - - id: BoxSurvival - id: RubberStampMime - type: entity noSpawn: true parent: ClothingBackpackChemistry id: ClothingBackpackChemistryFilled - components: - - type: StorageFill - contents: - - id: BoxSurvivalMedical - type: entity noSpawn: true @@ -199,7 +160,6 @@ components: - type: StorageFill contents: - - id: BoxSurvival - id: Bible - id: RubberStampChaplain @@ -210,7 +170,6 @@ components: - type: StorageFill contents: - - id: BoxSurvival - id: AcousticGuitarInstrument - id: SaxophoneInstrument @@ -221,7 +180,6 @@ components: - type: StorageFill contents: - - id: BoxSurvival - id: BookRandom - type: entity @@ -231,7 +189,6 @@ components: - type: StorageFill contents: - - id: BoxSurvival - id: Lighter - id: CigPackBlack - id: HandLabeler @@ -372,19 +329,11 @@ noSpawn: true parent: ClothingBackpackCargo id: ClothingBackpackCargoFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - type: entity noSpawn: true parent: ClothingBackpackSalvage id: ClothingBackpackSalvageFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival # Pirate diff --git a/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/duffelbag.yml b/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/duffelbag.yml index f7ad973b842..3cac13ab53e 100644 --- a/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/duffelbag.yml +++ b/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/duffelbag.yml @@ -2,10 +2,6 @@ noSpawn: true parent: ClothingBackpackDuffel id: ClothingBackpackDuffelFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - type: entity noSpawn: true @@ -14,7 +10,6 @@ components: - type: StorageFill contents: - - id: BoxHug - id: RubberStampClown - type: entity @@ -24,7 +19,6 @@ components: - type: StorageFill contents: - - id: BoxSurvivalSecurity - id: Flash # - id: MagazinePistol # DeltaV - Security doesn't get an extra mag @@ -35,7 +29,6 @@ components: - type: StorageFill contents: - - id: BoxSurvivalSecurity - id: Flash - id: ForensicPad - id: ForensicScanner @@ -53,10 +46,6 @@ noSpawn: true parent: ClothingBackpackDuffelMedical id: ClothingBackpackDuffelMedicalFilled - components: - - type: StorageFill - contents: - - id: BoxSurvivalMedical - type: entity noSpawn: true @@ -65,7 +54,6 @@ components: - type: StorageFill contents: - - id: BoxSurvivalMedical - id: EmergencyRollerBedSpawnFolded - type: entity @@ -75,10 +63,10 @@ components: - type: StorageFill contents: - - id: BoxSurvival - id: Flash #- name: StationCharter #- name: TelescopicBaton + - type: entity noSpawn: true parent: ClothingBackpackDuffelEngineering @@ -86,7 +74,6 @@ components: - type: StorageFill contents: - - id: BoxSurvivalEngineering - id: Flash #- id: TelescopicBaton @@ -97,7 +84,6 @@ components: - type: StorageFill contents: - - id: BoxSurvival - id: Flash #- id: TelescopicBaton @@ -108,7 +94,6 @@ components: - type: StorageFill contents: - - id: BoxSurvival - id: Flash #- id: TelescopicBaton @@ -119,7 +104,6 @@ components: - type: StorageFill contents: - - id: BoxSurvivalMedical - id: Flash #- id: TelescopicBaton @@ -130,7 +114,6 @@ components: - type: StorageFill contents: - - id: BoxSurvival - id: Flash #- id: TelescopicBaton @@ -141,7 +124,6 @@ components: - type: StorageFill contents: - - id: BoxSurvivalSecurity - id: Flash - id: MagazinePistol @@ -149,38 +131,21 @@ noSpawn: true parent: ClothingBackpackDuffelEngineering id: ClothingBackpackDuffelEngineeringFilled - components: - - type: StorageFill - contents: - - id: BoxSurvivalEngineering - type: entity noSpawn: true parent: ClothingBackpackDuffelAtmospherics id: ClothingBackpackDuffelAtmosphericsFilled - components: - - type: StorageFill - contents: - - id: BoxSurvivalEngineering - - type: entity noSpawn: true parent: ClothingBackpackDuffelScience id: ClothingBackpackDuffelScienceFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - type: entity noSpawn: true parent: ClothingBackpackDuffelHydroponics id: ClothingBackpackDuffelHydroponicsFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - type: entity noSpawn: true @@ -189,17 +154,12 @@ components: - type: StorageFill contents: - - id: BoxSurvival - id: RubberStampMime - type: entity noSpawn: true parent: ClothingBackpackDuffelChemistry id: ClothingBackpackDuffelChemistryFilled - components: - - type: StorageFill - contents: - - id: BoxSurvivalMedical - type: entity noSpawn: true @@ -208,7 +168,6 @@ components: - type: StorageFill contents: - - id: BoxSurvival - id: Bible - id: RubberStampChaplain @@ -219,7 +178,6 @@ components: - type: StorageFill contents: - - id: BoxSurvival - id: AcousticGuitarInstrument - id: SaxophoneInstrument @@ -230,7 +188,6 @@ components: - type: StorageFill contents: - - id: BoxSurvival - id: BookRandom - type: entity @@ -240,7 +197,6 @@ components: - type: StorageFill contents: - - id: BoxSurvival - id: Lighter - id: CigPackBlack - id: BoxForensicPad @@ -250,16 +206,8 @@ noSpawn: true parent: ClothingBackpackDuffelCargo id: ClothingBackpackDuffelCargoFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - type: entity noSpawn: true parent: ClothingBackpackDuffelSalvage id: ClothingBackpackDuffelSalvageFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival diff --git a/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/satchel.yml b/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/satchel.yml index 1a3dda66487..89ae8fdf477 100644 --- a/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/satchel.yml +++ b/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/satchel.yml @@ -2,10 +2,6 @@ noSpawn: true parent: ClothingBackpackSatchel id: ClothingBackpackSatchelFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - type: entity noSpawn: true @@ -14,7 +10,6 @@ components: - type: StorageFill contents: - - id: BoxSurvival - id: Crowbar - id: Wrench - id: Screwdriver @@ -38,7 +33,6 @@ components: - type: StorageFill contents: - - id: BoxSurvivalSecurity - id: Flash # - id: MagazinePistol # DeltaV - Security doesn't get an extra mag @@ -49,7 +43,6 @@ components: - type: StorageFill contents: - - id: BoxSurvivalSecurity - id: Flash - id: ForensicPad - id: ForensicScanner @@ -67,10 +60,6 @@ noSpawn: true parent: ClothingBackpackSatchelMedical id: ClothingBackpackSatchelMedicalFilled - components: - - type: StorageFill - contents: - - id: BoxSurvivalMedical - type: entity noSpawn: true @@ -79,7 +68,6 @@ components: - type: StorageFill contents: - - id: BoxSurvivalMedical - id: EmergencyRollerBedSpawnFolded - type: entity @@ -89,10 +77,10 @@ components: - type: StorageFill contents: - - id: BoxSurvival - id: Flash #- name: StationCharter #- name: TelescopicBaton + - type: entity noSpawn: true parent: ClothingBackpackSatchelEngineering @@ -100,7 +88,6 @@ components: - type: StorageFill contents: - - id: BoxSurvivalEngineering - id: Flash #- id: TelescopicBaton @@ -111,7 +98,6 @@ components: - type: StorageFill contents: - - id: BoxSurvival - id: Flash #- id: TelescopicBaton @@ -122,7 +108,6 @@ components: - type: StorageFill contents: - - id: BoxSurvival - id: Flash #- id: TelescopicBaton @@ -133,7 +118,6 @@ components: - type: StorageFill contents: - - id: BoxSurvivalMedical - id: Flash #- id: TelescopicBaton @@ -144,7 +128,6 @@ components: - type: StorageFill contents: - - id: BoxSurvival - id: Flash #- id: TelescopicBaton @@ -155,7 +138,6 @@ components: - type: StorageFill contents: - - id: BoxSurvivalSecurity - id: Flash - id: MagazinePistol @@ -163,46 +145,26 @@ noSpawn: true parent: ClothingBackpackSatchelEngineering id: ClothingBackpackSatchelEngineeringFilled - components: - - type: StorageFill - contents: - - id: BoxSurvivalEngineering - type: entity noSpawn: true parent: ClothingBackpackSatchelAtmospherics id: ClothingBackpackSatchelAtmosphericsFilled - components: - - type: StorageFill - contents: - - id: BoxSurvivalEngineering - type: entity noSpawn: true parent: ClothingBackpackSatchelScience id: ClothingBackpackSatchelScienceFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - type: entity noSpawn: true parent: ClothingBackpackSatchelHydroponics id: ClothingBackpackSatchelHydroponicsFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - type: entity noSpawn: true parent: ClothingBackpackSatchelChemistry id: ClothingBackpackSatchelChemistryFilled - components: - - type: StorageFill - contents: - - id: BoxSurvivalMedical - type: entity noSpawn: true @@ -211,7 +173,6 @@ components: - type: StorageFill contents: - - id: BoxSurvival - id: Bible - id: RubberStampChaplain @@ -222,7 +183,6 @@ components: - type: StorageFill contents: - - id: BoxSurvival - id: AcousticGuitarInstrument - id: SaxophoneInstrument @@ -233,7 +193,6 @@ components: - type: StorageFill contents: - - id: BoxSurvival - id: BookRandom - type: entity @@ -243,7 +202,6 @@ components: - type: StorageFill contents: - - id: BoxSurvival - id: BoxForensicPad - id: Lighter - id: CigPackBlack @@ -253,19 +211,11 @@ noSpawn: true parent: ClothingBackpackSatchelCargo id: ClothingBackpackSatchelCargoFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - type: entity noSpawn: true parent: ClothingBackpackSatchelSalvage id: ClothingBackpackSatchelSalvageFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - type: entity noSpawn: true @@ -274,7 +224,6 @@ components: - type: StorageFill contents: - - id: BoxSurvival - id: RubberStampMime - type: entity diff --git a/Resources/Prototypes/Catalog/Fills/Boxes/general.yml b/Resources/Prototypes/Catalog/Fills/Boxes/general.yml index e4181d27a21..59a9e8d0056 100644 --- a/Resources/Prototypes/Catalog/Fills/Boxes/general.yml +++ b/Resources/Prototypes/Catalog/Fills/Boxes/general.yml @@ -11,7 +11,7 @@ - type: Storage maxItemSize: Small grid: - - 0,0,2,2 + - 0,0,3,3 - type: Sprite state: box - type: EmitSoundOnPickup diff --git a/Resources/Prototypes/Catalog/VendingMachines/Inventories/clothesmate.yml b/Resources/Prototypes/Catalog/VendingMachines/Inventories/clothesmate.yml index ab5187a42c8..a00115525a8 100644 --- a/Resources/Prototypes/Catalog/VendingMachines/Inventories/clothesmate.yml +++ b/Resources/Prototypes/Catalog/VendingMachines/Inventories/clothesmate.yml @@ -1,121 +1,30 @@ - type: vendingMachineInventory id: ClothesMateInventory startingInventory: - ClothingBackpack: 5 - ClothingBackpackDuffel: 5 - ClothingBackpackSatchel: 3 + # STOP! ADD NOTHING TO THIS! GO PUT YOUR CLOTHES IN LOADOUTS INSTEAD! + ClothingBackpack: 2 + ClothingBackpackDuffel: 2 + ClothingBackpackSatchel: 2 ClothingBackpackSatchelLeather: 2 - ClothingRandomSpawner: 8 - ClothingHeadHatBeret: 4 + ClothingRandomSpawner: 6 ClothingHeadBandBlack: 2 - ClothingHeadBandBlue: 2 - ClothingHeadBandGreen: 2 - ClothingHeadBandRed: 2 - ClothingHeadBandSkull: 2 - ClothingHeadHatGreyFlatcap: 3 - ClothingHeadHatBrownFlatcap: 3 - ClothingUniformJumpsuitColorGrey: 8 - ClothingUniformJumpskirtColorGrey: 8 - ClothingUniformJumpsuitColorWhite: 3 - ClothingUniformJumpskirtColorWhite: 3 - ClothingUniformJumpsuitColorBlack: 3 - ClothingUniformJumpskirtColorBlack: 3 - ClothingUniformJumpsuitColorBlue: 2 - ClothingUniformJumpskirtColorBlue: 2 - ClothingUniformJumpsuitColorYellow: 2 - ClothingUniformJumpskirtColorYellow: 2 - ClothingUniformJumpsuitColorGreen: 2 - ClothingUniformJumpskirtColorGreen: 2 - ClothingUniformJumpsuitColorOrange: 2 - ClothingUniformJumpskirtColorOrange: 2 - ClothingUniformJumpsuitColorRed: 2 - ClothingUniformJumpskirtColorRed: 2 - ClothingUniformJumpsuitColorPurple: 2 - ClothingUniformJumpskirtColorPurple: 2 - ClothingUniformJumpsuitColorPink: 2 - ClothingUniformJumpskirtColorPink: 2 - ClothingUniformJumpsuitColorDarkBlue: 2 - ClothingUniformJumpskirtColorDarkBlue: 2 - ClothingUniformJumpsuitColorDarkGreen: 2 - ClothingUniformJumpskirtColorDarkGreen: 2 - ClothingUniformJumpsuitColorTeal: 2 - ClothingUniformJumpskirtColorTeal: 2 - ClothingUniformJumpsuitHawaiBlack: 2 - ClothingUniformJumpsuitHawaiBlue: 2 - ClothingUniformJumpsuitHawaiRed: 2 - ClothingUniformJumpsuitHawaiYellow: 2 - ClothingUniformJumpsuitFlannel: 2 - ClothingUniformJumpsuitCasualBlue: 2 - ClothingUniformJumpskirtCasualBlue: 2 - ClothingUniformJumpsuitCasualPurple: 2 - ClothingUniformJumpskirtCasualPurple: 2 - ClothingUniformJumpsuitCasualRed: 2 - ClothingUniformJumpskirtCasualRed: 2 - ClothingUniformJumpsuitTshirtJeans: 2 # Nyano - Clothing addition - ClothingUniformJumpsuitTshirtJeansGray: 2 # Nyano - Clothing addition - ClothingUniformJumpsuitTshirtJeansPeach: 2 # Nyano - Clothing addition - ClothingUniformJumpsuitJeansGreen: 2 # Nyano - Clothing addition - ClothingUniformJumpsuitJeansRed: 2 # Nyano - Clothing addition - ClothingUniformJumpsuitJeansBrown: 2 # Nyano - Clothing addition - ClothingUniformJumpsuitLostTourist: 2 # Nyano - Clothing addition - ClothingShoesColorBlack: 8 - ClothingShoesColorBrown: 4 - ClothingShoesColorWhite: 3 - ClothingShoesColorBlue: 2 - ClothingShoesColorYellow: 2 - ClothingShoesColorGreen: 2 - ClothingShoesColorOrange: 2 - ClothingShoesColorRed: 2 - ClothingShoesColorPurple: 2 - ClothingHeadHatGreysoft: 8 - ClothingHeadHatMimesoft: 3 - ClothingHeadHatBluesoft: 2 - ClothingHeadHatYellowsoft: 2 - ClothingHeadHatGreensoft: 2 - ClothingHeadHatOrangesoft: 2 - ClothingHeadHatRedsoft: 2 - ClothingHeadHatBlacksoft: 2 - ClothingHeadHatPurplesoft: 2 + ClothingHeadHatGreyFlatcap: 2 + ClothingUniformJumpsuitColorGrey: 2 + ClothingUniformJumpskirtColorGrey: 2 + ClothingShoesColorBlack: 4 + ClothingHeadHatGreysoft: 2 ClothingHeadHatCorpsoft: 2 - ClothingOuterWinterCoat: 2 # Nyano - Clothing addition - ClothingOuterWinterCoatLong: 2 # Nyano - Clothing addition - ClothingOuterWinterCoatPlaid: 2 # Nyano - Clothing addition - ClothingOuterCoatHyenhSweater: 2 # Nyano - Clothing addition - ClothingOuterCoatLettermanBlue: 2 # Nyano - Clothing addition - ClothingOuterCoatLettermanRed: 2 # Nyano - Clothing addition - ClothingOuterDenimJacket: 2 # DeltaV - Clothing addition - ClothingOuterCorporateJacket: 2 # DeltaV - Clothing addition - ClothingOuterCsCorporateJacket: 2 # Einstein Engines - Clothing addition - ClothingOuterEeCorporateJacket: 2 # Einstein Engines - Clothing addition - ClothingOuterHiCorporateJacket: 2 # Einstein Engines - Clothing addition - ClothingOuterHmCorporateJacket: 2 # Einstein Engines - Clothing addition - ClothingOuterIdCorporateJacket: 2 # Einstein Engines - Clothing addition - ClothingOuterZhCorporateJacket: 2 # Einstein Engines - Clothing addition - ClothingOuterGeCorporateJacket: 2 # Einstein Engines - Clothing addition - ClothingOuterFaCorporateJacket: 2 # Einstein Engines - Clothing addition - ClothingOuterDdCorporateJacket: 2 # Einstein Engines - Clothing addition - ClothingOuterBcCorporateJacket: 2 # Einstein Engines - Clothing addition - ClothingLongcoatNT: 2 # Floofstation - ClothingLongcoatAL: 2 # Floofstation - ClothingLongcoatBrown: 2 # Floofstation - ClothingLongcoatBlack: 2 # Floofstation - ClothingShoesBootsFishing: 2 # Nyano - Clothing addition - ClothingHeadTinfoil: 2 # Nyano - Clothing addition - ClothingHeadFishCap: 2 - ClothingHeadRastaHat: 2 + ClothingOuterWinterCoat: 2 + ClothingOuterCorporateJacket: 2 ClothingBeltStorageWaistbag: 3 ClothingEyesGlasses: 6 ClothingHandsGlovesColorBlack: 4 - ClothingHandsGlovesColorGray: 4 - ClothingHandsGlovesColorBrown: 2 - ClothingHandsGlovesColorWhite: 2 - ClothingHandsGlovesColorRed: 2 - ClothingHandsGlovesColorBlue: 2 - ClothingHandsGlovesColorGreen: 2 - ClothingHandsGlovesColorOrange: 2 - ClothingHandsGlovesColorPurple: 2 - ClothingEyesGlassesCheapSunglasses: 3 + ClothingEyesGlassesCheapSunglasses: 2 ClothingUniformLoinCloth: 5 # FloofStation + ClothingLongcoatNT: 2 # Floofstation + ClothingLongcoatAL: 2 # Floofstation + ClothingLongcoatBrown: 2 # Floofstation + ClothingLongcoatBlack: 2 # Floofstation contrabandInventory: ClothingMaskNeckGaiter: 2 ClothingUniformJumpsuitTacticool: 1 diff --git a/Resources/Prototypes/Catalog/VendingMachines/Inventories/sec.yml b/Resources/Prototypes/Catalog/VendingMachines/Inventories/sec.yml index 03eaf44ff36..cdc4bf4e41b 100644 --- a/Resources/Prototypes/Catalog/VendingMachines/Inventories/sec.yml +++ b/Resources/Prototypes/Catalog/VendingMachines/Inventories/sec.yml @@ -14,6 +14,7 @@ ClothingEyesHudSecurity: 2 ClothingEyesEyepatchHudSecurity: 2 ClothingBeltSecurityWebbing: 5 + CombatKnife: 3 Zipties: 12 RiotShield: 2 RiotLaserShield: 2 @@ -21,9 +22,10 @@ ClothingHeadHelmetInsulated: 2 # Nyanotrasen - Insulative headgear ClothingHeadCage: 2 # Nyanotrasen - Insulative headgear ClothingOuterArmorPlateCarrier: 2 # DeltaV - moved body armour from SecDrobe to SecTech - ClothingOuterArmorDuraVest: 2 - ClothingLongcoatSec: 2 # Floofstation + ClothingOuterArmorDuraVest: 2 ClothingHeadHelmetBasic: 2 # DeltaV - added helmets to the SecTech. Another line of defense between the tide and your grey matter. + BreachingCharge: 8 + ClothingLongcoatSec: 2 # Floofstation # security officers need to follow a diet regimen! contrabandInventory: FoodDonutHomer: 12 diff --git a/Resources/Prototypes/DeltaV/Catalog/Fills/Backpacks/StarterGear/backpack.yml b/Resources/Prototypes/DeltaV/Catalog/Fills/Backpacks/StarterGear/backpack.yml index dcde538f9cd..b73c1d5b4fc 100644 --- a/Resources/Prototypes/DeltaV/Catalog/Fills/Backpacks/StarterGear/backpack.yml +++ b/Resources/Prototypes/DeltaV/Catalog/Fills/Backpacks/StarterGear/backpack.yml @@ -18,7 +18,6 @@ components: - type: StorageFill contents: - - id: BoxSurvivalMedical - id: EmergencyRollerBedSpawnFolded - id: BodyBagFolded - id: Portafib @@ -30,7 +29,6 @@ components: - type: StorageFill contents: - - id: BoxSurvivalMedical - id: RubberStampPsychologist @@ -41,5 +39,4 @@ components: - type: StorageFill contents: - - id: BoxSurvival - id: RubberStampLawyer diff --git a/Resources/Prototypes/DeltaV/Catalog/Fills/Backpacks/StarterGear/duffelbag.yml b/Resources/Prototypes/DeltaV/Catalog/Fills/Backpacks/StarterGear/duffelbag.yml index 4aa423e0aed..50ef77a316f 100644 --- a/Resources/Prototypes/DeltaV/Catalog/Fills/Backpacks/StarterGear/duffelbag.yml +++ b/Resources/Prototypes/DeltaV/Catalog/Fills/Backpacks/StarterGear/duffelbag.yml @@ -5,7 +5,6 @@ components: - type: StorageFill contents: - - id: BoxSurvivalMedical - id: EmergencyRollerBedSpawnFolded - id: BodyBagFolded - id: Portafib @@ -17,7 +16,6 @@ components: - type: StorageFill contents: - - id: BoxSurvivalMedical - id: RubberStampPsychologist @@ -28,5 +26,4 @@ components: - type: StorageFill contents: - - id: BoxSurvival - id: RubberStampLawyer diff --git a/Resources/Prototypes/DeltaV/Catalog/Fills/Backpacks/StarterGear/satchel.yml b/Resources/Prototypes/DeltaV/Catalog/Fills/Backpacks/StarterGear/satchel.yml index 1ef1441b3b9..99a770e37e1 100644 --- a/Resources/Prototypes/DeltaV/Catalog/Fills/Backpacks/StarterGear/satchel.yml +++ b/Resources/Prototypes/DeltaV/Catalog/Fills/Backpacks/StarterGear/satchel.yml @@ -5,7 +5,6 @@ components: - type: StorageFill contents: - - id: BoxSurvivalMedical - id: EmergencyRollerBedSpawnFolded - id: BodyBagFolded - id: Portafib @@ -17,7 +16,6 @@ components: - type: StorageFill contents: - - id: BoxSurvivalMedical - id: RubberStampPsychologist @@ -28,5 +26,4 @@ components: - type: StorageFill contents: - - id: BoxSurvival - id: RubberStampLawyer diff --git a/Resources/Prototypes/DeltaV/Entities/Clothing/Back/backpacks.yml/backpacks.yml b/Resources/Prototypes/DeltaV/Entities/Clothing/Back/backpacks.yml/backpacks.yml index 38bbd956868..2fbc17d2585 100644 --- a/Resources/Prototypes/DeltaV/Entities/Clothing/Back/backpacks.yml/backpacks.yml +++ b/Resources/Prototypes/DeltaV/Entities/Clothing/Back/backpacks.yml/backpacks.yml @@ -5,7 +5,6 @@ components: - type: StorageFill contents: - - id: BoxSurvivalSecurity - id: EmergencyRollerBedSpawnFolded - id: BodyBagFolded - id: Portafib diff --git a/Resources/Prototypes/DeltaV/Entities/Clothing/Back/backpacks.yml/duffelbag.yml b/Resources/Prototypes/DeltaV/Entities/Clothing/Back/backpacks.yml/duffelbag.yml index caf5aa3515b..bcd12b5e1b1 100644 --- a/Resources/Prototypes/DeltaV/Entities/Clothing/Back/backpacks.yml/duffelbag.yml +++ b/Resources/Prototypes/DeltaV/Entities/Clothing/Back/backpacks.yml/duffelbag.yml @@ -5,7 +5,6 @@ components: - type: StorageFill contents: - - id: BoxSurvivalSecurity - id: EmergencyRollerBedSpawnFolded - id: BodyBagFolded - id: Portafib diff --git a/Resources/Prototypes/DeltaV/Entities/Clothing/Back/backpacks.yml/satchel.yml b/Resources/Prototypes/DeltaV/Entities/Clothing/Back/backpacks.yml/satchel.yml index 9c27500a1f7..31dc027a21e 100644 --- a/Resources/Prototypes/DeltaV/Entities/Clothing/Back/backpacks.yml/satchel.yml +++ b/Resources/Prototypes/DeltaV/Entities/Clothing/Back/backpacks.yml/satchel.yml @@ -5,7 +5,6 @@ components: - type: StorageFill contents: - - id: BoxSurvivalSecurity - id: EmergencyRollerBedSpawnFolded - id: BodyBagFolded - id: Portafib diff --git a/Resources/Prototypes/DeltaV/Entities/Clothing/Uniforms/jumpsuits.yml b/Resources/Prototypes/DeltaV/Entities/Clothing/Uniforms/jumpsuits.yml index 99021b47e42..8a0a500e6fa 100644 --- a/Resources/Prototypes/DeltaV/Entities/Clothing/Uniforms/jumpsuits.yml +++ b/Resources/Prototypes/DeltaV/Entities/Clothing/Uniforms/jumpsuits.yml @@ -45,8 +45,8 @@ - type: entity parent: ClothingUniformBase id: ClothingUniformJumpsuitSuitBlackMob - name: mobster's attire - description: A crisp red shirt and charcoal slacks. Reminds you of your debts. + name: red suit + description: A crisp red shirt and charcoal slacks. Reminds you of law enforcement. components: - type: Sprite sprite: DeltaV/Clothing/Uniforms/Jumpsuit/suitblackmob.rsi @@ -67,7 +67,7 @@ - type: entity parent: ClothingUniformBase id: ClothingUniformJumpsuitSuitBrownAlt - name: suspicious suit + name: dubious suit description: A crisp grey shirt and chocolate slacks. Reminds you of clandestine operators. components: - type: Sprite @@ -78,8 +78,8 @@ - type: entity parent: ClothingUniformBase id: ClothingUniformJumpsuitSuitBrownMob - name: gangster's attire - description: A crisp red shirt and chocolate slacks. Reminds you of drivebys. + name: mafioso suit + description: A crisp red shirt and chocolate slacks. Reminds you of family. components: - type: Sprite sprite: DeltaV/Clothing/Uniforms/Jumpsuit/suitbrownmob.rsi @@ -111,8 +111,8 @@ - type: entity parent: ClothingUniformBase id: ClothingUniformJumpsuitSuitWhiteMob - name: mafioso's attire - description: A crisp red shirt and ivory slacks. Reminds you of family. + name: gangster suit + description: A crisp red shirt and ivory slacks. Reminds you of organized Japanese crime. components: - type: Sprite sprite: DeltaV/Clothing/Uniforms/Jumpsuit/suitwhitemob.rsi diff --git a/Resources/Prototypes/DeltaV/Entities/Markers/Spawners/ghost_roles.yml b/Resources/Prototypes/DeltaV/Entities/Markers/Spawners/ghost_roles.yml index 1e014aab734..59020f67ca7 100644 --- a/Resources/Prototypes/DeltaV/Entities/Markers/Spawners/ghost_roles.yml +++ b/Resources/Prototypes/DeltaV/Entities/Markers/Spawners/ghost_roles.yml @@ -32,17 +32,17 @@ description: ghost-role-information-listeningop-description rules: ghost-role-information-listeningop-rules requirements: # Worth considering these numbers for the goal of making sure someone willing to MRP takes this. - - !type:OverallPlaytimeRequirement - time: 259200 # 72 hours + - !type:CharacterOverallTimeRequirement + min: 54000 # 15 hours - !type:DepartmentTimeRequirement department: Security - time: 40000 # 11.1 hours + time: 14400 # 4 hours - !type:DepartmentTimeRequirement department: Civilian - time: 40000 # 11.1 hours + time: 14400 # 4 hours - !type:DepartmentTimeRequirement department: Command - time: 40000 # 11.1 hours + time: 14400 # 4 hours - type: GhostRoleMobSpawner prototype: MobHumanSyndicateListener - type: Sprite diff --git a/Resources/Prototypes/DeltaV/Entities/Mobs/Customization/Markings/vulpkanin.yml b/Resources/Prototypes/DeltaV/Entities/Mobs/Customization/Markings/vulpkanin.yml index 502ddf35498..69bbb2bd96d 100644 --- a/Resources/Prototypes/DeltaV/Entities/Mobs/Customization/Markings/vulpkanin.yml +++ b/Resources/Prototypes/DeltaV/Entities/Mobs/Customization/Markings/vulpkanin.yml @@ -280,32 +280,32 @@ state: vulp-fade - type: marking - id: VulpTailTip + id: VulpTailAnimated bodyPart: Tail markingCategory: Tail - speciesRestriction: [Vulpkanin] + speciesRestriction: [] sprites: - sprite: DeltaV/Mobs/Customization/Vulpkanin/tail_markings.rsi - state: vulp + state: vulp_wag - sprite: DeltaV/Mobs/Customization/Vulpkanin/tail_markings.rsi - state: vulp-tip + state: vulp_wag-tip #fade - type: marking - id: VulpTailWag + id: VulpTailTip bodyPart: Tail markingCategory: Tail speciesRestriction: [Vulpkanin] sprites: - sprite: DeltaV/Mobs/Customization/Vulpkanin/tail_markings.rsi - state: vulp_wag + state: vulp - sprite: DeltaV/Mobs/Customization/Vulpkanin/tail_markings.rsi - state: vulp_wag-tip #fade + state: vulp-tip - type: marking - id: VulpTailWagTip + id: VulpTailTipAnimated bodyPart: Tail markingCategory: Tail - speciesRestriction: [Vulpkanin] + speciesRestriction: [] sprites: - sprite: DeltaV/Mobs/Customization/Vulpkanin/tail_markings.rsi state: vulp_wag @@ -357,32 +357,32 @@ state: fox-fade - type: marking - id: VulpTailFoxTip + id: VulpTailFoxAnimated bodyPart: Tail markingCategory: Tail - speciesRestriction: [Vulpkanin] + speciesRestriction: [] sprites: - sprite: DeltaV/Mobs/Customization/Vulpkanin/tail_markings.rsi - state: fox + state: fox_wag - sprite: DeltaV/Mobs/Customization/Vulpkanin/tail_markings.rsi - state: fox-tip + state: fox_wag-fade - type: marking - id: VulpTailFoxWag + id: VulpTailFoxTip bodyPart: Tail markingCategory: Tail speciesRestriction: [Vulpkanin] sprites: - sprite: DeltaV/Mobs/Customization/Vulpkanin/tail_markings.rsi - state: fox_wag + state: fox - sprite: DeltaV/Mobs/Customization/Vulpkanin/tail_markings.rsi - state: fox_wag-fade + state: fox-tip - type: marking - id: VulpTailFoxWagTip + id: VulpTailFoxTipAnimated bodyPart: Tail markingCategory: Tail - speciesRestriction: [Vulpkanin] + speciesRestriction: [] sprites: - sprite: DeltaV/Mobs/Customization/Vulpkanin/tail_markings.rsi state: fox_wag @@ -399,10 +399,10 @@ state: bushfluff - type: marking - id: VulpTailBushyWag + id: VulpTailBushyAnimated bodyPart: Tail markingCategory: Tail - speciesRestriction: [Vulpkanin] + speciesRestriction: [] sprites: - sprite: DeltaV/Mobs/Customization/Vulpkanin/tail_markings.rsi state: bushfluff_wag @@ -417,19 +417,28 @@ state: coyote - type: marking - id: VulpTailCoyoteWag + id: VulpTailCoyoteAnimated bodyPart: Tail markingCategory: Tail - speciesRestriction: [Vulpkanin] + speciesRestriction: [] sprites: - sprite: DeltaV/Mobs/Customization/Vulpkanin/tail_markings.rsi state: coyote_wag - type: marking - id: VulpTailCorgiWag + id: VulpTailCorgi bodyPart: Tail markingCategory: Tail speciesRestriction: [Vulpkanin] + sprites: + - sprite: DeltaV/Mobs/Customization/Vulpkanin/tail_markings.rsi + state: corgi + +- type: marking + id: VulpTailCorgiAnimated + bodyPart: Tail + markingCategory: Tail + speciesRestriction: [] sprites: - sprite: DeltaV/Mobs/Customization/Vulpkanin/tail_markings.rsi state: corgi_wag @@ -502,10 +511,19 @@ state: fluffy - type: marking - id: VulpTailDalmatianWag + id: VulpTailDalmatian bodyPart: Tail markingCategory: Tail speciesRestriction: [Vulpkanin] + sprites: + - sprite: DeltaV/Mobs/Customization/Vulpkanin/tail_markings.rsi + state: dalmatian + +- type: marking + id: VulpTailDalmatianAnimated + bodyPart: Tail + markingCategory: Tail + speciesRestriction: [] sprites: - sprite: DeltaV/Mobs/Customization/Vulpkanin/tail_markings.rsi state: dalmatian_wag diff --git a/Resources/Prototypes/DeltaV/Entities/Mobs/Species/vulpkanin.yml b/Resources/Prototypes/DeltaV/Entities/Mobs/Species/vulpkanin.yml index 9e4f80bfb52..0bcd71fbadb 100644 --- a/Resources/Prototypes/DeltaV/Entities/Mobs/Species/vulpkanin.yml +++ b/Resources/Prototypes/DeltaV/Entities/Mobs/Species/vulpkanin.yml @@ -97,6 +97,7 @@ Female: FemaleVulpkanin Unsexed: MaleVulpkanin - type: DogVision + - type: Wagging - type: LanguageKnowledge speaks: - GalacticCommon diff --git a/Resources/Prototypes/DeltaV/Entities/Objects/Consumable/Food/Containers/lunchbox.yml b/Resources/Prototypes/DeltaV/Entities/Objects/Consumable/Food/Containers/lunchbox.yml index 46e689615b3..c7aae33c76d 100644 --- a/Resources/Prototypes/DeltaV/Entities/Objects/Consumable/Food/Containers/lunchbox.yml +++ b/Resources/Prototypes/DeltaV/Entities/Objects/Consumable/Food/Containers/lunchbox.yml @@ -18,9 +18,9 @@ - type: Storage maxItemSize: Normal grid: - - 0,0,1,1 - - 3,0,1,1 - - 4,0,4,1 + - 0,0,1,2 + - 3,0,1,2 + - 4,0,4,2 - type: PhysicalComposition materialComposition: Plastic: 100 diff --git a/Resources/Prototypes/DeltaV/Roles/Jobs/Medical/medical_borg.yml b/Resources/Prototypes/DeltaV/Roles/Jobs/Medical/medical_borg.yml index e2047d3c200..6b1707b763a 100644 --- a/Resources/Prototypes/DeltaV/Roles/Jobs/Medical/medical_borg.yml +++ b/Resources/Prototypes/DeltaV/Roles/Jobs/Medical/medical_borg.yml @@ -5,11 +5,11 @@ description: job-description-medical-borg playTimeTracker: JobMedicalBorg requirements: - - !type:OverallPlaytimeRequirement - time: 216000 #60 hrs + - !type:CharacterOverallTimeRequirement + min: 21600 #6 hrs floof - !type:DepartmentTimeRequirement department: Medical - time: 21600 #6 hrs + min: 3600 #1 hrs floof canBeAntag: false icon: JobIconMedicalBorg supervisors: job-supervisors-cmo diff --git a/Resources/Prototypes/DeltaV/Roles/Jobs/Security/brigmedic.yml b/Resources/Prototypes/DeltaV/Roles/Jobs/Security/brigmedic.yml index adc6f95dfd4..daf7f1195c0 100644 --- a/Resources/Prototypes/DeltaV/Roles/Jobs/Security/brigmedic.yml +++ b/Resources/Prototypes/DeltaV/Roles/Jobs/Security/brigmedic.yml @@ -6,10 +6,10 @@ requirements: - !type:DepartmentTimeRequirement department: Medical - time: 21600 # 6 hrs + min: 21600 # 6 hrs - !type:DepartmentTimeRequirement department: Security - time: 18000 # 4 hrs + min: 18000 # 4 hrs startingGear: CorpsmanGear icon: "JobIconBrigmedic" supervisors: job-supervisors-hos diff --git a/Resources/Prototypes/DeltaV/Species/vulpkanin.yml b/Resources/Prototypes/DeltaV/Species/vulpkanin.yml index 0b4a06af2d6..8a3cd4c47ce 100644 --- a/Resources/Prototypes/DeltaV/Species/vulpkanin.yml +++ b/Resources/Prototypes/DeltaV/Species/vulpkanin.yml @@ -50,10 +50,10 @@ points: 1 required: false Legs: - points: 1 + points: 6 required: false Arms: - points: 1 + points: 6 required: false Snout: points: 1 diff --git a/Resources/Prototypes/DeltaV/Traits/altvision.yml b/Resources/Prototypes/DeltaV/Traits/altvision.yml index 97742d98ce5..390e14d4ad1 100644 --- a/Resources/Prototypes/DeltaV/Traits/altvision.yml +++ b/Resources/Prototypes/DeltaV/Traits/altvision.yml @@ -1,7 +1,6 @@ - type: trait id: UltraVision category: Visual - points: -1 requirements: - !type:CharacterSpeciesRequirement inverted: true @@ -18,7 +17,6 @@ - type: trait id: DogVision category: Visual - points: -1 requirements: - !type:CharacterSpeciesRequirement inverted: true diff --git a/Resources/Prototypes/Entities/Clothing/Belt/belts.yml b/Resources/Prototypes/Entities/Clothing/Belt/belts.yml index d90945a7eba..359165cfc50 100644 --- a/Resources/Prototypes/Entities/Clothing/Belt/belts.yml +++ b/Resources/Prototypes/Entities/Clothing/Belt/belts.yml @@ -472,6 +472,7 @@ - Sidearm - MagazinePistol - MagazineMagnum + - CombatKnife components: - Stunbaton - FlashOnTrigger diff --git a/Resources/Prototypes/Entities/Clothing/OuterClothing/coats.yml b/Resources/Prototypes/Entities/Clothing/OuterClothing/coats.yml index c78a5f9bdb5..a47a2bbcebc 100644 --- a/Resources/Prototypes/Entities/Clothing/OuterClothing/coats.yml +++ b/Resources/Prototypes/Entities/Clothing/OuterClothing/coats.yml @@ -66,8 +66,8 @@ - type: entity parent: ClothingOuterStorageBase id: ClothingOuterCoatInspector - name: inspector's coat - description: A strict inspector's coat for being intimidating during inspections. + name: slim trench coat + description: A slim minimalist trench coat best worn unbuttoned. components: - type: Sprite sprite: Clothing/OuterClothing/Coats/insp_coat.rsi diff --git a/Resources/Prototypes/Entities/Clothing/OuterClothing/hardsuits.yml b/Resources/Prototypes/Entities/Clothing/OuterClothing/hardsuits.yml index 974da1ebccd..e0d8e7290da 100644 --- a/Resources/Prototypes/Entities/Clothing/OuterClothing/hardsuits.yml +++ b/Resources/Prototypes/Entities/Clothing/OuterClothing/hardsuits.yml @@ -342,6 +342,9 @@ - type: HeldSpeedModifier - type: ToggleableClothing clothingPrototype: ClothingHeadHelmetHardsuitEngineeringWhite + - type: ClothingGrantComponent + component: + - type: SupermatterImmune #Chief Medical Officer's Hardsuit - type: entity diff --git a/Resources/Prototypes/Entities/Markers/Spawners/Random/vending.yml b/Resources/Prototypes/Entities/Markers/Spawners/Random/vending.yml index d55a7916b46..ca68d7df53b 100644 --- a/Resources/Prototypes/Entities/Markers/Spawners/Random/vending.yml +++ b/Resources/Prototypes/Entities/Markers/Spawners/Random/vending.yml @@ -31,4 +31,8 @@ - VendingMachineSoda - VendingMachineStarkist - VendingMachineSpaceUp + - VendingMachineFitness + - VendingMachineHotfood + - VendingMachineSolsnack + - VendingMachineWeeb chance: 1 diff --git a/Resources/Prototypes/Entities/Markers/Spawners/Random/vendingdrinks.yml b/Resources/Prototypes/Entities/Markers/Spawners/Random/vendingdrinks.yml index a911b7ebfc0..1e452098531 100644 --- a/Resources/Prototypes/Entities/Markers/Spawners/Random/vendingdrinks.yml +++ b/Resources/Prototypes/Entities/Markers/Spawners/Random/vendingdrinks.yml @@ -22,4 +22,5 @@ - VendingMachineSoda - VendingMachineStarkist - VendingMachineSpaceUp + - VendingMachineFitness chance: 1 diff --git a/Resources/Prototypes/Entities/Markers/Spawners/ghost_roles.yml b/Resources/Prototypes/Entities/Markers/Spawners/ghost_roles.yml index 3da346cdd65..712dfcf3a06 100644 --- a/Resources/Prototypes/Entities/Markers/Spawners/ghost_roles.yml +++ b/Resources/Prototypes/Entities/Markers/Spawners/ghost_roles.yml @@ -85,8 +85,8 @@ description: ghost-role-information-loneop-description rules: ghost-role-information-loneop-rules requirements: - - !type:OverallPlaytimeRequirement - time: 172800 # DeltaV - 48 hours + - !type:CharacterOverallTimeRequirement + min: 172800 # DeltaV - 48 hours - !type:DepartmentTimeRequirement # DeltaV - Security dept time requirement department: Security time: 36000 # DeltaV - 10 hours diff --git a/Resources/Prototypes/Entities/Mobs/Customization/Markings/makeup.yml b/Resources/Prototypes/Entities/Mobs/Customization/Markings/makeup.yml new file mode 100644 index 00000000000..901bf6e75cf --- /dev/null +++ b/Resources/Prototypes/Entities/Mobs/Customization/Markings/makeup.yml @@ -0,0 +1,87 @@ +- type: marking + id: MakeupLips + bodyPart: Head + markingCategory: Head + speciesRestriction: [Dwarf, Human, SlimePerson, Felinid, Oni, Harpy] # Delta V - Felinid, Oni, Harpy + coloring: + default: + type: + !type:SimpleColoring + color: "#7e2727" + sprites: + - sprite: Mobs/Customization/makeup.rsi + state: lips + +- type: marking + id: MakeupBlush + bodyPart: Head + markingCategory: Head + speciesRestriction: [Dwarf, Human, Reptilian, SlimePerson, Felinid, Oni, Vulpkanin, Harpy] # Delta V - Felinid, Oni, Vulpkanin, Harpy + coloring: + default: + type: + !type:SimpleColoring + color: "#d39394" + sprites: + - sprite: Mobs/Customization/makeup.rsi + state: blush + +- type: marking + id: MakeupNailPolishRight + bodyPart: RHand + markingCategory: Overlay + speciesRestriction: [Dwarf, Human, Reptilian, Arachnid, SlimePerson, Felinid, Oni, Vulpkanin] # Delta V - Felinid, Oni, Vulpkanin + coloring: + default: + type: + !type:SimpleColoring + color: "#702020" + sprites: + - sprite: Mobs/Customization/makeup.rsi + state: nail_polish_r + +- type: marking + id: MakeupNailPolishLeft + bodyPart: LHand + markingCategory: Overlay + speciesRestriction: [Dwarf, Human, Reptilian, Arachnid, SlimePerson, Felinid, Oni, Vulpkanin] # Delta V - Felinid, Oni, Vulpkanin + coloring: + default: + type: + !type:SimpleColoring + color: "#702020" + sprites: + - sprite: Mobs/Customization/makeup.rsi + state: nail_polish_l + +# Moth-specific + +- type: marking + id: MakeupMothLips + bodyPart: Head + markingCategory: Overlay # The marking category is in Overlay instead of Head + # because the Head category for moths only allows 1 + # marking and lips should be usable alongside blush + speciesRestriction: [Moth] + coloring: + default: + type: + !type:SimpleColoring + color: "#7e2727" + sprites: + - sprite: Mobs/Customization/makeup.rsi + state: moth_lips + +- type: marking + id: MakeupMothBlush + bodyPart: Head + markingCategory: Overlay + speciesRestriction: [Moth] + coloring: + default: + type: + !type:SimpleColoring + color: "#d39394" + sprites: + - sprite: Mobs/Customization/makeup.rsi + state: moth_blush diff --git a/Resources/Prototypes/Entities/Mobs/Customization/cyberlimbs/bishop.yml b/Resources/Prototypes/Entities/Mobs/Customization/cyberlimbs/bishop.yml new file mode 100644 index 00000000000..11f4967616b --- /dev/null +++ b/Resources/Prototypes/Entities/Mobs/Customization/cyberlimbs/bishop.yml @@ -0,0 +1,110 @@ +- type: marking + id: CyberLimbsMarkingBishopHead + bodyPart: Head + markingCategory: Head + speciesRestriction: [IPC] + sprites: + - sprite: Mobs/Customization/cyberlimbs/bishop/bishop_monitor.rsi + state: head + - sprite: Mobs/Customization/cyberlimbs/bishop/bishop_monitor.rsi + state: head-2 + +- type: marking + id: CyberLimbsMarkingBishopChest + bodyPart: Chest + markingCategory: Chest + speciesRestriction: [IPC] + sprites: + - sprite: Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi + state: torso-primary + - sprite: Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi + state: torso-secondary + +- type: marking + id: CyberLimbsMarkingBishopLArm + bodyPart: LArm + markingCategory: Arms + speciesRestriction: [IPC, Moth, Dwarf, Human, Arachnid, Felinid, Oni, Vulpkanin, HumanoidFoxes, Reptilian] + sprites: + - sprite: Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi + state: l_arm-primary + - sprite: Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi + state: l_arm-secondary + - sprite: Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi + state: l_arm-tertiary + +- type: marking + id: CyberLimbsMarkingBishopLHand + bodyPart: LHand + markingCategory: Arms + speciesRestriction: [IPC, Moth, Dwarf, Human, Arachnid, Felinid, Oni, Vulpkanin, HumanoidFoxes, Reptilian] + sprites: + - sprite: Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi + state: l_hand + +- type: marking + id: CyberLimbsMarkingBishopLLeg + bodyPart: LLeg + markingCategory: Legs + speciesRestriction: [IPC, Moth, Dwarf, Human, Arachnid, Felinid, Oni, Vulpkanin, HumanoidFoxes, Reptilian] + sprites: + - sprite: Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi + state: l_leg-primary + - sprite: Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi + state: l_leg-secondary + + +- type: marking + id: CyberLimbsMarkingBishopLFoot + bodyPart: LFoot + markingCategory: Legs + speciesRestriction: [IPC, Moth, Dwarf, Human, Arachnid, Felinid, Oni, Vulpkanin, HumanoidFoxes, Reptilian] + sprites: + - sprite: Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi + state: l_foot + + + +- type: marking + id: CyberLimbsMarkingBishopRArm + bodyPart: RArm + markingCategory: Arms + speciesRestriction: [IPC, Moth, Dwarf, Human, Arachnid, Felinid, Oni, Vulpkanin, HumanoidFoxes, Reptilian] + sprites: + - sprite: Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi + state: r_arm-primary + - sprite: Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi + state: r_arm-secondary + - sprite: Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi + state: r_arm-tertiary + + +- type: marking + id: CyberLimbsMarkingBishopRHand + bodyPart: RHand + markingCategory: Arms + speciesRestriction: [IPC, Moth, Dwarf, Human, Arachnid, Felinid, Oni, Vulpkanin, HumanoidFoxes, Reptilian] + sprites: + - sprite: Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi + state: r_hand + +- type: marking + id: CyberLimbsMarkingBishopRLeg + bodyPart: RLeg + markingCategory: Legs + speciesRestriction: [IPC, Moth, Dwarf, Human, Arachnid, Felinid, Oni, Vulpkanin, HumanoidFoxes, Reptilian] + sprites: + - sprite: Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi + state: r_leg-primary + - sprite: Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi + state: r_leg-secondary + + +- type: marking + id: CyberLimbsMarkingBishopRFoot + bodyPart: RFoot + markingCategory: Legs + speciesRestriction: [IPC, Moth, Dwarf, Human, Arachnid, Felinid, Oni, Vulpkanin, HumanoidFoxes, Reptilian] + sprites: + - sprite: Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi + state: r_foot diff --git a/Resources/Prototypes/Entities/Mobs/Customization/cyberlimbs/hesphiastos.yml b/Resources/Prototypes/Entities/Mobs/Customization/cyberlimbs/hesphiastos.yml new file mode 100644 index 00000000000..3103c640034 --- /dev/null +++ b/Resources/Prototypes/Entities/Mobs/Customization/cyberlimbs/hesphiastos.yml @@ -0,0 +1,115 @@ +- type: marking + id: CyberLimbsMarkingHesphiastosHead + bodyPart: Head + markingCategory: Head + speciesRestriction: [IPC] + sprites: + - sprite: Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_monitor.rsi + state: head-1 + - sprite: Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_monitor.rsi + state: head-2 + +- type: marking + id: CyberLimbsMarkingHesphiastosChest + bodyPart: Chest + markingCategory: Chest + speciesRestriction: [IPC] + sprites: + - sprite: Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi + state: torso-1 + - sprite: Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi + state: torso-2 + +- type: marking + id: CyberLimbsMarkingHesphiastosLArm + bodyPart: LArm + markingCategory: Arms + speciesRestriction: [IPC, Moth, Dwarf, Human, Arachnid, Felinid, Oni, Vulpkanin, HumanoidFoxes, Reptilian] + sprites: + - sprite: Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi + state: l_arm-1 + - sprite: Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi + state: l_arm-2 + +- type: marking + id: CyberLimbsMarkingHesphiastosLHand + bodyPart: LHand + markingCategory: Arms + speciesRestriction: [IPC, Moth, Dwarf, Human, Arachnid, Felinid, Oni, Vulpkanin, HumanoidFoxes, Reptilian] + sprites: + - sprite: Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi + state: l_hand-1 + - sprite: Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi + state: l_hand-2 + +- type: marking + id: CyberLimbsMarkingHesphiastosLLeg + bodyPart: LLeg + markingCategory: Legs + speciesRestriction: [IPC, Moth, Dwarf, Human, Arachnid, Felinid, Oni, Vulpkanin, HumanoidFoxes, Reptilian] + sprites: + - sprite: Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi + state: l_leg-1 + - sprite: Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi + state: l_leg-2 + + +- type: marking + id: CyberLimbsMarkingHesphiastosLFoot + bodyPart: LFoot + markingCategory: Legs + speciesRestriction: [IPC, Moth, Dwarf, Human, Arachnid, Felinid, Oni, Vulpkanin, HumanoidFoxes, Reptilian] + sprites: + - sprite: Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi + state: l_foot-1 + - sprite: Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi + state: l_foot-2 + + + +- type: marking + id: CyberLimbsMarkingHesphiastosRArm + bodyPart: RArm + markingCategory: Arms + speciesRestriction: [IPC, Moth, Dwarf, Human, Arachnid, Felinid, Oni, Vulpkanin, HumanoidFoxes, Reptilian] + sprites: + - sprite: Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi + state: r_arm-1 + - sprite: Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi + state: r_arm-2 + + +- type: marking + id: CyberLimbsMarkingHesphiastosRHand + bodyPart: RHand + markingCategory: Arms + speciesRestriction: [IPC, Moth, Dwarf, Human, Arachnid, Felinid, Oni, Vulpkanin, HumanoidFoxes, Reptilian] + sprites: + - sprite: Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi + state: r_hand-1 + - sprite: Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi + state: r_hand-2 + + +- type: marking + id: CyberLimbsMarkingHesphiastosRLeg + bodyPart: RLeg + markingCategory: Legs + speciesRestriction: [IPC, Moth, Dwarf, Human, Arachnid, Felinid, Oni, Vulpkanin, HumanoidFoxes, Reptilian] + sprites: + - sprite: Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi + state: r_leg-1 + - sprite: Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi + state: r_leg-2 + + +- type: marking + id: CyberLimbsMarkingHesphiastosRFoot + bodyPart: RFoot + markingCategory: Legs + speciesRestriction: [IPC, Moth, Dwarf, Human, Arachnid, Felinid, Oni, Vulpkanin, HumanoidFoxes, Reptilian] + sprites: + - sprite: Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi + state: r_foot-1 + - sprite: Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi + state: r_foot-2 diff --git a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml index eba1253dde4..9ff9837a3b9 100644 --- a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml +++ b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml @@ -223,7 +223,6 @@ understands: - GalacticCommon - RobotTalk - - type: CanWalk - type: entity id: BaseBorgChassisNT diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml b/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml index 7f3b1cae588..29234ea34cf 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml @@ -1313,7 +1313,6 @@ tags: - VimPilot - DoorBumpOpener - - type: CanWalk - type: entity name: monkey @@ -2442,6 +2441,12 @@ - type: Tag tags: - VimPilot + - type: LanguageKnowledge + speaks: + - Hissing + understands: + - Hissing + - type: entity name: possum @@ -2519,6 +2524,11 @@ - type: Tag tags: - VimPilot + - type: LanguageKnowledge + speaks: + - Hissing + understands: + - Hissing - type: entity name: fox @@ -2886,9 +2896,9 @@ - Syndicate - type: LanguageKnowledge speaks: - - Xeno + - Cat understands: - - Xeno + - Cat - GalacticCommon - type: entity @@ -3060,6 +3070,11 @@ barkMultiplier: 10 barks: - Sloth + - type: LanguageKnowledge # WHAT DOES THE SLOTH SAY??????? + speaks: + - Hissing + understands: + - Hissing - type: entity name: ferret @@ -3119,6 +3134,11 @@ - type: Tag tags: - VimPilot + - type: LanguageKnowledge + speaks: + - Hissing + understands: + - Hissing - type: entity name: hamster diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/elemental.yml b/Resources/Prototypes/Entities/Mobs/NPCs/elemental.yml index d209ff806ce..b1d037f756d 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/elemental.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/elemental.yml @@ -299,13 +299,6 @@ solution: bloodstream - type: DrainableSolution solution: bloodstream - - type: PotentialPsionic - - type: Psionic - removable: false - amplification: 1 - psychicFeedback: - - "reagent-slime-feedback" - - type: CanWalk - type: entity name: Reagent Slime Spawner diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/regalrat.yml b/Resources/Prototypes/Entities/Mobs/NPCs/regalrat.yml index 41154dc931b..cf563989bf5 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/regalrat.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/regalrat.yml @@ -125,7 +125,6 @@ understands: - GalacticCommon - Mouse - - type: CanWalk - type: entity id: MobRatKingBuff diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/slimes.yml b/Resources/Prototypes/Entities/Mobs/NPCs/slimes.yml index 3735bcc4eca..fbf133a0f1e 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/slimes.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/slimes.yml @@ -128,7 +128,6 @@ speechSounds: Slime - type: TypingIndicator proto: slime - - type: CanWalk - type: entity name: blue slime diff --git a/Resources/Prototypes/Entities/Mobs/Player/admin_ghost.yml b/Resources/Prototypes/Entities/Mobs/Player/admin_ghost.yml index 6291fd23335..6c9ec2049f4 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/admin_ghost.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/admin_ghost.yml @@ -95,6 +95,7 @@ - type: InventorySlots - type: Loadout prototypes: [ MobAghostGear ] + - type: SupermatterImmune - type: entity id: ActionAGhostShowSolar diff --git a/Resources/Prototypes/Entities/Mobs/Species/base.yml b/Resources/Prototypes/Entities/Mobs/Species/base.yml index 1b9e9674f44..c4906f6f975 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/base.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/base.yml @@ -229,7 +229,6 @@ - CanPilot - FootstepSound - DoorBumpOpener - - type: CanWalk - type: entity save: false diff --git a/Resources/Prototypes/Entities/Mobs/Species/harpy.yml b/Resources/Prototypes/Entities/Mobs/Species/harpy.yml index b265d9343a3..05d70e8adc5 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/harpy.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/harpy.yml @@ -119,8 +119,8 @@ False: {visible: false} True: {visible: true} - type: MovementSpeedModifier - baseWalkSpeed: 2.5 - baseSprintSpeed: 5.0 + baseWalkSpeed: 3 + baseSprintSpeed: 5.5 weightlessAcceleration: 2.5 - type: Inventory speciesId: harpy @@ -140,7 +140,6 @@ understands: - GalacticCommon - SolCommon - - type: entity save: false name: Urist McHands diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks.yml b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks.yml index cfe5294ff05..93d4b957fe7 100644 --- a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks.yml +++ b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks.yml @@ -34,11 +34,20 @@ - key: enum.TransferAmountUiKey.Key type: TransferAmountBoundUserInterface - type: EmitSoundOnPickup - sound: /Audio/SimpleStation14/Items/Handling/drinkglass_pickup.ogg + sound: + path: /Audio/SimpleStation14/Items/Handling/drinkglass_pickup.ogg + params: + volume: -2 - type: EmitSoundOnDrop - sound: /Audio/SimpleStation14/Items/Handling/drinkglass_drop.ogg + sound: + path: /Audio/SimpleStation14/Items/Handling/drinkglass_drop.ogg + params: + volume: -2 - type: EmitSoundOnLand - sound: /Audio/SimpleStation14/Items/Handling/drinkglass_drop.ogg + sound: + path: /Audio/SimpleStation14/Items/Handling/drinkglass_drop.ogg + params: + volume: -2 - type: entity parent: DrinkBase diff --git a/Resources/Prototypes/Entities/Objects/Devices/translators.yml b/Resources/Prototypes/Entities/Objects/Devices/translators.yml index 5a605122244..85b61de1f24 100644 --- a/Resources/Prototypes/Entities/Objects/Devices/translators.yml +++ b/Resources/Prototypes/Entities/Objects/Devices/translators.yml @@ -216,6 +216,7 @@ - Crab - Kobold - ScugSign + - Hissing requires: - GalacticCommon setLanguageOnInteract: false diff --git a/Resources/Prototypes/Entities/Objects/Materials/bluespace.yml b/Resources/Prototypes/Entities/Objects/Materials/bluespace.yml new file mode 100644 index 00000000000..f93534ecd5c --- /dev/null +++ b/Resources/Prototypes/Entities/Objects/Materials/bluespace.yml @@ -0,0 +1,56 @@ +- type: entity + parent: MaterialBase + id: MaterialBluespace + suffix: Full + name: bluespace crystal + components: + - type: Sprite + sprite: Nyanotrasen/Objects/Materials/materials.rsi + layers: + - state: bluespace_3 + map: ["base"] + - type: Appearance + - type: Material + - type: PhysicalComposition + materialComposition: + Bluespace: 100 + - type: Tag + tags: + - BluespaceCrystal + - RawMaterial + - type: Stack + stackType: Bluespace + baseLayer: base + layerStates: + - bluespace + - bluespace_2 + - bluespace_3 + count: 5 + - type: Item + size: Small + +- type: entity + parent: MaterialBluespace + id: MaterialBluespace1 + suffix: 1 + components: + - type: Sprite + state: bluespace + - type: Stack + count: 1 + +- type: entity + parent: MaterialBluespace1 + id: MaterialBluespace3 + suffix: 3 + components: + - type: Stack + count: 3 + +- type: entity + parent: MaterialBluespace1 + id: MaterialBluespace5 + suffix: 5 + components: + - type: Stack + count: 5 diff --git a/Resources/Prototypes/Entities/Objects/Misc/supermatter_sliver.yml b/Resources/Prototypes/Entities/Objects/Misc/supermatter_sliver.yml new file mode 100644 index 00000000000..d62935523d5 --- /dev/null +++ b/Resources/Prototypes/Entities/Objects/Misc/supermatter_sliver.yml @@ -0,0 +1,25 @@ +- type: entity + parent: BaseItem + id: SupermatterSliver + name: supermatter sliver + description: A shard from the station's Supermatter crystal. Highly radioactive. + components: + - type: PointLight + enabled: true + radius: 3 + energy: 2 + color: "#fff633" + - type: RadiationSource + intensity: .75 + - type: Icon + sprite: Supermatter/supermatter_sliver.rsi + state: icon + - type: Sprite + sprite: Supermatter/supermatter_sliver.rsi + state: icon + - type: StealTarget + stealGroup: SupermatterSliver + - type: Tag + tags: + - HighRiskItem + - type: SupermatterImmune diff --git a/Resources/Prototypes/Entities/Objects/Specific/Mech/mechs.yml b/Resources/Prototypes/Entities/Objects/Specific/Mech/mechs.yml index 471801f3a1f..6e5362d9bbb 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/Mech/mechs.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/Mech/mechs.yml @@ -92,7 +92,6 @@ - type: GuideHelp guides: - Robotics - - type: CanWalk - type: entity id: MechRipley diff --git a/Resources/Prototypes/Entities/Objects/Specific/Medical/medkits.yml b/Resources/Prototypes/Entities/Objects/Specific/Medical/medkits.yml index d7f2231ec99..62e5ab44762 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/Medical/medkits.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/Medical/medkits.yml @@ -10,7 +10,7 @@ - type: Storage maxItemSize: Small grid: - - 0,0,3,1 + - 0,0,3,2 - type: Item size: Large sprite: Objects/Specific/Medical/firstaidkits.rsi diff --git a/Resources/Prototypes/Entities/Objects/Specific/Medical/morgue.yml b/Resources/Prototypes/Entities/Objects/Specific/Medical/morgue.yml index 8f54bb8059c..da67b5a5928 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/Medical/morgue.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/Medical/morgue.yml @@ -130,6 +130,7 @@ solution: food - type: Extractable grindableSolutionName: food + - type: SupermatterImmune - type: entity parent: Ash diff --git a/Resources/Prototypes/Entities/Objects/Specific/Research/disk.yml b/Resources/Prototypes/Entities/Objects/Specific/Research/disk.yml index fa1b75530b6..862716c5123 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/Research/disk.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/Research/disk.yml @@ -36,6 +36,15 @@ - type: ResearchDisk points: 10000 +- type: entity + parent: ResearchDisk + id: ResearchDisk20000 + name: research point disk (20000) + description: A disk for the R&D server containing 20000 points. + components: + - type: ResearchDisk + points: 20000 + - type: entity parent: ResearchDisk id: ResearchDiskDebug diff --git a/Resources/Prototypes/Entities/Objects/Tools/tools.yml b/Resources/Prototypes/Entities/Objects/Tools/tools.yml index 9ac46dbe305..d135b2f29bb 100644 --- a/Resources/Prototypes/Entities/Objects/Tools/tools.yml +++ b/Resources/Prototypes/Entities/Objects/Tools/tools.yml @@ -5,12 +5,20 @@ description: This kills the wire. components: - type: EmitSoundOnPickup - sound: /Audio/SimpleStation14/Items/Handling/wirecutter_pickup.ogg + sound: + path: /Audio/SimpleStation14/Items/Handling/wirecutter_pickup.ogg + params: + volume: -2 - type: EmitSoundOnDrop - sound: /Audio/SimpleStation14/Items/Handling/wirecutter_drop.ogg + sound: + path: /Audio/SimpleStation14/Items/Handling/wirecutter_drop.ogg + params: + volume: -2 - type: EmitSoundOnLand sound: path: /Audio/Items/wirecutter_drop.ogg + params: + volume: -2 - type: Tag tags: - PlantSampleTaker @@ -55,12 +63,20 @@ description: Industrial grade torque in a small screwdriving package. components: - type: EmitSoundOnPickup - sound: /Audio/SimpleStation14/Items/Handling/screwdriver_pickup.ogg + sound: + path: /Audio/SimpleStation14/Items/Handling/screwdriver_pickup.ogg + params: + volume: -2 - type: EmitSoundOnDrop - sound: /Audio/SimpleStation14/Items/Handling/screwdriver_drop.ogg + sound: + path: /Audio/SimpleStation14/Items/Handling/screwdriver_drop.ogg + params: + volume: -2 - type: EmitSoundOnLand sound: path: /Audio/Items/screwdriver_drop.ogg + params: + volume: -2 - type: Tag tags: - Screwdriver @@ -103,12 +119,20 @@ description: 'A common tool for assembly and disassembly. Remember: righty tighty, lefty loosey.' components: - type: EmitSoundOnPickup - sound: /Audio/SimpleStation14/Items/Handling/wrench_pickup.ogg + sound: + path: /Audio/SimpleStation14/Items/Handling/wrench_pickup.ogg + params: + volume: -2 - type: EmitSoundOnDrop - sound: /Audio/SimpleStation14/Items/Handling/wrench_drop.ogg + sound: + path: /Audio/SimpleStation14/Items/Handling/wrench_drop.ogg + params: + volume: -2 - type: EmitSoundOnLand sound: path: /Audio/Items/wrench_drop.ogg + params: + volume: -2 - type: Tag tags: - Wrench @@ -146,12 +170,20 @@ description: A multipurpose tool to pry open doors and fight interdimensional invaders. components: - type: EmitSoundOnPickup - sound: /Audio/SimpleStation14/Items/Handling/crowbar_pickup.ogg + sound: + path: /Audio/SimpleStation14/Items/Handling/crowbar_pickup.ogg + params: + volume: -2 - type: EmitSoundOnDrop - sound: /Audio/SimpleStation14/Items/Handling/crowbar_drop.ogg + sound: + path: /Audio/SimpleStation14/Items/Handling/crowbar_drop.ogg + params: + volume: -2 - type: EmitSoundOnLand sound: path: /Audio/Items/crowbar_drop.ogg + params: + volume: -2 - type: Tag tags: - Crowbar diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Bombs/plastic.yml b/Resources/Prototypes/Entities/Objects/Weapons/Bombs/plastic.yml index 62f81fa5466..b39c8af9b25 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Bombs/plastic.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Bombs/plastic.yml @@ -1,4 +1,4 @@ -- type: entity +- type: entity id: BasePlasticExplosive parent: BaseItem abstract: true @@ -106,3 +106,32 @@ maxIntensity: 30 canCreateVacuum: false - type: ExplodeOnTrigger + +- type: entity + name: breaching charge + description: A breaching explosive for security officers to break through walls. + parent: SeismicCharge + id: BreachingCharge + components: + - type: Sprite + sprite: Objects/Weapons/Bombs/breaching.rsi + state: icon + layers: + - state: icon + map: ["base"] + - type: OnUseTimerTrigger + delay: 10 + delayOptions: [10, 15, 20, 25] + initialBeepDelay: 0 + beepSound: + path: /Audio/Effects/Cargo/buzz_two.ogg + params: + volume: -6 + startOnStick: true + canToggleStartOnStick: true + - type: Explosive + explosionType: DemolitionCharge + totalIntensity: 10 + intensitySlope: 10 + maxIntensity: 10 + canCreateVacuum: false diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Battery/battery_guns.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Battery/battery_guns.yml index fb2f56a6ed6..ec0a0a148bd 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Battery/battery_guns.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Battery/battery_guns.yml @@ -21,6 +21,7 @@ fireOnDropChance: 0.15 soundGunshot: path: /Audio/Weapons/Guns/Gunshots/laser.ogg + doRecoil: false - type: Battery maxCharge: 1000 startingCharge: 1000 @@ -48,6 +49,7 @@ - SemiAuto soundGunshot: path: /Audio/Weapons/Guns/Gunshots/laser.ogg + doRecoil: false - type: MagazineAmmoProvider - type: ItemSlots slots: diff --git a/Resources/Prototypes/Entities/Objects/base_item.yml b/Resources/Prototypes/Entities/Objects/base_item.yml index 55c4bbd6b79..84b5477f508 100644 --- a/Resources/Prototypes/Entities/Objects/base_item.yml +++ b/Resources/Prototypes/Entities/Objects/base_item.yml @@ -14,8 +14,6 @@ - type: EmitSoundOnLand sound: path: /Audio/Effects/drop.ogg - params: - volume: 2 - type: DamageOnHighSpeedImpact damage: types: diff --git a/Resources/Prototypes/Entities/Structures/Doors/Airlocks/easy_pry.yml b/Resources/Prototypes/Entities/Structures/Doors/Airlocks/easy_pry.yml deleted file mode 100644 index 04a58eebe07..00000000000 --- a/Resources/Prototypes/Entities/Structures/Doors/Airlocks/easy_pry.yml +++ /dev/null @@ -1,63 +0,0 @@ -- type: entity - parent: AirlockExternal - id: AirlockExternalEasyPry - suffix: External, EasyPry - description: It opens, it closes, it might crush you, and there might be only space behind it. Has to be manually activated. Has a valve labelled "TURN TO OPEN" - components: - - type: PryUnpowered - -- type: entity - parent: AirlockExternalGlass - id: AirlockExternalGlassEasyPry - suffix: External, Glass, EasyPry - description: It opens, it closes, it might crush you, and there might be only space behind it. Has to be manually activated. Has a valve labelled "TURN TO OPEN" - components: - - type: PryUnpowered - -- type: entity - parent: AirlockGlassShuttle - id: AirlockGlassShuttleEasyPry - suffix: EasyPry, Docking - description: Necessary for connecting two space craft together. Has a valve labelled "TURN TO OPEN" - components: - - type: PryUnpowered - -- type: entity - parent: AirlockShuttle - id: AirlockShuttleEasyPry - suffix: EasyPry, Docking - description: Necessary for connecting two space craft together. Has a valve labelled "TURN TO OPEN" - components: - - type: PryUnpowered - -- type: entity - parent: AirlockExternalLocked - id: AirlockExternalEasyPryLocked - suffix: External, EasyPry, Locked - description: It opens, it closes, it might crush you, and there might be only space behind it. Has to be manually activated. Has a valve labelled "TURN TO OPEN" - components: - - type: PryUnpowered - -- type: entity - parent: AirlockExternalGlassLocked - id: AirlockExternalGlassEasyPryLocked - suffix: External, Glass, EasyPry, Locked - description: It opens, it closes, it might crush you, and there might be only space behind it. Has to be manually activated. Has a valve labelled "TURN TO OPEN" - components: - - type: PryUnpowered - -- type: entity - parent: AirlockExternalGlassShuttleLocked - id: AirlockGlassShuttleEasyPryLocked - suffix: EasyPry, Docking, Locked - description: Necessary for connecting two space craft together. Has a valve labelled "TURN TO OPEN" - components: - - type: PryUnpowered - -- type: entity - parent: AirlockExternalShuttleLocked - id: AirlockShuttleEasyPryLocked - suffix: EasyPry, Docking, Locked - description: Necessary for connecting two space craft together. Has a valve labelled "TURN TO OPEN" - components: - - type: PryUnpowered diff --git a/Resources/Prototypes/Entities/Structures/Furniture/dresser.yml b/Resources/Prototypes/Entities/Structures/Furniture/dresser.yml index 2caa4010ca0..6c50b334091 100644 --- a/Resources/Prototypes/Entities/Structures/Furniture/dresser.yml +++ b/Resources/Prototypes/Entities/Structures/Furniture/dresser.yml @@ -51,6 +51,8 @@ parent: Dresser suffix: Filled components: + - type: StaticPrice + price: 5 - type: StorageFill contents: - id: ClothingNeckLGBTPin diff --git a/Resources/Prototypes/Entities/Structures/Machines/Computers/base_structurecomputers.yml b/Resources/Prototypes/Entities/Structures/Machines/Computers/base_structurecomputers.yml index 204e06c8600..b7ea7c6f6ca 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/Computers/base_structurecomputers.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/Computers/base_structurecomputers.yml @@ -61,3 +61,12 @@ - type: LightningTarget priority: 1 - type: RequireProjectileTarget + - type: LanguageSpeaker + currentLanguage: GalacticCommon + - type: LanguageKnowledge + speaks: + - GalacticCommon + - RobotTalk + understands: + - GalacticCommon + - RobotTalk diff --git a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml index 418a09b876c..0f615b20c58 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml @@ -170,6 +170,7 @@ - ShellTranquilizer - CartridgeLightRifle - CartridgeRifle + - CombatKnife - MagazineBoxPistol - MagazineBoxMagnum - MagazineBoxRifle @@ -707,6 +708,7 @@ runningState: icon staticRecipes: - ClothingEyesHudSecurity + - CombatKnife - Flash - Handcuffs - Zipties diff --git a/Resources/Prototypes/Entities/Structures/Machines/vending_machines.yml b/Resources/Prototypes/Entities/Structures/Machines/vending_machines.yml index fcc6e4974c1..02cdd80af35 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/vending_machines.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/vending_machines.yml @@ -322,7 +322,7 @@ parent: VendingMachine id: VendingMachineClothing name: ClothesMate - description: A vending machine for clothing. + description: A vending machine for dispensing the cheapest clothing Nanotrasen can buy. components: - type: VendingMachine pack: ClothesMateInventory diff --git a/Resources/Prototypes/Entities/Structures/Power/Generation/Singularity/singularity.yml b/Resources/Prototypes/Entities/Structures/Power/Generation/Singularity/singularity.yml index 25d219ab945..b8d66c61e38 100644 --- a/Resources/Prototypes/Entities/Structures/Power/Generation/Singularity/singularity.yml +++ b/Resources/Prototypes/Entities/Structures/Power/Generation/Singularity/singularity.yml @@ -3,6 +3,7 @@ name: gravitational singularity description: A mesmerizing swirl of darkness that sucks in everything. If it's moving towards you, run. components: + - type: SupermatterImmune - type: Clickable - type: AmbientSound volume: -4 diff --git a/Resources/Prototypes/Entities/Structures/Power/Generation/Supermatter/supermatter.yml b/Resources/Prototypes/Entities/Structures/Power/Generation/Supermatter/supermatter.yml new file mode 100644 index 00000000000..6fc3429600a --- /dev/null +++ b/Resources/Prototypes/Entities/Structures/Power/Generation/Supermatter/supermatter.yml @@ -0,0 +1,66 @@ +- type: entity + id: Supermatter + name: supermatter crystal + description: A strangely translucent and iridescent crystal. + placement: + mode: SnapgridCenter + components: + - type: Supermatter + - type: RadiationSource + - type: AmbientSound + range: 5 + volume: 0 + sound: + path: /Audio/Supermatter/calm.ogg + - type: Physics + - type: Speech + speechSounds: Pai + - type: Fixtures + fixtures: + fix1: + shape: + !type:PhysShapeAabb + bounds: "-0.25,-0.25,0.25,0.25" + mask: + - Impassable + - MidImpassable + - HighImpassable + - LowImpassable + - InteractImpassable + - Opaque + layer: + - MidImpassable + - HighImpassable + - BulletImpassable + - InteractImpassable + - type: Transform + anchored: true + noRot: true + - type: CollisionWake + enabled: false + - type: Clickable + - type: InteractionOutline + - type: Sprite + drawdepth: WallMountedItems + sprite: Supermatter/supermatter.rsi + state: supermatter + - type: Icon + sprite: Supermatter/supermatter.rsi + state: supermatter + - type: PointLight + enabled: true + radius: 10 + energy: 5 + color: "#ffe000" + - type: Explosive + explosionType: Supermatter + maxIntensity: 25000 + intensitySlope: 5 + totalIntensity: 25000 + - type: GuideHelp + guides: [ Supermatter, Power ] + - type: WarpPoint + follow: true + location: supermatter + - type: SinguloFood + energy: 10000 \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/coil.yml b/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/coil.yml index 48994ac7d84..55a22a59a58 100644 --- a/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/coil.yml +++ b/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/coil.yml @@ -5,6 +5,7 @@ placement: mode: SnapgridCenter components: + - type: SupermatterImmune - type: Transform anchored: true - type: Physics @@ -110,6 +111,7 @@ placement: mode: SnapgridCenter components: + - type: SupermatterImmune - type: Transform anchored: true - type: Physics diff --git a/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/energyball.yml b/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/energyball.yml index ea41ba3a20d..1cfdb9256a5 100644 --- a/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/energyball.yml +++ b/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/energyball.yml @@ -2,6 +2,7 @@ id: BaseEnergyBall abstract: true components: + - type: SupermatterImmune - type: Clickable - type: Physics bodyType: KinematicController diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Structures/Research/oracle.yml b/Resources/Prototypes/Entities/Structures/Specific/oracle.yml similarity index 56% rename from Resources/Prototypes/Nyanotrasen/Entities/Structures/Research/oracle.yml rename to Resources/Prototypes/Entities/Structures/Specific/oracle.yml index 8470737c702..754ab82c00c 100644 --- a/Resources/Prototypes/Nyanotrasen/Entities/Structures/Research/oracle.yml +++ b/Resources/Prototypes/Entities/Structures/Specific/oracle.yml @@ -13,7 +13,6 @@ - state: oracle-0 - map: ["enum.SolutionContainerLayers.Fill"] state: oracle-0 - - type: Oracle - type: Speech speechSounds: Tenor - type: PotentialPsionic @@ -45,6 +44,46 @@ - type: SpriteFade - type: Tag tags: [] - - type: GuideHelp - guides: - - Psionics + - type: Oracle + demandTypes: OracleDemandTypes + rewardReagents: OracleRewardReagents + rewardEntities: + - OracleRewardDisks + - OracleRewardCrystals + demandBlacklist: + tags: + - Bluespace + components: + - MobState + demandWhitelist: + components: + - Item + + +- type: weightedRandomEntity + id: OracleRewardDisks + weights: + ResearchDisk5000: 20 + ResearchDisk10000: 5 + ResearchDisk20000: 1 + +- type: weightedRandomEntity + id: OracleRewardCrystals + weights: + MaterialBluespace1: 3 + MaterialBluespace3: 10 + MaterialBluespace5: 2 + +- type: weightedRandom + id: OracleRewardReagents + weights: + LotophagoiOil: 7 + Ichor: 2 + Wine: 1.2 + Blood: 0.8 + +- type: weightedRandom + id: OracleDemandTypes + weights: + tech: 3 + plant: 1 # Plants are very annoying to procure most of the time diff --git a/Resources/Prototypes/Entities/Structures/Storage/Closets/base_structureclosets.yml b/Resources/Prototypes/Entities/Structures/Storage/Closets/base_structureclosets.yml index 23b1efdf535..e966a41780c 100644 --- a/Resources/Prototypes/Entities/Structures/Storage/Closets/base_structureclosets.yml +++ b/Resources/Prototypes/Entities/Structures/Storage/Closets/base_structureclosets.yml @@ -50,8 +50,12 @@ - type: EntityStorage closeSound: path: /Audio/Effects/closet_close.ogg + params: + volume: -4 openSound: path: /Audio/Effects/closet_open.ogg + params: + volume: -4 - type: ContainerContainer containers: entity_storage: !type:Container diff --git a/Resources/Prototypes/GameRules/roundstart.yml b/Resources/Prototypes/GameRules/roundstart.yml index e046b871fa7..0af55a7f9d0 100644 --- a/Resources/Prototypes/GameRules/roundstart.yml +++ b/Resources/Prototypes/GameRules/roundstart.yml @@ -132,21 +132,15 @@ components: - type: RampingStationEventScheduler -- type: entity - id: LongSurvivalStationEventScheduler - parent: BaseGameRule - noSpawn: true - components: - - type: RampingStationEventScheduler - shiftLengthOffset: -120 - - type: entity id: HellshiftStationEventScheduler parent: BaseGameRule noSpawn: true components: - type: RampingStationEventScheduler - shiftChaosModifier: 4 #30 minute HELL SHIFT + chaosModifier: 4 # By default, one event each 30-10 seconds after two hours. Changing CVars will cause this to deviate. + startingChaosRatio: 0.025 # Starts as slow as survival, but quickly ramps up + shiftLengthModifier: 2.5 # variation passes - type: entity diff --git a/Resources/Prototypes/Guidebook/engineering.yml b/Resources/Prototypes/Guidebook/engineering.yml index 21d17f02279..e08d46276cd 100644 --- a/Resources/Prototypes/Guidebook/engineering.yml +++ b/Resources/Prototypes/Guidebook/engineering.yml @@ -66,6 +66,7 @@ - Singularity - TEG - RTG + - Supermatter - type: guideEntry id: AME @@ -91,3 +92,8 @@ id: PortableGenerator name: guide-entry-portable-generator text: "/ServerInfo/Guidebook/Engineering/PortableGenerator.xml" + +- type: guideEntry + id: Supermatter + name: guide-entry-sm + text: "/ServerInfo/Guidebook/Engineering/Supermatter.xml" diff --git a/Resources/Prototypes/Language/languages.yml b/Resources/Prototypes/Language/languages.yml index 837a792b78b..59764f99835 100644 --- a/Resources/Prototypes/Language/languages.yml +++ b/Resources/Prototypes/Language/languages.yml @@ -39,7 +39,7 @@ - type: language id: Bubblish speech: - color: "#0077aa" + color: "#00a3e2dd" fontId: RubikBubbles obfuscation: !type:SyllableObfuscation @@ -56,7 +56,7 @@ - type: language id: Moffic speech: - color: "#869b29" + color: "#c7df2edd" fontId: Copperplate obfuscation: !type:SyllableObfuscation @@ -125,7 +125,7 @@ - type: language id: RootSpeak speech: - color: "#804000" + color: "#ce5e14dd" fontId: Noganas obfuscation: !type:SyllableObfuscation @@ -142,7 +142,7 @@ - type: language id: Nekomimetic speech: - color: "#803B56" + color: "#df57aaee" fontId: Manga obfuscation: !type:SyllableObfuscation @@ -202,7 +202,7 @@ - type: language id: Draconic speech: - color: "#228b22" + color: "#2aca2add" obfuscation: !type:SyllableObfuscation minSyllables: 2 @@ -297,7 +297,7 @@ - type: language id: Canilunzt speech: - color: "#b97a57" + color: "#d69b3dcc" obfuscation: !type:SyllableObfuscation minSyllables: 1 @@ -365,7 +365,7 @@ - type: language id: SolCommon speech: - color: "#8282fb" + color: "#8282fbaa" obfuscation: !type:SyllableObfuscation minSyllables: 1 @@ -576,6 +576,18 @@ - ss - ee +- type: language + id: Hissing + obfuscation: + !type:SyllableObfuscation + minSyllables: 2 + maxSyllables: 4 + replacement: + - hss + - iss + - ss + - is + # Example of a sign language. Not currently used anyhow. - type: language id: Sign diff --git a/Resources/Prototypes/Loadouts/Jobs/Heads/captain.yml b/Resources/Prototypes/Loadouts/Jobs/Heads/captain.yml index d8849472ff4..d77dabf557c 100644 --- a/Resources/Prototypes/Loadouts/Jobs/Heads/captain.yml +++ b/Resources/Prototypes/Loadouts/Jobs/Heads/captain.yml @@ -130,6 +130,11 @@ cost: 1 exclusive: true requirements: + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Diona + - Harpy - !type:CharacterJobRequirement jobs: - Captain diff --git a/Resources/Prototypes/Loadouts/Jobs/Heads/chiefEngineer.yml b/Resources/Prototypes/Loadouts/Jobs/Heads/chiefEngineer.yml index c4905591124..4de22bc9593 100644 --- a/Resources/Prototypes/Loadouts/Jobs/Heads/chiefEngineer.yml +++ b/Resources/Prototypes/Loadouts/Jobs/Heads/chiefEngineer.yml @@ -39,6 +39,11 @@ cost: 1 exclusive: true requirements: + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Diona + - Harpy - !type:CharacterJobRequirement jobs: - ChiefEngineer diff --git a/Resources/Prototypes/Loadouts/Jobs/Heads/chiefMedicalOfficer.yml b/Resources/Prototypes/Loadouts/Jobs/Heads/chiefMedicalOfficer.yml index c75c871b011..163bad29261 100644 --- a/Resources/Prototypes/Loadouts/Jobs/Heads/chiefMedicalOfficer.yml +++ b/Resources/Prototypes/Loadouts/Jobs/Heads/chiefMedicalOfficer.yml @@ -61,6 +61,11 @@ cost: 1 exclusive: true requirements: + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Diona + - Harpy - !type:CharacterJobRequirement jobs: - ChiefMedicalOfficer diff --git a/Resources/Prototypes/Loadouts/Jobs/Heads/command.yml b/Resources/Prototypes/Loadouts/Jobs/Heads/command.yml new file mode 100644 index 00000000000..c8c98b5eb44 --- /dev/null +++ b/Resources/Prototypes/Loadouts/Jobs/Heads/command.yml @@ -0,0 +1,12 @@ +- type: loadout + id: LoadoutCommandGlovesInspection + category: Jobs + cost: 1 + exclusive: true + requirements: + - !type:CharacterJobRequirement + jobs: + - HeadOfPersonnel + - Captain + items: + - ClothingHandsGlovesInspection diff --git a/Resources/Prototypes/Loadouts/Jobs/Heads/headOfPersonnel.yml b/Resources/Prototypes/Loadouts/Jobs/Heads/headOfPersonnel.yml index 3d3799c0adf..e6bc6ada049 100644 --- a/Resources/Prototypes/Loadouts/Jobs/Heads/headOfPersonnel.yml +++ b/Resources/Prototypes/Loadouts/Jobs/Heads/headOfPersonnel.yml @@ -97,8 +97,25 @@ cost: 1 exclusive: true requirements: + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Diona + - Harpy - !type:CharacterJobRequirement jobs: - HeadOfPersonnel items: - ClothingShoesBootsWinterHeadOfPersonel + +- type: loadout + id: LoadoutCommandHOPBedsheetIan + category: Jobs + cost: 2 + exclusive: true + requirements: + - !type:CharacterJobRequirement + jobs: + - HeadOfPersonnel + items: + - BedsheetIan diff --git a/Resources/Prototypes/Loadouts/Jobs/Heads/headOfSecurity.yml b/Resources/Prototypes/Loadouts/Jobs/Heads/headOfSecurity.yml index 4f0d785b14d..7be380d7474 100644 --- a/Resources/Prototypes/Loadouts/Jobs/Heads/headOfSecurity.yml +++ b/Resources/Prototypes/Loadouts/Jobs/Heads/headOfSecurity.yml @@ -168,6 +168,11 @@ cost: 1 exclusive: true requirements: + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Diona + - Harpy - !type:CharacterJobRequirement jobs: - HeadOfSecurity diff --git a/Resources/Prototypes/Loadouts/Jobs/Heads/quarterMaster.yml b/Resources/Prototypes/Loadouts/Jobs/Heads/quarterMaster.yml index 3359d8f5d74..15adc7d44e8 100644 --- a/Resources/Prototypes/Loadouts/Jobs/Heads/quarterMaster.yml +++ b/Resources/Prototypes/Loadouts/Jobs/Heads/quarterMaster.yml @@ -64,6 +64,11 @@ cost: 1 exclusive: true requirements: + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Diona + - Harpy - !type:CharacterJobRequirement jobs: - Quartermaster diff --git a/Resources/Prototypes/Loadouts/Jobs/Heads/researchDirector.yml b/Resources/Prototypes/Loadouts/Jobs/Heads/researchDirector.yml index 87cb0db1790..5d06e54efab 100644 --- a/Resources/Prototypes/Loadouts/Jobs/Heads/researchDirector.yml +++ b/Resources/Prototypes/Loadouts/Jobs/Heads/researchDirector.yml @@ -50,6 +50,11 @@ cost: 1 exclusive: true requirements: + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Diona + - Harpy - !type:CharacterJobRequirement jobs: - ResearchDirector diff --git a/Resources/Prototypes/Loadouts/Jobs/cargo.yml b/Resources/Prototypes/Loadouts/Jobs/cargo.yml index 87463862010..cdc83a3c0f7 100644 --- a/Resources/Prototypes/Loadouts/Jobs/cargo.yml +++ b/Resources/Prototypes/Loadouts/Jobs/cargo.yml @@ -1,3 +1,47 @@ +# Cargo technician +- type: loadout + id: LoadoutCargoOuterWinterCargo + category: Jobs + cost: 2 + exclusive: true + requirements: + - !type:CharacterJobRequirement + jobs: + - CargoTechnician + items: + - ClothingOuterWinterCargo + +- type: loadout + id: LoadoutCargoShoesBootsWinterCargo + category: Jobs + cost: 1 + exclusive: true + requirements: + - !type:CharacterJobRequirement + jobs: + - CargoTechnician + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Diona + - Harpy + items: + - ClothingShoesBootsWinterCargo + +# Salvage specialist + +- type: loadout + id: LoadoutCargoOuterWinterMiner + category: Jobs + cost: 2 + exclusive: true + requirements: + - !type:CharacterJobRequirement + jobs: + - SalvageSpecialist + items: + - ClothingOuterWinterMiner + - type: loadout id: LoadoutCargoNeckGoliathCloak category: Jobs diff --git a/Resources/Prototypes/Loadouts/Jobs/medical.yml b/Resources/Prototypes/Loadouts/Jobs/medical.yml index edf51747d00..f193dfaea2d 100644 --- a/Resources/Prototypes/Loadouts/Jobs/medical.yml +++ b/Resources/Prototypes/Loadouts/Jobs/medical.yml @@ -495,3 +495,109 @@ - Nearsighted items: - ClothingEyesPrescriptionMedHud + +- type: loadout + id: LoadoutMedicalEyesGlassesChemical + category: Jobs + cost: 2 + exclusive: true + requirements: + - !type:CharacterJobRequirement + jobs: + - Chemist + items: + - ClothingEyesGlassesChemical + +- type: loadout + id: LoadoutMedicalBedsheetMedical + category: Jobs + cost: 2 + exclusive: true + requirements: + - !type:CharacterDepartmentRequirement + departments: + - Medical + items: + - BedsheetMedical + +# Chemist PPE gear +- type: loadout + id: LoadoutMedicalUniformJumpsuitChemShirt + category: Jobs + cost: 2 + exclusive: true + requirements: + - !type:CharacterJobRequirement + jobs: + - Chemist + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Harpy + items: + - ClothingUniformJumpsuitChemShirt + +- type: loadout + id: LoadoutMedicalNeckTieChem + category: Jobs + cost: 1 + exclusive: true + requirements: + - !type:CharacterJobRequirement + jobs: + - Chemist + items: + - ClothingNeckTieChem + +- type: loadout + id: LoadoutMedicalShoesEnclosedChem + category: Jobs + cost: 1 + exclusive: true + requirements: + - !type:CharacterJobRequirement + jobs: + - Chemist + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Diona + - Harpy + items: + - ClothingShoesEnclosedChem + +- type: loadout + id: LoadoutMedicalOuterApronChemist + category: Jobs + cost: 2 + exclusive: true + requirements: + - !type:CharacterJobRequirement + jobs: + - Chemist + items: + - ClothingOuterApronChemist + +- type: loadout + id: LoadoutMedicalEyesGlassesChemist + category: Jobs + cost: 2 + exclusive: true + requirements: + - !type:CharacterJobRequirement + jobs: + - Chemist + items: + - ClothingEyesGlassesChemist + +- type: loadout + id: LoadoutMedicalHandsGlovesChemist + category: Jobs + cost: 1 + exclusive: true + requirements: + - !type:CharacterJobRequirement + jobs: + - Chemist + items: + - ClothingHandsGlovesChemist diff --git a/Resources/Prototypes/Loadouts/Jobs/security.yml b/Resources/Prototypes/Loadouts/Jobs/security.yml index 2809c9c1ae5..f1c64730378 100644 --- a/Resources/Prototypes/Loadouts/Jobs/security.yml +++ b/Resources/Prototypes/Loadouts/Jobs/security.yml @@ -255,6 +255,7 @@ - !type:CharacterSpeciesRequirement inverted: true species: + - Diona - Harpy - !type:CharacterJobRequirement jobs: @@ -362,6 +363,22 @@ items: - ClothingBeltSecurityWebbingFilled +# Equipment +- type: loadout + id: LoadoutSecurityCombatKnife + category: Jobs + cost: 1 + requirements: + - !type:CharacterSpeciesRequirement + species: + - Diona + - Harpy + - !type:CharacterDepartmentRequirement + departments: + - Security + items: + - CombatKnife + # TODO: Make this replace the secoff handgun and make it cheaper # # Species # - type: loadout diff --git a/Resources/Prototypes/Loadouts/Jobs/service.yml b/Resources/Prototypes/Loadouts/Jobs/service.yml index becb2cb3758..2a8f3ba942a 100644 --- a/Resources/Prototypes/Loadouts/Jobs/service.yml +++ b/Resources/Prototypes/Loadouts/Jobs/service.yml @@ -27,6 +27,149 @@ - ClothingHeadHatJesterAlt - ClothingShoesJester +- type: loadout + id: LoadoutServiceClownOuterWinter + category: Jobs + cost: 2 + exclusive: true + requirements: + - !type:CharacterJobRequirement + jobs: + - Clown + items: + - ClothingOuterWinterClown + +- type: loadout + id: LoadoutServiceClownOuterClownPriest + category: Jobs + cost: 2 + exclusive: true + requirements: + - !type:CharacterJobRequirement + jobs: + - Clown + items: + - ClothingOuterClownPriest + +- type: loadout + id: LoadoutServiceClownBootsWinter + category: Jobs + cost: 1 + exclusive: true + requirements: + - !type:CharacterJobRequirement + jobs: + - Clown + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Diona + - Harpy + items: + - ClothingShoesBootsWinterClown + +- type: loadout + id: LoadoutServiceClownMaskSexy + category: Jobs + cost: 1 + exclusive: true + requirements: + - !type:CharacterJobRequirement + jobs: + - Clown + items: + - ClothingMaskSexyClown + +- type: loadout + id: LoadoutServiceClownBedsheetClown + category: Jobs + cost: 2 + exclusive: true + requirements: + - !type:CharacterJobRequirement + jobs: + - Clown + items: + - BedsheetClown + +# Mime +- type: loadout + id: LoadoutServiceMimeOuterWinter + category: Jobs + cost: 2 + exclusive: true + requirements: + - !type:CharacterJobRequirement + jobs: + - Mime + items: + - ClothingOuterWinterMime + +- type: loadout + id: LoadoutServiceMimeMaskSad + category: Jobs + cost: 1 + exclusive: true + requirements: + - !type:CharacterJobRequirement + jobs: + - Mime + items: + - ClothingMaskSadMime + +- type: loadout + id: LoadoutServiceMimeMaskScared + category: Jobs + cost: 1 + exclusive: true + requirements: + - !type:CharacterJobRequirement + jobs: + - Mime + items: + - ClothingMaskScaredMime + +- type: loadout + id: LoadoutServiceMimeMaskSexy + category: Jobs + cost: 1 + exclusive: true + requirements: + - !type:CharacterJobRequirement + jobs: + - Mime + items: + - ClothingMaskSexyMime + +- type: loadout + id: LoadoutServiceMimeShoesBootsWinter + category: Jobs + cost: 1 + exclusive: true + requirements: + - !type:CharacterJobRequirement + jobs: + - Mime + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Diona + - Harpy + items: + - ClothingShoesBootsWinterMime + +- type: loadout + id: LoadoutServiceMimeBedsheetMime + category: Jobs + cost: 2 + exclusive: true + requirements: + - !type:CharacterJobRequirement + jobs: + - Mime + items: + - BedsheetMime + # Bartender - type: loadout id: LoadoutServiceBartenderUniformPurple diff --git a/Resources/Prototypes/Loadouts/categories.yml b/Resources/Prototypes/Loadouts/categories.yml index 79d2d7fe2bf..0dfccb096ca 100644 --- a/Resources/Prototypes/Loadouts/categories.yml +++ b/Resources/Prototypes/Loadouts/categories.yml @@ -18,6 +18,9 @@ - type: loadoutCategory id: Jobs +- type: loadoutCategory + id: Mask + - type: loadoutCategory id: Neck diff --git a/Resources/Prototypes/Loadouts/eyes.yml b/Resources/Prototypes/Loadouts/eyes.yml index 74226604e92..fed07c6bd6f 100644 --- a/Resources/Prototypes/Loadouts/eyes.yml +++ b/Resources/Prototypes/Loadouts/eyes.yml @@ -5,6 +5,34 @@ items: - ClothingEyesEyepatch +- type: loadout + id: LoadoutEyesGlasses + category: Eyes + cost: 1 + requirements: + - !type:CharacterTraitRequirement + inverted: true + traits: + - Nearsighted + items: + - ClothingEyesGlasses + +- type: loadout + id: LoadoutEyesGlassesJamjar + category: Eyes + cost: 2 + exclusive: true + items: + - ClothingEyesGlassesJamjar + +- type: loadout + id: LoadoutEyesGlassesJensen + category: Eyes + cost: 2 + exclusive: true + items: + - ClothingEyesGlassesJensen + - type: loadout id: LoadoutEyesBlindfold category: Eyes @@ -12,6 +40,14 @@ items: - ClothingEyesBlindfold +- type: loadout + id: LoadoutItemCheapSunglasses + category: Eyes + cost: 2 + exclusive: true + items: + - ClothingEyesGlassesCheapSunglasses + - type: loadout id: LoadoutItemSunglasses category: Eyes diff --git a/Resources/Prototypes/Loadouts/hands.yml b/Resources/Prototypes/Loadouts/hands.yml index 3604678d387..6cef6420571 100644 --- a/Resources/Prototypes/Loadouts/hands.yml +++ b/Resources/Prototypes/Loadouts/hands.yml @@ -113,3 +113,11 @@ exclusive: true items: - ClothingHandsGlovesRobohands + +- type: loadout + id: LoadoutHandsGlovesFingerless + category: Hands + cost: 1 + exclusive: true + items: + - ClothingHandsGlovesFingerless diff --git a/Resources/Prototypes/Loadouts/head.yml b/Resources/Prototypes/Loadouts/head.yml index 7c4468b14c8..d2c42066d4b 100644 --- a/Resources/Prototypes/Loadouts/head.yml +++ b/Resources/Prototypes/Loadouts/head.yml @@ -6,6 +6,11 @@ exclusive: true items: - ClothingHeadHatBeaverHat + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security - type: loadout id: LoadoutHeadTophat @@ -23,6 +28,27 @@ items: - ClothingHeadHatFedoraBlack +- type: loadout + id: LoadoutHeadFedoraBrown + category: Head + cost: 2 + exclusive: true + items: + - ClothingHeadHatFedoraBrown + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security + +- type: loadout + id: LoadoutHeadFedoraGrey + category: Head + cost: 2 + exclusive: true + items: + - ClothingHeadHatFedoraGrey + - type: loadout id: LoadoutHeadFedoraChoc category: Head @@ -30,6 +56,11 @@ exclusive: true items: - ClothingHeadHatFedoraChoc + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security - type: loadout id: LoadoutHeadFedoraWhite @@ -54,6 +85,11 @@ exclusive: true items: - ClothingHeadHatFlatBrown + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security - type: loadout id: LoadoutHeadHatCowboyBrown @@ -135,6 +171,11 @@ exclusive: true items: - ClothingHeadHatBluesoft + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security - type: loadout id: LoadoutHeadHatBluesoftFlipped @@ -143,6 +184,11 @@ exclusive: true items: - ClothingHeadHatBluesoftFlipped + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security - type: loadout id: LoadoutHeadHatCorpsoft @@ -167,6 +213,11 @@ exclusive: true items: - ClothingHeadHatGreensoft + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security - type: loadout id: LoadoutHeadHatGreensoftFlipped @@ -175,6 +226,11 @@ exclusive: true items: - ClothingHeadHatGreensoftFlipped + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security - type: loadout id: LoadoutHeadHatGreysoft @@ -192,6 +248,22 @@ items: - ClothingHeadHatGreysoftFlipped +- type: loadout + id: LoadoutHeadHatMimesoft + category: Head + cost: 1 + exclusive: true + items: + - ClothingHeadHatMimesoft + +- type: loadout + id: LoadoutHeadHatMimesoftFlipped + category: Head + cost: 1 + exclusive: true + items: + - ClothingHeadHatMimesoftFlipped + - type: loadout id: LoadoutHeadHatOrangesoft category: Head @@ -199,6 +271,11 @@ exclusive: true items: - ClothingHeadHatOrangesoft + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security - type: loadout id: LoadoutHeadHatOrangesoftFlipped @@ -207,6 +284,11 @@ exclusive: true items: - ClothingHeadHatOrangesoftFlipped + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security - type: loadout id: LoadoutHeadHatPurplesoft @@ -215,6 +297,11 @@ exclusive: true items: - ClothingHeadHatPurplesoft + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security - type: loadout id: LoadoutHeadHatPurplesoftFlipped @@ -223,6 +310,11 @@ exclusive: true items: - ClothingHeadHatPurplesoftFlipped + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security - type: loadout id: LoadoutHeadHatRedsoft @@ -247,6 +339,11 @@ exclusive: true items: - ClothingHeadHatYellowsoft + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security - type: loadout id: LoadoutHeadHatYellowsoftFlipped @@ -255,6 +352,11 @@ exclusive: true items: - ClothingHeadHatYellowsoftFlipped + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security # Headbands - type: loadout @@ -272,6 +374,11 @@ exclusive: true items: - ClothingHeadBandBlue + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security - type: loadout id: LoadoutHeadBandGold @@ -280,6 +387,11 @@ exclusive: true items: - ClothingHeadBandGold + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security - type: loadout id: LoadoutHeadBandGreen @@ -288,6 +400,11 @@ exclusive: true items: - ClothingHeadBandGreen + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security - type: loadout id: LoadoutHeadBandGrey @@ -296,6 +413,11 @@ exclusive: true items: - ClothingHeadBandGrey + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security - type: loadout id: LoadoutHeadBandRed @@ -320,6 +442,11 @@ exclusive: true items: - ClothingHeadBandMerc + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security - type: loadout id: LoadoutHeadBandBrown @@ -328,3 +455,135 @@ exclusive: true items: - ClothingHeadBandBrown + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security + +- type: loadout + id: LoadoutHeadFishCap + category: Head + cost: 2 + exclusive: true + items: + - ClothingHeadFishCap + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security + +- type: loadout + id: LoadoutHeadRastaHat + category: Head + cost: 4 + exclusive: true + items: + - ClothingHeadRastaHat + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security + +- type: loadout + id: LoadoutHeadFez + category: Head + cost: 2 + exclusive: true + items: + - ClothingHeadHatFez + +- type: loadout + id: LoadoutHeadBowlerHat + category: Head + cost: 2 + exclusive: true + items: + - ClothingHeadHatBowlerHat + +# Flatcaps +- type: loadout + id: LoadoutHeadGreyFlatcap + category: Head + cost: 2 + exclusive: true + items: + - ClothingHeadHatGreyFlatcap + +- type: loadout + id: LoadoutHeadBrownFlatcap + category: Head + cost: 2 + exclusive: true + items: + - ClothingHeadHatBrownFlatcap + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security + +# Berets +- type: loadout + id: LoadoutHeadBeret + category: Head + cost: 2 + exclusive: true + items: + - ClothingHeadHatBeret + +- type: loadout + id: LoadoutHeadBeretFrench + category: Head + cost: 2 + exclusive: true + items: + - ClothingHeadHatBeretFrench + +# Cowboy hats +- type: loadout + id: LoadoutHeadCowboyBrown + category: Head + cost: 2 + exclusive: true + items: + - ClothingHeadHatCowboyBrown + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security + +- type: loadout + id: LoadoutHeadCowboyBlack + category: Head + cost: 2 + exclusive: true + items: + - ClothingHeadHatCowboyBlack + +- type: loadout + id: LoadoutHeadCowboyWhite + category: Head + cost: 2 + exclusive: true + items: + - ClothingHeadHatCowboyWhite + +- type: loadout + id: LoadoutHeadCowboyGrey + category: Head + cost: 2 + exclusive: true + items: + - ClothingHeadHatCowboyGrey + +- type: loadout + id: LoadoutHeadCowboyRed + category: Head + cost: 2 + exclusive: true + items: + - ClothingHeadHatCowboyRed diff --git a/Resources/Prototypes/Loadouts/items.yml b/Resources/Prototypes/Loadouts/items.yml index 140cd1683f6..e09d02c463a 100644 --- a/Resources/Prototypes/Loadouts/items.yml +++ b/Resources/Prototypes/Loadouts/items.yml @@ -63,11 +63,18 @@ - CheapLighter - type: loadout - id: LoadoutItemMatches + id: LoadoutItemLighterFlippo category: Items - cost: 1 + cost: 3 + items: + - FlippoLighter + +- type: loadout + id: LoadoutItemSmokingPipeFilledTobacco + category: Items + cost: 2 items: - - Matchbox + - SmokingPipeFilledTobacco # Instruments - type: loadout @@ -176,6 +183,13 @@ items: - DoubleEmergencyOxygenTankFilled +- type: loadout + id: LoadoutItemClothingMaskBreath + category: Items + cost: 1 + items: + - ClothingMaskBreath + - type: loadout id: LoadoutItemsEmergencyCrowbar category: Items @@ -183,6 +197,277 @@ items: - CrowbarRed +- type: loadout + id: LoadoutItemFireExtinguisher + category: Items + cost: 3 + items: + - FireExtinguisher + +- type: loadout + id: LoadoutItemFlashlightLantern + category: Items + cost: 2 + items: + - FlashlightLantern + +- type: loadout + id: LoadoutItemFlare + category: Items + cost: 1 + items: + - Flare + +- type: loadout + id: LoadoutEmergencyMedipen + category: Items + cost: 1 + items: + - EmergencyMedipen + +- type: loadout + id: LoadoutSpaceMedipen + category: Items + cost: 1 + items: + - SpaceMedipen + +# Paperwork +- type: loadout + id: LoadoutItemPapers + category: Items + cost: 1 + items: + - Paper + - Paper + - Paper + - Paper + +- type: loadout + id: LoadoutItemBoxFolderGrey + category: Items + cost: 1 + items: + - BoxFolderGrey + +- type: loadout + id: LoadoutBookRandom + category: Items + cost: 1 + items: + - BookRandom + +- type: loadout + id: LoadoutPen + category: Items + cost: 1 + items: + - Pen + +# Food and drink +- type: loadout + id: LoadoutDrinkWaterBottleFull + category: Items + cost: 1 + items: + - DrinkWaterBottleFull + +- type: loadout + id: LoadoutItemLunchboxGenericFilledRandom + category: Items + cost: 3 + items: + - LunchboxGenericFilledRandom + +# Survival boxes +- type: loadout + id: LoadoutItemBoxSurvival + category: Items + cost: 2 #All survival kits are intentionally cheaper than their contents to help encourage people to buy them. The contents can be bought separately to save space, or as spares + items: + - BoxSurvival + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security + - Medical + - Engineering + - Epistemics + - !type:CharacterJobRequirement + inverted: true + jobs: + - Clown + +- type: loadout + id: LoadoutItemBoxSurvivalEngineering + category: Items + cost: 2 + items: + - BoxSurvivalEngineering + requirements: + - !type:CharacterDepartmentRequirement + departments: + - Engineering + +- type: loadout + id: LoadoutItemBoxSurvivalSecurity + category: Items + cost: 2 + items: + - BoxSurvivalSecurity + requirements: + - !type:CharacterDepartmentRequirement + departments: + - Security + - !type:CharacterJobRequirement + inverted: true + jobs: + - Brigmedic + +- type: loadout + id: LoadoutItemBoxSurvivalBrigmedic + category: Items + cost: 2 + items: + - BoxSurvivalBrigmedic + requirements: + - !type:CharacterJobRequirement + jobs: + - Brigmedic + +- type: loadout + id: LoadoutItemBoxSurvivalMedical + category: Items + cost: 2 + items: + - BoxSurvivalMedical + requirements: + - !type:CharacterDepartmentRequirement + departments: + - Medical + +- type: loadout + id: LoadoutItemBoxHug + category: Items + cost: 2 + items: + - BoxHug + requirements: + - !type:CharacterJobRequirement + jobs: + - Clown + +# Medkits +- type: loadout + id: LoadoutMedkitFilled + category: Items + cost: 4 + items: + - MedkitFilled + +- type: loadout + id: LoadoutMedkitBruteFilled + category: Items + cost: 4 + items: + - MedkitBruteFilled + requirements: + - !type:CharacterJobRequirement + jobs: + - MedicalDoctor + - Paramedic + - ChiefMedicalOfficer + - MedicalIntern + - Brigmedic + +- type: loadout + id: LoadoutMedkitBurnFilled + category: Items + cost: 4 + items: + - MedkitBurnFilled + requirements: + - !type:CharacterJobRequirement + jobs: + - MedicalDoctor + - Paramedic + - ChiefMedicalOfficer + - MedicalIntern + - Brigmedic + +- type: loadout + id: LoadoutMedkitToxinFilled + category: Items + cost: 4 + items: + - MedkitToxinFilled + requirements: + - !type:CharacterJobRequirement + jobs: + - MedicalDoctor + - Paramedic + - ChiefMedicalOfficer + - MedicalIntern + - Brigmedic + +- type: loadout + id: LoadoutMedkitOxygenFilled + category: Items + cost: 4 + items: + - MedkitOxygenFilled + requirements: + - !type:CharacterJobRequirement + jobs: + - MedicalDoctor + - Paramedic + - ChiefMedicalOfficer + - MedicalIntern + - Brigmedic + +- type: loadout + id: LoadoutMedkitRadiationFilled + category: Items + cost: 4 + items: + - MedkitRadiationFilled + requirements: + - !type:CharacterJobRequirement + jobs: + - MedicalDoctor + - Paramedic + - ChiefMedicalOfficer + - MedicalIntern + - Brigmedic + +- type: loadout + id: LoadoutMedkitAdvancedFilled + category: Items + cost: 5 + items: + - MedkitAdvancedFilled + requirements: + - !type:CharacterJobRequirement + jobs: + - MedicalDoctor + - Paramedic + - ChiefMedicalOfficer + - MedicalIntern + - Brigmedic + +- type: loadout + id: LoadoutMedkitCombatFilled + category: Items + cost: 4 # Discounted for the CMO and Corpsman + items: + - MedkitCombatFilled + requirements: + - !type:CharacterJobRequirement + jobs: + - ChiefMedicalOfficer + - Brigmedic + #Misc Items - type: loadout id: LoadoutItemPAI @@ -191,37 +476,54 @@ items: - PersonalAI +- type: loadout + id: LoadoutItemBackpackSatchelLeather + category: Items + cost: 1 + items: + - ClothingBackpackSatchelLeather + requirements: + - !type:CharacterJobRequirement + inverted: true + jobs: + - Prisoner + - type: loadout id: LoadoutItemWaistbag category: Items cost: 2 items: - ClothingBeltStorageWaistbag + requirements: + - !type:CharacterJobRequirement + inverted: true + jobs: + - Prisoner - type: loadout - id: LoadoutSolCommonTranslator + id: LoadoutItemCrayonBox category: Items - cost: 3 + cost: 4 items: - - SolCommonTranslator + - CrayonBox - type: loadout - id: LoadoutEmergencyNitrogenTank + id: LoadoutItemBarberScissors category: Items - cost: 1 + cost: 4 items: - - EmergencyNitrogenTankFilled + - BarberScissors - type: loadout - id: LoadoutExtendedEmergencyNitrogenTank + id: LoadoutSolCommonTranslator category: Items - cost: 2 + cost: 3 items: - - ExtendedEmergencyNitrogenTankFilled + - SolCommonTranslator - type: loadout - id: LoadoutDoubleEmergencyNitrogenTank + id: LoadoutHandLabeler category: Items cost: 3 items: - - DoubleEmergencyNitrogenTankFilled + - HandLabeler diff --git a/Resources/Prototypes/Loadouts/mask.yml b/Resources/Prototypes/Loadouts/mask.yml new file mode 100644 index 00000000000..67be1e70ffd --- /dev/null +++ b/Resources/Prototypes/Loadouts/mask.yml @@ -0,0 +1,143 @@ +- type: loadout + id: LoadoutMaskSterile + category: Mask + cost: 1 + exclusive: true + items: + - ClothingMaskSterile + +- type: loadout + id: LoadoutMaskMuzzle + category: Mask + cost: 2 + exclusive: true + items: + - ClothingMaskMuzzle + +- type: loadout + id: LoadoutMaskGas + category: Mask + cost: 1 + exclusive: true + items: + - ClothingMaskGas + +# Maskbands +- type: loadout + id: LoadoutMaskBandBlack + category: Mask + cost: 1 + exclusive: true + items: + - ClothingMaskBandBlack + +- type: loadout + id: LoadoutMaskBandBlue + category: Mask + cost: 1 + exclusive: true + items: + - ClothingMaskBandBlue + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security + +- type: loadout + id: LoadoutMaskBandGold + category: Mask + cost: 1 + exclusive: true + items: + - ClothingMaskBandGold + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security + +- type: loadout + id: LoadoutMaskBandGreen + category: Mask + cost: 1 + exclusive: true + items: + - ClothingMaskBandGreen + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security + +- type: loadout + id: LoadoutMaskBandGrey + category: Mask + cost: 1 + exclusive: true + items: + - ClothingMaskBandGrey + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security + +- type: loadout + id: LoadoutMaskBandRed + category: Mask + cost: 1 + exclusive: true + items: + - ClothingMaskBandRed + +- type: loadout + id: LoadoutMaskBandSkull + category: Mask + cost: 1 + exclusive: true + items: + - ClothingMaskBandSkull + +- type: loadout + id: LoadoutMaskBandMerc + category: Mask + cost: 2 + exclusive: true + items: + - ClothingMaskBandMerc + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security + +- type: loadout + id: LoadoutMaskBandBrown + category: Mask + cost: 1 + exclusive: true + items: + - ClothingMaskBandBrown + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security + +# Gaiters +- type: loadout + id: LoadoutMaskNeckGaiter + category: Mask + cost: 2 + exclusive: true + items: + - ClothingMaskNeckGaiter + +- type: loadout + id: LoadoutMaskNeckGaiterRed + category: Mask + cost: 2 + exclusive: true + items: + - ClothingMaskNeckGaiterRed diff --git a/Resources/Prototypes/Loadouts/neck.yml b/Resources/Prototypes/Loadouts/neck.yml index eb933de29ee..c7fc7003653 100644 --- a/Resources/Prototypes/Loadouts/neck.yml +++ b/Resources/Prototypes/Loadouts/neck.yml @@ -1,3 +1,12 @@ +- type: loadout + id: LoadoutNeckHeadphones + category: Neck + cost: 2 + exclusive: true + items: + - ClothingNeckHeadphones + +# Scarves - type: loadout id: LoadoutNeckScarfStripedRed category: Neck @@ -22,6 +31,46 @@ items: - ClothingNeckScarfStripedGreen +- type: loadout + id: LoadoutNeckScarfStripedBlack + category: Neck + cost: 1 + exclusive: true + items: + - ClothingNeckScarfStripedBlack + +- type: loadout + id: LoadoutNeckScarfStripedBrown + category: Neck + cost: 1 + exclusive: true + items: + - ClothingNeckScarfStripedBrown + +- type: loadout + id: LoadoutNeckScarfStripedLightBlue + category: Neck + cost: 1 + exclusive: true + items: + - ClothingNeckScarfStripedLightBlue + +- type: loadout + id: LoadoutNeckScarfStripedOrange + category: Neck + cost: 1 + exclusive: true + items: + - ClothingNeckScarfStripedOrange + +- type: loadout + id: LoadoutNeckScarfStripedPurple + category: Neck + cost: 1 + exclusive: true + items: + - ClothingNeckScarfStripedPurple + - type: loadout id: LoadoutNeckScarfStripedZebra category: Neck @@ -30,6 +79,48 @@ items: - ClothingNeckScarfStripedZebra +# Ties +- type: loadout + id: LoadoutNeckTieRed + category: Neck + cost: 1 + exclusive: true + items: + - ClothingNeckTieRed + +- type: loadout + id: LoadoutNeckTieWhite + category: Neck + cost: 1 + exclusive: true + items: + - ClothingNeckTieWhite + +- type: loadout + id: LoadoutNeckTieBlack + category: Neck + cost: 1 + exclusive: true + items: + - ClothingNeckTieBlack + +- type: loadout + id: LoadoutNeckTieBlue + category: Neck + cost: 1 + exclusive: true + items: + - ClothingNeckTieBlue + +- type: loadout + id: LoadoutNeckTieGreen + category: Neck + cost: 1 + exclusive: true + items: + - ClothingNeckTieGreen + + #Pride Accessories - type: loadout id: LoadoutItemsPrideLGBTPin @@ -102,3 +193,216 @@ exclusive: true items: - ClothingNeckTransPin + +# Bedsheets +- type: loadout + id: LoadoutNeckBedsheetBlack + category: Neck + cost: 2 + exclusive: true + items: + - BedsheetBlack + requirements: + - !type:CharacterDepartmentRequirement + departments: + - Civilian + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command + +- type: loadout + id: LoadoutNeckBedsheetBlue + category: Neck + cost: 2 + exclusive: true + items: + - BedsheetBlue + requirements: + - !type:CharacterDepartmentRequirement + departments: + - Civilian + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command + +- type: loadout + id: LoadoutNeckBedsheetBrown + category: Neck + cost: 2 + exclusive: true + items: + - BedsheetBrown + requirements: + - !type:CharacterDepartmentRequirement + departments: + - Civilian + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command + +- type: loadout + id: LoadoutNeckBedsheetCosmos + category: Neck + cost: 3 + exclusive: true + items: + - BedsheetCosmos + requirements: + - !type:CharacterDepartmentRequirement + departments: + - Civilian + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command + +- type: loadout + id: LoadoutNeckBedsheetGreen + category: Neck + cost: 2 + exclusive: true + items: + - BedsheetGreen + requirements: + - !type:CharacterDepartmentRequirement + departments: + - Civilian + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command + +- type: loadout + id: LoadoutNeckBedsheetGrey + category: Neck + cost: 2 + exclusive: true + items: + - BedsheetGrey + requirements: + - !type:CharacterDepartmentRequirement + departments: + - Civilian + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command + +- type: loadout + id: LoadoutNeckBedsheetOrange + category: Neck + cost: 2 + exclusive: true + items: + - BedsheetOrange + requirements: + - !type:CharacterDepartmentRequirement + departments: + - Civilian + - Logistics + - !type:CharacterJobRequirement + inverted: true + jobs: + - HeadOfPersonnel # Need to blacklist HoP and not command so other heads can wear this bedsheet + +- type: loadout + id: LoadoutNeckBedsheetPurple + category: Neck + cost: 2 + exclusive: true + items: + - BedsheetPurple + requirements: + - !type:CharacterDepartmentRequirement + departments: + - Civilian + - Epistemics + - !type:CharacterJobRequirement + inverted: true + jobs: + - HeadOfPersonnel # Need to blacklist HoP and not command so other heads can wear this bedsheet + +- type: loadout + id: LoadoutNeckBedsheetRainbow + category: Neck + cost: 2 + exclusive: true + items: + - BedsheetRainbow + requirements: + - !type:CharacterDepartmentRequirement + departments: + - Civilian + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command + +- type: loadout + id: LoadoutNeckBedsheetRed + category: Neck + cost: 2 + exclusive: true + items: + - BedsheetRed + requirements: + - !type:CharacterDepartmentRequirement + departments: + - Civilian + - Security + - !type:CharacterJobRequirement + inverted: true + jobs: + - HeadOfPersonnel # Need to blacklist HoP and not command so other heads can wear this bedsheet + +- type: loadout + id: LoadoutNeckBedsheetWhite + category: Neck + cost: 2 + exclusive: true + items: + - BedsheetWhite + requirements: + - !type:CharacterDepartmentRequirement + departments: + - Civilian + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command + +- type: loadout + id: LoadoutNeckBedsheetYellow + category: Neck + cost: 2 + exclusive: true + items: + - BedsheetYellow + requirements: + - !type:CharacterDepartmentRequirement + departments: + - Civilian + - Engineering + - !type:CharacterJobRequirement + inverted: true + jobs: + - HeadOfPersonnel # Need to blacklist HoP and not command so other heads can wear this bedsheet + +- type: loadout + id: LoadoutNeckBedsheetNT + category: Neck + cost: 2 + exclusive: true + items: + - BedsheetNT + requirements: + - !type:CharacterDepartmentRequirement + departments: + - Civilian + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command diff --git a/Resources/Prototypes/Loadouts/outerClothing.yml b/Resources/Prototypes/Loadouts/outerClothing.yml index c52f35b0f5d..da091412b6c 100644 --- a/Resources/Prototypes/Loadouts/outerClothing.yml +++ b/Resources/Prototypes/Loadouts/outerClothing.yml @@ -54,6 +54,13 @@ items: - ClothingOuterVestValet +- type: loadout + id: LoadoutOuterVest + category: Outer + cost: 1 + items: + - ClothingOuterVest + # Letterman Jackets - type: loadout id: LoadoutOuterCoatLettermanBlue @@ -168,3 +175,67 @@ cost: 2 items: - ClothingOuterZhCorporateJacket + +- type: loadout + id: LoadoutOuterDenimJacket + category: Outer + cost: 3 + items: + - ClothingOuterDenimJacket + +# Flannel +- type: loadout + id: LoadoutOuterFlannelRed + category: Outer + cost: 3 + items: + - ClothingOuterFlannelRed + +- type: loadout + id: LoadoutOuterFlannelGreen + category: Outer + cost: 3 + items: + - ClothingOuterFlannelGreen + +- type: loadout + id: LoadoutOuterFlannelBlue + category: Outer + cost: 3 + items: + - ClothingOuterFlannelBlue + +- type: loadout + id: LoadoutOuterCoatTrench + category: Outer + cost: 3 + items: + - ClothingOuterCoatTrench + +- type: loadout + id: LoadoutOuterCoatJensen + category: Outer + cost: 3 + items: + - ClothingOuterCoatJensen + +- type: loadout + id: LoadoutOuterCoatGentle + category: Outer + cost: 3 + items: + - ClothingOuterCoatGentle + +- type: loadout + id: LoadoutOuterCoatInspector + category: Outer + cost: 3 + items: + - ClothingOuterCoatInspector + +- type: loadout + id: LoadoutOuterCoatOvercoat + category: Outer + cost: 4 + items: + - ClothingOuterCoatOvercoat diff --git a/Resources/Prototypes/Loadouts/shoes.yml b/Resources/Prototypes/Loadouts/shoes.yml index bdea2b57ad1..470cac29834 100644 --- a/Resources/Prototypes/Loadouts/shoes.yml +++ b/Resources/Prototypes/Loadouts/shoes.yml @@ -8,6 +8,7 @@ - !type:CharacterSpeciesRequirement inverted: true species: + - Diona - Harpy items: - ClothingShoesColorBlack @@ -21,6 +22,7 @@ - !type:CharacterSpeciesRequirement inverted: true species: + - Diona - Harpy items: - ClothingShoesColorBlue @@ -34,6 +36,7 @@ - !type:CharacterSpeciesRequirement inverted: true species: + - Diona - Harpy items: - ClothingShoesColorBrown @@ -47,6 +50,7 @@ - !type:CharacterSpeciesRequirement inverted: true species: + - Diona - Harpy items: - ClothingShoesColorGreen @@ -60,6 +64,7 @@ - !type:CharacterSpeciesRequirement inverted: true species: + - Diona - Harpy items: - ClothingShoesColorOrange @@ -73,6 +78,7 @@ - !type:CharacterSpeciesRequirement inverted: true species: + - Diona - Harpy items: - ClothingShoesColorPurple @@ -86,6 +92,7 @@ - !type:CharacterSpeciesRequirement inverted: true species: + - Diona - Harpy items: - ClothingShoesColorRed @@ -99,6 +106,7 @@ - !type:CharacterSpeciesRequirement inverted: true species: + - Diona - Harpy items: - ClothingShoesColorWhite @@ -112,6 +120,7 @@ - !type:CharacterSpeciesRequirement inverted: true species: + - Diona - Harpy items: - ClothingShoesColorYellow @@ -125,10 +134,25 @@ - !type:CharacterSpeciesRequirement inverted: true species: + - Diona - Harpy items: - ClothingShoesGeta +- type: loadout + id: LoadoutShoesTourist + category: Shoes + cost: 2 + exclusive: true + requirements: + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Diona + - Harpy + items: + - ClothingShoesTourist + # Boots - type: loadout id: LoadoutShoesBootsWork @@ -139,6 +163,7 @@ - !type:CharacterSpeciesRequirement inverted: true species: + - Diona - Harpy items: - ClothingShoesBootsWork @@ -152,6 +177,7 @@ - !type:CharacterSpeciesRequirement inverted: true species: + - Diona - Harpy items: - ClothingShoesBootsLaceup @@ -165,6 +191,7 @@ - !type:CharacterSpeciesRequirement inverted: true species: + - Diona - Harpy items: - ClothingShoesBootsWinter @@ -178,6 +205,7 @@ - !type:CharacterSpeciesRequirement inverted: true species: + - Diona - Harpy items: - ClothingShoesBootsCowboyBrown @@ -191,6 +219,7 @@ - !type:CharacterSpeciesRequirement inverted: true species: + - Diona - Harpy items: - ClothingShoesBootsCowboyBlack @@ -204,6 +233,7 @@ - !type:CharacterSpeciesRequirement inverted: true species: + - Diona - Harpy items: - ClothingShoesBootsCowboyWhite @@ -217,10 +247,25 @@ - !type:CharacterSpeciesRequirement inverted: true species: + - Diona - Harpy items: - ClothingShoesBootsCowboyFancy +- type: loadout + id: LoadoutShoesBootsFishing + category: Shoes + cost: 2 + exclusive: true + requirements: + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Diona + - Harpy + items: + - ClothingShoesBootsFishing + # Miscellaneous - type: loadout id: LoadoutShoesSlippersDuck @@ -233,6 +278,7 @@ - !type:CharacterSpeciesRequirement inverted: true species: + - Diona - Harpy - !type:CharacterJobRequirement jobs: @@ -247,6 +293,7 @@ - !type:CharacterSpeciesRequirement inverted: true species: + - Diona - Harpy items: - ClothingShoesLeather @@ -260,6 +307,51 @@ - !type:CharacterSpeciesRequirement inverted: true species: + - Diona - Harpy items: - ClothingShoesMiscWhite + +- type: loadout + id: LoadoutShoesHighheelBoots + category: Shoes + cost: 3 + exclusive: true + requirements: + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Diona + - Harpy + items: + - ClothingShoesHighheelBoots + +# Socks +- type: loadout + id: LoadoutShoesUnderSocksCoder + category: Shoes + cost: 3 + exclusive: true + requirements: + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Diona + - Harpy + items: + - ClothingUnderSocksCoder + +# Socks +- type: loadout + id: LoadoutShoesUnderSocksBee + category: Shoes + cost: 3 + exclusive: true + requirements: + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Diona + - Harpy + items: + - ClothingUnderSocksBee diff --git a/Resources/Prototypes/Loadouts/uniform.yml b/Resources/Prototypes/Loadouts/uniform.yml index eb46acc2f60..5843cb30ee5 100644 --- a/Resources/Prototypes/Loadouts/uniform.yml +++ b/Resources/Prototypes/Loadouts/uniform.yml @@ -28,9 +28,14 @@ inverted: true species: - Harpy - - !type:CharacterJobRequirement - jobs: - - Passenger + - !type:CharacterDepartmentRequirement + departments: + - Civilian + - Security + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command - type: loadout id: LoadoutUniformJumpskirtColorBlack @@ -40,9 +45,14 @@ items: - ClothingUniformJumpskirtColorBlack requirements: - - !type:CharacterJobRequirement - jobs: - - Passenger + - !type:CharacterDepartmentRequirement + departments: + - Civilian + - Security + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command - type: loadout id: LoadoutUniformJumpsuitColorBlue @@ -56,9 +66,14 @@ inverted: true species: - Harpy - - !type:CharacterJobRequirement - jobs: - - Passenger + - !type:CharacterDepartmentRequirement + departments: + - Medical + - Civilian + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command - type: loadout id: LoadoutUniformJumpskirtColorBlue @@ -68,9 +83,14 @@ items: - ClothingUniformJumpskirtColorBlue requirements: - - !type:CharacterJobRequirement - jobs: - - Passenger + - !type:CharacterDepartmentRequirement + departments: + - Medical + - Civilian + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command - type: loadout id: LoadoutUniformJumpsuitColorGreen @@ -84,9 +104,13 @@ inverted: true species: - Harpy - - !type:CharacterJobRequirement - jobs: - - Passenger + - !type:CharacterDepartmentRequirement + departments: + - Civilian + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command - type: loadout id: LoadoutUniformJumpskirtColorGreen @@ -96,9 +120,13 @@ items: - ClothingUniformJumpskirtColorGreen requirements: - - !type:CharacterJobRequirement - jobs: - - Passenger + - !type:CharacterDepartmentRequirement + departments: + - Civilian + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command - type: loadout id: LoadoutUniformJumpsuitColorOrange @@ -112,9 +140,13 @@ inverted: true species: - Harpy - - !type:CharacterJobRequirement - jobs: - - Passenger + - !type:CharacterDepartmentRequirement + departments: + - Civilian + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command - type: loadout id: LoadoutUniformJumpskirtColorOrange @@ -124,9 +156,13 @@ items: - ClothingUniformJumpskirtColorOrange requirements: - - !type:CharacterJobRequirement - jobs: - - Passenger + - !type:CharacterDepartmentRequirement + departments: + - Civilian + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command - type: loadout id: LoadoutUniformJumpsuitColorPink @@ -140,9 +176,13 @@ inverted: true species: - Harpy - - !type:CharacterJobRequirement - jobs: - - Passenger + - !type:CharacterDepartmentRequirement + departments: + - Civilian + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command - type: loadout id: LoadoutUniformJumpskirtColorPink @@ -152,9 +192,13 @@ items: - ClothingUniformJumpskirtColorPink requirements: - - !type:CharacterJobRequirement - jobs: - - Passenger + - !type:CharacterDepartmentRequirement + departments: + - Civilian + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command - type: loadout id: LoadoutUniformJumpsuitColorRed @@ -168,9 +212,14 @@ inverted: true species: - Harpy - - !type:CharacterJobRequirement - jobs: - - Passenger + - !type:CharacterDepartmentRequirement + departments: + - Civilian + - Security + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command - type: loadout id: LoadoutUniformJumpskirtColorRed @@ -180,9 +229,14 @@ items: - ClothingUniformJumpskirtColorRed requirements: - - !type:CharacterJobRequirement - jobs: - - Passenger + - !type:CharacterDepartmentRequirement + departments: + - Civilian + - Security + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command - type: loadout id: LoadoutUniformJumpsuitColorWhite @@ -196,9 +250,15 @@ inverted: true species: - Harpy - - !type:CharacterJobRequirement - jobs: - - Passenger + - !type:CharacterDepartmentRequirement + departments: + - Civilian + - Medical + - Epistemics + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command - type: loadout id: LoadoutUniformJumpskirtColorWhite @@ -208,9 +268,15 @@ items: - ClothingUniformJumpskirtColorWhite requirements: - - !type:CharacterJobRequirement - jobs: - - Passenger + - !type:CharacterDepartmentRequirement + departments: + - Civilian + - Medical + - Epistemics + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command - type: loadout id: LoadoutUniformJumpsuitColorYellow @@ -224,9 +290,14 @@ inverted: true species: - Harpy - - !type:CharacterJobRequirement - jobs: - - Passenger + - !type:CharacterDepartmentRequirement + departments: + - Civilian + - Engineering + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command - type: loadout id: LoadoutUniformJumpskirtColorYellow @@ -236,9 +307,14 @@ items: - ClothingUniformJumpskirtColorYellow requirements: - - !type:CharacterJobRequirement - jobs: - - Passenger + - !type:CharacterDepartmentRequirement + departments: + - Civilian + - Engineering + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command - type: loadout id: LoadoutUniformJumpsuitColorDarkBlue @@ -252,9 +328,13 @@ inverted: true species: - Harpy - - !type:CharacterJobRequirement - jobs: - - Passenger + - !type:CharacterDepartmentRequirement + departments: + - Civilian + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command - type: loadout id: LoadoutUniformJumpskirtColorDarkBlue @@ -264,9 +344,13 @@ items: - ClothingUniformJumpskirtColorDarkBlue requirements: - - !type:CharacterJobRequirement - jobs: - - Passenger + - !type:CharacterDepartmentRequirement + departments: + - Civilian + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command - type: loadout id: LoadoutUniformJumpsuitColorTeal @@ -280,9 +364,13 @@ inverted: true species: - Harpy - - !type:CharacterJobRequirement - jobs: - - Passenger + - !type:CharacterDepartmentRequirement + departments: + - Civilian + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command - type: loadout id: LoadoutUniformJumpskirtColorTeal @@ -292,9 +380,13 @@ items: - ClothingUniformJumpskirtColorTeal requirements: - - !type:CharacterJobRequirement - jobs: - - Passenger + - !type:CharacterDepartmentRequirement + departments: + - Civilian + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command - type: loadout id: LoadoutUniformJumpsuitColorPurple @@ -308,9 +400,14 @@ inverted: true species: - Harpy - - !type:CharacterJobRequirement - jobs: - - Passenger + - !type:CharacterDepartmentRequirement + departments: + - Civilian + - Epistemics + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command - type: loadout id: LoadoutUniformJumpskirtColorPurple @@ -320,9 +417,14 @@ items: - ClothingUniformJumpskirtColorPurple requirements: - - !type:CharacterJobRequirement - jobs: - - Passenger + - !type:CharacterDepartmentRequirement + departments: + - Civilian + - Epistemics + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command - type: loadout id: LoadoutUniformJumpsuitColorDarkGreen @@ -336,9 +438,13 @@ inverted: true species: - Harpy - - !type:CharacterJobRequirement - jobs: - - Passenger + - !type:CharacterDepartmentRequirement + departments: + - Civilian + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command - type: loadout id: LoadoutUniformJumpskirtColorDarkGreen @@ -348,9 +454,13 @@ items: - ClothingUniformJumpskirtColorDarkGreen requirements: - - !type:CharacterJobRequirement - jobs: - - Passenger + - !type:CharacterDepartmentRequirement + departments: + - Civilian + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command - type: loadout id: LoadoutUniformJumpsuitColorLightBrown @@ -364,9 +474,13 @@ inverted: true species: - Harpy - - !type:CharacterJobRequirement - jobs: - - Passenger + - !type:CharacterDepartmentRequirement + departments: + - Civilian + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command - type: loadout id: LoadoutUniformJumpskirtColorLightBrown @@ -376,9 +490,13 @@ items: - ClothingUniformJumpskirtColorLightBrown requirements: - - !type:CharacterJobRequirement - jobs: - - Passenger + - !type:CharacterDepartmentRequirement + departments: + - Civilian + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command - type: loadout id: LoadoutUniformJumpsuitColorBrown @@ -392,9 +510,13 @@ inverted: true species: - Harpy - - !type:CharacterJobRequirement - jobs: - - Passenger + - !type:CharacterDepartmentRequirement + departments: + - Civilian + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command - type: loadout id: LoadoutUniformJumpskirtColorBrown @@ -404,9 +526,13 @@ items: - ClothingUniformJumpskirtColorBrown requirements: - - !type:CharacterJobRequirement - jobs: - - Passenger + - !type:CharacterDepartmentRequirement + departments: + - Civilian + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command - type: loadout id: LoadoutUniformJumpsuitColorMaroon @@ -420,9 +546,13 @@ inverted: true species: - Harpy - - !type:CharacterJobRequirement - jobs: - - Passenger + - !type:CharacterDepartmentRequirement + departments: + - Civilian + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command - type: loadout id: LoadoutUniformJumpskirtColorMaroon @@ -432,130 +562,957 @@ items: - ClothingUniformJumpskirtColorMaroon requirements: - - !type:CharacterJobRequirement - jobs: - - Passenger + - !type:CharacterDepartmentRequirement + departments: + - Civilian + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command -# Kendo - type: loadout - id: LoadoutUniformKendoHakama + id: LoadoutUniformJumpsuitFlannel category: Uniform cost: 2 exclusive: true items: - - ClothingUniformKendoHakama + - ClothingUniformJumpsuitFlannel + requirements: + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Harpy + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command - type: loadout - id: LoadoutUniformMartialGi + id: LoadoutUniformJumpskirtCasualBlue category: Uniform cost: 2 exclusive: true items: - - ClothingUniformMartialGi + - ClothingUniformJumpskirtCasualBlue + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security + - Command -# Kimono - type: loadout - id: LoadoutClothingKimonoBlue + id: LoadoutUniformJumpsuitCasualPurple category: Uniform - cost: 3 + cost: 2 exclusive: true items: - - ClothingKimonoBlue + - ClothingUniformJumpsuitCasualPurple + requirements: + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Harpy + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security + - Command - type: loadout - id: LoadoutClothingKimonoPink + id: LoadoutUniformJumpskirtCasualPurple category: Uniform - cost: 3 + cost: 2 exclusive: true items: - - ClothingKimonoPink + - ClothingUniformJumpskirtCasualPurple + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security + - Command - type: loadout - id: LoadoutClothingKimonoPurple + id: LoadoutUniformJumpsuitCasualRed category: Uniform - cost: 3 + cost: 2 exclusive: true items: - - ClothingKimonoPurple + - ClothingUniformJumpsuitCasualRed + requirements: + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Harpy + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command - type: loadout - id: LoadoutClothingKimonoSky + id: LoadoutUniformJumpskirtCasualRed category: Uniform - cost: 3 + cost: 2 exclusive: true items: - - ClothingKimonoSky + - ClothingUniformJumpskirtCasualRed + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command - type: loadout - id: LoadoutClothingKimonoGreen + id: LoadoutUniformJumpsuitTshirtJeans category: Uniform - cost: 3 + cost: 2 exclusive: true items: - - ClothingKimonoGreen + - ClothingUniformJumpsuitTshirtJeans + requirements: + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Harpy + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security + - Command -# Gakuran - type: loadout - id: LoadoutUniformSchoolGakuranBlack + id: LoadoutUniformJumpsuitTshirtJeansGray category: Uniform cost: 2 exclusive: true items: - - ClothingUniformSchoolGakuranBlack + - ClothingUniformJumpsuitTshirtJeansGray + requirements: + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Harpy + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command -# MNK Uniforms - type: loadout - id: LoadoutClothingMNKOfficeSkirt + id: LoadoutUniformJumpsuitTshirtJeansPeach category: Uniform - cost: 3 + cost: 2 exclusive: true items: - - ClothingUniformMNKOfficeSkirt + - ClothingUniformJumpsuitTshirtJeansPeach + requirements: + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Harpy + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command - type: loadout - id: LoadoutClothingMNKUnderGarment + id: LoadoutUniformJumpsuitJeansGreen category: Uniform - cost: 3 + cost: 2 exclusive: true items: - - ClothingUniformMNKUnderGarment + - ClothingUniformJumpsuitJeansGreen + requirements: + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Harpy + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security + - Command - type: loadout - id: LoadoutClothingMNKGymBra + id: LoadoutUniformJumpsuitJeansRed category: Uniform - cost: 3 + cost: 2 exclusive: true items: - - ClothingUniformMNKGymBra + - ClothingUniformJumpsuitJeansRed + requirements: + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Harpy + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command - type: loadout - id: LoadoutClothingMNKDressBlack + id: LoadoutUniformJumpsuitJeansBrown category: Uniform - cost: 4 + cost: 2 exclusive: true items: - - ClothingUniformMNKDressBlack + - ClothingUniformJumpsuitJeansBrown + requirements: + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Harpy + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security + - Command - type: loadout - id: LoadoutClothingMNKBlackOveralls + id: LoadoutUniformJumpsuitLostTourist category: Uniform cost: 3 exclusive: true items: - - ClothingUniformMNKBlackOveralls + - ClothingUniformJumpsuitLostTourist + requirements: + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Harpy + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security + - Command +# Hawaiian shirts - type: loadout - id: LoadoutClothingMNKBlackShoulder + id: LoadoutUniformJumpsuitHawaiBlack category: Uniform - cost: 3 + cost: 2 exclusive: true items: - - ClothingUniformMNKBlackShoulder + - ClothingUniformJumpsuitHawaiBlack + requirements: + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Harpy + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security + - Command - type: loadout - id: LoadoutClothingMNKTracksuitBlack + id: LoadoutUniformJumpsuitHawaiBlue category: Uniform - cost: 3 + cost: 2 exclusive: true items: - - ClothingUniformMNKTracksuitBlack + - ClothingUniformJumpsuitHawaiBlue + requirements: + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Harpy + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security + - Command + +- type: loadout + id: LoadoutUniformJumpsuitHawaiRed + category: Uniform + cost: 2 + exclusive: true + items: + - ClothingUniformJumpsuitHawaiRed + requirements: + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Harpy + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command + +- type: loadout + id: LoadoutUniformJumpsuitHawaiYellow + category: Uniform + cost: 2 + exclusive: true + items: + - ClothingUniformJumpsuitHawaiYellow + requirements: + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Harpy + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security + - Command + +# AutoDrobe clothes +- type: loadout + id: LoadoutUniformDressRed + category: Uniform + cost: 4 + exclusive: true + items: + - ClothingUniformDressRed + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command + +- type: loadout + id: LoadoutUniformJumpsuitSober + category: Uniform + cost: 2 + exclusive: true + items: + - ClothingUniformJumpsuitSober + requirements: + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Harpy + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command + +- type: loadout + id: LoadoutUniformSkirtTurtle + category: Uniform + cost: 2 + exclusive: true + items: + - ClothingUniformSkirtTurtle + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command + +- type: loadout + id: LoadoutUniformGeisha + category: Uniform + cost: 3 + exclusive: true + items: + - UniformGeisha + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command + +- type: loadout + id: LoadoutUniformCostumeArcDress + category: Uniform + cost: 2 + exclusive: true + items: + - ClothingCostumeArcDress + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security + - Command + +- type: loadout + id: LoadoutUniformCostumeMioSkirt + category: Uniform + cost: 2 + exclusive: true + items: + - ClothingCostumeMioSkirt + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security + - Command + +- type: loadout + id: LoadoutUniformCostumeNaota + category: Uniform + cost: 2 + exclusive: true + items: + - ClothingCostumeNaota + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security + - Command + +- type: loadout + id: LoadoutUniformJumpsuitLoungewear + category: Uniform + cost: 2 + exclusive: true + items: + - ClothingUniformJumpsuitLoungewear + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command + +# Bartender clothes +- type: loadout + id: LoadoutUniformJumpsuitBartender + category: Uniform + cost: 3 + exclusive: true + items: + - ClothingUniformJumpsuitBartender + requirements: + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Harpy + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security + - Command + +- type: loadout + id: LoadoutUniformJumpskirtBartender + category: Uniform + cost: 3 + exclusive: true + items: + - ClothingUniformJumpskirtBartender + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security + - Command + +# Kendo +- type: loadout + id: LoadoutUniformKendoHakama + category: Uniform + cost: 2 + exclusive: true + items: + - ClothingUniformKendoHakama + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command + +- type: loadout + id: LoadoutUniformMartialGi + category: Uniform + cost: 2 + exclusive: true + items: + - ClothingUniformMartialGi + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security + - Command + +# Kimono +- type: loadout + id: LoadoutClothingJumpsuitKimono + category: Uniform + cost: 3 + exclusive: true + items: + - ClothingUniformJumpsuitKimono + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security + - Command + +- type: loadout + id: LoadoutClothingKimonoBlue + category: Uniform + cost: 3 + exclusive: true + items: + - ClothingKimonoBlue + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security + - Command + +- type: loadout + id: LoadoutClothingKimonoPink + category: Uniform + cost: 3 + exclusive: true + items: + - ClothingKimonoPink + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security + - Command + +- type: loadout + id: LoadoutClothingKimonoPurple + category: Uniform + cost: 3 + exclusive: true + items: + - ClothingKimonoPurple + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security + - Command + +- type: loadout + id: LoadoutClothingKimonoSky + category: Uniform + cost: 3 + exclusive: true + items: + - ClothingKimonoSky + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security + - Command + +- type: loadout + id: LoadoutClothingKimonoGreen + category: Uniform + cost: 3 + exclusive: true + items: + - ClothingKimonoGreen + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security + - Command + +# Gakuran +- type: loadout + id: LoadoutUniformSchoolGakuranBlack + category: Uniform + cost: 2 + exclusive: true + items: + - ClothingUniformSchoolGakuranBlack + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command + +# Schoolgirl uniform +- type: loadout + id: LoadoutUniformSchoolgirlBlack + category: Uniform + cost: 3 + exclusive: true + items: + - UniformSchoolgirlBlack + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command + +- type: loadout + id: LoadoutUniformSchoolgirlBlue + category: Uniform + cost: 3 + exclusive: true + items: + - UniformSchoolgirlBlue + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security + - Command + +- type: loadout + id: LoadoutUniformSchoolgirlCyan + category: Uniform + cost: 3 + exclusive: true + items: + - UniformSchoolgirlCyan + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security + - Command + +- type: loadout + id: LoadoutUniformSchoolgirlGreen + category: Uniform + cost: 3 + exclusive: true + items: + - UniformSchoolgirlGreen + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security + - Command + +- type: loadout + id: LoadoutUniformSchoolgirlOrange + category: Uniform + cost: 3 + exclusive: true + items: + - UniformSchoolgirlOrange + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security + - Command + +- type: loadout + id: LoadoutUniformSchoolgirlPink + category: Uniform + cost: 3 + exclusive: true + items: + - UniformSchoolgirlPink + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security + - Command + +- type: loadout + id: LoadoutUniformSchoolgirlPurple + category: Uniform + cost: 3 + exclusive: true + items: + - UniformSchoolgirlPurple + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security + - Command + +- type: loadout + id: LoadoutUniformSchoolgirlRed + category: Uniform + cost: 3 + exclusive: true + items: + - UniformSchoolgirlRed + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command + +- type: loadout + id: LoadoutUniformSchoolgirlDusk + category: Uniform + cost: 3 + exclusive: true + items: + - UniformSchoolgirlDusk + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security + - Command + +- type: loadout + id: LoadoutUniformSchoolgirlBlazerTan + category: Uniform + cost: 3 + exclusive: true + items: + - UniformSchoolgirlBlazerTan + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Security + - Command + +# MNK Uniforms +- type: loadout + id: LoadoutClothingMNKOfficeSkirt + category: Uniform + cost: 3 + exclusive: true + items: + - ClothingUniformMNKOfficeSkirt + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command + +- type: loadout + id: LoadoutClothingMNKUnderGarment + category: Uniform + cost: 3 + exclusive: true + items: + - ClothingUniformMNKUnderGarment + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command + +- type: loadout + id: LoadoutClothingMNKGymBra + category: Uniform + cost: 3 + exclusive: true + items: + - ClothingUniformMNKGymBra + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command + +- type: loadout + id: LoadoutClothingMNKDressBlack + category: Uniform + cost: 4 + exclusive: true + items: + - ClothingUniformMNKDressBlack + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command + +- type: loadout + id: LoadoutClothingMNKBlackOveralls + category: Uniform + cost: 3 + exclusive: true + items: + - ClothingUniformMNKBlackOveralls + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command + +- type: loadout + id: LoadoutClothingMNKBlackShoulder + category: Uniform + cost: 3 + exclusive: true + items: + - ClothingUniformMNKBlackShoulder + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command + +- type: loadout + id: LoadoutClothingMNKTracksuitBlack + category: Uniform + cost: 3 + exclusive: true + items: + - ClothingUniformMNKTracksuitBlack + requirements: + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command + +# Suits +- type: loadout + id: LoadoutClothingJumpsuitSuitBlack + category: Uniform + cost: 2 + exclusive: true + items: + - ClothingUniformJumpsuitSuitBlack + requirements: + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Harpy + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command + +- type: loadout + id: LoadoutClothingJumpsuitSuitBlackAlt + category: Uniform + cost: 2 + exclusive: true + items: + - ClothingUniformJumpsuitSuitBlackAlt + requirements: + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Harpy + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command + +- type: loadout + id: LoadoutClothingJumpsuitSuitBlackMob + category: Uniform + cost: 2 + exclusive: true + items: + - ClothingUniformJumpsuitSuitBlackMob + requirements: + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Harpy + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command + +- type: loadout + id: LoadoutClothingJumpsuitSuitBrown + category: Uniform + cost: 2 + exclusive: true + items: + - ClothingUniformJumpsuitSuitBrown + requirements: + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Harpy + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command + - Security + +- type: loadout + id: LoadoutClothingJumpsuitSuitBrownAlt + category: Uniform + cost: 2 + exclusive: true + items: + - ClothingUniformJumpsuitSuitBrownAlt + requirements: + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Harpy + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command + +- type: loadout + id: LoadoutClothingJumpsuitSuitBrownMob + category: Uniform + cost: 2 + exclusive: true + items: + - ClothingUniformJumpsuitSuitBrownMob + requirements: + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Harpy + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command + +- type: loadout + id: LoadoutClothingJumpsuitSuitWhite + category: Uniform + cost: 2 + exclusive: true + items: + - ClothingUniformJumpsuitSuitWhite + requirements: + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Harpy + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command + - Security + +- type: loadout + id: LoadoutClothingJumpsuitSuitWhiteAlt + category: Uniform + cost: 2 + exclusive: true + items: + - ClothingUniformJumpsuitSuitWhiteAlt + requirements: + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Harpy + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command + +- type: loadout + id: LoadoutClothingJumpsuitSuitWhiteMob + category: Uniform + cost: 2 + exclusive: true + items: + - ClothingUniformJumpsuitSuitWhiteMob + requirements: + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Harpy + - !type:CharacterDepartmentRequirement + inverted: true + departments: + - Command diff --git a/Resources/Prototypes/Nyanotrasen/Catalog/Fills/Backpacks/StarterGear/backpack.yml b/Resources/Prototypes/Nyanotrasen/Catalog/Fills/Backpacks/StarterGear/backpack.yml index d72e0dd7cd8..810f9ec03b6 100644 --- a/Resources/Prototypes/Nyanotrasen/Catalog/Fills/Backpacks/StarterGear/backpack.yml +++ b/Resources/Prototypes/Nyanotrasen/Catalog/Fills/Backpacks/StarterGear/backpack.yml @@ -5,7 +5,6 @@ components: - type: StorageFill contents: - - id: BoxSurvival # - id: BoxForensicPad # DeltaV - Mantis is no longer a Detective - id: HandLabeler - id: PillMindbreakerToxin diff --git a/Resources/Prototypes/Nyanotrasen/Catalog/Fills/Backpacks/StarterGear/duffelbag.yml b/Resources/Prototypes/Nyanotrasen/Catalog/Fills/Backpacks/StarterGear/duffelbag.yml index 982b820ad10..88e33cdd252 100644 --- a/Resources/Prototypes/Nyanotrasen/Catalog/Fills/Backpacks/StarterGear/duffelbag.yml +++ b/Resources/Prototypes/Nyanotrasen/Catalog/Fills/Backpacks/StarterGear/duffelbag.yml @@ -5,7 +5,6 @@ components: - type: StorageFill contents: - - id: BoxSurvival # - id: BoxForensicPad # DeltaV - Mantis is no longer a Detective - id: HandLabeler - id: PillMindbreakerToxin diff --git a/Resources/Prototypes/Nyanotrasen/Catalog/Fills/Backpacks/StarterGear/satchel.yml b/Resources/Prototypes/Nyanotrasen/Catalog/Fills/Backpacks/StarterGear/satchel.yml index 5644f36c9ce..e90759ac8fb 100644 --- a/Resources/Prototypes/Nyanotrasen/Catalog/Fills/Backpacks/StarterGear/satchel.yml +++ b/Resources/Prototypes/Nyanotrasen/Catalog/Fills/Backpacks/StarterGear/satchel.yml @@ -5,7 +5,6 @@ components: - type: StorageFill contents: - - id: BoxSurvival # - id: BoxForensicPad # DeltaV - Mantis is no longer a Detective - id: HandLabeler - id: PillMindbreakerToxin diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Objects/Materials/materials.yml b/Resources/Prototypes/Nyanotrasen/Entities/Objects/Materials/materials.yml index 75bb4727da2..5aed17363ba 100644 --- a/Resources/Prototypes/Nyanotrasen/Entities/Objects/Materials/materials.yml +++ b/Resources/Prototypes/Nyanotrasen/Entities/Objects/Materials/materials.yml @@ -1,47 +1,3 @@ -- type: entity - parent: MaterialBase - id: MaterialBluespace - suffix: Full - name: bluespace crystal - components: - - type: Sprite - sprite: Nyanotrasen/Objects/Materials/materials.rsi - layers: - - state: bluespace_3 - map: ["base"] - - type: Appearance - - type: Material - - type: PhysicalComposition - materialComposition: - Bluespace: 100 - - type: Tag - tags: - - BluespaceCrystal - - RawMaterial - - type: Stack - stackType: Bluespace - baseLayer: base - layerStates: - - bluespace - - bluespace_2 - - bluespace_3 - count: 5 - - type: Item - size: Small - -- type: entity - parent: MaterialBluespace - id: MaterialBluespace1 - suffix: 1 - components: - - type: Sprite - state: bluespace - - type: Stack - stackType: Bluespace - count: 1 - - type: Item - size: Tiny - - type: entity parent: BaseItem id: HideMothroach diff --git a/Resources/Prototypes/Nyanotrasen/Roles/Jobs/Epistemics/forensicmantis.yml b/Resources/Prototypes/Nyanotrasen/Roles/Jobs/Epistemics/forensicmantis.yml index 15b2cdd4fa7..11ec7441b8e 100644 --- a/Resources/Prototypes/Nyanotrasen/Roles/Jobs/Epistemics/forensicmantis.yml +++ b/Resources/Prototypes/Nyanotrasen/Roles/Jobs/Epistemics/forensicmantis.yml @@ -4,11 +4,11 @@ description: job-description-mantis playTimeTracker: JobForensicMantis requirements: - - !type:OverallPlaytimeRequirement - time: 18000 + - !type:CharacterOverallTimeRequirement + min: 3600 # 1hr floof - !type:DepartmentTimeRequirement - department: Epistemics - time: 3600 + department: Epistemics # DeltaV - Epistemics Department replacing Science + min: 3600 # 1 hr floof startingGear: ForensicMantisGear icon: "JobIconForensicMantis" supervisors: job-supervisors-rd diff --git a/Resources/Prototypes/Nyanotrasen/Roles/Jobs/Security/prisonguard.yml b/Resources/Prototypes/Nyanotrasen/Roles/Jobs/Security/prisonguard.yml index 55d86d343dc..1880474517c 100644 --- a/Resources/Prototypes/Nyanotrasen/Roles/Jobs/Security/prisonguard.yml +++ b/Resources/Prototypes/Nyanotrasen/Roles/Jobs/Security/prisonguard.yml @@ -4,11 +4,11 @@ description: job-description-guard playTimeTracker: JobPrisonGuard requirements: - - !type:OverallPlaytimeRequirement - time: 18000 + - !type:CharacterOverallTimeRequirement + min: 7200 # 2hr floof - !type:DepartmentTimeRequirement department: Security - time: 14400 + min: 7200 # 2hr floof startingGear: PrisonGuardGear alwaysUseSpawner: true canBeAntag: false @@ -30,7 +30,7 @@ equipment: jumpsuit: ClothingUniformJumpsuitPrisonGuard back: ClothingBackpackSecurityFilled - shoes: ClothingShoesBootsJack + shoes: ClothingShoesBootsCombatFilled eyes: ClothingEyesGlassesSecurity head: ClothingHeadPrisonGuard id: PrisonGuardPDA diff --git a/Resources/Prototypes/Nyanotrasen/Roles/Jobs/Wildcards/gladiator.yml b/Resources/Prototypes/Nyanotrasen/Roles/Jobs/Wildcards/gladiator.yml index 27e3f84e9d7..a09cb2ac06b 100644 --- a/Resources/Prototypes/Nyanotrasen/Roles/Jobs/Wildcards/gladiator.yml +++ b/Resources/Prototypes/Nyanotrasen/Roles/Jobs/Wildcards/gladiator.yml @@ -9,7 +9,6 @@ icon: "JobIconGladiator" supervisors: job-supervisors-security setPreference: true -# whitelistRequired: true special: - !type:AddComponentSpecial components: diff --git a/Resources/Prototypes/Nyanotrasen/Roles/Jobs/Wildcards/prisoner.yml b/Resources/Prototypes/Nyanotrasen/Roles/Jobs/Wildcards/prisoner.yml index 8dce5d01fdd..acd98e86f66 100644 --- a/Resources/Prototypes/Nyanotrasen/Roles/Jobs/Wildcards/prisoner.yml +++ b/Resources/Prototypes/Nyanotrasen/Roles/Jobs/Wildcards/prisoner.yml @@ -6,9 +6,9 @@ startingGear: PrisonerGear alwaysUseSpawner: true canBeAntag: false -# whitelistRequired: true icon: "JobIconPrisoner" supervisors: job-supervisors-security + - type: startingGear id: PrisonerGear equipment: diff --git a/Resources/Prototypes/Nyanotrasen/Species/Oni.yml b/Resources/Prototypes/Nyanotrasen/Species/Oni.yml index ee8be0e5892..a6a63b29526 100644 --- a/Resources/Prototypes/Nyanotrasen/Species/Oni.yml +++ b/Resources/Prototypes/Nyanotrasen/Species/Oni.yml @@ -35,8 +35,8 @@ points: 1 required: false Legs: - points: 2 + points: 6 required: false Arms: - points: 2 + points: 6 required: false diff --git a/Resources/Prototypes/Nyanotrasen/Species/felinid.yml b/Resources/Prototypes/Nyanotrasen/Species/felinid.yml index 4751d581746..5eb26edd518 100644 --- a/Resources/Prototypes/Nyanotrasen/Species/felinid.yml +++ b/Resources/Prototypes/Nyanotrasen/Species/felinid.yml @@ -35,8 +35,8 @@ points: 1 required: false Legs: - points: 2 + points: 6 required: false Arms: - points: 2 + points: 6 required: false diff --git a/Resources/Prototypes/Objectives/objectiveGroups.yml b/Resources/Prototypes/Objectives/objectiveGroups.yml index b68f695050b..0bfc31bee19 100644 --- a/Resources/Prototypes/Objectives/objectiveGroups.yml +++ b/Resources/Prototypes/Objectives/objectiveGroups.yml @@ -26,6 +26,7 @@ LOLuckyBillStealObjective: 0.5 # DeltaV - LO steal objective, see Resources/Prototypes/DeltaV/Objectives/traitor.yml HoPBookIanDossierStealObjective: 1 # DeltaV - HoP steal objective, see Resources/Prototypes/DeltaV/Objectives/traitor.yml HoSGunStealObjective: 0.5 + StealSupermatterSliverObjective: 0.5 - type: weightedRandom id: TraitorObjectiveGroupKill diff --git a/Resources/Prototypes/Objectives/stealTargetGroups.yml b/Resources/Prototypes/Objectives/stealTargetGroups.yml index 11e503d7940..e93c9c319da 100644 --- a/Resources/Prototypes/Objectives/stealTargetGroups.yml +++ b/Resources/Prototypes/Objectives/stealTargetGroups.yml @@ -1,5 +1,12 @@ # Traitor single items +- type: stealTargetGroup + id: SupermatterSliver + name: supermatter sliver + sprite: + sprite: Supermatter/supermatter_sliver.rsi + state: icon + - type: stealTargetGroup id: Hypospray name: hypospray diff --git a/Resources/Prototypes/Objectives/traitor.yml b/Resources/Prototypes/Objectives/traitor.yml index ffeba32546d..d9c071c30c0 100644 --- a/Resources/Prototypes/Objectives/traitor.yml +++ b/Resources/Prototypes/Objectives/traitor.yml @@ -309,3 +309,15 @@ - type: StealCondition stealGroup: NukeDisk owner: objective-condition-steal-station + +- type: entity + noSpawn: true + parent: BaseTraitorStealObjective + id: StealSupermatterSliverObjective + components: + - type: Objective + difficulty: 3.5 + - type: StealCondition + stealGroup: SupermatterSliver + objectiveNoOwnerText: objective-condition-steal-smsliver-title + descriptionText: objective-condition-steal-smsliver-description \ No newline at end of file diff --git a/Resources/Prototypes/Nyanotrasen/Reagents/psionic.yml b/Resources/Prototypes/Reagents/psionic.yml similarity index 100% rename from Resources/Prototypes/Nyanotrasen/Reagents/psionic.yml rename to Resources/Prototypes/Reagents/psionic.yml diff --git a/Resources/Prototypes/Recipes/Lathes/security.yml b/Resources/Prototypes/Recipes/Lathes/security.yml index ffa74d460f9..08e11e4ff82 100644 --- a/Resources/Prototypes/Recipes/Lathes/security.yml +++ b/Resources/Prototypes/Recipes/Lathes/security.yml @@ -30,6 +30,15 @@ Steel: 300 Plastic: 300 +- type: latheRecipe + id: CombatKnife + result: CombatKnife + category: Weapons + completetime: 2 + materials: + Steel: 250 + Plastic: 100 + - type: latheRecipe id: WeaponLaserCarbine result: WeaponLaserCarbine diff --git a/Resources/Prototypes/Roles/Antags/ninja.yml b/Resources/Prototypes/Roles/Antags/ninja.yml index 23027805a1c..70833745290 100644 --- a/Resources/Prototypes/Roles/Antags/ninja.yml +++ b/Resources/Prototypes/Roles/Antags/ninja.yml @@ -5,5 +5,5 @@ setPreference: false objective: roles-antag-space-ninja-objective requirements: - - !type:OverallPlaytimeRequirement # DeltaV - Playtime requirement - time: 259200 # DeltaV - 72 hours + - !type:CharacterOverallTimeRequirement # DeltaV - Playtime requirement + min: 14400 # floof - 4 hours diff --git a/Resources/Prototypes/Roles/Antags/nukeops.yml b/Resources/Prototypes/Roles/Antags/nukeops.yml index 7375c02639c..4a3ff4309b8 100644 --- a/Resources/Prototypes/Roles/Antags/nukeops.yml +++ b/Resources/Prototypes/Roles/Antags/nukeops.yml @@ -5,11 +5,11 @@ setPreference: true objective: roles-antag-nuclear-operative-objective requirements: - - !type:OverallPlaytimeRequirement - time: 108000 # DeltaV - 30 hours - - !type:DepartmentTimeRequirement # DeltaV - Security dept time requirement + - !type:CharacterOverallTimeRequirement + min: 54000 # Floofstation - 15 hours + - !type:CharacterDepartmentTimeRequirement # DeltaV - Security dept time requirement department: Security - time: 36000 # DeltaV - 10 hours + min: 14400 # Floofstation - 4 hours - type: antag id: NukeopsMedic @@ -18,11 +18,11 @@ setPreference: true objective: roles-antag-nuclear-operative-agent-objective requirements: - - !type:OverallPlaytimeRequirement - time: 108000 # DeltaV - 30 hours - - !type:DepartmentTimeRequirement # DeltaV - Medical dept time requirement + - !type:CharacterOverallTimeRequirement + min: 54000 # Floofstation - 15 hours + - !type:CharacterDepartmentTimeRequirement # DeltaV - Medical dept time requirement department: Medical - time: 36000 # DeltaV - 10 hours + min: 14400 # Floofstation - 4 hours - type: antag id: NukeopsCommander @@ -31,12 +31,12 @@ setPreference: true objective: roles-antag-nuclear-operative-commander-objective requirements: - - !type:OverallPlaytimeRequirement - time: 216000 # DeltaV - 60 hours - - !type:DepartmentTimeRequirement # DeltaV - Security dept time requirement + - !type:CharacterOverallTimeRequirement + min: 54000 # Floofstation - 15 hours + - !type:CharacterDepartmentTimeRequirement # DeltaV - Security dept time requirement department: Security - time: 36000 # DeltaV - 10 hours - - !type:DepartmentTimeRequirement # DeltaV - Command dept time requirement + min: 14400 # Floofstation - 4 hours + - !type:CharacterDepartmentTimeRequirement # DeltaV - Command dept time requirement department: Command - time: 36000 # DeltaV - 10 hours + min: 14400 # Floofstation - 4 hours - !type:WhitelistRequirement # DeltaV - Whitelist requirement diff --git a/Resources/Prototypes/Roles/Antags/revolutionary.yml b/Resources/Prototypes/Roles/Antags/revolutionary.yml index 6f22bd1d58a..35423747c0a 100644 --- a/Resources/Prototypes/Roles/Antags/revolutionary.yml +++ b/Resources/Prototypes/Roles/Antags/revolutionary.yml @@ -5,11 +5,11 @@ setPreference: true objective: roles-antag-rev-head-objective requirements: - - !type:OverallPlaytimeRequirement # DeltaV - Playtime requirement - time: 172800 # DeltaV - 48 hours - - !type:DepartmentTimeRequirement # DeltaV - Command dept time requirement + - !type:CharacterOverallTimeRequirement # DeltaV - Playtime requirement + min: 54000 # Floofstation - 15 hours + - !type:CharacterDepartmentTimeRequirement # DeltaV - Command dept time requirement department: Command - time: 36000 # DeltaV - 10 hours + min: 14400 # Floofstation - 4 hours - type: antag id: Rev diff --git a/Resources/Prototypes/Roles/Antags/traitor.yml b/Resources/Prototypes/Roles/Antags/traitor.yml index 98fdb0ee47d..2034b248d33 100644 --- a/Resources/Prototypes/Roles/Antags/traitor.yml +++ b/Resources/Prototypes/Roles/Antags/traitor.yml @@ -5,5 +5,5 @@ setPreference: true objective: roles-antag-syndicate-agent-objective requirements: - - !type:OverallPlaytimeRequirement # DeltaV - Playtime requirement - time: 86400 # DeltaV - 24 hours + - !type:CharacterOverallTimeRequirement # DeltaV - Playtime requirement + min: 14400 # Floofstation - 4 hours diff --git a/Resources/Prototypes/Roles/Antags/zombie.yml b/Resources/Prototypes/Roles/Antags/zombie.yml index 6ff0f17edc7..9bce4a2789d 100644 --- a/Resources/Prototypes/Roles/Antags/zombie.yml +++ b/Resources/Prototypes/Roles/Antags/zombie.yml @@ -5,8 +5,8 @@ setPreference: true objective: roles-antag-initial-infected-objective requirements: - - !type:OverallPlaytimeRequirement # DeltaV - Playtime requirement - time: 43200 # DeltaV - 12 hours + - !type:CharacterOverallTimeRequirement # DeltaV - Playtime requirement + min: 14400 # Floofstation - 4 hours - type: antag id: Zombie diff --git a/Resources/Prototypes/Roles/Jobs/Cargo/quartermaster.yml b/Resources/Prototypes/Roles/Jobs/Cargo/quartermaster.yml index b03dd8abad6..07104382ecd 100644 --- a/Resources/Prototypes/Roles/Jobs/Cargo/quartermaster.yml +++ b/Resources/Prototypes/Roles/Jobs/Cargo/quartermaster.yml @@ -5,9 +5,12 @@ playTimeTracker: JobQuartermaster antagAdvantage: 6 # DeltaV - Reduced TC: Head of Staff requirements: - - !type:DepartmentTimeRequirement + # - !type:RoleTimeRequirement #DeltaV + # role: JobCargoTechnician + # time: 21600 #6 hrs + - !type:CharacterDepartmentTimeRequirement department: Logistics # DeltaV - Logistics Department replacing Cargo - time: 3600 #DeltaV 1 hour + min: 14400 #Floofstation 4 hour weight: 10 startingGear: QuartermasterGear icon: "JobIconQuarterMaster" diff --git a/Resources/Prototypes/Roles/Jobs/Command/captain.yml b/Resources/Prototypes/Roles/Jobs/Command/captain.yml index 14ec96f4e2f..8e5e7a26efa 100644 --- a/Resources/Prototypes/Roles/Jobs/Command/captain.yml +++ b/Resources/Prototypes/Roles/Jobs/Command/captain.yml @@ -4,24 +4,24 @@ description: job-description-captain playTimeTracker: JobCaptain requirements: - - !type:DepartmentTimeRequirement + - !type:CharacterDepartmentTimeRequirement department: Logistics # DeltaV - Logistics Department replacing Cargo - time: 3600 # 1 hour - - !type:DepartmentTimeRequirement + min: 14400 # Floofstation - 4 hour + - !type:CharacterDepartmentTimeRequirement department: Engineering - time: 3600 # 1 hour - - !type:DepartmentTimeRequirement + min: 14400 # Floofstation - 4 hour + - !type:CharacterDepartmentTimeRequirement department: Medical - time: 3600 # 1 hours - - !type:DepartmentTimeRequirement + min: 14400 # Floofstation - 4 hour + - !type:CharacterDepartmentTimeRequirement department: Security - time: 3600 # 1 hours - - !type:DepartmentTimeRequirement # DeltaV - Epistemics dept time requirement + min: 14400 # Floofstation - 4 hour + - !type:CharacterDepartmentTimeRequirement # DeltaV - Epistemics dept time requirement department: Epistemics # DeltaV - Epistemics Department replacing Science - time: 3600 # 1 hours - - !type:DepartmentTimeRequirement + min: 14400 # Floofstation - 4 hour + - !type:CharacterDepartmentTimeRequirement department: Command - time: 3600 # 1 hours + min: 14400 # Floofstation - 4 hour weight: 20 startingGear: CaptainGear icon: "JobIconCaptain" diff --git a/Resources/Prototypes/Roles/Jobs/Command/head_of_personnel.yml b/Resources/Prototypes/Roles/Jobs/Command/head_of_personnel.yml index 3bd97f518e4..7f9764fdfe4 100644 --- a/Resources/Prototypes/Roles/Jobs/Command/head_of_personnel.yml +++ b/Resources/Prototypes/Roles/Jobs/Command/head_of_personnel.yml @@ -5,9 +5,9 @@ playTimeTracker: JobHeadOfPersonnel antagAdvantage: 6 # DeltaV - Reduced TC: Head of Staff requirements: - - !type:DepartmentTimeRequirement # DeltaV - Civilian dept time requirement + - !type:CharacterDepartmentTimeRequirement # DeltaV - Civilian dept time requirement department: Civilian - time: 3600 # 1 hour + min: 14400 # Floofstation 4 hours weight: 10 # DeltaV - Changed HoP weight from 20 to 10 due to them not being more important than other Heads startingGear: HoPGear icon: "JobIconHeadOfPersonnel" diff --git a/Resources/Prototypes/Roles/Jobs/Engineering/atmospheric_technician.yml b/Resources/Prototypes/Roles/Jobs/Engineering/atmospheric_technician.yml index 6371978425d..79f682cf3ed 100644 --- a/Resources/Prototypes/Roles/Jobs/Engineering/atmospheric_technician.yml +++ b/Resources/Prototypes/Roles/Jobs/Engineering/atmospheric_technician.yml @@ -3,6 +3,10 @@ name: job-name-atmostech description: job-description-atmostech playTimeTracker: JobAtmosphericTechnician + requirements: + - !type:CharacterDepartmentTimeRequirement + department: Engineering + min: 3600 # Floofstation - 1 hour antagAdvantage: 10 # DeltaV - Reduced TC: External Access + Fireaxe + Free Hardsuit startingGear: AtmosphericTechnicianGear icon: "JobIconAtmosphericTechnician" diff --git a/Resources/Prototypes/Roles/Jobs/Engineering/chief_engineer.yml b/Resources/Prototypes/Roles/Jobs/Engineering/chief_engineer.yml index bbf2f28d89b..7bc6d6a1adb 100644 --- a/Resources/Prototypes/Roles/Jobs/Engineering/chief_engineer.yml +++ b/Resources/Prototypes/Roles/Jobs/Engineering/chief_engineer.yml @@ -4,11 +4,9 @@ description: job-description-ce playTimeTracker: JobChiefEngineer requirements: - - !type:DepartmentTimeRequirement + - !type:CharacterDepartmentTimeRequirement department: Engineering - time: 3600 # DeltaV - 25 hours -# - !type:OverallPlaytimeRequirement -# time: 72000 # DeltaV - 20 hours + min: 14400 # Floofstation - 4 hour weight: 10 startingGear: ChiefEngineerGear icon: "JobIconChiefEngineer" diff --git a/Resources/Prototypes/Roles/Jobs/Engineering/senior_engineer.yml b/Resources/Prototypes/Roles/Jobs/Engineering/senior_engineer.yml index 2d7ac9c3e11..df88432dd8b 100644 --- a/Resources/Prototypes/Roles/Jobs/Engineering/senior_engineer.yml +++ b/Resources/Prototypes/Roles/Jobs/Engineering/senior_engineer.yml @@ -4,6 +4,10 @@ description: job-description-senior-engineer playTimeTracker: JobSeniorEngineer setPreference: false # DeltaV - Disable Senior Roles round start selection + requirements: + - !type:CharacterDepartmentTimeRequirement + department: Engineering + min: 14400 # Floofstation 4 hrs startingGear: SeniorEngineerGear icon: "JobIconSeniorEngineer" supervisors: job-supervisors-ce diff --git a/Resources/Prototypes/Roles/Jobs/Engineering/station_engineer.yml b/Resources/Prototypes/Roles/Jobs/Engineering/station_engineer.yml index 7e685a33b52..5e905f59bff 100644 --- a/Resources/Prototypes/Roles/Jobs/Engineering/station_engineer.yml +++ b/Resources/Prototypes/Roles/Jobs/Engineering/station_engineer.yml @@ -3,6 +3,9 @@ name: job-name-engineer description: job-description-engineer playTimeTracker: JobStationEngineer + requirements: + - !type:CharacterOverallTimeRequirement + min: 14400 # 4hr floof antagAdvantage: 3 # DeltaV - Reduced TC: External Access + Engineering startingGear: StationEngineerGear icon: "JobIconStationEngineer" diff --git a/Resources/Prototypes/Roles/Jobs/Engineering/technical_assistant.yml b/Resources/Prototypes/Roles/Jobs/Engineering/technical_assistant.yml index 116065f1fae..ea441566588 100644 --- a/Resources/Prototypes/Roles/Jobs/Engineering/technical_assistant.yml +++ b/Resources/Prototypes/Roles/Jobs/Engineering/technical_assistant.yml @@ -3,6 +3,9 @@ name: job-name-technical-assistant description: job-description-technical-assistant playTimeTracker: JobTechnicalAssistant + requirements: + - !type:CharacterOverallTimeRequirement + min: 3600 # 1hr floof antagAdvantage: 3 # DeltaV - Reduced TC: External Access + Engineering startingGear: TechnicalAssistantGear icon: "JobIconTechnicalAssistant" diff --git a/Resources/Prototypes/Roles/Jobs/Medical/chief_medical_officer.yml b/Resources/Prototypes/Roles/Jobs/Medical/chief_medical_officer.yml index 07f35d2cd7c..02f399ee8db 100644 --- a/Resources/Prototypes/Roles/Jobs/Medical/chief_medical_officer.yml +++ b/Resources/Prototypes/Roles/Jobs/Medical/chief_medical_officer.yml @@ -7,9 +7,9 @@ playTimeTracker: JobChiefMedicalOfficer antagAdvantage: 6 # DeltaV - Reduced TC: Head of Staff requirements: - - !type:DepartmentTimeRequirement + - !type:CharacterDepartmentTimeRequirement department: Medical - time: 3600 # DeltaV - 12 hours + min: 14400 # Floofstation - 4 hour weight: 10 startingGear: CMOGear icon: "JobIconChiefMedicalOfficer" diff --git a/Resources/Prototypes/Roles/Jobs/Medical/senior_physician.yml b/Resources/Prototypes/Roles/Jobs/Medical/senior_physician.yml index e63b1a121be..4cca9e57bc1 100644 --- a/Resources/Prototypes/Roles/Jobs/Medical/senior_physician.yml +++ b/Resources/Prototypes/Roles/Jobs/Medical/senior_physician.yml @@ -4,6 +4,10 @@ description: job-description-senior-physician playTimeTracker: JobSeniorPhysician setPreference: false # DeltaV - Disable Senior Roles round start selection + requirements: + - !type:CharacterDepartmentTimeRequirement + department: Medical + min: 14400 # Floofstation 4 hrs startingGear: SeniorPhysicianGear icon: "JobIconSeniorPhysician" supervisors: job-supervisors-cmo diff --git a/Resources/Prototypes/Roles/Jobs/Science/borg.yml b/Resources/Prototypes/Roles/Jobs/Science/borg.yml index c3efd2a64ac..e62be04beec 100644 --- a/Resources/Prototypes/Roles/Jobs/Science/borg.yml +++ b/Resources/Prototypes/Roles/Jobs/Science/borg.yml @@ -4,8 +4,8 @@ description: job-description-borg playTimeTracker: JobBorg requirements: - - !type:OverallPlaytimeRequirement - time: 3600 #60 hrs + - !type:CharacterOverallTimeRequirement + min: 3600 #1 hr canBeAntag: false icon: JobIconBorg supervisors: job-supervisors-rd diff --git a/Resources/Prototypes/Roles/Jobs/Science/research_assistant.yml b/Resources/Prototypes/Roles/Jobs/Science/research_assistant.yml index 4d4038d7c02..20bbe131bb0 100644 --- a/Resources/Prototypes/Roles/Jobs/Science/research_assistant.yml +++ b/Resources/Prototypes/Roles/Jobs/Science/research_assistant.yml @@ -3,11 +3,6 @@ name: job-name-research-assistant description: job-description-research-assistant playTimeTracker: JobResearchAssistant - requirements: - # - !type:DepartmentTimeRequirement # DeltaV - Removes time limit - # department: Science - # time: 54000 #15 hrs - # inverted: true # stop playing intern if you're good at science! startingGear: ResearchAssistantGear icon: "JobIconResearchAssistant" supervisors: job-supervisors-science diff --git a/Resources/Prototypes/Roles/Jobs/Science/research_director.yml b/Resources/Prototypes/Roles/Jobs/Science/research_director.yml index 9051a6c618b..e6de7e4cac3 100644 --- a/Resources/Prototypes/Roles/Jobs/Science/research_director.yml +++ b/Resources/Prototypes/Roles/Jobs/Science/research_director.yml @@ -5,9 +5,9 @@ playTimeTracker: JobResearchDirector antagAdvantage: 6 requirements: - - !type:DepartmentTimeRequirement + - !type:CharacterDepartmentTimeRequirement department: Epistemics # DeltaV - Epistemics Department replacing Science - time: 3600 # DeltaV - 15 hours + min: 14400 # Floofstation - 4 hour weight: 10 startingGear: ResearchDirectorGear icon: "JobIconResearchDirector" diff --git a/Resources/Prototypes/Roles/Jobs/Science/senior_researcher.yml b/Resources/Prototypes/Roles/Jobs/Science/senior_researcher.yml index ee63fa9b715..dd6dbeca721 100644 --- a/Resources/Prototypes/Roles/Jobs/Science/senior_researcher.yml +++ b/Resources/Prototypes/Roles/Jobs/Science/senior_researcher.yml @@ -4,6 +4,10 @@ description: job-description-senior-researcher playTimeTracker: JobSeniorResearcher setPreference: false # DeltaV - Disable Senior Roles round start selection + requirements: + - !type:CharacterDepartmentTimeRequirement + department: Epistemics # DeltaV - Epistemics Department replacing Science + min: 14400 # Floofstation 4 hrs startingGear: SeniorResearcherGear icon: "JobIconSeniorResearcher" supervisors: job-supervisors-rd diff --git a/Resources/Prototypes/Roles/Jobs/Security/detective.yml b/Resources/Prototypes/Roles/Jobs/Security/detective.yml index 665d2e07f13..e90fa4d759e 100644 --- a/Resources/Prototypes/Roles/Jobs/Security/detective.yml +++ b/Resources/Prototypes/Roles/Jobs/Security/detective.yml @@ -4,8 +4,9 @@ description: job-description-detective playTimeTracker: JobDetective requirements: - - !type:OverallPlaytimeRequirement - time: 3600 # DeltaV - 1 hour + - !type:CharacterDepartmentTimeRequirement + department: Security + min: 14400 # Floofstation - 4 hour startingGear: DetectiveGear icon: "JobIconDetective" supervisors: job-supervisors-hos @@ -16,6 +17,8 @@ - Maintenance - Service - Detective + - External + - Cryogenics special: - !type:AddImplantSpecial implants: [ MindShieldImplant ] diff --git a/Resources/Prototypes/Roles/Jobs/Security/head_of_security.yml b/Resources/Prototypes/Roles/Jobs/Security/head_of_security.yml index 97f1caa5501..bde72f9b020 100644 --- a/Resources/Prototypes/Roles/Jobs/Security/head_of_security.yml +++ b/Resources/Prototypes/Roles/Jobs/Security/head_of_security.yml @@ -4,9 +4,9 @@ description: job-description-hos playTimeTracker: JobHeadOfSecurity requirements: - - !type:DepartmentTimeRequirement + - !type:CharacterDepartmentTimeRequirement # DeltaV - Command dept time requirement department: Security - time: 3600 # 60 hrs + min: 14400 # Floofstation - 4 hour weight: 10 startingGear: HoSGear icon: "JobIconHeadOfSecurity" diff --git a/Resources/Prototypes/Roles/Jobs/Security/security_cadet.yml b/Resources/Prototypes/Roles/Jobs/Security/security_cadet.yml index 2dc344128f0..b2333f3d0ed 100644 --- a/Resources/Prototypes/Roles/Jobs/Security/security_cadet.yml +++ b/Resources/Prototypes/Roles/Jobs/Security/security_cadet.yml @@ -4,8 +4,8 @@ description: job-description-cadet playTimeTracker: JobSecurityCadet requirements: - - !type:OverallPlaytimeRequirement - time: 3600 # DeltaV - 1 hour + - !type:CharacterOverallTimeRequirement + min: 3600 # Floofstation - 1 hour startingGear: SecurityCadetGear icon: "JobIconSecurityCadet" supervisors: job-supervisors-security diff --git a/Resources/Prototypes/Roles/Jobs/Security/security_officer.yml b/Resources/Prototypes/Roles/Jobs/Security/security_officer.yml index 64d290ff956..c55f10a4662 100644 --- a/Resources/Prototypes/Roles/Jobs/Security/security_officer.yml +++ b/Resources/Prototypes/Roles/Jobs/Security/security_officer.yml @@ -4,8 +4,9 @@ description: job-description-security playTimeTracker: JobSecurityOfficer requirements: - - !type:OverallPlaytimeRequirement - time: 3600 # DeltaV - 1 hour + - !type:CharacterDepartmentTimeRequirement + department: Security + min: 3600 # Floofstation - 1 hour startingGear: SecurityOfficerGear icon: "JobIconSecurityOfficer" supervisors: job-supervisors-hos diff --git a/Resources/Prototypes/Roles/Jobs/Security/senior_officer.yml b/Resources/Prototypes/Roles/Jobs/Security/senior_officer.yml index 4b78db87edc..6940d74bb25 100644 --- a/Resources/Prototypes/Roles/Jobs/Security/senior_officer.yml +++ b/Resources/Prototypes/Roles/Jobs/Security/senior_officer.yml @@ -5,8 +5,9 @@ playTimeTracker: JobSeniorOfficer setPreference: false # DeltaV - Disable Senior Roles round start selection requirements: - - !type:OverallPlaytimeRequirement - time: 3600 # DeltaV - 1 hour + - !type:CharacterDepartmentTimeRequirement + department: Security + min: 3600 # Floofstation - 1 hour startingGear: SeniorOfficerGear icon: "JobIconSeniorOfficer" supervisors: job-supervisors-hos diff --git a/Resources/Prototypes/Roles/Jobs/Security/warden.yml b/Resources/Prototypes/Roles/Jobs/Security/warden.yml index 9f94f14743f..59d1e08656c 100644 --- a/Resources/Prototypes/Roles/Jobs/Security/warden.yml +++ b/Resources/Prototypes/Roles/Jobs/Security/warden.yml @@ -4,8 +4,9 @@ description: job-description-warden playTimeTracker: JobWarden requirements: - - !type:OverallPlaytimeRequirement - time: 3600 # DeltaV - 1 hour + - !type:CharacterDepartmentTimeRequirement + department: Security + min: 3600 # Floofstation - 1 hour startingGear: WardenGear icon: "JobIconWarden" supervisors: job-supervisors-hos diff --git a/Resources/Prototypes/Species/arachnid.yml b/Resources/Prototypes/Species/arachnid.yml index 07a72cda176..5dedba1b447 100644 --- a/Resources/Prototypes/Species/arachnid.yml +++ b/Resources/Prototypes/Species/arachnid.yml @@ -64,10 +64,10 @@ points: 1 required: false Legs: - points: 2 + points: 6 required: false Arms: - points: 2 + points: 6 required: false - type: humanoidBaseSprite diff --git a/Resources/Prototypes/Species/human.yml b/Resources/Prototypes/Species/human.yml index 94b21ec9620..49f8839cac3 100644 --- a/Resources/Prototypes/Species/human.yml +++ b/Resources/Prototypes/Species/human.yml @@ -56,10 +56,10 @@ points: 1 required: false Legs: - points: 2 + points: 6 required: false Arms: - points: 2 + points: 6 required: false - type: humanoidBaseSprite diff --git a/Resources/Prototypes/Species/moth.yml b/Resources/Prototypes/Species/moth.yml index fb41b526db4..b0d965eafb8 100644 --- a/Resources/Prototypes/Species/moth.yml +++ b/Resources/Prototypes/Species/moth.yml @@ -68,10 +68,10 @@ points: 1 required: false Legs: - points: 2 + points: 6 required: false Arms: - points: 2 + points: 6 required: false - type: humanoidBaseSprite diff --git a/Resources/Prototypes/Species/reptilian.yml b/Resources/Prototypes/Species/reptilian.yml index 752918e2f0c..dc5a56534b4 100644 --- a/Resources/Prototypes/Species/reptilian.yml +++ b/Resources/Prototypes/Species/reptilian.yml @@ -65,10 +65,10 @@ points: 1 required: false Legs: - points: 2 + points: 6 required: false Arms: - points: 2 + points: 6 required: false - type: humanoidBaseSprite diff --git a/Resources/Prototypes/Traits/neutral.yml b/Resources/Prototypes/Traits/neutral.yml index 28f6adc170a..ab5bcb238d7 100644 --- a/Resources/Prototypes/Traits/neutral.yml +++ b/Resources/Prototypes/Traits/neutral.yml @@ -31,7 +31,6 @@ - type: trait id: NormalVision category: Visual - points: -1 requirements: - !type:CharacterSpeciesRequirement species: diff --git a/Resources/Prototypes/Traits/skills.yml b/Resources/Prototypes/Traits/skills.yml index 250696c1a88..16b628a56d8 100644 --- a/Resources/Prototypes/Traits/skills.yml +++ b/Resources/Prototypes/Traits/skills.yml @@ -26,3 +26,42 @@ stealth: Subtle stripTimeReduction: 0 stripTimeMultiplier: 0.667 + requirements: + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Felinid + +- type: trait + id: SignLanguage + category: Visual + points: -1 + components: + - type: LanguageKnowledgeModifier + speaks: + - Sign + understands: + - Sign + +- type: trait + id: Voracious + category: Physical + points: -1 + components: + - type: ConsumeDelayModifier + foodDelayMultiplier: 0.5 + drinkDelayMultiplier: 0.5 + +- type: trait + id: LightStep + category: Auditory + points: -1 + components: + - type: FootstepVolumeModifier + sprintVolumeModifier: -10 + walkVolumeModifier: -10 + requirements: + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Felinid diff --git a/Resources/Prototypes/explosion.yml b/Resources/Prototypes/explosion.yml index 1eaf4f52ff4..7ef2e774a71 100644 --- a/Resources/Prototypes/explosion.yml +++ b/Resources/Prototypes/explosion.yml @@ -117,3 +117,19 @@ lightColor: Orange texturePath: /Textures/Effects/fire.rsi fireStates: 6 + +- type: explosion + id: Supermatter + damagePerIntensity: + types: + Radiation: 5 + Heat: 4 + Blunt: 3 + Piercing: 3 + tileBreakChance: [0, 0.5, 1] + tileBreakIntensity: [0, 10, 30] + tileBreakRerollReduction: 20 + lightColor: Yellow + fireColor: Green + texturePath: /Textures/Effects/fire_greyscale.rsi + fireStates: 3 diff --git a/Resources/Prototypes/game_presets.yml b/Resources/Prototypes/game_presets.yml index 7e83f224433..7d7169bf10a 100644 --- a/Resources/Prototypes/game_presets.yml +++ b/Resources/Prototypes/game_presets.yml @@ -20,17 +20,6 @@ - HellshiftStationEventScheduler - BasicRoundstartVariation -- type: gamePreset - id: SurvivalLonger - alias: - - longsurvival - showInVote: true - name: longsurvival-title - description: longsurvival-description - rules: - - LongSurvivalStationEventScheduler - - BasicRoundstartVariation - - type: gamePreset id: AllAtOnce name: all-at-once-title diff --git a/Resources/Prototypes/tags.yml b/Resources/Prototypes/tags.yml index c2e46d5f590..9b0ad51cfb6 100644 --- a/Resources/Prototypes/tags.yml +++ b/Resources/Prototypes/tags.yml @@ -1119,10 +1119,10 @@ id: SmallMech - type: Tag - id: SnapPop + id: Smokable - type: Tag - id: Smokable + id: SnapPop - type: Tag id: SnowyLabs diff --git a/Resources/ServerInfo/Guidebook/Engineering/Supermatter.xml b/Resources/ServerInfo/Guidebook/Engineering/Supermatter.xml new file mode 100644 index 00000000000..6e89df44324 --- /dev/null +++ b/Resources/ServerInfo/Guidebook/Engineering/Supermatter.xml @@ -0,0 +1,65 @@ + + + + + # The Supermatter Engine + + So you've decided to take on the challenge and set up the Supermatter Engine? First, let's give you a short overview of the main Supermatter crystal beforehand. + + Its primary features are emitting electrical arcs that are harnessed to power the station through tesla coils. + + Side effects include radiation emission, releasing hot oxygen and plasma, heating the air around, and exploding, transforming into a black hole or an energy ball and eating the entire station if you screw up hard enough. + + It begins inert but being hit by an object or a projectile will activate it and it'll start exhibiting nearly all of the aforementioned properties. + + ## Words of Warning + + 1. The Supermatter crystal is [color=red]VERY DANGEROUS[/color]. Activating the crystal should be the last step in setting up any form of Supermatter based power! + + 2. [color=red]PUT YOUR RADIATION SUIT ON[/color]. + + 3. Most the Supermatter setup involves a gas loop that is designed to cool down the Supermatter chamber. Please have at least some knowledge of gases and their atmospheric properties. + + 4. Anything that bumps into the Supermatter is [color=red]fundamentally annihilated[/color]. [color=red]Do not touch it[/color]. This means weld and bolt the door to the chamber. + + ## Gas Interactions + + Here's a list of all gases from least dangerous to most dangerous. + + 1. [color=#bffffe]Frezon[/color]. Aside from cooling down the Supermatter, it basically stops power and waste production, which may come handy if the Supermatter is close to delaminating and you need to shut it down fast. + + 2. [color=#c20000]Nitrogen[/color]. N2 is the basic gas most Supermatter setups will run exclusively, being very simple to set up for. It dampens the power generation from heat, and reduces the amount of plasma the SM belches out, making it good for when you aren't trying to do something silly. + + 3. [color=#b16d6d]Nitrous oxide[/color]. Reinforces the heat resistance of the crystal, allowing for much hotter setups than usual. However, at high temperatures it will decompose into Nitrogen and Oxygen. While N2 is good, O2 certainly is not. This O2 will also react with the Plasma to create Tritium and then a Tritium fire. + + 4. [color=#62d5ca]Oxygen[/color]. Provides a boost to power transmission without actively increasing the waste gas amount or temperature. Pretty risky to use, as any disruption of the cooling loop will soon cause a plasma fire in the crystal chamber. Even just a high concentration of O2 will activate and continuously power the crystal. + + 5. [color=#19b348]Ammonia[/color]. Increases the power generation slightly at a minor cost to the heat penalty. + + 6. [color=#979797]Carbon Dioxide[/color]. In low concentrations, it will increase the crystal's power generation. In high concentrations it will raise the crystal's energy to extremely high levels. With poor management and insufficient or downright bad preparation, it will eventually exceed safe energy levels and begin a charge delamination, producing electric arcs and anomalies until it eventually explodes into a Tesla ball. + + [color=red]7[/color]. [color=#ff9d00]Plasma[/color]. Very similar to Oxygen but provides a higher power boost as well as a much higher waste and heat penalty. The extreme pressures and volumes of gas produced by this gas are very likely to clog pipes and overheat the chamber. + + [color=red]8[/color]. [color=#08a800]Tritium[/color]. Increases the power production of the Supermatter by up to 3 times, there is one slight issue with it. It is dangerous. It is very dangerous. Tritium is a horrifyingly irritable and jumpy gas. While it isn't as harmful to the heat level as Plasma is (just barely), it also has the second worst heat capacity of all gasses while Plasma has the second highest. This means that Plasma can be kept happy with enough cooling, whereas Tritium eagerly goes from a safe space loop into a burning hellfire. Add to this the byproduct of large amounts of Oxygen production (not exclusive to Tritium, an issue in a Plasma engine too), and you have a tritium fire and a very hot crystal. Do not use this gas unless you have a very strong understanding of atmospherics and the Supermatter, and are willing to get creative. + + ## Practical guide to the Supermatter + + Now, forget about everything you've just read and get to setting up the most basic loop there is: the Nitrogen loop. + + The atmospheric setup in its' most basic form should look like this: + + (We did not have enough budget for images, here is a text representation) + + 1. Nitrogen gets pumped into the chamber by passive vents from one side + + 2. Every gas gets pumped out of the chamber by using scrubbers set on Siphon on the other side. + + 3. The output gets filtered, cooled down, and excess nitrogen gets either routed into space or rerouted into the input. + + That's basically it. I hope you understand at least something in this example. Now get to it! + + ## Experiment + + You're not a real engineer if you haven't figured out the most efficient way to produce electricity using the Supermatter crystal, are you? + + \ No newline at end of file diff --git a/Resources/Textures/DeltaV/Mobs/Customization/Vulpkanin/tail_markings.rsi/corgi.png b/Resources/Textures/DeltaV/Mobs/Customization/Vulpkanin/tail_markings.rsi/corgi.png new file mode 100644 index 00000000000..fc9cb1c8917 Binary files /dev/null and b/Resources/Textures/DeltaV/Mobs/Customization/Vulpkanin/tail_markings.rsi/corgi.png differ diff --git a/Resources/Textures/DeltaV/Mobs/Customization/Vulpkanin/tail_markings.rsi/dalmatian.png b/Resources/Textures/DeltaV/Mobs/Customization/Vulpkanin/tail_markings.rsi/dalmatian.png new file mode 100644 index 00000000000..74d7e7cf9a2 Binary files /dev/null and b/Resources/Textures/DeltaV/Mobs/Customization/Vulpkanin/tail_markings.rsi/dalmatian.png differ diff --git a/Resources/Textures/DeltaV/Mobs/Customization/Vulpkanin/tail_markings.rsi/meta.json b/Resources/Textures/DeltaV/Mobs/Customization/Vulpkanin/tail_markings.rsi/meta.json index 15211a3bda6..2ae83a80f2e 100644 --- a/Resources/Textures/DeltaV/Mobs/Customization/Vulpkanin/tail_markings.rsi/meta.json +++ b/Resources/Textures/DeltaV/Mobs/Customization/Vulpkanin/tail_markings.rsi/meta.json @@ -96,6 +96,10 @@ "directions": 4, "delays": [[0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2], [0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2], [0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2], [0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2]] }, + { + "name": "corgi", + "directions": 4 + }, { "name": "corgi_wag", "directions": 4, @@ -137,6 +141,10 @@ "name": "fluffy", "directions": 4 }, + { + "name": "dalmatian", + "directions": 4 + }, { "name": "dalmatian_wag", "directions": 4, diff --git a/Resources/Textures/Interface/Actions/wagging.rsi/icon-on.png b/Resources/Textures/Interface/Actions/wagging.rsi/icon-on.png new file mode 100644 index 00000000000..4901ced9215 Binary files /dev/null and b/Resources/Textures/Interface/Actions/wagging.rsi/icon-on.png differ diff --git a/Resources/Textures/Interface/Actions/wagging.rsi/icon.png b/Resources/Textures/Interface/Actions/wagging.rsi/icon.png new file mode 100644 index 00000000000..6dbb54fe2f2 Binary files /dev/null and b/Resources/Textures/Interface/Actions/wagging.rsi/icon.png differ diff --git a/Resources/Textures/Interface/Actions/wagging.rsi/meta.json b/Resources/Textures/Interface/Actions/wagging.rsi/meta.json new file mode 100644 index 00000000000..022930052e5 --- /dev/null +++ b/Resources/Textures/Interface/Actions/wagging.rsi/meta.json @@ -0,0 +1,17 @@ +{ + "version": 1, + "license": "CC0-1.0", + "copyright": "Created by dootythefrooty (Discord 273243513800622090)", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + }, + { + "name": "icon-on" + } + ] +} diff --git a/Resources/Textures/Interface/Misc/health_icons.rsi/Critical.png b/Resources/Textures/Interface/Misc/health_icons.rsi/Critical.png index 779874eaaeb..15a49721745 100644 Binary files a/Resources/Textures/Interface/Misc/health_icons.rsi/Critical.png and b/Resources/Textures/Interface/Misc/health_icons.rsi/Critical.png differ diff --git a/Resources/Textures/Interface/Misc/health_icons.rsi/Dead.png b/Resources/Textures/Interface/Misc/health_icons.rsi/Dead.png index beceebd05cf..8cebd954186 100644 Binary files a/Resources/Textures/Interface/Misc/health_icons.rsi/Dead.png and b/Resources/Textures/Interface/Misc/health_icons.rsi/Dead.png differ diff --git a/Resources/Textures/Mobs/Aliens/Xenos/rouny.rsi/crit.png b/Resources/Textures/Mobs/Aliens/Xenos/rouny.rsi/crit.png index 0be8b9b1ddb..23a7ec0af6c 100644 Binary files a/Resources/Textures/Mobs/Aliens/Xenos/rouny.rsi/crit.png and b/Resources/Textures/Mobs/Aliens/Xenos/rouny.rsi/crit.png differ diff --git a/Resources/Textures/Mobs/Aliens/Xenos/rouny.rsi/dead.png b/Resources/Textures/Mobs/Aliens/Xenos/rouny.rsi/dead.png index 2761d22dbf7..cd355b61529 100644 Binary files a/Resources/Textures/Mobs/Aliens/Xenos/rouny.rsi/dead.png and b/Resources/Textures/Mobs/Aliens/Xenos/rouny.rsi/dead.png differ diff --git a/Resources/Textures/Mobs/Aliens/Xenos/rouny.rsi/meta.json b/Resources/Textures/Mobs/Aliens/Xenos/rouny.rsi/meta.json index ce2209e72dd..cc020d01c46 100644 --- a/Resources/Textures/Mobs/Aliens/Xenos/rouny.rsi/meta.json +++ b/Resources/Textures/Mobs/Aliens/Xenos/rouny.rsi/meta.json @@ -1,24 +1,24 @@ { - "version": 1, - "license": "CC-BY-SA-3.0", - "copyright": "https://github.com/tgstation/TerraGov-Marine-Corps/blob/a2034543920664ddf0c0f3c681bf1d8003dc2ade/icons/Xeno/2x2_Xenos.dmi", - "size": { - "x": 64, - "y": 64 - }, - "states": [ - { - "name": "running", - "directions": 4 + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "DakoDragon, discord ID: 56038550335922176", + "size": { + "x": 64, + "y": 64 }, - { - "name": "sleeping" - }, - { - "name": "dead" - }, - { - "name": "crit" - } - ] + "states": [ + { + "name": "running", + "directions": 4 + }, + { + "name": "sleeping" + }, + { + "name": "dead" + }, + { + "name": "crit" + } + ] } diff --git a/Resources/Textures/Mobs/Aliens/Xenos/rouny.rsi/running.png b/Resources/Textures/Mobs/Aliens/Xenos/rouny.rsi/running.png index 2bbe1c603eb..1438285113f 100644 Binary files a/Resources/Textures/Mobs/Aliens/Xenos/rouny.rsi/running.png and b/Resources/Textures/Mobs/Aliens/Xenos/rouny.rsi/running.png differ diff --git a/Resources/Textures/Mobs/Aliens/Xenos/rouny.rsi/sleeping.png b/Resources/Textures/Mobs/Aliens/Xenos/rouny.rsi/sleeping.png index 06ff2250d0e..9221665dd85 100644 Binary files a/Resources/Textures/Mobs/Aliens/Xenos/rouny.rsi/sleeping.png and b/Resources/Textures/Mobs/Aliens/Xenos/rouny.rsi/sleeping.png differ diff --git a/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_alt1.rsi/head.png b/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_alt1.rsi/head.png new file mode 100644 index 00000000000..81c98564b9a Binary files /dev/null and b/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_alt1.rsi/head.png differ diff --git a/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_alt1.rsi/meta.json b/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_alt1.rsi/meta.json new file mode 100644 index 00000000000..9f87381cd87 --- /dev/null +++ b/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_alt1.rsi/meta.json @@ -0,0 +1,15 @@ +{ + "version": 1, + "copyright": "Sprites from Paradise Station (https://github.com/ParadiseSS13/Paradise)", + "license": "CC-BY-SA-3.0", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "head", + "directions": 4 + } + ] +} \ No newline at end of file diff --git a/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/head.png b/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/head.png new file mode 100644 index 00000000000..a89de820f47 Binary files /dev/null and b/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/head.png differ diff --git a/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/l_arm-primary.png b/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/l_arm-primary.png new file mode 100644 index 00000000000..5d6b133523b Binary files /dev/null and b/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/l_arm-primary.png differ diff --git a/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/l_arm-secondary.png b/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/l_arm-secondary.png new file mode 100644 index 00000000000..de40773897f Binary files /dev/null and b/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/l_arm-secondary.png differ diff --git a/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/l_arm-tertiary.png b/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/l_arm-tertiary.png new file mode 100644 index 00000000000..7b83ecf161b Binary files /dev/null and b/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/l_arm-tertiary.png differ diff --git a/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/l_foot.png b/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/l_foot.png new file mode 100644 index 00000000000..534085a97c3 Binary files /dev/null and b/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/l_foot.png differ diff --git a/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/l_hand.png b/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/l_hand.png new file mode 100644 index 00000000000..771cd025a86 Binary files /dev/null and b/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/l_hand.png differ diff --git a/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/l_leg-primary.png b/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/l_leg-primary.png new file mode 100644 index 00000000000..05f568654e6 Binary files /dev/null and b/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/l_leg-primary.png differ diff --git a/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/l_leg-secondary.png b/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/l_leg-secondary.png new file mode 100644 index 00000000000..a96f9eb3854 Binary files /dev/null and b/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/l_leg-secondary.png differ diff --git a/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/meta.json b/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/meta.json new file mode 100644 index 00000000000..a3e6753cc44 --- /dev/null +++ b/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/meta.json @@ -0,0 +1,79 @@ +{ + "version": 1, + "copyright": "Sprites originally from Paradise Station (https://github.com/ParadiseSS13/Paradise). Monochromatic version made by: DayOS (https://github.com/Day-OS)", + "license": "CC-BY-SA-3.0", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "l_foot", + "directions": 4 + }, + { + "name": "r_foot", + "directions": 4 + }, + { + "name": "l_leg-primary", + "directions": 4 + }, + { + "name": "l_leg-secondary", + "directions": 4 + }, + { + "name": "r_leg-primary", + "directions": 4 + }, + { + "name": "r_leg-secondary", + "directions": 4 + }, + { + "name": "torso-primary", + "directions": 4 + }, + { + "name": "torso-secondary", + "directions": 4 + }, + { + "name": "l_arm-primary", + "directions": 4 + }, + { + "name": "l_arm-secondary", + "directions": 4 + }, + { + "name": "l_arm-tertiary", + "directions": 4 + }, + { + "name": "r_arm-primary", + "directions": 4 + }, + { + "name": "r_arm-secondary", + "directions": 4 + }, + { + "name": "r_arm-tertiary", + "directions": 4 + }, + { + "name": "l_hand", + "directions": 4 + }, + { + "name": "r_hand", + "directions": 4 + }, + { + "name": "head", + "directions": 4 + } + ] +} \ No newline at end of file diff --git a/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/r_arm-primary.png b/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/r_arm-primary.png new file mode 100644 index 00000000000..c8087d3fc19 Binary files /dev/null and b/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/r_arm-primary.png differ diff --git a/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/r_arm-secondary.png b/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/r_arm-secondary.png new file mode 100644 index 00000000000..2cf2346bd84 Binary files /dev/null and b/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/r_arm-secondary.png differ diff --git a/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/r_arm-tertiary.png b/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/r_arm-tertiary.png new file mode 100644 index 00000000000..0b5cecfd6c3 Binary files /dev/null and b/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/r_arm-tertiary.png differ diff --git a/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/r_foot.png b/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/r_foot.png new file mode 100644 index 00000000000..a8fbe8635ea Binary files /dev/null and b/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/r_foot.png differ diff --git a/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/r_hand.png b/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/r_hand.png new file mode 100644 index 00000000000..db11be34056 Binary files /dev/null and b/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/r_hand.png differ diff --git a/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/r_leg-primary.png b/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/r_leg-primary.png new file mode 100644 index 00000000000..d6288eedc3c Binary files /dev/null and b/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/r_leg-primary.png differ diff --git a/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/r_leg-secondary.png b/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/r_leg-secondary.png new file mode 100644 index 00000000000..7a406c93187 Binary files /dev/null and b/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/r_leg-secondary.png differ diff --git a/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/torso-primary.png b/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/torso-primary.png new file mode 100644 index 00000000000..08cabfc99dc Binary files /dev/null and b/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/torso-primary.png differ diff --git a/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/torso-secondary.png b/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/torso-secondary.png new file mode 100644 index 00000000000..4e61c144a95 Binary files /dev/null and b/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_main.rsi/torso-secondary.png differ diff --git a/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_monitor.rsi/head-2.png b/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_monitor.rsi/head-2.png new file mode 100644 index 00000000000..ca3cb6e9e36 Binary files /dev/null and b/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_monitor.rsi/head-2.png differ diff --git a/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_monitor.rsi/head.png b/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_monitor.rsi/head.png new file mode 100644 index 00000000000..a175f4dfcec Binary files /dev/null and b/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_monitor.rsi/head.png differ diff --git a/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_monitor.rsi/meta.json b/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_monitor.rsi/meta.json new file mode 100644 index 00000000000..ea5456fea10 --- /dev/null +++ b/Resources/Textures/Mobs/Customization/cyberlimbs/bishop/bishop_monitor.rsi/meta.json @@ -0,0 +1,19 @@ +{ + "version": 1, + "copyright": "Sprites originally from Paradise Station (https://github.com/ParadiseSS13/Paradise). Monochromatic version made by: DayOS (https://github.com/Day-OS)", + "license": "CC-BY-SA-3.0", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "head", + "directions": 4 + }, + { + "name": "head-2", + "directions": 4 + } + ] +} \ No newline at end of file diff --git a/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_alt1.rsi/head.png b/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_alt1.rsi/head.png new file mode 100644 index 00000000000..b6446e6a6d2 Binary files /dev/null and b/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_alt1.rsi/head.png differ diff --git a/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_alt1.rsi/meta.json b/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_alt1.rsi/meta.json new file mode 100644 index 00000000000..9f87381cd87 --- /dev/null +++ b/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_alt1.rsi/meta.json @@ -0,0 +1,15 @@ +{ + "version": 1, + "copyright": "Sprites from Paradise Station (https://github.com/ParadiseSS13/Paradise)", + "license": "CC-BY-SA-3.0", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "head", + "directions": 4 + } + ] +} \ No newline at end of file diff --git a/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/l_arm-1.png b/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/l_arm-1.png new file mode 100644 index 00000000000..54ecbe28321 Binary files /dev/null and b/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/l_arm-1.png differ diff --git a/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/l_arm-2.png b/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/l_arm-2.png new file mode 100644 index 00000000000..c9a529d9ebb Binary files /dev/null and b/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/l_arm-2.png differ diff --git a/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/l_foot-1.png b/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/l_foot-1.png new file mode 100644 index 00000000000..a4e96f5d745 Binary files /dev/null and b/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/l_foot-1.png differ diff --git a/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/l_foot-2.png b/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/l_foot-2.png new file mode 100644 index 00000000000..6be2024018b Binary files /dev/null and b/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/l_foot-2.png differ diff --git a/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/l_hand-1.png b/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/l_hand-1.png new file mode 100644 index 00000000000..87466284b3b Binary files /dev/null and b/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/l_hand-1.png differ diff --git a/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/l_hand-2.png b/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/l_hand-2.png new file mode 100644 index 00000000000..b871a179333 Binary files /dev/null and b/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/l_hand-2.png differ diff --git a/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/l_leg-1.png b/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/l_leg-1.png new file mode 100644 index 00000000000..880384f5ee9 Binary files /dev/null and b/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/l_leg-1.png differ diff --git a/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/l_leg-2.png b/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/l_leg-2.png new file mode 100644 index 00000000000..90b10eb4be5 Binary files /dev/null and b/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/l_leg-2.png differ diff --git a/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/meta.json b/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/meta.json new file mode 100644 index 00000000000..9f4ca1ee51f --- /dev/null +++ b/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/meta.json @@ -0,0 +1,83 @@ +{ + "version": 1, + "copyright": "Sprites originally from Paradise Station (https://github.com/ParadiseSS13/Paradise). Monochromatic version made by: DayOS (https://github.com/Day-OS)", + "license": "CC-BY-SA-3.0", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "l_foot-1", + "directions": 4 + }, + { + "name": "l_foot-2", + "directions": 4 + }, + { + "name": "r_foot-1", + "directions": 4 + }, + { + "name": "r_foot-2", + "directions": 4 + }, + { + "name": "l_leg-1", + "directions": 4 + }, + { + "name": "l_leg-2", + "directions": 4 + }, + { + "name": "r_leg-1", + "directions": 4 + }, + { + "name": "r_leg-2", + "directions": 4 + }, + { + "name": "torso-1", + "directions": 4 + }, + { + "name": "torso-2", + "directions": 4 + }, + { + "name": "l_arm-1", + "directions": 4 + }, + { + "name": "l_arm-2", + "directions": 4 + }, + { + "name": "r_arm-1", + "directions": 4 + }, + { + "name": "r_arm-2", + "directions": 4 + }, + { + "name": "l_hand-1", + "directions": 4 + }, + { + "name": "l_hand-2", + "directions": 4 + }, + { + "name": "r_hand-1", + "directions": 4 + }, + { + "name": "r_hand-2", + "directions": 4 + } + ] +} \ No newline at end of file diff --git a/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/r_arm-1.png b/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/r_arm-1.png new file mode 100644 index 00000000000..5e770056ed9 Binary files /dev/null and b/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/r_arm-1.png differ diff --git a/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/r_arm-2.png b/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/r_arm-2.png new file mode 100644 index 00000000000..56b363d862a Binary files /dev/null and b/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/r_arm-2.png differ diff --git a/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/r_foot-1.png b/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/r_foot-1.png new file mode 100644 index 00000000000..8994994011c Binary files /dev/null and b/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/r_foot-1.png differ diff --git a/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/r_foot-2.png b/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/r_foot-2.png new file mode 100644 index 00000000000..9ca884025fd Binary files /dev/null and b/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/r_foot-2.png differ diff --git a/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/r_hand-1.png b/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/r_hand-1.png new file mode 100644 index 00000000000..13a46c2e092 Binary files /dev/null and b/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/r_hand-1.png differ diff --git a/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/r_hand-2.png b/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/r_hand-2.png new file mode 100644 index 00000000000..d203e571fca Binary files /dev/null and b/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/r_hand-2.png differ diff --git a/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/r_leg-1.png b/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/r_leg-1.png new file mode 100644 index 00000000000..bb762db0c49 Binary files /dev/null and b/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/r_leg-1.png differ diff --git a/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/r_leg-2.png b/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/r_leg-2.png new file mode 100644 index 00000000000..16f0ee16471 Binary files /dev/null and b/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/r_leg-2.png differ diff --git a/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/torso-1.png b/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/torso-1.png new file mode 100644 index 00000000000..45fb93052e4 Binary files /dev/null and b/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/torso-1.png differ diff --git a/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/torso-2.png b/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/torso-2.png new file mode 100644 index 00000000000..a8782ac3b04 Binary files /dev/null and b/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_main.rsi/torso-2.png differ diff --git a/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_monitor.rsi/head-1.png b/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_monitor.rsi/head-1.png new file mode 100644 index 00000000000..21e0ccbbcb8 Binary files /dev/null and b/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_monitor.rsi/head-1.png differ diff --git a/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_monitor.rsi/head-2.png b/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_monitor.rsi/head-2.png new file mode 100644 index 00000000000..0d351d8822a Binary files /dev/null and b/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_monitor.rsi/head-2.png differ diff --git a/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_monitor.rsi/meta.json b/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_monitor.rsi/meta.json new file mode 100644 index 00000000000..9d2654d15cb --- /dev/null +++ b/Resources/Textures/Mobs/Customization/cyberlimbs/hesphiastos/hesphiastos_monitor.rsi/meta.json @@ -0,0 +1,19 @@ +{ + "version": 1, + "copyright": "Sprites originally from Paradise Station (https://github.com/ParadiseSS13/Paradise). Monochromatic version made by: DayOS (https://github.com/Day-OS)", + "license": "CC-BY-SA-3.0", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "head-1", + "directions": 4 + }, + { + "name": "head-2", + "directions": 4 + } + ] +} \ No newline at end of file diff --git a/Resources/Textures/Mobs/Customization/makeup.rsi/blush.png b/Resources/Textures/Mobs/Customization/makeup.rsi/blush.png new file mode 100644 index 00000000000..9e672df8c31 Binary files /dev/null and b/Resources/Textures/Mobs/Customization/makeup.rsi/blush.png differ diff --git a/Resources/Textures/Mobs/Customization/makeup.rsi/lips.png b/Resources/Textures/Mobs/Customization/makeup.rsi/lips.png new file mode 100644 index 00000000000..1e5034a92fb Binary files /dev/null and b/Resources/Textures/Mobs/Customization/makeup.rsi/lips.png differ diff --git a/Resources/Textures/Mobs/Customization/makeup.rsi/meta.json b/Resources/Textures/Mobs/Customization/makeup.rsi/meta.json new file mode 100644 index 00000000000..422f1eec834 --- /dev/null +++ b/Resources/Textures/Mobs/Customization/makeup.rsi/meta.json @@ -0,0 +1,35 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Sprites by angelofallars (github)", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "lips", + "directions": 4 + }, + { + "name": "blush", + "directions": 4 + }, + { + "name": "nail_polish_l", + "directions": 4 + }, + { + "name": "nail_polish_r", + "directions": 4 + }, + { + "name": "moth_lips", + "directions": 4 + }, + { + "name": "moth_blush", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/Mobs/Customization/makeup.rsi/moth_blush.png b/Resources/Textures/Mobs/Customization/makeup.rsi/moth_blush.png new file mode 100644 index 00000000000..c66a862be01 Binary files /dev/null and b/Resources/Textures/Mobs/Customization/makeup.rsi/moth_blush.png differ diff --git a/Resources/Textures/Mobs/Customization/makeup.rsi/moth_lips.png b/Resources/Textures/Mobs/Customization/makeup.rsi/moth_lips.png new file mode 100644 index 00000000000..72c6f57c6ef Binary files /dev/null and b/Resources/Textures/Mobs/Customization/makeup.rsi/moth_lips.png differ diff --git a/Resources/Textures/Mobs/Customization/makeup.rsi/nail_polish_l.png b/Resources/Textures/Mobs/Customization/makeup.rsi/nail_polish_l.png new file mode 100644 index 00000000000..73175b4e2c8 Binary files /dev/null and b/Resources/Textures/Mobs/Customization/makeup.rsi/nail_polish_l.png differ diff --git a/Resources/Textures/Mobs/Customization/makeup.rsi/nail_polish_r.png b/Resources/Textures/Mobs/Customization/makeup.rsi/nail_polish_r.png new file mode 100644 index 00000000000..6ce26ba4aec Binary files /dev/null and b/Resources/Textures/Mobs/Customization/makeup.rsi/nail_polish_r.png differ diff --git a/Resources/Textures/Objects/Storage/boxes.rsi/box.png b/Resources/Textures/Objects/Storage/boxes.rsi/box.png index e62e0f699fb..08c3cc3129b 100644 Binary files a/Resources/Textures/Objects/Storage/boxes.rsi/box.png and b/Resources/Textures/Objects/Storage/boxes.rsi/box.png differ diff --git a/Resources/Textures/Objects/Storage/boxes.rsi/box_hug.png b/Resources/Textures/Objects/Storage/boxes.rsi/box_hug.png index f9f0e4dbf3d..d00717065f9 100644 Binary files a/Resources/Textures/Objects/Storage/boxes.rsi/box_hug.png and b/Resources/Textures/Objects/Storage/boxes.rsi/box_hug.png differ diff --git a/Resources/Textures/Objects/Storage/boxes.rsi/box_of_doom.png b/Resources/Textures/Objects/Storage/boxes.rsi/box_of_doom.png index 50379bb4752..7f72fb85a44 100644 Binary files a/Resources/Textures/Objects/Storage/boxes.rsi/box_of_doom.png and b/Resources/Textures/Objects/Storage/boxes.rsi/box_of_doom.png differ diff --git a/Resources/Textures/Objects/Storage/boxes.rsi/box_of_doom_big.png b/Resources/Textures/Objects/Storage/boxes.rsi/box_of_doom_big.png index 00833bb163c..cbfd43456b9 100644 Binary files a/Resources/Textures/Objects/Storage/boxes.rsi/box_of_doom_big.png and b/Resources/Textures/Objects/Storage/boxes.rsi/box_of_doom_big.png differ diff --git a/Resources/Textures/Objects/Storage/boxes.rsi/box_olive.png b/Resources/Textures/Objects/Storage/boxes.rsi/box_olive.png index 4ddd8ac4fbf..db0d3b1ffd1 100644 Binary files a/Resources/Textures/Objects/Storage/boxes.rsi/box_olive.png and b/Resources/Textures/Objects/Storage/boxes.rsi/box_olive.png differ diff --git a/Resources/Textures/Objects/Storage/boxes.rsi/box_science.png b/Resources/Textures/Objects/Storage/boxes.rsi/box_science.png index de33c9b97e5..f0222fe9231 100644 Binary files a/Resources/Textures/Objects/Storage/boxes.rsi/box_science.png and b/Resources/Textures/Objects/Storage/boxes.rsi/box_science.png differ diff --git a/Resources/Textures/Objects/Storage/boxes.rsi/meta.json b/Resources/Textures/Objects/Storage/boxes.rsi/meta.json index 53ac39b639b..b30927da33c 100644 --- a/Resources/Textures/Objects/Storage/boxes.rsi/meta.json +++ b/Resources/Textures/Objects/Storage/boxes.rsi/meta.json @@ -1,7 +1,7 @@ { "version": 1, "license": "CC-BY-SA-3.0", - "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/cc65477c04f7403ca8a457bd5bae69a01abadbf0, encryptokey was taken from Baystation12 at https://github.com/infinitystation/Baystation12/blob/073f678cdce92edb8fcd55f9ffc9f0523bf31506/icons/obj/radio.dmi and modified by lapatison. boxwidetoy, shelltoy, swab, flare, inflatable, trashbag, magazine, holo and forensic created by potato1234x (github) for ss14 based on toys.rsi, mouth_swab.rsi, flare.rsi, inflatable_wall.rsi, trashbag.rsi, caseless_pistol_mag.rsi, guardians.rsi and bureaucracy.rsi respectively, candle and darts created by TheShuEd for ss14, throwing_knives and vials was drawn by Ubaser, evidence_markers by moomoobeef.", + "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/cc65477c04f7403ca8a457bd5bae69a01abadbf0, encryptokey was taken from Baystation12 at https://github.com/infinitystation/Baystation12/blob/073f678cdce92edb8fcd55f9ffc9f0523bf31506/icons/obj/radio.dmi and modified by lapatison. boxwidetoy, shelltoy, swab, flare, inflatable, trashbag, magazine, holo and forensic created by potato1234x (github) for ss14 based on toys.rsi, mouth_swab.rsi, flare.rsi, inflatable_wall.rsi, trashbag.rsi, caseless_pistol_mag.rsi, guardians.rsi and bureaucracy.rsi respectively, candle and darts created by TheShuEd for ss14, throwing_knives and vials was drawn by Ubaser, evidence_markers by moomoobeef, Boxes by mefinks.", "size": { "x": 32, "y": 32 diff --git a/Resources/Textures/Objects/Weapons/Bombs/breaching.rsi/icon.png b/Resources/Textures/Objects/Weapons/Bombs/breaching.rsi/icon.png new file mode 100644 index 00000000000..5bd58663b6e Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Bombs/breaching.rsi/icon.png differ diff --git a/Resources/Textures/Objects/Weapons/Bombs/breaching.rsi/inhand-left.png b/Resources/Textures/Objects/Weapons/Bombs/breaching.rsi/inhand-left.png new file mode 100644 index 00000000000..4ea978c6992 Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Bombs/breaching.rsi/inhand-left.png differ diff --git a/Resources/Textures/Objects/Weapons/Bombs/breaching.rsi/inhand-right.png b/Resources/Textures/Objects/Weapons/Bombs/breaching.rsi/inhand-right.png new file mode 100644 index 00000000000..2b675ecabf5 Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Bombs/breaching.rsi/inhand-right.png differ diff --git a/Resources/Textures/Objects/Weapons/Bombs/breaching.rsi/meta.json b/Resources/Textures/Objects/Weapons/Bombs/breaching.rsi/meta.json new file mode 100644 index 00000000000..678ffd9abd5 --- /dev/null +++ b/Resources/Textures/Objects/Weapons/Bombs/breaching.rsi/meta.json @@ -0,0 +1,31 @@ + { + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "made by rosieposieeee (github) for ss14", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + }, + { + "name": "primed", + "delays": [ + [ + 0.1, + 0.1 + ] + ] + }, + { + "name": "inhand-left", + "directions": 4 + }, + { + "name": "inhand-right", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/Objects/Weapons/Bombs/breaching.rsi/primed.png b/Resources/Textures/Objects/Weapons/Bombs/breaching.rsi/primed.png new file mode 100644 index 00000000000..135cc2d3492 Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Bombs/breaching.rsi/primed.png differ diff --git a/Resources/Textures/Supermatter/supermatter.rsi/meta.json b/Resources/Textures/Supermatter/supermatter.rsi/meta.json new file mode 100644 index 00000000000..6bca0558a89 --- /dev/null +++ b/Resources/Textures/Supermatter/supermatter.rsi/meta.json @@ -0,0 +1,15 @@ +{ + "version": 1, + "copyright": "Taken and edited from https://tgstation13.org/wiki/images/a/a4/Supermatter-bg.gif", + "license": "CC-BY-SA-3.0", + "size": { + "x": 32, + "y": 48 + }, + "states": [ + { + "name": "supermatter", + "delays": [ [ 0.08, 0.08, 0.08 ] ] + } + ] +} \ No newline at end of file diff --git a/Resources/Textures/Supermatter/supermatter.rsi/supermatter.png b/Resources/Textures/Supermatter/supermatter.rsi/supermatter.png new file mode 100644 index 00000000000..0c5747a315f Binary files /dev/null and b/Resources/Textures/Supermatter/supermatter.rsi/supermatter.png differ diff --git a/Resources/Textures/Supermatter/supermatter_sliver.rsi/icon.png b/Resources/Textures/Supermatter/supermatter_sliver.rsi/icon.png new file mode 100644 index 00000000000..2187706b107 Binary files /dev/null and b/Resources/Textures/Supermatter/supermatter_sliver.rsi/icon.png differ diff --git a/Resources/Textures/Supermatter/supermatter_sliver.rsi/meta.json b/Resources/Textures/Supermatter/supermatter_sliver.rsi/meta.json new file mode 100644 index 00000000000..f157223291c --- /dev/null +++ b/Resources/Textures/Supermatter/supermatter_sliver.rsi/meta.json @@ -0,0 +1,14 @@ +{ + "version": 1, + "copyright": "Taken and edited from https://github.com/tgstation/tgstation/blob/master/icons/obj/antags/syndicate_tools.dmi", + "license": "CC-BY-SA-3.0", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + } + ] +} \ No newline at end of file diff --git a/Resources/toolshedEngineCommandPerms.yml b/Resources/toolshedEngineCommandPerms.yml index ac7ffddd5f9..97de43e0b1f 100644 --- a/Resources/toolshedEngineCommandPerms.yml +++ b/Resources/toolshedEngineCommandPerms.yml @@ -50,7 +50,8 @@ - methods - ioc -- Commands: +- Flags: ADMIN + Commands: - fuck - ent - as