diff --git a/Content.Client/Flight/Components/FlightVisualsComponent.cs b/Content.Client/Flight/Components/FlightVisualsComponent.cs new file mode 100644 index 0000000000..3f378f60ef --- /dev/null +++ b/Content.Client/Flight/Components/FlightVisualsComponent.cs @@ -0,0 +1,40 @@ +using Robust.Client.Graphics; +using Robust.Shared.GameStates; + +namespace Content.Client.Flight.Components; + +[RegisterComponent] +public sealed partial class FlightVisualsComponent : Component +{ + /// + /// How long does the animation last + /// + [DataField] + public float Speed; + + /// + /// How far it goes in any direction. + /// + [DataField] + public float Multiplier; + + /// + /// How much the limbs (if there are any) rotate. + /// + [DataField] + public float Offset; + + /// + /// Are we animating layers or the entire sprite? + /// + public bool AnimateLayer = false; + public int? TargetLayer; + + [DataField] + public string AnimationKey = "default"; + + [ViewVariables(VVAccess.ReadWrite)] + public ShaderInstance Shader = default!; + + +} \ No newline at end of file diff --git a/Content.Client/Flight/FlightSystem.cs b/Content.Client/Flight/FlightSystem.cs new file mode 100644 index 0000000000..bd1a6767bd --- /dev/null +++ b/Content.Client/Flight/FlightSystem.cs @@ -0,0 +1,67 @@ +using Robust.Client.GameObjects; +using Content.Shared.Flight; +using Content.Shared.Flight.Events; +using Content.Client.Flight.Components; + +namespace Content.Client.Flight; +public sealed class FlightSystem : SharedFlightSystem +{ + [Dependency] private readonly IEntityManager _entityManager = default!; + public override void Initialize() + { + base.Initialize(); + + SubscribeNetworkEvent(OnFlight); + + } + + private void OnFlight(FlightEvent args) + { + var uid = GetEntity(args.Uid); + if (!_entityManager.TryGetComponent(uid, out SpriteComponent? sprite) + || !args.IsAnimated + || !_entityManager.TryGetComponent(uid, out FlightComponent? flight)) + return; + + + int? targetLayer = null; + if (flight.IsLayerAnimated && flight.Layer is not null) + { + targetLayer = GetAnimatedLayer(uid, flight.Layer, sprite); + if (targetLayer == null) + return; + } + + if (args.IsFlying && args.IsAnimated && flight.AnimationKey != "default") + { + var comp = new FlightVisualsComponent + { + AnimateLayer = flight.IsLayerAnimated, + AnimationKey = flight.AnimationKey, + Multiplier = flight.ShaderMultiplier, + Offset = flight.ShaderOffset, + Speed = flight.ShaderSpeed, + TargetLayer = targetLayer, + }; + AddComp(uid, comp); + } + if (!args.IsFlying) + RemComp(uid); + } + + public int? GetAnimatedLayer(EntityUid uid, string targetLayer, SpriteComponent? sprite = null) + { + if (!Resolve(uid, ref sprite)) + return null; + + int index = 0; + foreach (var layer in sprite.AllLayers) + { + // This feels like absolute shitcode, isn't there a better way to check for it? + if (layer.Rsi?.Path.ToString() == targetLayer) + return index; + index++; + } + return null; + } +} \ No newline at end of file diff --git a/Content.Client/Flight/FlyingVisualizerSystem.cs b/Content.Client/Flight/FlyingVisualizerSystem.cs new file mode 100644 index 0000000000..6dde6cf563 --- /dev/null +++ b/Content.Client/Flight/FlyingVisualizerSystem.cs @@ -0,0 +1,64 @@ +using Content.Client.Flight.Components; +using Robust.Client.GameObjects; +using Robust.Client.Graphics; +using Robust.Shared.Prototypes; + +namespace Content.Client.Flight; + +/// +/// Handles offsetting an entity while flying +/// +public sealed class FlyingVisualizerSystem : EntitySystem +{ + [Dependency] private readonly IPrototypeManager _protoMan = default!; + [Dependency] private readonly SpriteSystem _spriteSystem = default!; + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnStartup); + SubscribeLocalEvent(OnShutdown); + SubscribeLocalEvent(OnBeforeShaderPost); + } + + private void OnStartup(EntityUid uid, FlightVisualsComponent comp, ComponentStartup args) + { + comp.Shader = _protoMan.Index(comp.AnimationKey).InstanceUnique(); + AddShader(uid, comp.Shader, comp.AnimateLayer, comp.TargetLayer); + SetValues(comp, comp.Speed, comp.Offset, comp.Multiplier); + } + + private void OnShutdown(EntityUid uid, FlightVisualsComponent comp, ComponentShutdown args) + { + AddShader(uid, null, comp.AnimateLayer, comp.TargetLayer); + } + + private void AddShader(Entity entity, ShaderInstance? shader, bool animateLayer, int? layer) + { + if (!Resolve(entity, ref entity.Comp, false)) + return; + + if (!animateLayer) + entity.Comp.PostShader = shader; + + if (animateLayer && layer is not null) + entity.Comp.LayerSetShader(layer.Value, shader); + + entity.Comp.GetScreenTexture = shader is not null; + entity.Comp.RaiseShaderEvent = shader is not null; + } + + /// + /// This function can be used to modify the shader's values while its running. + /// + private void OnBeforeShaderPost(EntityUid uid, FlightVisualsComponent comp, ref BeforePostShaderRenderEvent args) + { + SetValues(comp, comp.Speed, comp.Offset, comp.Multiplier); + } + + private void SetValues(FlightVisualsComponent comp, float speed, float offset, float multiplier) + { + comp.Shader.SetParameter("Speed", speed); + comp.Shader.SetParameter("Offset", offset); + comp.Shader.SetParameter("Multiplier", multiplier); + } +} \ No newline at end of file diff --git a/Content.Client/Guidebook/Controls/GuideFoodComposition.xaml b/Content.Client/Guidebook/Controls/GuideFoodComposition.xaml new file mode 100644 index 0000000000..6a3072ce08 --- /dev/null +++ b/Content.Client/Guidebook/Controls/GuideFoodComposition.xaml @@ -0,0 +1,21 @@ + + + + + + diff --git a/Content.Client/Guidebook/Controls/GuideFoodComposition.xaml.cs b/Content.Client/Guidebook/Controls/GuideFoodComposition.xaml.cs new file mode 100644 index 0000000000..b4f25a02e4 --- /dev/null +++ b/Content.Client/Guidebook/Controls/GuideFoodComposition.xaml.cs @@ -0,0 +1,31 @@ +using Content.Client.UserInterface.ControlExtensions; +using Content.Shared.Chemistry.Reagent; +using Content.Shared.FixedPoint; +using JetBrains.Annotations; +using Robust.Client.AutoGenerated; +using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.XAML; + +namespace Content.Client.Guidebook.Controls; + +[UsedImplicitly, GenerateTypedNameReferences] +public sealed partial class GuideFoodComposition : BoxContainer, ISearchableControl +{ + public GuideFoodComposition(ReagentPrototype proto, FixedPoint2 quantity) + { + RobustXamlLoader.Load(this); + + ReagentLabel.Text = proto.LocalizedName; + AmountLabel.Text = quantity.ToString(); + } + + public bool CheckMatchesSearch(string query) + { + return this.ChildrenContainText(query); + } + + public void SetHiddenState(bool state, string query) + { + Visible = CheckMatchesSearch(query) ? state : !state; + } +} diff --git a/Content.Client/Guidebook/Controls/GuideFoodEmbed.xaml b/Content.Client/Guidebook/Controls/GuideFoodEmbed.xaml new file mode 100644 index 0000000000..8aa2b10356 --- /dev/null +++ b/Content.Client/Guidebook/Controls/GuideFoodEmbed.xaml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Content.Client/Guidebook/Controls/GuideFoodEmbed.xaml.cs b/Content.Client/Guidebook/Controls/GuideFoodEmbed.xaml.cs new file mode 100644 index 0000000000..355d3a020f --- /dev/null +++ b/Content.Client/Guidebook/Controls/GuideFoodEmbed.xaml.cs @@ -0,0 +1,161 @@ +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using Content.Client.Chemistry.EntitySystems; +using Content.Client.Guidebook.Richtext; +using Content.Client.Message; +using Content.Client.Nutrition.EntitySystems; +using Content.Shared.Chemistry.Reagent; +using Content.Shared.FixedPoint; +using JetBrains.Annotations; +using Robust.Client.AutoGenerated; +using Robust.Client.Graphics; +using Robust.Client.UserInterface; +using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.XAML; +using Robust.Shared.Prototypes; +using Robust.Shared.Utility; + +namespace Content.Client.Guidebook.Controls; + +/// +/// Control for embedding a food recipe into a guidebook. +/// +[UsedImplicitly, GenerateTypedNameReferences] +public sealed partial class GuideFoodEmbed : BoxContainer, IDocumentTag, ISearchableControl +{ + [Dependency] private readonly IEntitySystemManager _systemManager = default!; + [Dependency] private readonly IPrototypeManager _prototype = default!; + + private readonly FoodGuideDataSystem _foodGuideData; + private readonly ISawmill _logger = default!; + + public GuideFoodEmbed() + { + RobustXamlLoader.Load(this); + IoCManager.InjectDependencies(this); + _foodGuideData = _systemManager.GetEntitySystem(); + _logger = Logger.GetSawmill("food guide"); + MouseFilter = MouseFilterMode.Stop; + } + + public GuideFoodEmbed(FoodGuideEntry entry) : this() + { + GenerateControl(entry); + } + + public bool CheckMatchesSearch(string query) + { + return FoodName.GetMessage()?.Contains(query, StringComparison.InvariantCultureIgnoreCase) == true + || FoodDescription.GetMessage()?.Contains(query, StringComparison.InvariantCultureIgnoreCase) == true; + } + + public void SetHiddenState(bool state, string query) + { + Visible = CheckMatchesSearch(query) ? state : !state; + } + + public bool TryParseTag(Dictionary args, [NotNullWhen(true)] out Control? control) + { + control = null; + if (!args.TryGetValue("Food", out var id)) + { + _logger.Error("Food embed tag is missing food prototype argument."); + return false; + } + + if (!_foodGuideData.TryGetData(id, out var data)) + { + _logger.Warning($"Specified food prototype \"{id}\" does not have any known sources."); + return false; + } + + GenerateControl(data); + + control = this; + return true; + } + + private void GenerateControl(FoodGuideEntry data) + { + _prototype.TryIndex(data.Result, out var proto); + if (proto == null) + { + FoodName.SetMarkup(Loc.GetString("guidebook-food-unknown-proto", ("id", data.Result))); + return; + } + + var composition = data.Composition + .Select(it => _prototype.TryIndex(it.Reagent.Prototype, out var reagent) ? (reagent, it.Quantity) : (null, 0)) + .Where(it => it.reagent is not null) + .Cast<(ReagentPrototype, FixedPoint2)>() + .ToList(); + + #region Colors + + CalculateColors(composition, out var textColor, out var backgroundColor); + + NameBackground.PanelOverride = new StyleBoxFlat + { + BackgroundColor = backgroundColor + }; + FoodName.SetMarkup(Loc.GetString("guidebook-food-name", ("color", textColor), ("name", proto.Name))); + + #endregion + + #region Sources + + foreach (var source in data.Sources.OrderBy(it => it.OutputCount)) + { + var control = new GuideFoodSource(proto, source, _prototype); + SourcesDescriptionContainer.AddChild(control); + } + + #endregion + + #region Composition + + foreach (var (reagent, quantity) in composition) + { + var control = new GuideFoodComposition(reagent, quantity); + CompositionDescriptionContainer.AddChild(control); + } + + #endregion + + FormattedMessage description = new(); + description.AddText(proto?.Description ?? string.Empty); + // Cannot describe food flavor or smth beause food is entirely server-side + + FoodDescription.SetMessage(description); + } + + private void CalculateColors(List<(ReagentPrototype, FixedPoint2)> composition, out Color text, out Color background) + { + // Background color is calculated as the weighted average of the colors of the composition. + // Text color is determined based on background luminosity. + float r = 0, g = 0, b = 0; + FixedPoint2 weight = 0; + + foreach (var (proto, quantity) in composition) + { + var tcolor = proto.SubstanceColor; + var prevalence = + quantity <= 0 ? 0f + : weight == 0f ? 1f + : (quantity / (weight + quantity)).Float(); + + r = r * (1 - prevalence) + tcolor.R * prevalence; + g = g * (1 - prevalence) + tcolor.G * prevalence; + b = b * (1 - prevalence) + tcolor.B * prevalence; + + if (quantity > 0) + weight += quantity; + } + + // Copied from GuideReagentEmbed which was probably copied from stackoverflow. This is the formula for color luminosity. + var lum = 0.2126f * r + 0.7152f * g + 0.0722f; + + background = new Color(r, g, b); + text = lum > 0.5f ? Color.Black : Color.White; + } +} diff --git a/Content.Client/Guidebook/Controls/GuideFoodGroupEmbed.xaml b/Content.Client/Guidebook/Controls/GuideFoodGroupEmbed.xaml new file mode 100644 index 0000000000..da671adaa7 --- /dev/null +++ b/Content.Client/Guidebook/Controls/GuideFoodGroupEmbed.xaml @@ -0,0 +1,4 @@ + + + diff --git a/Content.Client/Guidebook/Controls/GuideFoodGroupEmbed.xaml.cs b/Content.Client/Guidebook/Controls/GuideFoodGroupEmbed.xaml.cs new file mode 100644 index 0000000000..0e1034e394 --- /dev/null +++ b/Content.Client/Guidebook/Controls/GuideFoodGroupEmbed.xaml.cs @@ -0,0 +1,38 @@ +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using Content.Client.Guidebook.Richtext; +using Content.Client.Nutrition.EntitySystems; +using JetBrains.Annotations; +using Robust.Client.AutoGenerated; +using Robust.Client.UserInterface; +using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.XAML; +using Robust.Shared.Prototypes; + +namespace Content.Client.Guidebook.Controls; + +[UsedImplicitly, GenerateTypedNameReferences] +public sealed partial class GuideFoodGroupEmbed : BoxContainer, IDocumentTag +{ + [Dependency] private readonly IEntitySystemManager _sysMan = default!; + [Dependency] private readonly IPrototypeManager _prototype = default!; + + public GuideFoodGroupEmbed() + { + RobustXamlLoader.Load(this); + IoCManager.InjectDependencies(this); + MouseFilter = MouseFilterMode.Stop; + + foreach (var data in _sysMan.GetEntitySystem().Registry.OrderBy(it => it.Identifier)) + { + var embed = new GuideFoodEmbed(data); + GroupContainer.AddChild(embed); + } + } + + public bool TryParseTag(Dictionary args, [NotNullWhen(true)] out Control? control) + { + control = this; + return true; + } +} diff --git a/Content.Client/Guidebook/Controls/GuideFoodSource.xaml b/Content.Client/Guidebook/Controls/GuideFoodSource.xaml new file mode 100644 index 0000000000..74e3a2ec30 --- /dev/null +++ b/Content.Client/Guidebook/Controls/GuideFoodSource.xaml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + diff --git a/Content.Client/Guidebook/Controls/GuideFoodSource.xaml.cs b/Content.Client/Guidebook/Controls/GuideFoodSource.xaml.cs new file mode 100644 index 0000000000..b0fee70975 --- /dev/null +++ b/Content.Client/Guidebook/Controls/GuideFoodSource.xaml.cs @@ -0,0 +1,160 @@ +using System.Linq; +using Content.Client.Chemistry.EntitySystems; +using Content.Client.UserInterface.ControlExtensions; +using Content.Shared.Chemistry.Reagent; +using Content.Shared.FixedPoint; +using Content.Shared.Nutrition.Components; +using JetBrains.Annotations; +using Robust.Client.AutoGenerated; +using Robust.Client.GameObjects; +using Robust.Client.Graphics; +using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.XAML; +using Robust.Shared.Prototypes; +using Robust.Shared.Utility; + +namespace Content.Client.Guidebook.Controls; + +[UsedImplicitly, GenerateTypedNameReferences] +public sealed partial class GuideFoodSource : BoxContainer, ISearchableControl +{ + private readonly IPrototypeManager _protoMan; + private readonly SpriteSystem _sprites = default!; + + public GuideFoodSource(IPrototypeManager protoMan) + { + RobustXamlLoader.Load(this); + _protoMan = protoMan; + _sprites = IoCManager.Resolve().GetEntitySystem(); + } + + public GuideFoodSource(EntityPrototype result, FoodSourceData entry, IPrototypeManager protoMan) : this(protoMan) + { + switch (entry) + { + case FoodButcheringData butchering: + GenerateControl(butchering); + break; + case FoodSlicingData slicing: + GenerateControl(slicing); + break; + case FoodRecipeData recipe: + GenerateControl(recipe); + break; + case FoodReactionData reaction: + GenerateControl(reaction); + break; + default: + throw new ArgumentOutOfRangeException(nameof(entry), entry, null); + } + + GenerateOutputs(result, entry); + } + + private void GenerateControl(FoodButcheringData entry) + { + if (!_protoMan.TryIndex(entry.Butchered, out var ent)) + { + SourceLabel.SetMessage(Loc.GetString("guidebook-food-unknown-proto", ("id", entry.Butchered))); + return; + } + + SetSource(ent); + ProcessingLabel.Text = Loc.GetString("guidebook-food-processing-butchering"); + + ProcessingTexture.Texture = entry.Type switch + { + ButcheringType.Knife => GetRsiTexture("/Textures/Objects/Weapons/Melee/kitchen_knife.rsi", "icon"), + _ => GetRsiTexture("/Textures/Structures/meat_spike.rsi", "spike") + }; + } + + private void GenerateControl(FoodSlicingData entry) + { + if (!_protoMan.TryIndex(entry.Sliced, out var ent)) + { + SourceLabel.SetMessage(Loc.GetString("guidebook-food-unknown-proto", ("id", entry.Sliced))); + return; + } + + SetSource(ent); + ProcessingLabel.Text = Loc.GetString("guidebook-food-processing-slicing"); + ProcessingTexture.Texture = GetRsiTexture("/Textures/Objects/Misc/utensils.rsi", "plastic_knife"); + } + + private void GenerateControl(FoodRecipeData entry) + { + if (!_protoMan.TryIndex(entry.Recipe, out var recipe)) + { + SourceLabel.SetMessage(Loc.GetString("guidebook-food-unknown-proto", ("id", entry.Result))); + return; + } + + var combinedSolids = recipe.IngredientsSolids + .Select(it => _protoMan.TryIndex(it.Key, out var proto) ? FormatIngredient(proto, it.Value) : "") + .Where(it => it.Length > 0); + var combinedLiquids = recipe.IngredientsReagents + .Select(it => _protoMan.TryIndex(it.Key, out var proto) ? FormatIngredient(proto, it.Value) : "") + .Where(it => it.Length > 0); + + var combinedIngredients = string.Join("\n", combinedLiquids.Union(combinedSolids)); + SourceLabel.SetMessage(Loc.GetString("guidebook-food-processing-recipe", ("ingredients", combinedIngredients))); + + ProcessingTexture.Texture = GetRsiTexture("/Textures/Structures/Machines/microwave.rsi", "mw"); + ProcessingLabel.Text = Loc.GetString("guidebook-food-processing-cooking", ("time", recipe.CookTime)); + } + + private void GenerateControl(FoodReactionData entry) + { + if (!_protoMan.TryIndex(entry.Reaction, out var reaction)) + { + SourceLabel.SetMessage(Loc.GetString("guidebook-food-unknown-proto", ("id", entry.Reaction))); + return; + } + + var combinedReagents = reaction.Reactants + .Select(it => _protoMan.TryIndex(it.Key, out var proto) ? FormatIngredient(proto, it.Value.Amount) : "") + .Where(it => it.Length > 0); + + SourceLabel.SetMessage(Loc.GetString("guidebook-food-processing-recipe", ("ingredients", string.Join("\n", combinedReagents)))); + ProcessingTexture.TexturePath = "/Textures/Interface/Misc/beakerlarge.png"; + ProcessingLabel.Text = Loc.GetString("guidebook-food-processing-reaction"); + } + + private Texture GetRsiTexture(string path, string state) + { + return _sprites.Frame0(new SpriteSpecifier.Rsi(new ResPath(path), state)); + } + + private void GenerateOutputs(EntityPrototype result, FoodSourceData entry) + { + OutputsLabel.Text = Loc.GetString("guidebook-food-output", ("name", result.Name), ("number", entry.OutputCount)); + OutputsTexture.Texture = _sprites.Frame0(result); + } + + private void SetSource(EntityPrototype ent) + { + SourceLabel.SetMessage(ent.Name); + OutputsTexture.Texture = _sprites.Frame0(ent); + } + + private string FormatIngredient(EntityPrototype proto, FixedPoint2 amount) + { + return Loc.GetString("guidebook-food-ingredient-solid", ("name", proto.Name), ("amount", amount)); + } + + private string FormatIngredient(ReagentPrototype proto, FixedPoint2 amount) + { + return Loc.GetString("guidebook-food-ingredient-liquid", ("name", proto.LocalizedName), ("amount", amount)); + } + + public bool CheckMatchesSearch(string query) + { + return this.ChildrenContainText(query); + } + + public void SetHiddenState(bool state, string query) + { + Visible = CheckMatchesSearch(query) ? state : !state; + } +} diff --git a/Content.Client/Language/LanguageMenuWindow.xaml.cs b/Content.Client/Language/LanguageMenuWindow.xaml.cs index 11d1c290d1..ed6ec6b3e2 100644 --- a/Content.Client/Language/LanguageMenuWindow.xaml.cs +++ b/Content.Client/Language/LanguageMenuWindow.xaml.cs @@ -1,4 +1,5 @@ using Content.Client.Language.Systems; +using Content.Shared.Language.Events; using Robust.Client.AutoGenerated; using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.CustomControls; @@ -7,7 +8,7 @@ namespace Content.Client.Language; [GenerateTypedNameReferences] -public sealed partial class LanguageMenuWindow : DefaultWindow +public sealed partial class LanguageMenuWindow : DefaultWindow, IEntityEventSubscriber { private readonly LanguageSystem _clientLanguageSystem; private readonly List _entries = new(); @@ -17,6 +18,14 @@ public LanguageMenuWindow() { RobustXamlLoader.Load(this); _clientLanguageSystem = IoCManager.Resolve().GetEntitySystem(); + + _clientLanguageSystem.OnLanguagesChanged += OnUpdateState; + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + _clientLanguageSystem.OnLanguagesChanged -= OnUpdateState; } protected override void Opened() @@ -28,6 +37,11 @@ protected override void Opened() } + private void OnUpdateState(object? sender, LanguagesUpdatedMessage args) + { + UpdateState(args.CurrentLanguage, args.Spoken); + } + public void UpdateState(string currentLanguage, List spokenLanguages) { var langName = Loc.GetString($"language-{currentLanguage}-name"); diff --git a/Content.Client/Language/Systems/LanguageSystem.cs b/Content.Client/Language/Systems/LanguageSystem.cs index 5dc2fc1f4e..cb6bb60512 100644 --- a/Content.Client/Language/Systems/LanguageSystem.cs +++ b/Content.Client/Language/Systems/LanguageSystem.cs @@ -29,6 +29,8 @@ public sealed class LanguageSystem : SharedLanguageSystem /// public List UnderstoodLanguages { get; private set; } = new(); + public event EventHandler? OnLanguagesChanged; + public override void Initialize() { base.Initialize(); @@ -39,9 +41,13 @@ public override void Initialize() private void OnLanguagesUpdated(LanguagesUpdatedMessage message) { + // TODO this entire thing is horrible. If someone is willing to refactor this, LanguageSpeakerComponent should become shared with SendOnlyToOwner = true + // That way, this system will be able to use the existing networking infrastructure instead of relying on this makeshift... whatever this is. CurrentLanguage = message.CurrentLanguage; SpokenLanguages = message.Spoken; UnderstoodLanguages = message.Understood; + + OnLanguagesChanged?.Invoke(this, message); } private void OnRunLevelChanged(object? sender, RunLevelChangedEventArgs args) diff --git a/Content.Client/Nutrition/EntitySystems/FoodGuideDataSystem.cs b/Content.Client/Nutrition/EntitySystems/FoodGuideDataSystem.cs new file mode 100644 index 0000000000..37c7a25e21 --- /dev/null +++ b/Content.Client/Nutrition/EntitySystems/FoodGuideDataSystem.cs @@ -0,0 +1,30 @@ +using Content.Client.Chemistry.EntitySystems; +using Robust.Shared.Prototypes; + +namespace Content.Client.Nutrition.EntitySystems; + +public sealed class FoodGuideDataSystem : SharedFoodGuideDataSystem +{ + public override void Initialize() + { + SubscribeNetworkEvent(OnReceiveRegistryUpdate); + } + + private void OnReceiveRegistryUpdate(FoodGuideRegistryChangedEvent message) + { + Registry = message.Changeset; + } + + public bool TryGetData(EntProtoId result, out FoodGuideEntry entry) + { + var index = Registry.FindIndex(it => it.Result == result); + if (index == -1) + { + entry = default; + return false; + } + + entry = Registry[index]; + return true; + } +} diff --git a/Content.Client/Options/UI/Tabs/KeyRebindTab.xaml.cs b/Content.Client/Options/UI/Tabs/KeyRebindTab.xaml.cs index 3d8ae50748..198eb5e4fb 100644 --- a/Content.Client/Options/UI/Tabs/KeyRebindTab.xaml.cs +++ b/Content.Client/Options/UI/Tabs/KeyRebindTab.xaml.cs @@ -97,6 +97,12 @@ private void HandleToggleWalk(BaseButton.ButtonToggledEventArgs args) _deferCommands.Add(_inputManager.SaveToUserData); } + private void HandleDefaultWalk(BaseButton.ButtonToggledEventArgs args) + { + _cfg.SetCVar(CCVars.DefaultWalk, args.Pressed); + _cfg.SaveToFile(); + } + private void HandleStaticStorageUI(BaseButton.ButtonToggledEventArgs args) { _cfg.SetCVar(CCVars.StaticStorageUI, args.Pressed); @@ -161,6 +167,7 @@ void AddCheckBox(string checkBoxName, bool currentState, Action(OnUpdatePredicted); SubscribeLocalEvent(OnUpdateRelayTargetPredicted); SubscribeLocalEvent(OnUpdatePullablePredicted); + + Subs.CVar(_config, CCVars.DefaultWalk, _ => RaiseNetworkEvent(new UpdateInputCVarsMessage())); } private void OnUpdatePredicted(EntityUid uid, InputMoverComponent component, ref UpdateIsPredictedEvent args) diff --git a/Content.Client/RCD/RCDMenu.xaml.cs b/Content.Client/RCD/RCDMenu.xaml.cs index 51ec66ea44..3eb0397a69 100644 --- a/Content.Client/RCD/RCDMenu.xaml.cs +++ b/Content.Client/RCD/RCDMenu.xaml.cs @@ -68,7 +68,7 @@ public RCDMenu(EntityUid owner, RCDMenuBoundUserInterface bui) tooltip = Loc.GetString(entProto.Name); } - tooltip = char.ToUpper(tooltip[0]) + tooltip.Remove(0, 1); + tooltip = OopsConcat(char.ToUpper(tooltip[0]).ToString(), tooltip.Remove(0, 1)); var button = new RCDMenuButton() { @@ -119,6 +119,12 @@ public RCDMenu(EntityUid owner, RCDMenuBoundUserInterface bui) SendRCDSystemMessageAction += bui.SendRCDSystemMessage; } + private static string OopsConcat(string a, string b) + { + // This exists to prevent Roslyn being clever and compiling something that fails sandbox checks. + return a + b; + } + private void AddRCDMenuButtonOnClickActions(Control control) { var radialContainer = control as RadialContainer; diff --git a/Content.Client/ShortConstruction/UI/ShortConstructionMenuBUI.cs b/Content.Client/ShortConstruction/UI/ShortConstructionMenuBUI.cs index 37606d8656..4d50d91e16 100644 --- a/Content.Client/ShortConstruction/UI/ShortConstructionMenuBUI.cs +++ b/Content.Client/ShortConstruction/UI/ShortConstructionMenuBUI.cs @@ -66,7 +66,7 @@ private RadialMenu FormMenu() var mainContainer = new RadialContainer { - Radius = 36f / MathF.Sin(MathF.PI / crafting.Prototypes.Count) + Radius = 36f / MathF.Sin(MathF.PI / 2f / crafting.Prototypes.Count) }; foreach (var protoId in crafting.Prototypes) diff --git a/Content.Client/UserInterface/Systems/Language/LanguageMenuUIController.cs b/Content.Client/UserInterface/Systems/Language/LanguageMenuUIController.cs index f36521ce81..e351a16bfb 100644 --- a/Content.Client/UserInterface/Systems/Language/LanguageMenuUIController.cs +++ b/Content.Client/UserInterface/Systems/Language/LanguageMenuUIController.cs @@ -2,7 +2,6 @@ using Content.Client.Gameplay; using Content.Client.UserInterface.Controls; using Content.Shared.Input; -using Content.Shared.Language.Events; using Robust.Client.UserInterface.Controllers; using Robust.Client.UserInterface.Controls; using Robust.Shared.Input.Binding; @@ -18,12 +17,6 @@ public sealed class LanguageMenuUIController : UIController, IOnStateEntered UIManager.GetActiveUIWidgetOrNull()?.LanguageButton; - public override void Initialize() - { - SubscribeNetworkEvent((LanguagesUpdatedMessage message, EntitySessionEventArgs _) => - LanguageWindow?.UpdateState(message.CurrentLanguage, message.Spoken)); - } - public void OnStateEntered(GameplayState state) { DebugTools.Assert(LanguageWindow == null); @@ -31,6 +24,17 @@ public void OnStateEntered(GameplayState state) LanguageWindow = UIManager.CreateWindow(); LayoutContainer.SetAnchorPreset(LanguageWindow, LayoutContainer.LayoutPreset.CenterTop); + LanguageWindow.OnClose += () => + { + if (LanguageButton != null) + LanguageButton.Pressed = false; + }; + LanguageWindow.OnOpen += () => + { + if (LanguageButton != null) + LanguageButton.Pressed = true; + }; + CommandBinds.Builder.Bind(ContentKeyFunctions.OpenLanguageMenu, InputCmdHandler.FromDelegate(_ => ToggleWindow())).Register(); } @@ -60,12 +64,6 @@ public void LoadButton() return; LanguageButton.OnPressed += LanguageButtonPressed; - - if (LanguageWindow == null) - return; - - LanguageWindow.OnClose += () => LanguageButton.Pressed = false; - LanguageWindow.OnOpen += () => LanguageButton.Pressed = true; } private void LanguageButtonPressed(ButtonEventArgs args) diff --git a/Content.IntegrationTests/Tests/Slipping/SlippingTest.cs b/Content.IntegrationTests/Tests/Slipping/SlippingTest.cs index 61dcc3331d..28da7a9465 100644 --- a/Content.IntegrationTests/Tests/Slipping/SlippingTest.cs +++ b/Content.IntegrationTests/Tests/Slipping/SlippingTest.cs @@ -34,7 +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); + var sprintWalks = sys.Config.GetCVar(CCVars.DefaultWalk); await SpawnTarget("TrashBananaPeel"); // var modifier = Comp(Player).SprintSpeedModifier; diff --git a/Content.Server/Body/Components/BloodstreamComponent.cs b/Content.Server/Body/Components/BloodstreamComponent.cs index dd93da9598..a272d5f365 100644 --- a/Content.Server/Body/Components/BloodstreamComponent.cs +++ b/Content.Server/Body/Components/BloodstreamComponent.cs @@ -181,9 +181,9 @@ public sealed partial class BloodstreamComponent : Component public bool HasBloodDeficiency = false; /// - /// How much reagent of blood should be removed with blood deficiency in each update interval? + /// How much percentage of max blood volume should be removed with blood deficiency in each update interval? /// [DataField] - public FixedPoint2 BloodDeficiencyLossAmount; + public float BloodDeficiencyLossPercentage; } } diff --git a/Content.Server/Body/Systems/BloodstreamSystem.cs b/Content.Server/Body/Systems/BloodstreamSystem.cs index b37ac5efeb..91ed7a2480 100644 --- a/Content.Server/Body/Systems/BloodstreamSystem.cs +++ b/Content.Server/Body/Systems/BloodstreamSystem.cs @@ -122,7 +122,7 @@ public override void Update(float frameTime) if (bloodstream.HasBloodDeficiency) { if (!_mobStateSystem.IsDead(uid)) - RemoveBlood(uid, bloodstream.BloodDeficiencyLossAmount, bloodstream); + RemoveBlood(uid, bloodstream.BloodMaxVolume * bloodstream.BloodDeficiencyLossPercentage, bloodstream); } // Adds blood to their blood level if it is below the maximum. else if (bloodSolution.Volume < bloodSolution.MaxVolume && !_mobStateSystem.IsDead(uid)) @@ -349,6 +349,14 @@ public void SetBloodLossThreshold(EntityUid uid, float threshold, BloodstreamCom comp.BloodlossThreshold = threshold; } + public void SetBloodMaxVolume(EntityUid uid, FixedPoint2 volume, BloodstreamComponent? comp = null) + { + if (!Resolve(uid, ref comp)) + return; + + comp.BloodMaxVolume = volume; + } + /// /// Attempts to modify the blood level of this entity directly. /// diff --git a/Content.Server/Chemistry/ReagentEffects/ChemAddMoodlet.cs b/Content.Server/Chemistry/ReagentEffects/ChemAddMoodlet.cs new file mode 100644 index 0000000000..f5bb629299 --- /dev/null +++ b/Content.Server/Chemistry/ReagentEffects/ChemAddMoodlet.cs @@ -0,0 +1,34 @@ +using Content.Shared.Chemistry.Reagent; +using Content.Shared.Mood; +using JetBrains.Annotations; +using Robust.Shared.Prototypes; + +namespace Content.Server.Chemistry.ReagentEffects; + +/// +/// Adds a moodlet to an entity. +/// +[UsedImplicitly] +public sealed partial class ChemAddMoodlet : ReagentEffect +{ + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + { + var protoMan = IoCManager.Resolve(); + return Loc.GetString("reagent-effect-guidebook-add-moodlet", + ("amount", protoMan.Index(MoodPrototype.Id).MoodChange), + ("timeout", protoMan.Index(MoodPrototype.Id).Timeout)); + } + + /// + /// The mood prototype to be applied to the using entity. + /// + [DataField(required: true)] + public ProtoId MoodPrototype = default!; + + public override void Effect(ReagentEffectArgs args) + { + var entityManager = IoCManager.Resolve(); + var ev = new MoodEffectEvent(MoodPrototype); + entityManager.EventBus.RaiseLocalEvent(args.SolutionEntity, ev); + } +} diff --git a/Content.Server/Flight/FlightSystem.cs b/Content.Server/Flight/FlightSystem.cs new file mode 100644 index 0000000000..e056fc24ec --- /dev/null +++ b/Content.Server/Flight/FlightSystem.cs @@ -0,0 +1,158 @@ + +using Content.Shared.Cuffs.Components; +using Content.Shared.Damage.Components; +using Content.Shared.DoAfter; +using Content.Shared.Flight; +using Content.Shared.Flight.Events; +using Content.Shared.Mobs; +using Content.Shared.Popups; +using Content.Shared.Stunnable; +using Content.Shared.Zombies; +using Robust.Shared.Audio.Systems; + +namespace Content.Server.Flight; +public sealed class FlightSystem : SharedFlightSystem +{ + [Dependency] private readonly SharedAudioSystem _audio = default!; + [Dependency] private readonly SharedDoAfterSystem _doAfter = default!; + [Dependency] private readonly SharedPopupSystem _popupSystem = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnToggleFlight); + SubscribeLocalEvent(OnFlightDoAfter); + SubscribeLocalEvent(OnMobStateChangedEvent); + SubscribeLocalEvent(OnZombified); + SubscribeLocalEvent(OnKnockedDown); + SubscribeLocalEvent(OnStunned); + SubscribeLocalEvent(OnSleep); + } + public override void Update(float frameTime) + { + base.Update(frameTime); + + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var uid, out var component)) + { + if (!component.On) + continue; + + component.TimeUntilFlap -= frameTime; + + if (component.TimeUntilFlap > 0f) + continue; + + _audio.PlayPvs(component.FlapSound, uid); + component.TimeUntilFlap = component.FlapInterval; + + } + } + + #region Core Functions + private void OnToggleFlight(EntityUid uid, FlightComponent component, ToggleFlightEvent args) + { + // If the user isnt flying, we check for conditionals and initiate a doafter. + if (!component.On) + { + if (!CanFly(uid, component)) + return; + + var doAfterArgs = new DoAfterArgs(EntityManager, + uid, component.ActivationDelay, + new FlightDoAfterEvent(), uid, target: uid) + { + BlockDuplicate = true, + BreakOnTargetMove = true, + BreakOnUserMove = true, + BreakOnDamage = true, + NeedHand = true + }; + + if (!_doAfter.TryStartDoAfter(doAfterArgs)) + return; + } + else + ToggleActive(uid, false, component); + } + + private void OnFlightDoAfter(EntityUid uid, FlightComponent component, FlightDoAfterEvent args) + { + if (args.Handled || args.Cancelled) + return; + + ToggleActive(uid, true, component); + args.Handled = true; + } + + #endregion + + #region Conditionals + + private bool CanFly(EntityUid uid, FlightComponent component) + { + if (TryComp(uid, out var cuffableComp) && !cuffableComp.CanStillInteract) + { + _popupSystem.PopupEntity(Loc.GetString("no-flight-while-restrained"), uid, uid, PopupType.Medium); + return false; + } + + if (HasComp(uid)) + { + _popupSystem.PopupEntity(Loc.GetString("no-flight-while-zombified"), uid, uid, PopupType.Medium); + return false; + } + return true; + } + + private void OnMobStateChangedEvent(EntityUid uid, FlightComponent component, MobStateChangedEvent args) + { + if (!component.On + || args.NewMobState is MobState.Critical or MobState.Dead) + return; + + ToggleActive(args.Target, false, component); + } + + private void OnZombified(EntityUid uid, FlightComponent component, ref EntityZombifiedEvent args) + { + if (!component.On) + return; + + ToggleActive(args.Target, false, component); + if (!TryComp(uid, out var stamina)) + return; + Dirty(uid, stamina); + } + + private void OnKnockedDown(EntityUid uid, FlightComponent component, ref KnockedDownEvent args) + { + if (!component.On) + return; + + ToggleActive(uid, false, component); + } + + private void OnStunned(EntityUid uid, FlightComponent component, ref StunnedEvent args) + { + if (!component.On) + return; + + ToggleActive(uid, false, component); + } + + private void OnSleep(EntityUid uid, FlightComponent component, ref SleepStateChangedEvent args) + { + if (!component.On + || !args.FellAsleep) + return; + + ToggleActive(uid, false, component); + if (!TryComp(uid, out var stamina)) + return; + + Dirty(uid, stamina); + } + #endregion +} \ No newline at end of file diff --git a/Content.Server/HeightAdjust/BloodstreamAdjustSystem.cs b/Content.Server/HeightAdjust/BloodstreamAdjustSystem.cs index 92e03e0c11..9ba0ee4b00 100644 --- a/Content.Server/HeightAdjust/BloodstreamAdjustSystem.cs +++ b/Content.Server/HeightAdjust/BloodstreamAdjustSystem.cs @@ -1,4 +1,5 @@ using Content.Server.Body.Components; +using Content.Server.Body.Systems; using Content.Server.Chemistry.Containers.EntitySystems; using Content.Shared.CCVar; using Content.Shared.Chemistry.Reagent; @@ -10,6 +11,7 @@ namespace Content.Server.HeightAdjust; public sealed class BloodstreamAdjustSystem : EntitySystem { + [Dependency] private readonly BloodstreamSystem _bloodstream = default!; [Dependency] private readonly IConfigurationManager _config = default!; [Dependency] private readonly ContestsSystem _contests = default!; [Dependency] private readonly SolutionContainerSystem _solutionContainer = default!; @@ -40,6 +42,8 @@ public bool TryAdjustBloodstream(Entity ent) bloodSolution.MaxVolume = newVolume; bloodSolution.SetContents([new ReagentQuantity(bloodstream.BloodReagent, newBloodLevel, null)], false); + _bloodstream.SetBloodMaxVolume(ent.Owner, newVolume, bloodstream); + return true; } } diff --git a/Content.Server/Language/TranslatorSystem.cs b/Content.Server/Language/TranslatorSystem.cs index 6cdca12440..a893993e88 100644 --- a/Content.Server/Language/TranslatorSystem.cs +++ b/Content.Server/Language/TranslatorSystem.cs @@ -9,6 +9,7 @@ using Content.Shared.PowerCell; using Content.Shared.Language.Components.Translators; using Robust.Shared.Containers; +using Robust.Shared.Timing; namespace Content.Server.Language; @@ -27,7 +28,7 @@ public override void Initialize() SubscribeLocalEvent(OnProxyDetermineLanguages); SubscribeLocalEvent(OnTranslatorInserted); - SubscribeLocalEvent(OnTranslatorRemoved); + SubscribeLocalEvent(OnTranslatorParentChanged); SubscribeLocalEvent(OnTranslatorToggle); SubscribeLocalEvent(OnPowerCellSlotEmpty); } @@ -65,8 +66,7 @@ private void OnProxyDetermineLanguages(EntityUid uid, HoldsTranslatorComponent c private void OnTranslatorInserted(EntityUid translator, HandheldTranslatorComponent component, EntGotInsertedIntoContainerMessage args) { - if (args.Container.Owner is not {Valid: true} holder - || !EntityManager.HasComponent(holder)) + if (args.Container.Owner is not {Valid: true} holder || !HasComp(holder)) return; var intrinsic = EnsureComp(holder); @@ -75,14 +75,19 @@ private void OnTranslatorInserted(EntityUid translator, HandheldTranslatorCompon _language.UpdateEntityLanguages(holder); } - private void OnTranslatorRemoved(EntityUid translator, HandheldTranslatorComponent component, EntGotRemovedFromContainerMessage args) + private void OnTranslatorParentChanged(EntityUid translator, HandheldTranslatorComponent component, EntParentChangedMessage args) { - if (args.Container.Owner is not {Valid: true} holder - || !EntityManager.TryGetComponent(holder, out var intrinsic)) + if (!HasComp(args.OldParent)) return; - intrinsic.Translators.RemoveWhere(it => it.Owner == translator); - _language.UpdateEntityLanguages(holder); + // Update the translator on the next tick - this is necessary because there's a good chance the removal from a container + // Was caused by the player moving the translator within their inventory rather than removing it. + // If that is not the case, then OnProxyDetermineLanguages will remove this translator from HoldsTranslatorComponent.Translators. + Timer.Spawn(0, () => + { + if (Exists(args.OldParent) && TryComp(args.OldParent, out var speaker)) + _language.UpdateEntityLanguages(args.OldParent.Value, speaker); + }); } private void OnTranslatorToggle(EntityUid translator, HandheldTranslatorComponent translatorComp, ActivateInWorldEvent args) @@ -125,6 +130,9 @@ private void OnPowerCellSlotEmpty(EntityUid translator, HandheldTranslatorCompon component.Enabled = false; _powerCell.SetPowerCellDrawEnabled(translator, false); OnAppearanceChange(translator, component); + + if (_containers.TryGetContainingContainer(translator, out var holderCont) && TryComp(holderCont.Owner, out var languageComp)) + _language.UpdateEntityLanguages(holderCont.Owner, languageComp); } private void CopyLanguages(BaseTranslatorComponent from, DetermineEntityLanguagesEvent to, LanguageKnowledgeComponent knowledge) diff --git a/Content.Server/Medical/PenLightSystem.cs b/Content.Server/Medical/PenLightSystem.cs index f48a84d047..0e0f22684a 100644 --- a/Content.Server/Medical/PenLightSystem.cs +++ b/Content.Server/Medical/PenLightSystem.cs @@ -1,4 +1,5 @@ using Content.Server.DoAfter; +using Content.Server.Popups; using Content.Server.PowerCell; using Content.Shared.Damage; using Content.Shared.DoAfter; @@ -7,6 +8,7 @@ using Content.Shared.Eye.Blinding.Components; using Content.Shared.Interaction; using Content.Shared.Medical; +using Content.Shared.Mobs.Components; using Content.Shared.Mobs.Systems; using Content.Shared.Traits.Assorted.Components; using Robust.Server.GameObjects; @@ -22,7 +24,9 @@ public sealed class PenLightSystem : EntitySystem [Dependency] private readonly IEntityManager _entityManager = default!; [Dependency] private readonly DoAfterSystem _doAfter = default!; [Dependency] private readonly PowerCellSystem _powerCell = default!; + [Dependency] private readonly PopupSystem _popup = default!; [Dependency] private readonly UserInterfaceSystem _uiSystem = default!; + /// public override void Initialize() { @@ -30,20 +34,23 @@ public override void Initialize() SubscribeLocalEvent(OnDoAfter); } - private void OnAfterInteract(EntityUid uid, PenLightComponent component, AfterInteractEvent args) + private void OnAfterInteract(EntityUid uid, PenLightComponent component, ref AfterInteractEvent args) { - if (args.Handled - || args.Target is not { } target) + if (args.Handled + || args.Target is not {} target + || target == null + || !args.CanReach + || !HasComp(target) + || !_powerCell.HasDrawCharge(uid, user: args.User)) return; - args.Handled = TryStartExam(uid, target, args.User, component); } private void OnDoAfter(Entity uid, ref PenLightDoAfterEvent args) { - if (args.Handled - || args.Cancelled - || args.Target == null + if (args.Handled + || args.Cancelled + || args.Target == null || !_powerCell.HasDrawCharge(uid, user: args.User)) return; @@ -52,6 +59,13 @@ private void OnDoAfter(Entity uid, ref PenLightDoAfterEvent a args.Handled = true; } + /// + /// Checks if the PointLight component is enabled. + /// + private bool IsLightEnabled(EntityUid uid) + { + return TryComp(uid, out var pointLight) && pointLight.Enabled; + } /// /// Actually handles the exam interaction. @@ -61,6 +75,18 @@ public bool TryStartExam(EntityUid uid, EntityUid target, EntityUid user, PenLig if (!Resolve(uid, ref component)) return false; + if (!IsLightEnabled(uid)) + { + if (user != null) + _popup.PopupEntity(Loc.GetString("penlight-off"), uid, user); + return false; + } + // can't examine your own eyes, dingus + if (user == target) + { + _popup.PopupEntity(Loc.GetString("penlight-cannot-examine-self"), uid, user); + return false; + } return _doAfter.TryStartDoAfter(new DoAfterArgs(EntityManager, user, component.ExamSpeed, new PenLightDoAfterEvent(), uid, target, uid) { @@ -73,7 +99,7 @@ public bool TryStartExam(EntityUid uid, EntityUid target, EntityUid user, PenLig } private void OpenUserInterface(EntityUid user, EntityUid penlight) { - if (!TryComp(user, out var actor) + if (!TryComp(user, out var actor) || !_uiSystem.TryGetUi(penlight, PenLightUiKey.Key, out var ui)) return; @@ -86,8 +112,10 @@ private void OpenUserInterface(EntityUid user, EntityUid penlight) private void Diagnose(EntityUid penlight, EntityUid target) { if (!_uiSystem.TryGetUi(penlight, PenLightUiKey.Key, out var ui) - || !HasComp(target)) + || !HasComp(target) + || !HasComp(target)) return; + // Blind var blind = _entityManager.HasComponent(target); diff --git a/Content.Server/Mood/MoodSystem.cs b/Content.Server/Mood/MoodSystem.cs index f2dc87ffd6..7e4789bf14 100644 --- a/Content.Server/Mood/MoodSystem.cs +++ b/Content.Server/Mood/MoodSystem.cs @@ -53,8 +53,6 @@ public override void Initialize() SubscribeLocalEvent(OnDamageChange); SubscribeLocalEvent(OnRefreshMoveSpeed); SubscribeLocalEvent(OnRemoveEffect); - - SubscribeLocalEvent(OnTraitStartup); } private void OnShutdown(EntityUid uid, MoodComponent component, ComponentShutdown args) @@ -101,15 +99,6 @@ private void OnRefreshMoveSpeed(EntityUid uid, MoodComponent component, RefreshM args.ModifySpeed(1, modifier); } - private void OnTraitStartup(EntityUid uid, MoodModifyTraitComponent component, ComponentStartup args) - { - if (_debugMode - || component.MoodId is null) - return; - - RaiseLocalEvent(uid, new MoodEffectEvent($"{component.MoodId}")); - } - private void OnMoodEffect(EntityUid uid, MoodComponent component, MoodEffectEvent args) { if (_debugMode @@ -195,9 +184,28 @@ private void RemoveTimedOutEffect(EntityUid uid, string prototypeId, string? cat comp.CategorisedEffects.Remove(category); } + ReplaceMood(uid, prototypeId); RefreshMood(uid, comp); } + /// + /// Some moods specifically create a moodlet upon expiration. This is normally used for "Addiction" type moodlets, + /// such as a positive moodlet from an addictive substance that becomes a negative moodlet when a timer ends. + /// + /// + /// Moodlets that use this should probably also share a category with each other, but this isn't necessarily required. + /// Only if you intend that "Re-using the drug" should also remove the negative moodlet. + /// + private void ReplaceMood(EntityUid uid, string prototypeId) + { + if (!_prototypeManager.TryIndex(prototypeId, out var proto) + || proto.MoodletOnEnd is null) + return; + + var ev = new MoodEffectEvent(proto.MoodletOnEnd); + EntityManager.EventBus.RaiseLocalEvent(uid, ev); + } + private void OnMobStateChanged(EntityUid uid, MoodComponent component, MobStateChangedEvent args) { if (_debugMode) diff --git a/Content.Server/Nutrition/EntitySystems/FoodGuideDataSystem.cs b/Content.Server/Nutrition/EntitySystems/FoodGuideDataSystem.cs new file mode 100644 index 0000000000..f21c509ace --- /dev/null +++ b/Content.Server/Nutrition/EntitySystems/FoodGuideDataSystem.cs @@ -0,0 +1,138 @@ +using System.Linq; +using Content.Client.Chemistry.EntitySystems; +using Content.Server.Chemistry.ReactionEffects; +using Content.Server.Nutrition.Components; +using Content.Shared.Chemistry.Components.SolutionManager; +using Content.Shared.Chemistry.Reaction; +using Content.Shared.Chemistry.Reagent; +using Content.Shared.Kitchen; +using Content.Shared.Nutrition.Components; +using Robust.Server.Player; +using Robust.Shared.Enums; +using Robust.Shared.Player; +using Robust.Shared.Prototypes; +using Robust.Shared.Utility; + +namespace Content.Server.Nutrition.EntitySystems; + +public sealed class FoodGuideDataSystem : SharedFoodGuideDataSystem +{ + public static readonly ProtoId[] ReagentWhitelist = + [ + "Nutriment", + "Vitamin", + "Protein", + "UncookedAnimalProteins", + "Fat", + "Water" + ]; + + public static readonly string[] ComponentNamesBlacklist = ["HumanoidAppearance"]; + + public static readonly string[] SuffixBlacklist = ["debug", "do not map", "admeme"]; + + [Dependency] private readonly IPlayerManager _player = default!; + [Dependency] private readonly IPrototypeManager _protoMan = default!; + + private Dictionary> _sources = new(); + + public override void Initialize() + { + SubscribeLocalEvent(OnPrototypesReloaded); + _player.PlayerStatusChanged += OnPlayerStatusChanged; + + ReloadRecipes(); + } + + private void OnPrototypesReloaded(PrototypesReloadedEventArgs args) + { + if (!args.WasModified() + && !args.WasModified() + && !args.WasModified() + ) + return; + + ReloadRecipes(); + } + + public void ReloadRecipes() + { + // TODO: add this code to the list of known recipes because this is spaghetti + _sources.Clear(); + + // Butcherable and slicable entities + foreach (var ent in _protoMan.EnumeratePrototypes()) + { + if (ent.Abstract + || ent.Components.Any(it => ComponentNamesBlacklist.Contains(it.Key)) + || ent.SetSuffix is {} suffix && SuffixBlacklist.Any(it => suffix.Contains(it, StringComparison.OrdinalIgnoreCase)) + ) + continue; + + if (ent.TryGetComponent(out var butcherable)) + { + var butcheringSource = new FoodButcheringData(ent, butcherable); + foreach (var butchlet in butcherable.SpawnedEntities) + { + if (butchlet.PrototypeId is null) + continue; + + _sources.GetOrNew(butchlet.PrototypeId).Add(butcheringSource); + } + } + + if (ent.TryGetComponent(out var slicable) && slicable.Slice is not null) + { + _sources.GetOrNew(slicable.Slice).Add(new FoodSlicingData(ent, slicable.Slice.Value, slicable.TotalCount)); + } + } + + // Recipes + foreach (var recipe in _protoMan.EnumeratePrototypes()) + { + _sources.GetOrNew(recipe.Result).Add(new FoodRecipeData(recipe)); + } + + // Entity-spawning reactions + foreach (var reaction in _protoMan.EnumeratePrototypes()) + { + foreach (var effect in reaction.Effects) + { + if (effect is not CreateEntityReactionEffect entEffect) + continue; + + _sources.GetOrNew(entEffect.Entity).Add(new FoodReactionData(reaction, entEffect.Entity, (int) entEffect.Number)); + } + } + + Registry.Clear(); + + foreach (var (result, sources) in _sources) + { + var proto = _protoMan.Index(result); + var composition = proto.TryGetComponent(out var food) && proto.TryGetComponent(out var manager) + ? manager?.Solutions?[food.Solution]?.Contents?.ToArray() ?? [] + : []; + + // We filter out food without whitelisted reagents because well when people look for food they usually expect FOOD and not insulated gloves. + // And we get insulated and other gloves because they have ButcherableComponent and they are also moth food + if (!composition.Any(it => ReagentWhitelist.Contains(it.Reagent.Prototype))) + continue; + + // We also limit the number of sources to 10 because it's a huge performance strain to render 500 raw meat recipes. + var distinctSources = sources.DistinctBy(it => it.Identitier).Take(10); + var entry = new FoodGuideEntry(result, proto.Name, distinctSources.ToArray(), composition); + Registry.Add(entry); + } + + RaiseNetworkEvent(new FoodGuideRegistryChangedEvent(Registry)); + } + + private void OnPlayerStatusChanged(object? sender, SessionStatusEventArgs args) + { + if (args.NewStatus != SessionStatus.Connected) + return; + + RaiseNetworkEvent(new FoodGuideRegistryChangedEvent(Registry), args.Session); + } +} diff --git a/Content.Server/Power/Components/ActiveChargerComponent.cs b/Content.Server/Power/Components/ActiveChargerComponent.cs new file mode 100644 index 0000000000..9f75db853d --- /dev/null +++ b/Content.Server/Power/Components/ActiveChargerComponent.cs @@ -0,0 +1,7 @@ +using Content.Shared.Containers.ItemSlots; +using Content.Shared.Power; + +namespace Content.Server.Power.Components; + +[RegisterComponent] +public sealed partial class ActiveChargerComponent : Component { } diff --git a/Content.Server/Power/Components/ChargingComponent.cs b/Content.Server/Power/Components/ChargingComponent.cs deleted file mode 100644 index db7c14f708..0000000000 --- a/Content.Server/Power/Components/ChargingComponent.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Content.Shared.Containers.ItemSlots; -using Content.Shared.Power; - -namespace Content.Server.Power.Components -{ - [RegisterComponent] - public sealed partial class ChargingComponent : Component - { - /// - ///References the entity of the charger that is currently powering this battery - /// - public EntityUid ChargerUid; - - /// - ///References the component of the charger that is currently powering this battery - /// - public ChargerComponent ChargerComponent; - } -} diff --git a/Content.Server/Power/EntitySystems/BatterySystem.cs b/Content.Server/Power/EntitySystems/BatterySystem.cs index 1c5d83b094..cbe61f6671 100644 --- a/Content.Server/Power/EntitySystems/BatterySystem.cs +++ b/Content.Server/Power/EntitySystems/BatterySystem.cs @@ -21,7 +21,6 @@ public override void Initialize() SubscribeLocalEvent(OnBatteryRejuvenate); SubscribeLocalEvent(CalculateBatteryPrice); SubscribeLocalEvent(OnEmpPulse); - SubscribeLocalEvent(OnEmpDisabledRemoved); SubscribeLocalEvent(PreSync); SubscribeLocalEvent(PostSync); @@ -106,17 +105,6 @@ private void OnEmpPulse(EntityUid uid, BatteryComponent component, ref EmpPulseE UseCharge(uid, args.EnergyConsumption, component); } - // if a disabled battery is put into a recharged, - // allow the recharger to start recharging again after the disable ends - private void OnEmpDisabledRemoved(EntityUid uid, BatteryComponent component, ref EmpDisabledRemoved args) - { - if (!TryComp(uid, out var charging)) - return; - - var ev = new ChargerUpdateStatusEvent(); - RaiseLocalEvent(charging.ChargerUid, ref ev); - } - public float UseCharge(EntityUid uid, float value, BatteryComponent? battery = null) { if (value <= 0 || !Resolve(uid, ref battery) || battery.CurrentCharge == 0) @@ -191,10 +179,6 @@ public bool IsFull(EntityUid uid, BatteryComponent? battery = null) if (!Resolve(uid, ref battery)) return false; - // If the battery is full, remove its charging component. - if (TryComp(uid, out _)) - RemComp(uid); - return battery.CurrentCharge / battery.MaxCharge >= 0.99f; } } diff --git a/Content.Server/Power/EntitySystems/ChargerSystem.cs b/Content.Server/Power/EntitySystems/ChargerSystem.cs index ae6b024162..db16dfa008 100644 --- a/Content.Server/Power/EntitySystems/ChargerSystem.cs +++ b/Content.Server/Power/EntitySystems/ChargerSystem.cs @@ -1,16 +1,13 @@ using Content.Server.Power.Components; -using Content.Server.Emp; using Content.Server.PowerCell; using Content.Shared.Examine; using Content.Shared.Power; using Content.Shared.PowerCell.Components; -using Content.Shared.Emp; using JetBrains.Annotations; using Robust.Shared.Containers; using System.Diagnostics.CodeAnalysis; using Content.Shared.Storage.Components; using Robust.Server.Containers; -using Content.Shared.Whitelist; namespace Content.Server.Power.EntitySystems; @@ -31,11 +28,6 @@ public override void Initialize() SubscribeLocalEvent(OnInsertAttempt); SubscribeLocalEvent(OnEntityStorageInsertAttempt); SubscribeLocalEvent(OnChargerExamine); - - SubscribeLocalEvent(OnUpdateStatus); - - SubscribeLocalEvent(OnEmpPulse); - SubscribeLocalEvent(OnEmpDisabledRemoved); } private void OnStartup(EntityUid uid, ChargerComponent component, ComponentStartup args) @@ -48,58 +40,21 @@ private void OnChargerExamine(EntityUid uid, ChargerComponent component, Examine args.PushMarkup(Loc.GetString("charger-examine", ("color", "yellow"), ("chargeRate", (int) component.ChargeRate))); } - private void StartChargingBattery(EntityUid uid, ChargerComponent component, EntityUid target) - { - bool charge = true; - - if (HasComp(uid)) - charge = false; - else - if (!TryComp(target, out var battery)) - charge = false; - else - if (Math.Abs(battery.MaxCharge - battery.CurrentCharge) < 0.01) - charge = false; - - // wrap functionality in an if statement instead of returning... - if (charge) - { - var charging = EnsureComp(target); - charging.ChargerUid = uid; - charging.ChargerComponent = component; - } - - // ...so the status always updates (for insertin a power cell) - UpdateStatus(uid, component); - } - - private void StopChargingBattery(EntityUid uid, ChargerComponent component, EntityUid target) - { - if (HasComp(target)) - RemComp(target); - UpdateStatus(uid, component); - } - public override void Update(float frameTime) { - var query = EntityQueryEnumerator(); - while (query.MoveNext(out var uid, out var charging)) + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var uid, out _, out var charger, out var containerComp)) { - if (!TryComp(charging.ChargerUid, out var chargerComponent)) + if (!_container.TryGetContainer(uid, charger.SlotId, out var container, containerComp)) continue; - if (charging.ChargerComponent.Status == CellChargerStatus.Off || charging.ChargerComponent.Status == CellChargerStatus.Empty) + if (charger.Status == CellChargerStatus.Empty || charger.Status == CellChargerStatus.Charged || container.ContainedEntities.Count == 0) continue; - if (HasComp(charging.ChargerUid)) - continue; - - if (!TryComp(uid, out var battery)) - continue; - - if (Math.Abs(battery.MaxCharge - battery.CurrentCharge) < 0.01) - StopChargingBattery(charging.ChargerUid, charging.ChargerComponent, uid); - TransferPower(charging.ChargerUid, uid, charging.ChargerComponent, frameTime); + foreach (var contained in container.ContainedEntities) + { + TransferPower(uid, contained, charger, frameTime); + } } } @@ -116,7 +71,7 @@ private void OnInserted(EntityUid uid, ChargerComponent component, EntInsertedIn if (args.Container.ID != component.SlotId) return; - StartChargingBattery(uid, component, args.Entity); + UpdateStatus(uid, component); } private void OnRemoved(EntityUid uid, ChargerComponent component, EntRemovedFromContainerMessage args) @@ -124,7 +79,7 @@ private void OnRemoved(EntityUid uid, ChargerComponent component, EntRemovedFrom if (args.Container.ID != component.SlotId) return; - StopChargingBattery(uid, component, args.Entity); + UpdateStatus(uid, component); } /// @@ -157,11 +112,6 @@ private void OnEntityStorageInsertAttempt(EntityUid uid, ChargerComponent compon args.Cancelled = true; } - private void OnUpdateStatus(EntityUid uid, ChargerComponent component, ref ChargerUpdateStatusEvent args) - { - UpdateStatus(uid, component); - } - private void UpdateStatus(EntityUid uid, ChargerComponent component) { var status = GetStatus(uid, component); @@ -176,6 +126,15 @@ private void UpdateStatus(EntityUid uid, ChargerComponent component) component.Status = status; + if (component.Status == CellChargerStatus.Charging) + { + AddComp(uid); + } + else + { + RemComp(uid); + } + switch (component.Status) { case CellChargerStatus.Off: @@ -187,7 +146,7 @@ private void UpdateStatus(EntityUid uid, ChargerComponent component) _appearance.SetData(uid, CellVisual.Light, CellChargerStatus.Empty, appearance); break; case CellChargerStatus.Charging: - receiver.Load = component.ChargeRate; //does not scale with multiple slotted batteries + receiver.Load = component.ChargeRate; _appearance.SetData(uid, CellVisual.Light, CellChargerStatus.Charging, appearance); break; case CellChargerStatus.Charged: @@ -198,42 +157,6 @@ private void UpdateStatus(EntityUid uid, ChargerComponent component) throw new ArgumentOutOfRangeException(); } } - - private void OnEmpPulse(EntityUid uid, ChargerComponent component, ref EmpPulseEvent args) - { - // we don't care if we haven't been disabled - if (!args.Disabled) - return; - - // if the recharger is hit by an emp pulse, - // stop recharging contained batteries to save resources - if (!_container.TryGetContainer(uid, component.SlotId, out var container)) - return; - - foreach (var containedEntity in container.ContainedEntities) - { - if (!SearchForBattery(containedEntity, out _, out _)) - continue; - - StopChargingBattery(uid, component, containedEntity); - } - } - - private void OnEmpDisabledRemoved(EntityUid uid, ChargerComponent component, ref EmpDisabledRemoved args) - { - // if an emp disable subsides, - // attempt to start charging all batteries - if (!_container.TryGetContainer(uid, component.SlotId, out var container)) - return; - - foreach (var containedEntity in container.ContainedEntities) - { - if (!SearchForBattery(containedEntity, out _, out _)) - continue; - - StartChargingBattery(uid, component, containedEntity); - } - } private CellChargerStatus GetStatus(EntityUid uid, ChargerComponent component) { @@ -255,28 +178,13 @@ private CellChargerStatus GetStatus(EntityUid uid, ChargerComponent component) if (container.ContainedEntities.Count == 0) return CellChargerStatus.Empty; - var statusOut = CellChargerStatus.Off; - - foreach (var containedEntity in container.ContainedEntities) - { - // if none of the slotted items are actually batteries, represent the charger as off - if (!SearchForBattery(containedEntity, out _, out _)) - continue; - - // if all batteries are either EMP'd or fully charged, represent the charger as fully charged - statusOut = CellChargerStatus.Charged; - if (HasComp(containedEntity)) - continue; - - if (!HasComp(containedEntity)) - continue; + if (!SearchForBattery(container.ContainedEntities[0], out _, out var heldBattery)) + return CellChargerStatus.Off; - // if we have atleast one battery being charged, represent the charger as charging; - statusOut = CellChargerStatus.Charging; - break; - } + if (Math.Abs(heldBattery.MaxCharge - heldBattery.CurrentCharge) < 0.01) + return CellChargerStatus.Charged; - return statusOut; + return CellChargerStatus.Charging; } private void TransferPower(EntityUid uid, EntityUid targetEntity, ChargerComponent component, float frameTime) @@ -293,11 +201,11 @@ private void TransferPower(EntityUid uid, EntityUid targetEntity, ChargerCompone if (!SearchForBattery(targetEntity, out var batteryUid, out var heldBattery)) return; - _battery.TrySetCharge(batteryUid.Value, heldBattery.CurrentCharge + component.ChargeRate * frameTime, heldBattery); + _battery.SetCharge(batteryUid.Value, heldBattery.CurrentCharge + component.ChargeRate * frameTime, heldBattery); // Just so the sprite won't be set to 99.99999% visibility if (heldBattery.MaxCharge - heldBattery.CurrentCharge < 0.01) { - _battery.TrySetCharge(batteryUid.Value, heldBattery.MaxCharge, heldBattery); + _battery.SetCharge(batteryUid.Value, heldBattery.MaxCharge, heldBattery); } UpdateStatus(uid, component); @@ -315,6 +223,3 @@ private bool SearchForBattery(EntityUid uid, [NotNullWhen(true)] out EntityUid? return true; } } - -[ByRefEvent] -public record struct ChargerUpdateStatusEvent(); \ No newline at end of file diff --git a/Content.Server/Traits/Assorted/ModifyMoodTraitComponent.cs b/Content.Server/Traits/Assorted/ModifyMoodTraitComponent.cs deleted file mode 100644 index f9ae3b36f3..0000000000 --- a/Content.Server/Traits/Assorted/ModifyMoodTraitComponent.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Content.Shared.Traits.Assorted.Components; - -/// -/// Used for traits that add a starting moodlet. -/// -[RegisterComponent] -public sealed partial class MoodModifyTraitComponent : Component -{ - [DataField] - public string? MoodId = null; -} diff --git a/Content.Server/Traits/BloodDeficiencyComponent.cs b/Content.Server/Traits/BloodDeficiencyComponent.cs index 616f60cd83..c6219d3e02 100644 --- a/Content.Server/Traits/BloodDeficiencyComponent.cs +++ b/Content.Server/Traits/BloodDeficiencyComponent.cs @@ -7,8 +7,8 @@ namespace Content.Server.Traits.Assorted; public sealed partial class BloodDeficiencyComponent : Component { // - // How much reagent of blood should be removed in each update interval? + /// How much percentage of max blood volume should be removed in each update interval? // [DataField(required: true)] - public float BloodLossAmount; + public float BloodLossPercentage; } diff --git a/Content.Server/Traits/BloodDeficiencySystem.cs b/Content.Server/Traits/BloodDeficiencySystem.cs index f1ae490995..ee7a39e46e 100644 --- a/Content.Server/Traits/BloodDeficiencySystem.cs +++ b/Content.Server/Traits/BloodDeficiencySystem.cs @@ -18,6 +18,6 @@ private void OnStartup(EntityUid uid, BloodDeficiencyComponent component, Compon return; bloodstream.HasBloodDeficiency = true; - bloodstream.BloodDeficiencyLossAmount = component.BloodLossAmount; + bloodstream.BloodDeficiencyLossPercentage = component.BloodLossPercentage; } } diff --git a/Content.Server/Traits/TraitSystem.cs b/Content.Server/Traits/TraitSystem.cs index d6f13cb52a..39812f65b6 100644 --- a/Content.Server/Traits/TraitSystem.cs +++ b/Content.Server/Traits/TraitSystem.cs @@ -12,6 +12,7 @@ using Robust.Shared.Utility; using Content.Server.Abilities.Psionics; using Content.Shared.Psionics; +using Content.Shared.Mood; namespace Content.Server.Traits; @@ -65,6 +66,7 @@ public void AddTrait(EntityUid uid, TraitPrototype traitPrototype) AddTraitComponents(uid, traitPrototype); AddTraitActions(uid, traitPrototype); AddTraitPsionics(uid, traitPrototype); + AddTraitMoodlets(uid, traitPrototype); } /// @@ -139,4 +141,18 @@ public void AddTraitPsionics(EntityUid uid, TraitPrototype traitPrototype) if (_prototype.TryIndex(powerProto, out var psionicPower)) _psionicAbilities.InitializePsionicPower(uid, psionicPower, false); } + + /// + /// If a trait includes any moodlets, this adds the moodlets to the receiving entity. + /// While I can't stop you, you shouldn't use this to add temporary moodlets. + /// + public void AddTraitMoodlets(EntityUid uid, TraitPrototype traitPrototype) + { + if (traitPrototype.MoodEffects is null) + return; + + foreach (var moodProto in traitPrototype.MoodEffects) + if (_prototype.TryIndex(moodProto, out var moodlet)) + RaiseLocalEvent(uid, new MoodEffectEvent(moodlet.ID)); + } } diff --git a/Content.Shared/CCVar/CCVars.cs b/Content.Shared/CCVar/CCVars.cs index d52c442f30..de8bc81312 100644 --- a/Content.Shared/CCVar/CCVars.cs +++ b/Content.Shared/CCVar/CCVars.cs @@ -404,13 +404,6 @@ 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); - /// /// Whether item slots, such as power cell slots or AME fuel cell slots, should support quick swap if it is not otherwise specified in their YAML prototype. /// @@ -2006,6 +1999,12 @@ public static readonly CVarDef public static readonly CVarDef ToggleWalk = CVarDef.Create("control.toggle_walk", false, CVar.CLIENTONLY | CVar.ARCHIVE); + /// + /// Whether the player mob is walking by default instead of running. + /// + public static readonly CVarDef DefaultWalk = + CVarDef.Create("control.default_walk", true, CVar.CLIENT | CVar.REPLICATED | CVar.ARCHIVE); + /* * STORAGE */ @@ -2467,5 +2466,21 @@ public static readonly CVarDef CVarDef.Create("reclaimer.allow_gibbing", true, CVar.SERVER); #endregion + + #region Jetpack System + + /// + /// When true, Jetpacks can be enabled anywhere, even in gravity. + /// + public static readonly CVarDef JetpackEnableAnywhere = + CVarDef.Create("jetpack.enable_anywhere", false, CVar.REPLICATED); + + /// + /// When true, jetpacks can be enabled on grids that have zero gravity. + /// + public static readonly CVarDef JetpackEnableInNoGravity = + CVarDef.Create("jetpack.enable_in_no_gravity", true, CVar.REPLICATED); + + #endregion } } diff --git a/Content.Shared/Chat/SharedChatSystem.cs b/Content.Shared/Chat/SharedChatSystem.cs index c48d70405f..efbcc9bed5 100644 --- a/Content.Shared/Chat/SharedChatSystem.cs +++ b/Content.Shared/Chat/SharedChatSystem.cs @@ -154,10 +154,16 @@ public string SanitizeMessageCapital(string message) if (string.IsNullOrEmpty(message)) return message; // Capitalize first letter - message = char.ToUpper(message[0]) + message.Remove(0, 1); + message = OopsConcat(char.ToUpper(message[0]).ToString(), message.Remove(0, 1)); return message; } + private static string OopsConcat(string a, string b) + { + // This exists to prevent Roslyn being clever and compiling something that fails sandbox checks. + return a + b; + } + public string SanitizeMessageCapitalizeTheWordI(string message, string theWordI = "i") { if (string.IsNullOrEmpty(message)) diff --git a/Content.Shared/Chemistry/EntitySystems/RehydratableSystem.cs b/Content.Shared/Chemistry/EntitySystems/RehydratableSystem.cs index e260280ae4..44bfb583dd 100644 --- a/Content.Shared/Chemistry/EntitySystems/RehydratableSystem.cs +++ b/Content.Shared/Chemistry/EntitySystems/RehydratableSystem.cs @@ -1,12 +1,14 @@ using Content.Shared.Chemistry.Components; using Content.Shared.FixedPoint; using Content.Shared.Popups; +using Robust.Shared.Network; using Robust.Shared.Random; namespace Content.Shared.Chemistry.EntitySystems; public sealed class RehydratableSystem : EntitySystem { + [Dependency] private readonly INetManager _net = default!; [Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly SharedPopupSystem _popup = default!; [Dependency] private readonly SharedSolutionContainerSystem _solutions = default!; @@ -31,6 +33,9 @@ private void OnSolutionChange(Entity ent, ref SolutionCon // Try not to make this public if you can help it. private void Expand(Entity ent) { + if (_net.IsClient) + return; // no + var (uid, comp) = ent; var randomMob = _random.Pick(comp.PossibleSpawns); diff --git a/Content.Shared/Cuffs/SharedCuffableSystem.cs b/Content.Shared/Cuffs/SharedCuffableSystem.cs index ebbafef7f0..9777b23988 100644 --- a/Content.Shared/Cuffs/SharedCuffableSystem.cs +++ b/Content.Shared/Cuffs/SharedCuffableSystem.cs @@ -7,6 +7,7 @@ using Content.Shared.Contests; using Content.Shared.Cuffs.Components; using Content.Shared.Database; +using Content.Shared.Flight; using Content.Shared.DoAfter; using Content.Shared.Hands; using Content.Shared.Hands.Components; @@ -479,6 +480,13 @@ public bool TryCuffing(EntityUid user, EntityUid target, EntityUid handcuff, Han return true; } + if (TryComp(target, out var flight) && flight.On) + { + _popup.PopupClient(Loc.GetString("handcuff-component-target-flying-error", + ("targetName", Identity.Name(target, EntityManager, user))), user, user); + return true; + } + var cuffTime = handcuffComponent.CuffTime; if (HasComp(target)) @@ -731,4 +739,4 @@ private sealed partial class AddCuffDoAfterEvent : SimpleDoAfterEvent { } } -} +} \ No newline at end of file diff --git a/Content.Shared/Damage/Components/StaminaComponent.cs b/Content.Shared/Damage/Components/StaminaComponent.cs index 65c025c3ad..b78fe97809 100644 --- a/Content.Shared/Damage/Components/StaminaComponent.cs +++ b/Content.Shared/Damage/Components/StaminaComponent.cs @@ -39,6 +39,13 @@ public sealed partial class StaminaComponent : Component [ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField] public float CritThreshold = 100f; + /// + /// A dictionary of active stamina drains, with the key being the source of the drain, + /// DrainRate how much it changes per tick, and ModifiesSpeed if it should slow down the user. + /// + [DataField, AutoNetworkedField] + public Dictionary ActiveDrains = new(); + /// /// How long will this mob be stunned for? /// @@ -63,4 +70,4 @@ public sealed partial class StaminaComponent : Component /// [DataField, AutoNetworkedField] public float SlowdownMultiplier = 0.75f; -} +} \ No newline at end of file diff --git a/Content.Shared/Damage/Systems/StaminaSystem.cs b/Content.Shared/Damage/Systems/StaminaSystem.cs index f8a0f7c62b..e4840a6630 100644 --- a/Content.Shared/Damage/Systems/StaminaSystem.cs +++ b/Content.Shared/Damage/Systems/StaminaSystem.cs @@ -258,7 +258,7 @@ public bool TryTakeStamina(EntityUid uid, float value, StaminaComponent? compone } public void TakeStaminaDamage(EntityUid uid, float value, StaminaComponent? component = null, - EntityUid? source = null, EntityUid? with = null, bool visual = true, SoundSpecifier? sound = null) + EntityUid? source = null, EntityUid? with = null, bool visual = true, SoundSpecifier? sound = null, bool? allowsSlowdown = true) { if (!Resolve(uid, ref component, false) || value == 0) @@ -284,8 +284,8 @@ public void TakeStaminaDamage(EntityUid uid, float value, StaminaComponent? comp if (component.NextUpdate < nextUpdate) component.NextUpdate = nextUpdate; } - - _movementSpeed.RefreshMovementSpeedModifiers(uid); + if (allowsSlowdown == true) + _movementSpeed.RefreshMovementSpeedModifiers(uid); SetStaminaAlert(uid, component); if (!component.Critical) @@ -328,27 +328,51 @@ public void TakeStaminaDamage(EntityUid uid, float value, StaminaComponent? comp } } + public void ToggleStaminaDrain(EntityUid target, float drainRate, bool enabled, bool modifiesSpeed, EntityUid? source = null) + { + if (!TryComp(target, out var stamina)) + return; + + // If theres no source, we assume its the target that caused the drain. + var actualSource = source ?? target; + + if (enabled) + { + stamina.ActiveDrains[actualSource] = (drainRate, modifiesSpeed); + EnsureComp(target); + } + else + stamina.ActiveDrains.Remove(actualSource); + + Dirty(target, stamina); + } + public override void Update(float frameTime) { base.Update(frameTime); - if (!_timing.IsFirstTimePredicted) return; var stamQuery = GetEntityQuery(); var query = EntityQueryEnumerator(); var curTime = _timing.CurTime; - while (query.MoveNext(out var uid, out _)) { // Just in case we have active but not stamina we'll check and account for it. if (!stamQuery.TryGetComponent(uid, out var comp) || - comp.StaminaDamage <= 0f && !comp.Critical) + comp.StaminaDamage <= 0f && !comp.Critical && comp.ActiveDrains.Count == 0) { RemComp(uid); continue; } - + if (comp.ActiveDrains.Count > 0) + foreach (var (source, (drainRate, modifiesSpeed)) in comp.ActiveDrains) + TakeStaminaDamage(uid, + drainRate * frameTime, + comp, + source: source, + visual: false, + allowsSlowdown: modifiesSpeed); // Shouldn't need to consider paused time as we're only iterating non-paused stamina components. var nextUpdate = comp.NextUpdate; @@ -363,8 +387,11 @@ public override void Update(float frameTime) } comp.NextUpdate += TimeSpan.FromSeconds(1f); - TakeStaminaDamage(uid, -comp.Decay, comp); - Dirty(comp); + // If theres no active drains, recover stamina. + if (comp.ActiveDrains.Count == 0) + TakeStaminaDamage(uid, -comp.Decay, comp); + + Dirty(uid, comp); } } @@ -380,7 +407,6 @@ private void EnterStamCrit(EntityUid uid, StaminaComponent? component = null) component.StaminaDamage = component.CritThreshold; _stunSystem.TryParalyze(uid, component.StunTime, true); - // Give them buffer before being able to be re-stunned component.NextUpdate = _timing.CurTime + component.StunTime + StamCritBufferTime; EnsureComp(uid); @@ -407,4 +433,4 @@ private void ExitStamCrit(EntityUid uid, StaminaComponent? component = null) /// Raised before stamina damage is dealt to allow other systems to cancel it. /// [ByRefEvent] -public record struct BeforeStaminaDamageEvent(float Value, bool Cancelled = false); +public record struct BeforeStaminaDamageEvent(float Value, bool Cancelled = false); \ No newline at end of file diff --git a/Content.Shared/Flight/Events.cs b/Content.Shared/Flight/Events.cs new file mode 100644 index 0000000000..6666971b53 --- /dev/null +++ b/Content.Shared/Flight/Events.cs @@ -0,0 +1,24 @@ +using Robust.Shared.Serialization; +using Content.Shared.DoAfter; + +namespace Content.Shared.Flight.Events; + +[Serializable, NetSerializable] +public sealed partial class DashDoAfterEvent : SimpleDoAfterEvent { } + +[Serializable, NetSerializable] +public sealed partial class FlightDoAfterEvent : SimpleDoAfterEvent { } + +[Serializable, NetSerializable] +public sealed class FlightEvent : EntityEventArgs +{ + public NetEntity Uid { get; } + public bool IsFlying { get; } + public bool IsAnimated { get; } + public FlightEvent(NetEntity uid, bool isFlying, bool isAnimated) + { + Uid = uid; + IsFlying = isFlying; + IsAnimated = isAnimated; + } +} diff --git a/Content.Shared/Flight/FlightComponent.cs b/Content.Shared/Flight/FlightComponent.cs new file mode 100644 index 0000000000..d250744544 --- /dev/null +++ b/Content.Shared/Flight/FlightComponent.cs @@ -0,0 +1,101 @@ +using Robust.Shared.Audio; +using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; + +namespace Content.Shared.Flight; + +/// +/// Adds an action that allows the user to become temporarily +/// weightless at the cost of stamina and hand usage. +/// +[RegisterComponent, NetworkedComponent(), AutoGenerateComponentState] +public sealed partial class FlightComponent : Component +{ + [DataField(customTypeSerializer: typeof(PrototypeIdSerializer))] + public string? ToggleAction = "ActionToggleFlight"; + + [DataField, AutoNetworkedField] + public EntityUid? ToggleActionEntity; + + /// + /// Is the user flying right now? + /// + [DataField, AutoNetworkedField] + public bool On; + + /// + /// Stamina drain per second when flying + /// + [DataField, AutoNetworkedField] + public float StaminaDrainRate = 6.0f; + + /// + /// DoAfter delay until the user becomes weightless. + /// + [DataField, AutoNetworkedField] + public float ActivationDelay = 1.0f; + + /// + /// Speed modifier while in flight + /// + [DataField, AutoNetworkedField] + public float SpeedModifier = 2.0f; + + /// + /// Path to a sound specifier or collection for the noises made during flight + /// + [DataField] + public SoundSpecifier FlapSound = new SoundCollectionSpecifier("WingFlaps"); + + /// + /// Is the flight animated? + /// + [DataField] + public bool IsAnimated = true; + + /// + /// Does the animation animate a layer?. + /// + [DataField] + public bool IsLayerAnimated; + + /// + /// Which RSI layer path does this animate? + /// + [DataField] + public string? Layer; + + /// + /// Whats the speed of the shader? + /// + [DataField] + public float ShaderSpeed = 6.0f; + + /// + /// How much are the values in the shader's calculations multiplied by? + /// + [DataField] + public float ShaderMultiplier = 0.01f; + + /// + /// What is the offset on the shader? + /// + [DataField] + public float ShaderOffset = 0.25f; + + /// + /// What animation does the flight use? + /// + + [DataField] + public string AnimationKey = "default"; + + /// + /// Time between sounds being played + /// + [DataField] + public float FlapInterval = 1.0f; + + public float TimeUntilFlap; +} diff --git a/Content.Shared/Flight/SharedFlightSystem.cs b/Content.Shared/Flight/SharedFlightSystem.cs new file mode 100644 index 0000000000..281c6d70f0 --- /dev/null +++ b/Content.Shared/Flight/SharedFlightSystem.cs @@ -0,0 +1,104 @@ +using Content.Shared.Actions; +using Content.Shared.Movement.Systems; +using Content.Shared.Damage.Systems; +using Content.Shared.Hands.Components; +using Content.Shared.Hands.EntitySystems; +using Content.Shared.Interaction.Components; +using Content.Shared.Inventory.VirtualItem; +using Content.Shared.Flight.Events; + +namespace Content.Shared.Flight; +public abstract class SharedFlightSystem : EntitySystem +{ + [Dependency] private readonly SharedActionsSystem _actionsSystem = default!; + [Dependency] private readonly SharedVirtualItemSystem _virtualItem = default!; + [Dependency] private readonly StaminaSystem _staminaSystem = default!; + [Dependency] private readonly SharedHandsSystem _hands = default!; + [Dependency] private readonly MovementSpeedModifierSystem _movementSpeed = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnStartup); + SubscribeLocalEvent(OnShutdown); + SubscribeLocalEvent(OnRefreshMoveSpeed); + } + + #region Core Functions + private void OnStartup(EntityUid uid, FlightComponent component, ComponentStartup args) + { + _actionsSystem.AddAction(uid, ref component.ToggleActionEntity, component.ToggleAction); + } + + private void OnShutdown(EntityUid uid, FlightComponent component, ComponentShutdown args) + { + _actionsSystem.RemoveAction(uid, component.ToggleActionEntity); + } + + public void ToggleActive(EntityUid uid, bool active, FlightComponent component) + { + component.On = active; + component.TimeUntilFlap = 0f; + _actionsSystem.SetToggled(component.ToggleActionEntity, component.On); + RaiseNetworkEvent(new FlightEvent(GetNetEntity(uid), component.On, component.IsAnimated)); + _staminaSystem.ToggleStaminaDrain(uid, component.StaminaDrainRate, active, false); + _movementSpeed.RefreshMovementSpeedModifiers(uid); + UpdateHands(uid, active); + Dirty(uid, component); + } + + private void UpdateHands(EntityUid uid, bool flying) + { + if (!TryComp(uid, out var handsComponent)) + return; + + if (flying) + BlockHands(uid, handsComponent); + else + FreeHands(uid); + } + + private void BlockHands(EntityUid uid, HandsComponent handsComponent) + { + var freeHands = 0; + foreach (var hand in _hands.EnumerateHands(uid, handsComponent)) + { + if (hand.HeldEntity == null) + { + freeHands++; + continue; + } + + // Is this entity removable? (they might have handcuffs on) + if (HasComp(hand.HeldEntity) && hand.HeldEntity != uid) + continue; + + _hands.DoDrop(uid, hand, true, handsComponent); + freeHands++; + if (freeHands == 2) + break; + } + if (_virtualItem.TrySpawnVirtualItemInHand(uid, uid, out var virtItem1)) + EnsureComp(virtItem1.Value); + + if (_virtualItem.TrySpawnVirtualItemInHand(uid, uid, out var virtItem2)) + EnsureComp(virtItem2.Value); + } + + private void FreeHands(EntityUid uid) + { + _virtualItem.DeleteInHandsMatching(uid, uid); + } + + private void OnRefreshMoveSpeed(EntityUid uid, FlightComponent component, RefreshMovementSpeedModifiersEvent args) + { + if (!component.On) + return; + + args.ModifySpeed(component.SpeedModifier, component.SpeedModifier); + } + + #endregion +} +public sealed partial class ToggleFlightEvent : InstantActionEvent { } diff --git a/Content.Shared/Gravity/SharedFloatingVisualizerSystem.cs b/Content.Shared/Gravity/SharedFloatingVisualizerSystem.cs index 57136116ca..8fe9e00e7e 100644 --- a/Content.Shared/Gravity/SharedFloatingVisualizerSystem.cs +++ b/Content.Shared/Gravity/SharedFloatingVisualizerSystem.cs @@ -1,5 +1,6 @@ using System.Numerics; using Robust.Shared.Map; +using Content.Shared.Flight.Events; namespace Content.Shared.Gravity; @@ -17,6 +18,7 @@ public override void Initialize() SubscribeLocalEvent(OnComponentStartup); SubscribeLocalEvent(OnGravityChanged); SubscribeLocalEvent(OnEntParentChanged); + SubscribeNetworkEvent(OnFlight); } /// @@ -62,10 +64,24 @@ private void OnGravityChanged(ref GravityChangedEvent args) } } + private void OnFlight(FlightEvent args) + { + var uid = GetEntity(args.Uid); + if (!TryComp(uid, out var floating)) + return; + floating.CanFloat = args.IsFlying; + + if (!args.IsFlying + || !args.IsAnimated) + return; + + FloatAnimation(uid, floating.Offset, floating.AnimationKey, floating.AnimationTime); + } + private void OnEntParentChanged(EntityUid uid, FloatingVisualsComponent component, ref EntParentChangedMessage args) { var transform = args.Transform; if (CanFloat(uid, component, transform)) FloatAnimation(uid, component.Offset, component.AnimationKey, component.AnimationTime); } -} +} \ No newline at end of file diff --git a/Content.Shared/Gravity/SharedGravitySystem.cs b/Content.Shared/Gravity/SharedGravitySystem.cs index 100d2ee74f..55187bf14a 100644 --- a/Content.Shared/Gravity/SharedGravitySystem.cs +++ b/Content.Shared/Gravity/SharedGravitySystem.cs @@ -8,6 +8,7 @@ using Robust.Shared.Physics.Components; using Robust.Shared.Serialization; using Robust.Shared.Timing; +using Content.Shared.Flight; namespace Content.Shared.Gravity { @@ -24,6 +25,9 @@ public bool IsWeightless(EntityUid uid, PhysicsComponent? body = null, Transform if ((body?.BodyType & (BodyType.Static | BodyType.Kinematic)) != 0) return false; + if (TryComp(uid, out var flying) && flying.On) + return true; + if (TryComp(uid, out var ignoreGravityComponent)) return ignoreGravityComponent.Weightless; @@ -142,4 +146,4 @@ public GravityComponentState(bool enabled) } } } -} +} \ No newline at end of file diff --git a/Content.Shared/Medical/PenLightComponent.cs b/Content.Shared/Medical/PenLightComponent.cs index 50dacae3dc..770e8af7e9 100644 --- a/Content.Shared/Medical/PenLightComponent.cs +++ b/Content.Shared/Medical/PenLightComponent.cs @@ -9,6 +9,7 @@ namespace Content.Shared.Medical; [RegisterComponent, NetworkedComponent, AutoGenerateComponentPause] public sealed partial class PenLightComponent : Component { + /// /// Cooldown Time, exams take a bit /// diff --git a/Content.Shared/Mood/MoodEffectPrototype.cs b/Content.Shared/Mood/MoodEffectPrototype.cs index ad21faec80..ab9bca0160 100644 --- a/Content.Shared/Mood/MoodEffectPrototype.cs +++ b/Content.Shared/Mood/MoodEffectPrototype.cs @@ -12,24 +12,34 @@ public sealed class MoodEffectPrototype : IPrototype public string ID { get; } = default!; public string Description => Loc.GetString($"mood-effect-{ID}"); + /// /// If they already have an effect with the same category, the new one will replace the old one. /// [DataField, ValidatePrototypeId] public string? Category; + /// /// How much should this moodlet modify an entity's Mood. /// [DataField(required: true)] public float MoodChange; + /// /// How long, in Seconds, does this moodlet last? If omitted, the moodlet will last until canceled by any system. /// [DataField] public int Timeout; + /// /// Should this moodlet be hidden from the player? EG: No popups or chat messages. /// [DataField] public bool Hidden; + + /// + /// When not null, this moodlet will replace itself with another Moodlet upon expiration. + /// + [DataField] + public ProtoId? MoodletOnEnd; } diff --git a/Content.Shared/Movement/Components/InputMoverComponent.cs b/Content.Shared/Movement/Components/InputMoverComponent.cs index 916ecc90af..40cb532e60 100644 --- a/Content.Shared/Movement/Components/InputMoverComponent.cs +++ b/Content.Shared/Movement/Components/InputMoverComponent.cs @@ -74,11 +74,12 @@ public sealed partial class InputMoverComponent : Component public const float LerpTime = 1.0f; - //NOTE I don't think I'm supposed to do this - public bool Sprinting => IoCManager.Resolve().GetCVar(CCVars.GamePressToSprint) + public bool Sprinting => DefaultSprinting ? (HeldMoveButtons & MoveButtons.Walk) != 0x0 : (HeldMoveButtons & MoveButtons.Walk) == 0x0; + public bool DefaultSprinting = true; + [ViewVariables(VVAccess.ReadWrite)] public bool CanMove = true; @@ -94,6 +95,6 @@ public sealed class InputMoverComponentState : ComponentState public Angle TargetRelativeRotation; public Angle RelativeRotation; public TimeSpan LerpTarget; - public bool CanMove; + public bool CanMove, DefaultSprinting; } } diff --git a/Content.Shared/Movement/Events/UpdateInputCVarsMessage.cs b/Content.Shared/Movement/Events/UpdateInputCVarsMessage.cs new file mode 100644 index 0000000000..415a833f10 --- /dev/null +++ b/Content.Shared/Movement/Events/UpdateInputCVarsMessage.cs @@ -0,0 +1,9 @@ +using Robust.Shared.Serialization; + +namespace Content.Shared.Movement.Events; + +/// +/// Raised from the client to the server to require the server to update the client's input CVars. +/// +[Serializable, NetSerializable] +public sealed class UpdateInputCVarsMessage : EntityEventArgs { } diff --git a/Content.Shared/Movement/Systems/SharedJetpackSystem.cs b/Content.Shared/Movement/Systems/SharedJetpackSystem.cs index 8c42511f84..8d358f8db3 100644 --- a/Content.Shared/Movement/Systems/SharedJetpackSystem.cs +++ b/Content.Shared/Movement/Systems/SharedJetpackSystem.cs @@ -1,9 +1,11 @@ using Content.Shared.Actions; +using Content.Shared.CCVar; using Content.Shared.Gravity; using Content.Shared.Interaction.Events; using Content.Shared.Movement.Components; using Content.Shared.Movement.Events; using Content.Shared.Popups; +using Robust.Shared.Configuration; using Robust.Shared.Containers; using Robust.Shared.Physics.Components; using Robust.Shared.Physics.Systems; @@ -20,6 +22,7 @@ public abstract class SharedJetpackSystem : EntitySystem [Dependency] private readonly SharedPopupSystem _popup = default!; [Dependency] private readonly SharedPhysicsSystem _physics = default!; [Dependency] private readonly ActionContainerSystem _actionContainer = default!; + [Dependency] private readonly IConfigurationManager _config = default!; public override void Initialize() { @@ -125,8 +128,11 @@ private void OnJetpackToggle(EntityUid uid, JetpackComponent component, ToggleJe private bool CanEnableOnGrid(EntityUid? gridUid) { - return gridUid == null || - (!HasComp(gridUid)); + return _config.GetCVar(CCVars.JetpackEnableAnywhere) + || gridUid == null + || _config.GetCVar(CCVars.JetpackEnableInNoGravity) + && TryComp(gridUid, out var comp) + && comp.Enabled; } private void OnJetpackGetAction(EntityUid uid, JetpackComponent component, GetItemActionsEvent args) diff --git a/Content.Shared/Movement/Systems/SharedMoverController.CVars.cs b/Content.Shared/Movement/Systems/SharedMoverController.CVars.cs new file mode 100644 index 0000000000..97c837eb8e --- /dev/null +++ b/Content.Shared/Movement/Systems/SharedMoverController.CVars.cs @@ -0,0 +1,43 @@ +using Content.Shared.CCVar; +using Content.Shared.Mind.Components; +using Content.Shared.Movement.Components; +using Content.Shared.Movement.Events; +using Robust.Shared.Configuration; + +namespace Content.Shared.Movement.Systems; + +public abstract partial class SharedMoverController +{ + [Dependency] private readonly INetConfigurationManager _netConfig = default!; + + private void InitializeCVars() + { + SubscribeLocalEvent(OnMindAdded); + SubscribeLocalEvent(OnMindRemoved); + SubscribeNetworkEvent(OnUpdateCVars); + } + + private void OnMindAdded(Entity ent, ref MindAddedMessage args) + { + if (args.Mind.Comp.Session?.Channel is not { } channel) + return; + + ent.Comp.DefaultSprinting = _netConfig.GetClientCVar(channel, CCVars.DefaultWalk); + WalkingAlert(ent, ent.Comp); + } + + private void OnMindRemoved(Entity ent, ref MindRemovedMessage args) + { + // If it's an ai-controlled mob, we probably want them sprinting by default. + ent.Comp.DefaultSprinting = true; + } + + private void OnUpdateCVars(UpdateInputCVarsMessage msg, EntitySessionEventArgs args) + { + if (args.SenderSession.AttachedEntity is not { } uid || !TryComp(uid, out var mover)) + return; + + mover.DefaultSprinting = _netConfig.GetClientCVar(args.SenderSession.Channel, CCVars.DefaultWalk); + WalkingAlert(uid, mover); + } +} diff --git a/Content.Shared/Movement/Systems/SharedMoverController.Input.cs b/Content.Shared/Movement/Systems/SharedMoverController.Input.cs index 50cffa6ffe..d72ce6e2a2 100644 --- a/Content.Shared/Movement/Systems/SharedMoverController.Input.cs +++ b/Content.Shared/Movement/Systems/SharedMoverController.Input.cs @@ -5,6 +5,7 @@ using Content.Shared.Input; using Content.Shared.Movement.Components; using Content.Shared.Movement.Events; +using Robust.Shared.Configuration; using Robust.Shared.GameStates; using Robust.Shared.Input; using Robust.Shared.Input.Binding; @@ -108,6 +109,7 @@ private void OnMoverHandleState(EntityUid uid, InputMoverComponent component, Co component.TargetRelativeRotation = state.TargetRelativeRotation; component.CanMove = state.CanMove; component.RelativeEntity = EnsureEntity(state.RelativeEntity, uid); + component.DefaultSprinting = state.DefaultSprinting; // Reset component.LastInputTick = GameTick.Zero; @@ -131,6 +133,7 @@ private void OnMoverGetState(EntityUid uid, InputMoverComponent component, ref C HeldMoveButtons = component.HeldMoveButtons, RelativeRotation = component.RelativeRotation, TargetRelativeRotation = component.TargetRelativeRotation, + DefaultSprinting = component.DefaultSprinting }; } @@ -334,7 +337,7 @@ private void OnInputInit(EntityUid uid, InputMoverComponent component, Component component.RelativeEntity = xform.GridUid ?? xform.MapUid; component.TargetRelativeRotation = Angle.Zero; - WalkingAlert(uid, !component.Sprinting); + WalkingAlert(uid, component); } private void HandleRunChange(EntityUid uid, ushort subTick, bool walking) @@ -346,8 +349,8 @@ private void HandleRunChange(EntityUid uid, ushort subTick, bool walking) // if we swap to relay then stop our existing input if we ever change back. if (moverComp != null) { - WalkingAlert(uid, walking); SetMoveInput(moverComp, MoveButtons.None); + WalkingAlert(uid, moverComp); } HandleRunChange(relayMover.RelayEntity, subTick, walking); @@ -467,8 +470,8 @@ private void ResetSubtick(InputMoverComponent component) public void SetSprinting(EntityUid entity, InputMoverComponent component, ushort subTick, bool walking) { // Logger.Info($"[{_gameTiming.CurTick}/{subTick}] Sprint: {enabled}"); - WalkingAlert(entity, walking); SetMoveInput(entity, component, subTick, walking, MoveButtons.Walk); + WalkingAlert(entity, component); } /// @@ -620,7 +623,7 @@ public enum MoveButtons : byte Down = 2, Left = 4, Right = 8, - Walk = 16, // This may be either a sprint button or a walk button, depending on server config + Walk = 16, // This may be either a sprint button or a walk button, depending on mover config AnyDirection = Up | Down | Left | Right, } diff --git a/Content.Shared/Movement/Systems/SharedMoverController.cs b/Content.Shared/Movement/Systems/SharedMoverController.cs index 3cc35e7bc6..a3dc705ac1 100644 --- a/Content.Shared/Movement/Systems/SharedMoverController.cs +++ b/Content.Shared/Movement/Systems/SharedMoverController.cs @@ -98,6 +98,7 @@ public override void Initialize() InitializeInput(); InitializeRelay(); + InitializeCVars(); Subs.CVar(_configManager, CCVars.RelativeMovement, value => _relativeMovement = value, true); Subs.CVar(_configManager, CCVars.StopSpeed, value => _stopSpeed = value, true); UpdatesBefore.Add(typeof(TileFrictionController)); @@ -298,10 +299,9 @@ protected void HandleMobMovement( PhysicsSystem.SetAngularVelocity(physicsUid, 0, body: physicsComponent); } - private void WalkingAlert(EntityUid player, bool walking) + private void WalkingAlert(EntityUid player, InputMoverComponent component) { - walking = _configManager.GetCVar(CCVars.GamePressToSprint) ? !walking : walking; - _alerts.ShowAlert(player, AlertType.Walking, walking ? (short) 0 : (short) 1); + _alerts.ShowAlert(player, AlertType.Walking, component.Sprinting ? (short) 1 : (short) 0); } public void LerpRotation(EntityUid uid, InputMoverComponent mover, float frameTime) diff --git a/Content.Shared/Nutrition/Components/ButcherableComponent.cs b/Content.Shared/Nutrition/Components/ButcherableComponent.cs index 4fce45422a..975d4329dc 100644 --- a/Content.Shared/Nutrition/Components/ButcherableComponent.cs +++ b/Content.Shared/Nutrition/Components/ButcherableComponent.cs @@ -1,5 +1,6 @@ using Content.Shared.Storage; using Robust.Shared.GameStates; +using Robust.Shared.Serialization; namespace Content.Shared.Nutrition.Components { @@ -25,6 +26,7 @@ public sealed partial class ButcherableComponent : Component public bool BeingButchered; } + [Serializable, NetSerializable] public enum ButcheringType : byte { Knife, // e.g. goliaths diff --git a/Content.Shared/Nutrition/EntitySystems/SharedFoodGuideDataSystem.cs b/Content.Shared/Nutrition/EntitySystems/SharedFoodGuideDataSystem.cs new file mode 100644 index 0000000000..c31776cd75 --- /dev/null +++ b/Content.Shared/Nutrition/EntitySystems/SharedFoodGuideDataSystem.cs @@ -0,0 +1,158 @@ +using System.Linq; +using Content.Shared.Chemistry.Reaction; +using Content.Shared.Chemistry.Reagent; +using Content.Shared.Kitchen; +using Content.Shared.Nutrition.Components; +using Content.Shared.Storage; +using Robust.Shared.Prototypes; +using Robust.Shared.Serialization; + +namespace Content.Client.Chemistry.EntitySystems; + +public abstract class SharedFoodGuideDataSystem : EntitySystem +{ + public List Registry = new(); +} + +[Serializable, NetSerializable] +public sealed class FoodGuideRegistryChangedEvent : EntityEventArgs +{ + [DataField] + public List Changeset; + + public FoodGuideRegistryChangedEvent(List changeset) + { + Changeset = changeset; + } +} + +[DataDefinition, Serializable, NetSerializable] +public partial struct FoodGuideEntry +{ + [DataField] + public EntProtoId Result; + + [DataField] + public string Identifier; // Used for sorting + + [DataField] + public FoodSourceData[] Sources; + + [DataField] + public ReagentQuantity[] Composition; + + public FoodGuideEntry(EntProtoId result, string identifier, FoodSourceData[] sources, ReagentQuantity[] composition) + { + Result = result; + Identifier = identifier; + Sources = sources; + Composition = composition; + } +} + +[ImplicitDataDefinitionForInheritors, Serializable, NetSerializable] +public abstract partial class FoodSourceData +{ + /// + /// Number of products created from this source. Used for primary ordering. + /// + public abstract int OutputCount { get; } + + /// + /// A string used to distinguish different sources. Typically the name of the related entity. + /// + public string Identitier; + + public abstract bool IsSourceOf(EntProtoId food); +} + +[Serializable, NetSerializable] +public sealed partial class FoodButcheringData : FoodSourceData +{ + [DataField] + public EntProtoId Butchered; + + [DataField] + public ButcheringType Type; + + [DataField] + public List Results; + + public override int OutputCount => Results.Count; + + public FoodButcheringData(EntityPrototype butchered, ButcherableComponent comp) + { + Identitier = butchered.Name; + Butchered = butchered.ID; + Type = comp.Type; + Results = comp.SpawnedEntities; + } + + public override bool IsSourceOf(EntProtoId food) => Results.Any(it => it.PrototypeId == food); +} + +[Serializable, NetSerializable] +public sealed partial class FoodSlicingData : FoodSourceData +{ + [DataField] + public EntProtoId Sliced, Result; + + [DataField] + private int _outputCount; + public override int OutputCount => _outputCount; + + public FoodSlicingData(EntityPrototype sliced, EntProtoId result, int outputCount) + { + Identitier = sliced.Name; + Sliced = sliced.ID; + Result = result; + _outputCount = outputCount; // Server-only + } + + public override bool IsSourceOf(EntProtoId food) => food == Result; +} + +[Serializable, NetSerializable] +public sealed partial class FoodRecipeData : FoodSourceData +{ + [DataField] + public ProtoId Recipe; + + [DataField] + public EntProtoId Result; + + public override int OutputCount => 1; + + public FoodRecipeData(FoodRecipePrototype proto) + { + Identitier = proto.Name; + Recipe = proto.ID; + Result = proto.Result; + } + + public override bool IsSourceOf(EntProtoId food) => food == Result; +} + +[Serializable, NetSerializable] +public sealed partial class FoodReactionData : FoodSourceData +{ + [DataField] + public ProtoId Reaction; + + [DataField] + public EntProtoId Result; + + [DataField] + private int _outputCount; + public override int OutputCount => _outputCount; + + public FoodReactionData(ReactionPrototype reaction, EntProtoId result, int outputCount) + { + Identitier = reaction.Name; + Reaction = reaction.ID; + Result = result; + _outputCount = outputCount; + } + + public override bool IsSourceOf(EntProtoId food) => food == Result; +} diff --git a/Content.Shared/Traits/Prototypes/TraitPrototype.cs b/Content.Shared/Traits/Prototypes/TraitPrototype.cs index 7bdff058ee..cd4b02a1e6 100644 --- a/Content.Shared/Traits/Prototypes/TraitPrototype.cs +++ b/Content.Shared/Traits/Prototypes/TraitPrototype.cs @@ -1,4 +1,5 @@ using Content.Shared.Customization.Systems; +using Content.Shared.Mood; using Content.Shared.Psionics; using Robust.Shared.Prototypes; using Robust.Shared.Utility; @@ -56,4 +57,10 @@ public sealed partial class TraitPrototype : IPrototype /// [DataField] public List? PsionicPowers { get; private set; } = default!; + + /// + /// The list of all Moodlets that this trait adds. + /// + [DataField] + public List>? MoodEffects { get; private set; } = default!; } diff --git a/Resources/Audio/Effects/Flight/wingflap1.ogg b/Resources/Audio/Effects/Flight/wingflap1.ogg new file mode 100644 index 0000000000..724ac3ecd2 Binary files /dev/null and b/Resources/Audio/Effects/Flight/wingflap1.ogg differ diff --git a/Resources/Audio/Effects/Flight/wingflap2.ogg b/Resources/Audio/Effects/Flight/wingflap2.ogg new file mode 100644 index 0000000000..b0264a1317 Binary files /dev/null and b/Resources/Audio/Effects/Flight/wingflap2.ogg differ diff --git a/Resources/Audio/Effects/Flight/wingflap3.ogg b/Resources/Audio/Effects/Flight/wingflap3.ogg new file mode 100644 index 0000000000..aeb0e21acf Binary files /dev/null and b/Resources/Audio/Effects/Flight/wingflap3.ogg differ diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index d7068562a8..6a8111cec5 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -6130,3 +6130,254 @@ Entries: id: 6340 time: '2024-09-09T14:21:56.0000000+00:00' url: https://github.com/Simple-Station/Einstein-Engines/pull/794 +- author: Mnemotechnician + changes: + - type: Add + message: >- + The "food recipes" page in guidebook now contains an automatically + generated list of food recipes. + id: 6341 + time: '2024-09-11T17:55:11.0000000+00:00' + url: https://github.com/Simple-Station/Einstein-Engines/pull/783 +- author: VMSolidus + changes: + - type: Add + message: Rat Kings have returned to the default event rotation. + id: 6342 + time: '2024-09-11T19:59:32.0000000+00:00' + url: https://github.com/Simple-Station/Einstein-Engines/pull/903 +- author: VMSolidus + changes: + - type: Add + message: Jetpacks now work in zero gravity. + - type: Add + message: >- + New CCVar "jetpack.enable_anywhere" allows server hosts to optionally + make it so that jetpacks can be used anywhere, even in gravity and on + grids. + - type: Add + message: >- + New CCVar "jetpack.enable_in_no_gravity" allows server hosts to + optionally disable jetpacks being usable in zero gravity. + id: 6343 + time: '2024-09-11T19:59:45.0000000+00:00' + url: https://github.com/Simple-Station/Einstein-Engines/pull/901 +- author: VMSolidus + changes: + - type: Add + message: >- + Medical Job related items are now part of a Medical loadout group, and + have all been significantly discounted. + id: 6344 + time: '2024-09-11T20:00:07.0000000+00:00' + url: https://github.com/Simple-Station/Einstein-Engines/pull/902 +- author: Tilkku + changes: + - type: Tweak + message: Penlight Exam Messages + - type: Fix + message: Penlights now need to be on in order to examine + - type: Fix + message: Penlights can no longer be used on self + id: 6345 + time: '2024-09-11T20:02:51.0000000+00:00' + url: https://github.com/Simple-Station/Einstein-Engines/pull/900 +- author: Mnemotechnician + changes: + - type: Fix + message: Fixed a couple issues with the language menu UI and translators. + id: 6346 + time: '2024-09-11T20:03:25.0000000+00:00' + url: https://github.com/Simple-Station/Einstein-Engines/pull/893 +- author: Mocho + changes: + - type: Add + message: >- + Cargo Job related items are now part of a Cargo loadout group, and have + all been significantly discounted. + id: 6347 + time: '2024-09-11T20:27:13.0000000+00:00' + url: https://github.com/Simple-Station/Einstein-Engines/pull/909 +- author: Mocho + changes: + - type: Add + message: >- + Security Job related items are now part of a Security loadout group, and + have all been significantly discounted. + id: 6348 + time: '2024-09-11T20:39:55.0000000+00:00' + url: https://github.com/Simple-Station/Einstein-Engines/pull/908 +- author: Mocho + changes: + - type: Add + message: >- + Service Job related items are now part of a Service loadout group, and + have all been significantly discounted. + - type: Tweak + message: >- + Musicians now have significant discounts on all instruments in loadouts, + but can only take a maximum of 3. + id: 6349 + time: '2024-09-11T20:52:21.0000000+00:00' + url: https://github.com/Simple-Station/Einstein-Engines/pull/906 +- author: Mocho + changes: + - type: Add + message: >- + Engineering Job related items are now part of a Engineering loadout + group, and have all been significantly discounted. + id: 6350 + time: '2024-09-11T21:03:37.0000000+00:00' + url: https://github.com/Simple-Station/Einstein-Engines/pull/907 +- author: Squishy77 + changes: + - type: Add + message: >- + added rcds to the list of possible re and ported over the re update from + delta + - type: Tweak + message: >- + tweaked the costs of boards re-machine boards to be more consistent with + their post hyper lathe update counter parts + id: 6351 + time: '2024-09-12T00:12:39.0000000+00:00' + url: https://github.com/Simple-Station/Einstein-Engines/pull/910 +- author: SleepyScarecrow + changes: + - type: Tweak + message: Ethanol Contents + - type: Fix + message: SnowWhite Recipe + - type: Tweak + message: Ethanol overdose changed from 15 to 45 + id: 6352 + time: '2024-09-12T00:14:06.0000000+00:00' + url: https://github.com/Simple-Station/Einstein-Engines/pull/911 +- author: Mnemotechnician + changes: + - type: Add + message: Ported a number of jukebox songs from Delta-V. + id: 6353 + time: '2024-09-12T00:14:56.0000000+00:00' + url: https://github.com/Simple-Station/Einstein-Engines/pull/912 +- author: Skubman + changes: + - type: Fix + message: >- + Blood Deficiency now makes you lose a consistent percentage of blood + regardless of your blood volume, which is dictated by size. This makes + the time to low blood and death consistent for every character of all + sizes with this trait. + id: 6354 + time: '2024-09-12T00:15:18.0000000+00:00' + url: https://github.com/Simple-Station/Einstein-Engines/pull/895 +- author: stellar-novas + changes: + - type: Add + message: Airlocks once again have access wires. Happy hacking! + id: 6355 + time: '2024-09-14T00:48:34.0000000+00:00' + url: https://github.com/Simple-Station/Einstein-Engines/pull/916 +- author: Mocho + changes: + - type: Add + message: >- + Science Job related items are now part of a Science loadout group, and + have all been significantly discounted. + - type: Add + message: Added more clothing to the science section in loadouts. + - type: Tweak + message: Adjusted command loadout item pricing. + - type: Tweak + message: Added localization strings for the new loadout groups. + id: 6356 + time: '2024-09-14T01:00:26.0000000+00:00' + url: https://github.com/Simple-Station/Einstein-Engines/pull/914 +- author: VMSolidus + changes: + - type: Add + message: >- + Added missing Localizations for Departments, Jobs, and Loadout Item + Groups. + - type: Add + message: >- + Bartender-Specific loadouts! Bartenders can now choose to spawn with + either their classic shotgun, or a Mosin Nagant that comes preloaded + with rubber bullets. + id: 6357 + time: '2024-09-14T01:12:40.0000000+00:00' + url: https://github.com/Simple-Station/Einstein-Engines/pull/915 +- author: CilliePaint + changes: + - type: Tweak + message: Stuffed Lawyer's Pockets with Space Law guides! + - type: Remove + message: Took away Atmos backpacks as Starting equipment. + id: 6358 + time: '2024-09-14T05:41:40.0000000+00:00' + url: https://github.com/Simple-Station/Einstein-Engines/pull/897 +- author: Mnemotechnician + changes: + - type: Add + message: >- + You can now choose whether you want to walk or run by default in the + settings. + id: 6359 + time: '2024-09-14T05:44:56.0000000+00:00' + url: https://github.com/Simple-Station/Einstein-Engines/pull/889 +- author: VMSolidus + changes: + - type: Add + message: >- + Drug Addictions! Drug addictions are long lasting Moodlet-Pairs. The + first consisting of a temporary Mood bonus that is refreshed by + consuming the drug, and the second consisting of an extremely long + lasting mood penalty, which replaces the mood bonus should you go a long + enough time between consuming the drug in question. + - type: Add + message: Nicotine Addiction has been added as a new minor negative trait. + - type: Add + message: >- + Drugs/Reagents can now affect your character's Mood! Both with, and + without Addiction. + - type: Add + message: >- + TraitSystem has had functionality added for directly adding Moodlets to + a character upon joining the round, such as drug addictions, or + permanent mood modifications like Sanguine/Saturnine + - type: Add + message: >- + Lotophagoi Oil now induces an extremely powerful drug addiction, + providing an extremely large mood benefit for a short time. Which when + it wears off, creates an equally extreme mood penalty that lasts for a + very long time(or until you drink more Loto Oil). + id: 6360 + time: '2024-09-14T06:48:55.0000000+00:00' + url: https://github.com/Simple-Station/Einstein-Engines/pull/896 +- author: Mnemotechnician + changes: + - type: Fix + message: Cyborg recharging stations finally work again. + - type: Fix + message: >- + Rehydratable entities (such as monkey cubes) no longer spawn a second + client-side entity when rehydrated. + id: 6361 + time: '2024-09-14T17:55:41.0000000+00:00' + url: https://github.com/Simple-Station/Einstein-Engines/pull/888 +- author: VMSolidus + changes: + - type: Tweak + message: The Uncloneable trait is only worth one point now. + id: 6362 + time: '2024-09-14T18:01:21.0000000+00:00' + url: https://github.com/Simple-Station/Einstein-Engines/pull/868 +- author: Mocho + changes: + - type: Add + message: >- + Harpies are now able to fly on station for limited periods of time, + moving faster at the cost of stamina. + id: 6363 + time: '2024-09-16T04:41:44.0000000+00:00' + url: https://github.com/Simple-Station/Einstein-Engines/pull/919 diff --git a/Resources/Locale/en-US/cuffs/components/handcuff-component.ftl b/Resources/Locale/en-US/cuffs/components/handcuff-component.ftl index 16447f4251..1f8a895164 100644 --- a/Resources/Locale/en-US/cuffs/components/handcuff-component.ftl +++ b/Resources/Locale/en-US/cuffs/components/handcuff-component.ftl @@ -3,6 +3,7 @@ handcuff-component-cuffs-broken-error = The restraints are broken! handcuff-component-target-has-no-hands-error = {$targetName} has no hands! handcuff-component-target-has-no-free-hands-error = {$targetName} has no free hands! handcuff-component-too-far-away-error = You are too far away to use the restraints! +handcuff-component-target-flying-error = You cannot reach {$targetName}'s hands! handcuff-component-start-cuffing-observer = {$user} starts restraining {$target}! handcuff-component-start-cuffing-target-message = You start restraining {$targetName}. handcuff-component-start-cuffing-by-other-message = {$otherName} starts restraining you! 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 2eab749c35..7d6af11f37 100644 --- a/Resources/Locale/en-US/escape-menu/ui/options-menu.ftl +++ b/Resources/Locale/en-US/escape-menu/ui/options-menu.ftl @@ -115,6 +115,7 @@ ui-options-header-general = General ui-options-hotkey-keymap = Use US QWERTY Keys ui-options-hotkey-toggle-walk = Toggle Speed +ui-options-hotkey-default-walk = Walk by default ui-options-function-move-up = Move Up ui-options-function-move-left = Move Left diff --git a/Resources/Locale/en-US/flight/flight_system.ftl b/Resources/Locale/en-US/flight/flight_system.ftl new file mode 100644 index 0000000000..12693cc846 --- /dev/null +++ b/Resources/Locale/en-US/flight/flight_system.ftl @@ -0,0 +1,2 @@ +no-flight-while-restrained = You can't fly right now. +no-flight-while-zombified = You can't use your wings right now. \ No newline at end of file diff --git a/Resources/Locale/en-US/guidebook/chemistry/effects.ftl b/Resources/Locale/en-US/guidebook/chemistry/effects.ftl index db2f3816f6..dbb24a3caf 100644 --- a/Resources/Locale/en-US/guidebook/chemistry/effects.ftl +++ b/Resources/Locale/en-US/guidebook/chemistry/effects.ftl @@ -361,4 +361,11 @@ reagent-effect-guidebook-chem-reroll-psionic = { $chance -> [1] Allows *[other] allow - } a chance to get a different psionic power \ No newline at end of file + } a chance to get a different psionic power + +reagent-effect-guidebook-add-moodlet = + modifies mood by {$amount} + { $timeout -> + [0] indefinitely + *[other] for {$timeout} seconds + } \ No newline at end of file diff --git a/Resources/Locale/en-US/guidebook/food.ftl b/Resources/Locale/en-US/guidebook/food.ftl new file mode 100644 index 0000000000..bd4fa03251 --- /dev/null +++ b/Resources/Locale/en-US/guidebook/food.ftl @@ -0,0 +1,16 @@ +guidebook-food-name = [bold][color={$color}]{CAPITALIZE($name)}[/color][/bold] +guidebook-food-unknown-proto = Unknown prototype +guidebook-food-sources-header = Sources +guidebook-food-sources-ent-wrapper = {$name} +guidebook-food-reagents-header = Chemical composition + +guidebook-food-processing-butchering = Butcher +guidebook-food-processing-slicing = Slice +guidebook-food-processing-cooking = Microwave for {$time}s +guidebook-food-processing-reaction = Mix + +guidebook-food-processing-recipe = {$ingredients} +guidebook-food-ingredient-solid = add {$amount} {$name} +guidebook-food-ingredient-liquid = add {$amount}u {$name} + +guidebook-food-output = {$name} ({$number}) diff --git a/Resources/Locale/en-US/loadouts/categories.ftl b/Resources/Locale/en-US/loadouts/categories.ftl index 6dde7128d8..9a3291ed8a 100644 --- a/Resources/Locale/en-US/loadouts/categories.ftl +++ b/Resources/Locale/en-US/loadouts/categories.ftl @@ -8,6 +8,7 @@ loadout-category-Head = Head loadout-category-Items = Items loadout-category-Jobs = Jobs loadout-category-JobsAUncategorized = Uncategorized +loadout-category-JobsCargo = Logistics loadout-category-JobsCommand = Command loadout-category-JobsCommandAUncategorized = Uncategorized loadout-category-JobsCommandCaptain = Captain @@ -17,6 +18,13 @@ loadout-category-JobsCommandHOP = Head of Personnel loadout-category-JobsCommandHOS = Head of Security loadout-category-JobsCommandQM = Logistics Officer loadout-category-JobsCommandRD = Mystagogue +loadout-category-JobsEngineering = Engineering +loadout-category-JobsMedical = Medical +loadout-category-JobsScience = Epistemics +loadout-category-JobsSecurity = Security +loadout-category-JobsService = Service +loadout-category-JobsServiceUncategorized = Uncategorized +loadout-category-JobsServiceBartender = Bartender loadout-category-Mask = Mask loadout-category-Neck = Neck loadout-category-Outer = Outer diff --git a/Resources/Locale/en-US/loadouts/itemgroups.ftl b/Resources/Locale/en-US/loadouts/itemgroups.ftl new file mode 100644 index 0000000000..29aca3ddb9 --- /dev/null +++ b/Resources/Locale/en-US/loadouts/itemgroups.ftl @@ -0,0 +1,66 @@ +# This list is sorted Mixed Alphabetically with Generic always being placed first, Departments alphabetically, Items Groups Alphabetically, and Jobs Alphabetically after all Department items +# Generic - Clothing +character-item-group-LoadoutEyes = Civilian Eyewear +character-item-group-LoadoutGloves = Civilian Gloves +character-item-group-LoadoutHead = Civilian Headgear +character-item-group-LoadoutMasks = Civilian Masks +character-item-group-LoadoutNeck = Civilian Neckwear +character-item-group-LoadoutOuter = Civilian Outerwear +character-item-group-LoadoutShoes = Civilian Shoes +character-item-group-LoadoutUniformsCivilian = Civilian Uniforms + +# Generic - Items +character-item-group-LoadoutAirTank = Emergency Air Tanks +character-item-group-LoadoutLighters = Lighters +character-item-group-LoadoutInstrumentsAny = Musical Instruments (Non-Musician) +character-item-group-LoadoutSmokes = Smokeables +character-item-group-LoadoutBoxKits = Survival Kits +character-item-group-LoadoutWritables = Writing Tools + +# Cargo +character-item-group-LoadoutNeckCargo = Logistics Neckwear +character-item-group-LoadoutOuterCargo = Logistics Outerwear +character-item-group-LoadoutShoesCargo = Logistics Shoes + +# Engineering +character-item-group-LoadoutEyesEngineering = Engineering Eyewear +character-item-group-LoadoutHeadEngineering = Engineering Headgear +character-item-group-LoadoutOuterEngineering = Engineering Outerwear +character-item-group-LoadoutUniformsEngineering = Engineering Uniforms + +# Medical +character-item-group-LoadoutEyesMedical = Medical Eyewear +character-item-group-LoadoutGlovesMedical = Medical Gloves +character-item-group-LoadoutHeadMedical = Medical Headgear +character-item-group-LoadoutNeckMedical = Medical Neckwear +character-item-group-LoadoutOuterMedical = Medical Outerwear +character-item-group-LoadoutShoesMedical = Medical Shoes +character-item-group-LoadoutUniformsMedical = Medical Uniforms + +# Security +character-item-group-LoadoutBeltSecurity = Security Belts +character-item-group-LoadoutEquipmentSecurity = Security Equipment +character-item-group-LoadoutEyesSecurity = Security Eyewear +character-item-group-LoadoutGlovesSecurity = Security Gloves +character-item-group-LoadoutHeadSecurity = Security Headgear +character-item-group-LoadoutMaskSecurity = Security Masks +character-item-group-LoadoutNeckSecurity = Security Neckwear +character-item-group-LoadoutOuterSecurity = Security Outerwear +character-item-group-LoadoutShoesSecurity = Security Shoes +character-item-group-LoadoutUniformsSecurity = Security Uniforms + +# Service +character-item-group-LoadoutEquipmentService = Service Equipment +character-item-group-LoadoutMaskService = Service Masks +character-item-group-LoadoutNeckService = Service Neckwear +character-item-group-LoadoutOuterService = Service Outerwear +character-item-group-LoadoutShoesService = Service Shoes +character-item-group-LoadoutUniformsService = Service Uniforms + +# Service - Bartender +character-item-group-LoadoutBartenderAmmo = Bartender Ammo +character-item-group-LoadoutBartenderOuterwear = Bartender Outerwear +character-item-group-LoadoutBartenderWeapon = Bartender Weapon + +# Service - Musician +character-item-group-LoadoutMusicianInstruments = Musician Instruments diff --git a/Resources/Locale/en-US/medical/components/penlight.ftl b/Resources/Locale/en-US/medical/components/penlight.ftl index f0639ad738..c8a5d66f5d 100644 --- a/Resources/Locale/en-US/medical/components/penlight.ftl +++ b/Resources/Locale/en-US/medical/components/penlight.ftl @@ -1,11 +1,12 @@ penlight-off = The pen light is off. +penlight-cannot-examine-self = You cannot examine your own eyes. pen-light-exam-title = Pen Light pen-light-window-entity-eyes-text = {$entityName}'s conditions: pen-light-window-no-patient-data-text = No patient data. pen-light-window-entity-unknown-text = unknown pen-light-exam-blind-text = The patient's eyes are glassy and unfocused. They can't follow the light at all. -pen-light-exam-drunk-text = The patient's eyes are slow to follow the light, droopy. -pen-light-exam-eyedamage-text = The patient's eyes are partially focused, though they struggle to look at the light for too long. +pen-light-exam-drunk-text = There's a clear delay between moving the light and the patient's eyes following. +pen-light-exam-eyedamage-text = The patient's eyes have dark spots within the pupil, evident when the light is shone in them. pen-light-exam-hallucinating-text = The patient's eyes are wandering around, with dilated pupils. They don't focus on the light. pen-light-exam-healthy-text = The patient follows the light perfectly with no stuttering. \ No newline at end of file diff --git a/Resources/Locale/en-US/mood/mood.ftl b/Resources/Locale/en-US/mood/mood.ftl index bd64d52582..a931a30fb3 100644 --- a/Resources/Locale/en-US/mood/mood.ftl +++ b/Resources/Locale/en-US/mood/mood.ftl @@ -54,3 +54,16 @@ mood-effect-RevolutionFocused = VIVA LA REVOLUTION!!! mood-effect-CultFocused = Dark Gods, grant me strength! mood-effect-TraitSanguine = I have nothing to worry about. I'm sure everything will turn out well in the end! + +# Addictions +mood-effect-LotoTranscendence = + I CAN SEE ALL THAT IS, ALL THAT WILL EVER BE, AND ALL THAT EVER WAS. ALL OF CREATION HAS OPENED TO MY MIND! + I MUST HAVE IT ALL. I MUST KNOW IT ALL. ALL OF IT. FOREVER! +mood-effect-LotoEnthrallment = + It has fled from me... The heart of all creation is gone from my soul, leaving behind an emptiness I cannot bear. + I fear that I will wither to nothing if I cannot drink from the cup of knowledge once again. + +mood-effect-NicotineBenefit = + I feel as if I have been standing my entire life and I just sat down. +mood-effect-NicotineWithdrawal = + I could really go for a smoke right now. \ No newline at end of file diff --git a/Resources/Locale/en-US/traits/traits.ftl b/Resources/Locale/en-US/traits/traits.ftl index e049af3c62..ff329a12a7 100644 --- a/Resources/Locale/en-US/traits/traits.ftl +++ b/Resources/Locale/en-US/traits/traits.ftl @@ -227,3 +227,7 @@ trait-description-AnomalousPositronics = Whether by intentional design from the manufacturer, black market modifications, or accidental omission, your positronic brain lacks its standard psionic insulation. As a being that can be argued to have a soul, this by extension means that it is possible for you to be influenced by the Noosphere. + +trait-name-AddictionNicotine = Nicotine Addiction +trait-description-AddictionNicotine = + You have an addiction to Nicotine, and will require frequent smoke breaks to keep your mood in check. \ No newline at end of file diff --git a/Resources/Prototypes/Catalog/Fills/Lockers/service.yml b/Resources/Prototypes/Catalog/Fills/Lockers/service.yml index b86fa2e1f5..83bbdb435f 100644 --- a/Resources/Prototypes/Catalog/Fills/Lockers/service.yml +++ b/Resources/Prototypes/Catalog/Fills/Lockers/service.yml @@ -5,8 +5,6 @@ components: - type: StorageFill contents: - - id: ClothingOuterArmorDuraVest # DeltaV - ClothingOuterArmorBasicSlim replaced in favour of stabproof vest - - id: WeaponShotgunDoubleBarreledRubber - id: DrinkShaker - id: ClothingEyesHudBeer - id: HandLabeler @@ -17,8 +15,6 @@ prob: 0.5 - id: DrinkBottleBeer prob: 0.5 - - id: BoxBeanbag - amount: 2 - id: RagItem amount: 2 - id: LunchboxServiceFilledRandom # Delta-V Lunchboxes! diff --git a/Resources/Prototypes/CharacterItemGroups/cargoGroups.yml b/Resources/Prototypes/CharacterItemGroups/cargoGroups.yml new file mode 100644 index 0000000000..6b12652b33 --- /dev/null +++ b/Resources/Prototypes/CharacterItemGroups/cargoGroups.yml @@ -0,0 +1,19 @@ +- type: characterItemGroup + id: LoadoutOuterCargo + items: + - type: loadout + id: LoadoutCargoOuterWinterCargo + - type: loadout + id: LoadoutCargoOuterWinterMiner + +- type: characterItemGroup + id: LoadoutNeckCargo + items: + - type: loadout + id: LoadoutCargoNeckGoliathCloak + +- type: characterItemGroup + id: LoadoutShoesCargo + items: + - type: loadout + id: LoadoutCargoShoesBootsWinterCargo diff --git a/Resources/Prototypes/CharacterItemGroups/engineeringGroups.yml b/Resources/Prototypes/CharacterItemGroups/engineeringGroups.yml new file mode 100644 index 0000000000..6db873cecf --- /dev/null +++ b/Resources/Prototypes/CharacterItemGroups/engineeringGroups.yml @@ -0,0 +1,39 @@ +- type: characterItemGroup + id: LoadoutUniformsEngineering + items: + - type: loadout + id: LoadoutEngineeringUniformHazard + - type: loadout + id: LoadoutEngineeringUniformJumpskirtSenior + - type: loadout + id: LoadoutEngineeringUniformJumpsuitSenior + +- type: characterItemGroup + id: LoadoutOuterEngineering + items: + - type: loadout + id: LoadoutEngineeringOuterHazard + - type: loadout + id: LoadoutEngineeringChickenSuit + +- type: characterItemGroup + id: LoadoutHeadEngineering + items: + - type: loadout + id: LoadoutEngineeringHeadBeret + - type: loadout + id: LoadoutEngineeringHeadHardhatBlue + - type: loadout + id: LoadoutEngineeringHeadHardhatOrange + - type: loadout + id: LoadoutEngineeringHeadHardhatRed + - type: loadout + id: LoadoutEngineeringHeadHardhatWhite + - type: loadout + id: LoadoutEngineeringHeadHardhatYellow + +- type: characterItemGroup + id: LoadoutEyesEngineering + items: + - type: loadout + id: LoadoutEngineeringEyesMeson \ No newline at end of file diff --git a/Resources/Prototypes/CharacterItemGroups/medicalGroups.yml b/Resources/Prototypes/CharacterItemGroups/medicalGroups.yml new file mode 100644 index 0000000000..396f07290f --- /dev/null +++ b/Resources/Prototypes/CharacterItemGroups/medicalGroups.yml @@ -0,0 +1,101 @@ +- type: characterItemGroup + id: LoadoutUniformsMedical + items: + - type: loadout + id: LoadoutMedicalUniformScrubsBlue + - type: loadout + id: LoadoutMedicalUniformScrubsGreen + - type: loadout + id: LoadoutMedicalUniformScrubsPurple + - type: loadout + id: LoadoutMedicalUniformScrubsCyan + - type: loadout + id: LoadoutMedicalUniformScrubsBlack + - type: loadout + id: LoadoutMedicalUniformScrubsPink + - type: loadout + id: LoadoutMedicalUniformScrubsCybersun + - type: loadout + id: LoadoutMedicalUniformParamedicJumpsuit + - type: loadout + id: LoadoutMedicalUniformParamedicJumpskirt + - type: loadout + id: LoadoutMedicalUniformJumpskirtSenior + - type: loadout + id: LoadoutMedicalUniformJumpsuitSenior + - type: loadout + id: LoadoutMedicalUniformJumpsuitChemShirt + +- type: characterItemGroup + id: LoadoutOuterMedical + items: + - type: loadout + id: LoadoutMedicalOuterLabcoat + - type: loadout + id: LoadoutMedicalOuterCybersunWindbreaker + - type: loadout + id: LoadoutMedicalOuterLabcoatChem + - type: loadout + id: LoadoutMedicalOuterApronChemist + +- type: characterItemGroup + id: LoadoutGlovesMedical + items: + - type: loadout + id: LoadoutMedicalGlovesNitrile + - type: loadout + id: LoadoutMedicalHandsGlovesChemist + +- type: characterItemGroup + id: LoadoutNeckMedical + items: + - type: loadout + id: LoadoutMedicalNeckStethoscope + - type: loadout + id: LoadoutMedicalBedsheetMedical + - type: loadout + id: LoadoutMedicalNeckTieChem + +- type: characterItemGroup + id: LoadoutHeadMedical + items: + - type: loadout + id: LoadoutMedicalHeadNurse + - type: loadout + id: LoadoutMedicalHeadBeretSeniorPhysician + - type: loadout + id: LoadoutMedicalHeadSurgcapBlue + - type: loadout + id: LoadoutMedicalHeadSurgcapPurple + - type: loadout + id: LoadoutMedicalHeadSurgcapGreen + - type: loadout + id: LoadoutMedicalHeadSurgcapCyan + - type: loadout + id: LoadoutMedicalHeadSurgcapBlack + - type: loadout + id: LoadoutMedicalHeadSurgcapPink + - type: loadout + id: LoadoutMedicalHeadSurgcapWhite + - type: loadout + id: LoadoutMedicalHeadSurgcapCybersun + +- type: characterItemGroup + id: LoadoutEyesMedical + items: + - type: loadout + id: LoadoutMedicalEyesHudMedical + - type: loadout + id: LoadoutMedicalEyesEyepatchHudMedical + - type: loadout + id: LoadoutMedicalEyesHudMedicalPrescription + - type: loadout + id: LoadoutMedicalEyesGlassesChemical + - type: loadout + id: LoadoutMedicalEyesGlassesChemist + +- type: characterItemGroup + id: LoadoutShoesMedical + items: + - type: loadout + id: LoadoutMedicalShoesEnclosedChem diff --git a/Resources/Prototypes/CharacterItemGroups/musicianInstrumentsGroups.yml b/Resources/Prototypes/CharacterItemGroups/musicianInstrumentsGroups.yml new file mode 100644 index 0000000000..ccad399e74 --- /dev/null +++ b/Resources/Prototypes/CharacterItemGroups/musicianInstrumentsGroups.yml @@ -0,0 +1,31 @@ +- type: characterItemGroup + id: LoadoutMusicianInstruments + maxItems: 3 + items: + - type: loadout + id: LoadoutItemSynthesizerInstrumentMusician + - type: loadout + id: LoadoutItemMicrophoneInstrumentMusician + - type: loadout + id: LoadoutItemKalimbaInstrumentMusician + - type: loadout + id: LoadoutItemTrumpetInstrumentMusician + - type: loadout + id: LoadoutItemElectricGuitarInstrumentMusician + - type: loadout + id: LoadoutItemBassGuitarInstrumentMusician + - type: loadout + id: LoadoutItemRockGuitarInstrumentMusician + - type: loadout + id: LoadoutItemAcousticGuitarInstrumentMusician + - type: loadout + id: LoadoutItemViolinInstrumentMusician + - type: loadout + id: LoadoutItemHarmonicaInstrumentMusician + - type: loadout + id: LoadoutItemAccordionInstrumentMusician + - type: loadout + id: LoadoutItemFluteInstrumentMusician + - type: loadout + id: LoadoutItemOcarinaInstrumentMusician + diff --git a/Resources/Prototypes/CharacterItemGroups/scienceGroups.yml b/Resources/Prototypes/CharacterItemGroups/scienceGroups.yml new file mode 100644 index 0000000000..e5e43760da --- /dev/null +++ b/Resources/Prototypes/CharacterItemGroups/scienceGroups.yml @@ -0,0 +1,103 @@ +- type: characterItemGroup + id: LoadoutUniformsScience + items: + - type: loadout + id: LoadoutScienceUniformJumpskirtSenior + - type: loadout + id: LoadoutScienceUniformJumpsuitSenior + - type: loadout + id: LoadoutScienceUniformJumpskirtRoboticist + - type: loadout + id: LoadoutScienceUniformJumpsuitRoboticist + - type: loadout + id: LoadoutScienceUniformJumpsuitMonasticRobeDark + - type: loadout + id: LoadoutScienceUniformJumpsuitMonasticRobeLight + +- type: characterItemGroup + id: LoadoutOuterScience + items: + - type: loadout + id: LoadoutScienceOuterCoat + - type: loadout + id: LoadoutScienceOuterLabcoat + - type: loadout + id: LoadoutSciencegOuterCoatRobo + - type: loadout + id: LoadoutScienceOuterWinterSci + - type: loadout + id: LoadoutScienceOuterLabcoatSeniorResearcher + - type: loadout + id: LoadoutScienceOuterExplorerLabcoat + - type: loadout + id: LoadoutOuterRobeTechPriest + - type: loadout + id: LoadoutOuterPlagueSuit + - type: loadout + id: LoadoutOuterNunRobe + - type: loadout + id: LoadoutOuterHoodieBlack + - type: loadout + id: LoadoutOuterHoodieChaplain + - type: loadout + id: LoadoutScienceOuterWinterCoatMantis + +- type: characterItemGroup + id: LoadoutGlovesScience + items: + - type: loadout + id: LoadoutScienceHandsGlovesColorPurple + - type: loadout + id: LoadoutScienceHandsGlovesLatex + - type: loadout + id: LoadoutScienceHandsGlovesRobohands + +- type: characterItemGroup + id: LoadoutNeckScience + items: + - type: loadout + id: LoadoutScienceNeckTieSci + - type: loadout + id: LoadoutScienceNeckScarfStripedPurple + - type: loadout + id: LoadoutScienceNeckStoleChaplain + - type: loadout + id: LoadoutScienceNeckScarfStripedBlack + +- type: characterItemGroup + id: LoadoutMaskScience + items: + - type: loadout + id: LoadoutScienceMaskPlague + +- type: characterItemGroup + id: LoadoutHeadScience + items: + - type: loadout + id: LoadoutScienceHeadHatBeret + - type: loadout + id: LoadoutHeadHoodTechPriest + - type: loadout + id: LoadoutScienceHeadHatFez + - type: loadout + id: LoadoutScienceHeadHatHoodNunHood + - type: loadout + id: LoadoutScienceHeadHatPlaguedoctor + - type: loadout + id: LoadoutScienceHeadHatWitch + - type: loadout + id: LoadoutScienceHeadHatWitch1 + +- type: characterItemGroup + id: LoadoutEyesScience + items: + - type: loadout + id: LoadoutScienceEyesHudDiagnostic + - type: loadout + id: LoadoutScienceEyesEyepatchHudDiag + +- type: characterItemGroup + id: LoadoutShoesScience + items: + - type: loadout + id: LoadoutScienceShoesBootsWinterSci diff --git a/Resources/Prototypes/CharacterItemGroups/securityGroups.yml b/Resources/Prototypes/CharacterItemGroups/securityGroups.yml new file mode 100644 index 0000000000..edd5f8700a --- /dev/null +++ b/Resources/Prototypes/CharacterItemGroups/securityGroups.yml @@ -0,0 +1,142 @@ +- type: characterItemGroup + id: LoadoutUniformsSecurity + items: + - type: loadout + id: LoadoutSecurityUniformJumpsuitBlue + - type: loadout + id: LoadoutSecurityUniformJumpskirtBlue + - type: loadout + id: LoadoutSecurityUniformJumpsuitGrey + - type: loadout + id: LoadoutSecurityUniformJumpskirtGrey + - type: loadout + id: LoadoutSecurityUniformJumpsuitSenior + - type: loadout + id: LoadoutSecurityUniformJumpskirtSenior + - type: loadout + id: LoadoutSecurityUniformJumpsuitWardenBlue + - type: loadout + id: LoadoutSecurityUniformJumpskirtWardenBlue + - type: loadout + id: LoadoutSecurityUniformJumpsuitWardenGrey + - type: loadout + id: LoadoutSecurityUniformJumpskirtWardenGrey + - type: loadout + id: LoadoutSecurityUniformJumpsuitHoSBlue + - type: loadout + id: LoadoutSecurityUniformJumpskirtHoSBlue + - type: loadout + id: LoadoutSecurityUniformJumpsuitHoSGrey + - type: loadout + id: LoadoutSecurityUniformJumpskirtHoSGrey + - type: loadout + id: LoadoutUniformJumpsuitSecFormal + - type: loadout + id: LoadoutUniformJumpsuitSecSummer + +- type: characterItemGroup + id: LoadoutOuterSecurity + items: + - type: loadout + id: LoadoutClothingOuterArmorPlateCarrier + - type: loadout + id: LoadoutClothingOuterArmorDuraVest + - type: loadout + id: LoadoutClothingOuterCoatDetective + - type: loadout + id: LoadoutOuterVestDetective + - type: loadout + id: LoadoutClothingOuterCoatWarden + - type: loadout + id: LoadoutClothingOuterCoatHoSTrench + - type: loadout + id: LoadoutClothingOuterWinterHoS + +- type: characterItemGroup + id: LoadoutGlovesSecurity + items: + - type: loadout + id: LoadoutClothingHandsGlovesNitrile + +- type: characterItemGroup + id: LoadoutNeckSecurity + items: + - type: loadout + id: LoadoutClothingNeckCloakHos + - type: loadout + id: LoadoutClothingNeckMantleHOS + - type: loadout + id: LoadoutBedsheetBrigmedic + +- type: characterItemGroup + id: LoadoutHeadSecurity + items: + - type: loadout + id: LoadoutSecurityHeadHatBeret + - type: loadout + id: LoadoutClothingHeadHelmetBasic + - type: loadout + id: LoadoutClothingHeadHatBeretBrigmedic + - type: loadout + id: LoadoutClothingHeadHatBeretCorpsman + - type: loadout + id: LoadoutClothingHeadHatBeretWarden + - type: loadout + id: LoadoutClothingHeadHatBeretHoS + - type: loadout + id: LoadoutClothingHeadHelmetInsulated + +- type: characterItemGroup + id: LoadoutMaskSecurity + items: + - type: loadout + id: LoadoutSecurityMaskGasSwat + +- type: characterItemGroup + id: LoadoutBeltSecurity + items: + - type: loadout + id: LoadoutSecurityBeltWebbing + - type: loadout + id: LoadoutClothingBeltCorpsmanWebbing + - type: loadout + id: LoadoutClothingBeltSecurity + +- type: characterItemGroup + id: LoadoutEyesSecurity + items: + - type: loadout + id: LoadoutSecurityEyesHudSecurity + - type: loadout + id: ClothingEyesGlassesSunglasses + - type: loadout + id: LoadoutSecurityEyesEyepatchHudSecurity + - type: loadout + id: LoadoutSecurityEyesHudSecurityPrescription + - type: loadout + id: LoadoutClothingEyesGlassesSecurity + +- type: characterItemGroup + id: LoadoutShoesSecurity + items: + - type: loadout + id: LoadoutSecurityShoesJackboots + - type: loadout + id: LoadoutClothingShoesBootsCombat + +- type: characterItemGroup + maxItems: 5 # No clue what the actual number should be. + id: LoadoutEquipmentSecurity + items: + - type: loadout + id: LoadoutSecurityCombatKnife + - type: loadout + id: LoadoutSecurityFlash + - type: loadout + id: LoadoutSecurityDisabler + - type: loadout + id: LoadoutMagazinePistolRubber + - type: loadout + id: LoadoutSpeedLoaderMagnumRubber + + diff --git a/Resources/Prototypes/CharacterItemGroups/serviceGroups.yml b/Resources/Prototypes/CharacterItemGroups/serviceGroups.yml new file mode 100644 index 0000000000..01ec0aaeea --- /dev/null +++ b/Resources/Prototypes/CharacterItemGroups/serviceGroups.yml @@ -0,0 +1,100 @@ +- type: characterItemGroup + id: LoadoutUniformsService + items: + - type: loadout + id: LoadoutServiceClownOutfitJester + - type: loadout + id: LoadoutServiceClownOutfitJesterAlt + - type: loadout + id: LoadoutServiceBartenderUniformPurple + - type: loadout + id: LoadoutServiceBotanistUniformOveralls + - type: loadout + id: LoadoutServiceLawyerUniformBlueSuit + - type: loadout + id: LoadoutServiceLawyerUniformBlueSkirt + - type: loadout + id: LoadoutServiceLawyerUniformRedSuit + - type: loadout + id: LoadoutServiceLawyerUniformRedSkirt + - type: loadout + id: LoadoutServiceLawyerUniformPurpleSuit + - type: loadout + id: LoadoutServiceLawyerUniformPurpleSkirt + - type: loadout + id: LoadoutServiceLawyerUniformGoodSuit + - type: loadout + id: LoadoutServiceLawyerUniformGoodSkirt + - type: loadout + id: LoadoutServiceReporterUniformJournalist + - type: loadout + id: LoadoutServiceReporterUniformDetectivesuit + - type: loadout + id: LoadoutServiceReporterUniformDetectiveskirt + +- type: characterItemGroup + id: LoadoutOuterService + items: + - type: loadout + id: LoadoutServiceClownOuterWinter + - type: loadout + id: LoadoutServiceClownOuterClownPriest + - type: loadout + id: LoadoutServiceMimeOuterWinter + +- type: characterItemGroup + id: LoadoutNeckService + items: + - type: loadout + id: LoadoutServiceClownBedsheetClown + - type: loadout + id: LoadoutServiceMimeBedsheetMime + +- type: characterItemGroup + id: LoadoutMaskService + items: + - type: loadout + id: LoadoutServiceClownMaskSexy + - type: loadout + id: LoadoutServiceMimeMaskSad + - type: loadout + id: LoadoutServiceMimeMaskScared + - type: loadout + id: LoadoutServiceMimeMaskSexy + +- type: characterItemGroup + id: LoadoutShoesService + items: + - type: loadout + id: LoadoutServiceClownBootsWinter + - type: loadout + id: LoadoutServiceMimeShoesBootsWinter + +- type: characterItemGroup + id: LoadoutEquipmentService + items: + - type: loadout + id: LoadoutServiceClownCowToolboxFilled + +# Bartender +- type: characterItemGroup + id: LoadoutBartenderOuterwear + items: + - type: loadout + id: LoadoutServiceBartenderArmorDuraVest + +- type: characterItemGroup + id: LoadoutBartenderAmmo + items: + - type: loadout + id: LoadoutServiceBartenderBoxBeanbags + - type: loadout + id: LoadoutServiceBartenderBoxLightRifleRubber + +- type: characterItemGroup + id: LoadoutBartenderWeapon + items: + - type: loadout + id: LoadoutServiceBartenderShotgunDoubleBarreledRubber + - type: loadout + id: LoadoutServiceBartenderMosinRubber diff --git a/Resources/Prototypes/DeltaV/Reagents/Consumable/Drink/drinks.yml b/Resources/Prototypes/DeltaV/Reagents/Consumable/Drink/drinks.yml index c568c1bc75..7fdc51f1de 100644 --- a/Resources/Prototypes/DeltaV/Reagents/Consumable/Drink/drinks.yml +++ b/Resources/Prototypes/DeltaV/Reagents/Consumable/Drink/drinks.yml @@ -19,7 +19,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.3 + amount: 0.336 - !type:PopupMessage conditions: - !type:ReagentThreshold @@ -55,7 +55,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.20 + amount: 0.133 Poison: effects: - !type:HealthChange @@ -83,7 +83,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.15 + amount: 0.16 - type: reagent id: GreenGrass @@ -105,7 +105,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.05 + amount: 0.083 - type: reagent id: Daiquiri @@ -128,7 +128,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.25 + amount: 0.3 - type: reagent id: ArsonistsBrew @@ -151,7 +151,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.30 + amount: 0.08 Poison: effects: - !type:HealthChange @@ -179,6 +179,14 @@ metamorphicMaxFillLevels: 4 metamorphicFillBaseName: fill- metamorphicChangeColor: false + metabolisms: + Drink: + effects: + - !type:SatiateThirst + factor: 2 + - !type:AdjustReagent + reagent: Ethanol + amount: 0.015 - type: reagent id: Mothamphetamine @@ -201,7 +209,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.25 + amount: 0.126 Poison: effects: - !type:Jitter diff --git a/Resources/Prototypes/Entities/Clothing/Shoes/magboots.yml b/Resources/Prototypes/Entities/Clothing/Shoes/magboots.yml index 880239b51e..9381b3f208 100644 --- a/Resources/Prototypes/Entities/Clothing/Shoes/magboots.yml +++ b/Resources/Prototypes/Entities/Clothing/Shoes/magboots.yml @@ -28,6 +28,10 @@ - type: Tag tags: - WhitelistChameleon + - type: ReverseEngineering + difficulty: 2 + recipes: + - ClothingShoesBootsMag - type: entity parent: ClothingShoesBootsMag diff --git a/Resources/Prototypes/Entities/Markers/environmental.yml b/Resources/Prototypes/Entities/Markers/environmental.yml new file mode 100644 index 0000000000..0642518356 --- /dev/null +++ b/Resources/Prototypes/Entities/Markers/environmental.yml @@ -0,0 +1,100 @@ +# Radiation +- type: entity + name: Marker Radiation + id: MarkerRadiation1 + parent: MarkerBase + suffix: intensity 1 + components: + - type: Sprite + layers: + - sprite: Markers/environment.rsi + state: base-green + shader: unshaded + - sprite: Markers/environment.rsi + shader: unshaded + state: rad + - type: RadiationSource + intensity: 1 + +- type: entity + parent: MarkerRadiation1 + id: MarkerRadiation2 + suffix: intensity 2 + components: + - type: RadiationSource + intensity: 2 + +- type: entity + parent: MarkerRadiation1 + id: MarkerRadiation3 + suffix: intensity 3 + components: + - type: RadiationSource + intensity: 3 + +- type: entity + parent: MarkerRadiation1 + id: MarkerRadiation4 + suffix: intensity 4 + components: + - type: RadiationSource + intensity: 4 + +- type: entity + parent: MarkerRadiation1 + id: MarkerRadiation5 + suffix: intensity 5 + components: + - type: RadiationSource + intensity: 5 + +- type: entity + parent: MarkerRadiation1 + id: MarkerRadiation10 + suffix: intensity 10 + components: + - type: RadiationSource + intensity: 10 + +# Invisible Walls +- type: entity + name: Marker Blocker + id: MarkerBlocker + parent: MarkerBase + suffix: invisible wall + components: + - type: Sprite + layers: + - sprite: Markers/environment.rsi + state: base-blue + shader: unshaded + - sprite: Markers/environment.rsi + shader: unshaded + state: wall + - type: PlacementReplacement + key: blocker + - type: Fixtures + fixtures: + fix1: + shape: + !type:PhysShapeAabb + bounds: "-0.5,-0.5,0.5,0.5" + mask: + - FullTileMask + layer: + - WallLayer + density: 1000 + - type: Physics + bodyType: Static + + +# Weather Blocker +- type: entity + name: Marker Weather Blocker + id: MarkerWeatherblocker + parent: MarkerBase + components: + - type: Sprite + sprite: Markers/environment.rsi + state: weather + - type: BlockWeather diff --git a/Resources/Prototypes/Entities/Mobs/Species/harpy.yml b/Resources/Prototypes/Entities/Mobs/Species/harpy.yml index 788b21eafb..05ac3de8bb 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/harpy.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/harpy.yml @@ -5,6 +5,10 @@ id: MobHarpyBase abstract: true components: + - type: Flight + isLayerAnimated: true + layer: "/Textures/Mobs/Customization/Harpy/harpy_wings.rsi" + animationKey: "Flap" - type: Singer proto: HarpySinger - type: Sprite @@ -197,3 +201,15 @@ icon: DeltaV/Interface/Actions/harpy_syrinx.png itemIconStyle: BigAction event: !type:VoiceMaskSetNameEvent + +- type: entity + id: ActionToggleFlight + name: Fly + description: Make use of your wings to fly. Beat the flightless bird allegations. + noSpawn: true + components: + - type: InstantAction + checkCanInteract: false + icon: { sprite: Interface/Actions/flight.rsi, state: flight_off } + iconOn: { sprite : Interface/Actions/flight.rsi, state: flight_on } + event: !type:ToggleFlightEvent \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/Machine/production.yml b/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/Machine/production.yml index 62f3bbcb3f..891dfc1e79 100644 --- a/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/Machine/production.yml +++ b/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/Machine/production.yml @@ -29,6 +29,10 @@ Amount: 1 DefaultPrototype: Igniter ExamineName: Igniter + - type: ReverseEngineering # Delta + difficulty: 2 + recipes: + - AutolatheHyperConvectionMachineCircuitboard - type: entity id: ProtolatheMachineCircuitboard @@ -66,6 +70,10 @@ Amount: 1 DefaultPrototype: Igniter ExamineName: Igniter + - type: ReverseEngineering # Delta + difficulty: 2 + recipes: + - ProtolatheHyperConvectionMachineCircuitboard - type: entity id: BiofabricatorMachineCircuitboard @@ -79,6 +87,10 @@ MatterBin: 4 materialRequirements: Glass: 1 + - type: ReverseEngineering # Delta + difficulty: 2 + recipes: + - BiofabricatorMachineCircuitboard - type: entity id: SecurityTechFabCircuitboard @@ -151,10 +163,6 @@ Amount: 2 DefaultPrototype: Beaker ExamineName: Glass Beaker - - type: ReverseEngineering # Nyano - difficulty: 3 - recipes: - - CircuitImprinterMachineCircuitboard - type: entity id: ExosuitFabricatorMachineCircuitboard @@ -171,7 +179,7 @@ materialRequirements: Glass: 5 - type: ReverseEngineering # Nyano - difficulty: 3 + difficulty: 2 recipes: - ExosuitFabricatorMachineCircuitboard - type: GuideHelp @@ -202,10 +210,6 @@ requirements: MatterBin: 1 Manipulator: 2 - - type: ReverseEngineering # Nyano - difficulty: 2 - recipes: - - UniformPrinterMachineCircuitboard - type: entity id: VaccinatorMachineCircuitboard @@ -313,6 +317,10 @@ materialRequirements: Glass: 1 Steel: 5 + - type: ReverseEngineering # Delta + difficulty: 3 + recipes: + - ArtifactCrusherMachineCircuitboard - type: entity parent: BaseMachineCircuitboard @@ -350,6 +358,10 @@ Cable: 5 PlasmaGlass: 15 MetalRod: 4 + - type: ReverseEngineering # Nyano + difficulty: 2 + recipes: + - AnomalyVesselExperimentalCircuitboard - type: entity parent: BaseMachineCircuitboard @@ -367,6 +379,10 @@ materialRequirements: PlasmaGlass: 5 Cable: 5 + - type: ReverseEngineering # Delta + difficulty: 3 + recipes: + - AnomalySynchronizerCircuitboard - type: entity parent: BaseMachineCircuitboard @@ -451,6 +467,10 @@ deconstructionTarget: null graph: ThermomachineBoard node: hellfirefreezer + - type: ReverseEngineering # Delta + difficulty: 3 + recipes: + - HellfireFreezerMachineCircuitBoard - type: entity parent: BaseMachineCircuitboard @@ -596,6 +616,10 @@ materialRequirements: Steel: 1 Cable: 2 + - type: ReverseEngineering # Delta + difficulty: 3 + recipes: + - CrewMonitoringServerMachineCircuitboard - type: entity id: CryoPodMachineCircuitboard @@ -635,10 +659,6 @@ Amount: 2 DefaultPrototype: Beaker ExamineName: Glass Beaker - - type: ReverseEngineering # Nyano - difficulty: 2 - recipes: - - ChemMasterMachineCircuitboard - type: entity id: ChemDispenserMachineCircuitboard @@ -660,10 +680,6 @@ Amount: 2 DefaultPrototype: Beaker ExamineName: Glass Beaker - - type: ReverseEngineering # Nyano - difficulty: 2 - recipes: - - ChemDispenserMachineCircuitboard - type: entity id: BiomassReclaimerMachineCircuitboard @@ -750,9 +766,6 @@ PowerCell: 4 materialRequirements: CableHV: 10 - - type: ReverseEngineering # Nyano - recipes: - - SMESMachineCircuitboard - type: entity id: CellRechargerCircuitboard @@ -862,6 +875,10 @@ materialComposition: Steel: 30 Plastic: 30 + - type: ReverseEngineering # Delta + difficulty: 2 + recipes: + - TurboItemRechargerCircuitboard - type: entity id: SubstationMachineCircuitboard @@ -877,9 +894,6 @@ materialRequirements: CableMV: 5 CableHV: 5 - - type: ReverseEngineering # Nyano - recipes: - - SubstationMachineCircuitboard - type: PhysicalComposition materialComposition: Glass: 200 @@ -921,7 +935,7 @@ DefaultPrototype: SaxophoneInstrument ExamineName: Woodwind Instrument - type: ReverseEngineering # Nyano - difficulty: 3 + difficulty: 2 recipes: - DawInstrumentMachineCircuitboard @@ -938,10 +952,6 @@ Capacitor: 1 materialRequirements: CableHV: 5 - - type: ReverseEngineering # Nyano - difficulty: 2 - recipes: - - GeneratorPlasmaMachineCircuitboard - type: PhysicalComposition materialComposition: Glass: 200 @@ -949,6 +959,10 @@ Silicon: 20 - type: StaticPrice price: 40 + - type: ReverseEngineering # Nyano + difficulty: 2 + recipes: + - PortableGeneratorPacmanMachineCircuitboard - type: entity id: ThrusterMachineCircuitboard @@ -961,6 +975,10 @@ Capacitor: 4 materialRequirements: Steel: 5 + - type: ReverseEngineering # Delta + difficulty: 3 + recipes: + - ThrusterMachineCircuitboard - type: entity id: GyroscopeMachineCircuitboard @@ -974,6 +992,10 @@ Capacitor: 1 materialRequirements: Glass: 2 + - type: ReverseEngineering # Delta + difficulty: 3 + recipes: + - GyroscopeMachineCircuitboard - type: entity id: PortableGeneratorSuperPacmanMachineCircuitboard @@ -993,12 +1015,12 @@ Glass: 200 chemicalComposition: Silicon: 20 + - type: StaticPrice + price: 40 - type: ReverseEngineering # Nyano difficulty: 2 recipes: - PortableGeneratorSuperPacmanMachineCircuitboard - - type: StaticPrice - price: 40 - type: entity id: PortableGeneratorJrPacmanMachineCircuitboard @@ -1020,6 +1042,10 @@ Silicon: 20 - type: StaticPrice price: 40 + - type: ReverseEngineering # Nyano + difficulty: 2 + recipes: + - PortableGeneratorJrPacmanMachineCircuitboard - type: entity id: ReagentGrinderMachineCircuitboard @@ -1054,7 +1080,7 @@ Capacitor: 2 materialRequirements: Glass: 1 - - type: ReverseEngineering # Nyano + - type: ReverseEngineering # Delta difficulty: 2 recipes: - HotplateMachineCircuitboard @@ -1072,6 +1098,10 @@ materialRequirements: Glass: 2 Cable: 5 + - type: ReverseEngineering # Delta + difficulty: 2 + recipes: + - ElectricGrillMachineCircuitboard - type: entity id: StasisBedMachineCircuitboard @@ -1137,6 +1167,10 @@ materialRequirements: Steel: 5 Plastic: 5 + - type: ReverseEngineering # Delta + difficulty: 2 + recipes: + - MaterialReclaimerMachineCircuitboard - type: entity id: OreProcessorMachineCircuitboard @@ -1152,9 +1186,6 @@ Manipulator: 3 materialRequirements: Glass: 1 - - type: ReverseEngineering # Nyano - recipes: - - OreProcessorMachineCircuitboard - type: entity parent: BaseMachineCircuitboard @@ -1170,6 +1201,10 @@ Manipulator: 3 materialRequirements: Glass: 1 + - type: ReverseEngineering # Delta + difficulty: 2 + recipes: + - OreProcessorIndustrialMachineCircuitboard - type: entity id: SheetifierMachineCircuitboard @@ -1216,6 +1251,10 @@ Amount: 1 DefaultPrototype: ForkPlastic ExamineName: Utensil + - type: ReverseEngineering # Delta + difficulty: 2 + recipes: + - FatExtractorMachineCircuitboard - type: entity parent: BaseMachineCircuitboard @@ -1229,6 +1268,10 @@ MatterBin: 1 materialRequirements: Steel: 1 + - type: ReverseEngineering # Delta + difficulty: 2 + recipes: + - FlatpackerMachineCircuitboard - type: entity id: EmitterCircuitboard @@ -1348,9 +1391,6 @@ Amount: 1 DefaultPrototype: Beaker ExamineName: Glass Beaker - - type: ReverseEngineering # Nyano - recipes: - - BoozeDispenserMachineCircuitboard - type: entity id: CargoTelepadMachineCircuitboard @@ -1367,6 +1407,10 @@ materialRequirements: Steel: 5 Bluespace: 2 #DeltaV Bluespace Exists + - type: ReverseEngineering # Delta + difficulty: 3 + recipes: + - CargoTelepadMachineCircuitboard - type: entity id: SodaDispenserMachineCircuitboard @@ -1385,9 +1429,6 @@ Amount: 1 DefaultPrototype: Beaker ExamineName: Glass Beaker - - type: ReverseEngineering # Nyano - recipes: - - SodaDispenserMachineCircuitboard - type: entity id: TelecomServerCircuitboard @@ -1437,6 +1478,10 @@ Steel: 5 CableHV: 5 Uranium: 2 + - type: ReverseEngineering # Delta + difficulty: 3 + recipes: + - MiniGravityGeneratorCircuitboard - type: entity id: ShuttleGunSvalinnMachineGunCircuitboard @@ -1454,6 +1499,10 @@ materialRequirements: Steel: 5 CableHV: 5 + - type: ReverseEngineering # Delta + difficulty: 3 + recipes: + - ShuttleGunSvalinnMachineGunCircuitboard - type: entity id: ShuttleGunPerforatorCircuitboard @@ -1471,6 +1520,10 @@ materialRequirements: Steel: 10 CableHV: 5 + - type: ReverseEngineering # Delta + difficulty: 3 + recipes: + - ShuttleGunPerforatorCircuitboard - type: entity id: ShuttleGunFriendshipCircuitboard @@ -1488,6 +1541,10 @@ materialRequirements: Steel: 7 CableHV: 5 + - type: ReverseEngineering # Delta + difficulty: 3 + recipes: + - ShuttleGunFriendshipCircuitboard - type: entity id: ShuttleGunDusterCircuitboard @@ -1506,6 +1563,10 @@ Steel: 10 CableHV: 5 Uranium: 2 + - type: ReverseEngineering # Delta + difficulty: 4 + recipes: + - ShuttleGunDusterCircuitboard - type: entity id: ShuttleGunKineticCircuitboard @@ -1523,6 +1584,10 @@ materialRequirements: Steel: 5 CableHV: 2 + - type: ReverseEngineering # Delta + difficulty: 2 + recipes: + - ShuttleGunKineticCircuitboard - type: entity parent: BaseMachineCircuitboard @@ -1536,6 +1601,10 @@ Manipulator: 3 materialRequirements: Glass: 1 + - type: ReverseEngineering # Delta + difficulty: 2 + recipes: + - ReagentGrinderIndustrialMachineCircuitboard - type: entity parent: BaseMachineCircuitboard @@ -1550,3 +1619,8 @@ Steel: 2 Glass: 5 Cable: 2 + - type: ReverseEngineering # Delta + difficulty: 2 + recipes: + - JukeboxCircuitBoard + diff --git a/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/computer.yml b/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/computer.yml index 833ca2becd..35a941e759 100644 --- a/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/computer.yml +++ b/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/computer.yml @@ -122,6 +122,10 @@ prototype: ComputerSalvageExpedition - type: StealTarget stealGroup: SalvageExpeditionsComputerCircuitboard + - type: ReverseEngineering # Nyano + difficulty: 2 + recipes: + - SalvageExpeditionsComputerCircuitboard - type: entity parent: BaseComputerCircuitboard @@ -177,6 +181,10 @@ - type: Tag tags: - ComputerTelevisionCircuitboard + - type: ReverseEngineering # Nyano + difficulty: 2 + recipes: + - ComputerTelevisionCircuitboard - type: entity parent: BaseComputerCircuitboard @@ -286,6 +294,10 @@ components: - type: ComputerBoard prototype: ComputerRadar + - type: ReverseEngineering # Nyano + difficulty: 2 + recipes: + - RadarConsoleCircuitboard - type: entity parent: BaseComputerCircuitboard @@ -339,6 +351,10 @@ components: - type: ComputerBoard prototype: ComputerShuttle + - type: ReverseEngineering # Nyano + difficulty: 3 + recipes: + - ShuttleConsoleCircuitboard - type: entity parent: BaseComputerCircuitboard @@ -396,6 +412,10 @@ price: 150 - type: ComputerBoard prototype: ComputerMassMedia + - type: ReverseEngineering # Nyano + difficulty: 3 + recipes: + - ComputerMassMediaCircuitboard - type: entity parent: BaseComputerCircuitboard diff --git a/Resources/Prototypes/Entities/Objects/Devices/hand_teleporter.yml b/Resources/Prototypes/Entities/Objects/Devices/hand_teleporter.yml index 2e6c2d8c27..deac20e05e 100644 --- a/Resources/Prototypes/Entities/Objects/Devices/hand_teleporter.yml +++ b/Resources/Prototypes/Entities/Objects/Devices/hand_teleporter.yml @@ -9,10 +9,6 @@ layers: - state: icon - type: HandTeleporter - - type: ReverseEngineering # Nyano - difficulty: 4 - recipes: - - HandTeleporter - type: Tag tags: - HighRiskItem diff --git a/Resources/Prototypes/Entities/Objects/Devices/holoprojectors.yml b/Resources/Prototypes/Entities/Objects/Devices/holoprojectors.yml index 5cbf64c560..b7ad8ddd6a 100644 --- a/Resources/Prototypes/Entities/Objects/Devices/holoprojectors.yml +++ b/Resources/Prototypes/Entities/Objects/Devices/holoprojectors.yml @@ -68,6 +68,7 @@ - type: StaticPrice price: 80 - type: ReverseEngineering # Nyano + difficulty: 3 recipes: - HolofanProjector @@ -98,6 +99,10 @@ - HolofanProjector - type: StaticPrice price: 130 + - type: ReverseEngineering # Nyano + difficulty: 3 + recipes: + - HoloprojectorField - type: entity parent: HoloprojectorField diff --git a/Resources/Prototypes/Entities/Objects/Devices/swapper.yml b/Resources/Prototypes/Entities/Objects/Devices/swapper.yml index 8a743f4796..3ab014b28c 100644 --- a/Resources/Prototypes/Entities/Objects/Devices/swapper.yml +++ b/Resources/Prototypes/Entities/Objects/Devices/swapper.yml @@ -25,3 +25,7 @@ - type: Tag tags: - QuantumSpinInverter + - type: ReverseEngineering # Delta + difficulty: 4 + recipes: + - DeviceQuantumSpinInverter diff --git a/Resources/Prototypes/Entities/Objects/Specific/chemistry.yml b/Resources/Prototypes/Entities/Objects/Specific/chemistry.yml index 9e68879fb4..fd32523d8f 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/chemistry.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/chemistry.yml @@ -227,6 +227,10 @@ beaker: maxVol: 60 canReact: false + - type: ReverseEngineering # Delta + difficulty: 3 + recipes: + - CryostasisBeaker - type: entity name: bluespace beaker @@ -245,6 +249,10 @@ beaker: maxVol: 1000 canMix: true + - type: ReverseEngineering # Delta + difficulty: 4 + recipes: + - BluespaceBeaker - type: entity name: dropper @@ -401,6 +409,10 @@ tags: - Syringe - Trash + - type: ReverseEngineering # Delta + difficulty: 4 + recipes: + - SyringeBluespace - type: entity id: SyringeCryostasis @@ -432,7 +444,10 @@ tags: - Syringe - Trash - + - type: ReverseEngineering # Delta + difficulty: 3 + recipes: + - SyringeCryostasis - type: entity name: pill diff --git a/Resources/Prototypes/Entities/Objects/Tools/handheld_mass_scanner.yml b/Resources/Prototypes/Entities/Objects/Tools/handheld_mass_scanner.yml index 5647737219..131bb1960b 100644 --- a/Resources/Prototypes/Entities/Objects/Tools/handheld_mass_scanner.yml +++ b/Resources/Prototypes/Entities/Objects/Tools/handheld_mass_scanner.yml @@ -38,6 +38,10 @@ type: RadarConsoleBoundUserInterface - type: StaticPrice price: 150 + - type: ReverseEngineering # Delta + difficulty: 3 + recipes: + - HandHeldMassScanner - type: entity id: HandHeldMassScannerEmpty @@ -69,4 +73,4 @@ name: power-cell-slot-component-slot-name-default startingItem: PowerCellMicroreactor disableEject: true - swap: false \ No newline at end of file + swap: false diff --git a/Resources/Prototypes/Entities/Objects/Tools/jaws_of_life.yml b/Resources/Prototypes/Entities/Objects/Tools/jaws_of_life.yml index 36d2f1308f..12521ff644 100644 --- a/Resources/Prototypes/Entities/Objects/Tools/jaws_of_life.yml +++ b/Resources/Prototypes/Entities/Objects/Tools/jaws_of_life.yml @@ -58,6 +58,10 @@ angle: 20 soundHit: collection: MetalThud + - type: ReverseEngineering # Delta + difficulty: 3 + recipes: + - JawsOfLife - type: entity name: syndicate jaws of life diff --git a/Resources/Prototypes/Entities/Objects/Tools/tools.yml b/Resources/Prototypes/Entities/Objects/Tools/tools.yml index a6926f1d8c..c0d4fa179f 100644 --- a/Resources/Prototypes/Entities/Objects/Tools/tools.yml +++ b/Resources/Prototypes/Entities/Objects/Tools/tools.yml @@ -413,10 +413,6 @@ Plastic: 100 # - type: DynamicPrice # price: 100 - - type: ReverseEngineering # Nyano - difficulty: 2 - recipes: - - PowerDrill - type: StaticPrice price: 100 - type: MeleeWeapon @@ -433,6 +429,10 @@ angle: 20 soundHit: path: "/Audio/Items/drill_hit.ogg" + - type: ReverseEngineering # Nyano + difficulty: 2 + recipes: + - PowerDrill - type: entity id: RCD @@ -478,7 +478,7 @@ - type: PhysicalComposition materialComposition: Steel: 600 - Plastic: 100 + Plastic: 150 - type: StaticPrice price: 100 - type: UserInterface @@ -487,6 +487,10 @@ type: RCDMenuBoundUserInterface - type: ActivatableUI key: enum.RcdUiKey.Key + - type: ReverseEngineering # Nyano + difficulty: 3 + recipes: + - RCD - type: entity id: RCDEmpty @@ -548,7 +552,7 @@ heldPrefix: ammo - type: PhysicalComposition materialComposition: - Steel: 100 + Steel: 300 Plastic: 100 - type: StaticPrice price: 60 diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Snipers/snipers.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Snipers/snipers.yml index adb8e323f4..4b58642c30 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Snipers/snipers.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Snipers/snipers.yml @@ -55,6 +55,16 @@ path: /Audio/Weapons/Guns/Gunshots/sniper.ogg fireOnDropChance: 1 +- type: entity + name: Kardashev-Mosin + parent: WeaponSniperMosin + id: WeaponSniperMosinRubber + description: A weapon for hunting, or endless trench warfare. Uses .30 rifle rubber ammo. + suffix: Non-Lethal + components: + - type: BallisticAmmoProvider + proto: CartridgeLightRifleRubber + - type: entity name: Hristov parent: BaseWeaponSniper diff --git a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml index c6fa4c38cd..2d4bc9e0d8 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml @@ -355,6 +355,8 @@ - AnimalTranslator - MofficTranslatorImplanter - MofficTranslator + - RCDAmmo #DeltaV + - RCD #EE - type: EmagLatheRecipes emagDynamicRecipes: - ExplosivePayload @@ -1414,4 +1416,4 @@ - type: MaterialStorage whitelist: tags: - - PrizeTicket \ No newline at end of file + - PrizeTicket diff --git a/Resources/Prototypes/Guidebook/shiftandcrew.yml b/Resources/Prototypes/Guidebook/shiftandcrew.yml index 3c4618902e..66f9e7316d 100644 --- a/Resources/Prototypes/Guidebook/shiftandcrew.yml +++ b/Resources/Prototypes/Guidebook/shiftandcrew.yml @@ -41,3 +41,4 @@ id: Food Recipes name: guide-entry-foodrecipes text: "/ServerInfo/Guidebook/Service/FoodRecipes.xml" + filterEnabled: true diff --git a/Resources/Prototypes/Loadouts/Categories/categories.yml b/Resources/Prototypes/Loadouts/Categories/categories.yml index 77b1adbe56..80ed6d0efc 100644 --- a/Resources/Prototypes/Loadouts/Categories/categories.yml +++ b/Resources/Prototypes/Loadouts/Categories/categories.yml @@ -1,6 +1,6 @@ # Alphabetically ordered, except for Uncategorized since it is always first # AUncategorized is always first in subcategories to stay consistent with the root Uncategorized -# AUncategorized is not a spelling mistake, and might have more As added as needed +# AUncategorized is not a spelling mistake, and might have more As added as needed - type: loadoutCategory id: Uncategorized @@ -27,7 +27,13 @@ root: true subCategories: - JobsAUncategorized + - JobsCargo - JobsCommand + - JobsEngineering + - JobsMedical + - JobsScience + - JobsSecurity + - JobsService - type: loadoutCategory id: JobsAUncategorized @@ -44,7 +50,6 @@ - JobsCommandQM - JobsCommandRD - - type: loadoutCategory id: JobsCommandAUncategorized @@ -69,6 +74,32 @@ - type: loadoutCategory id: JobsCommandRD +- type: loadoutCategory + id: JobsCargo + +- type: loadoutCategory + id: JobsEngineering + +- type: loadoutCategory + id: JobsMedical + +- type: loadoutCategory + id: JobsScience + +- type: loadoutCategory + id: JobsSecurity + +- type: loadoutCategory + id: JobsService + subCategories: + - JobsServiceUncategorized + - JobsServiceBartender + +- type: loadoutCategory + id: JobsServiceUncategorized + +- type: loadoutCategory + id: JobsServiceBartender - type: loadoutCategory id: Mask diff --git a/Resources/Prototypes/Loadouts/Jobs/Heads/captain.yml b/Resources/Prototypes/Loadouts/Jobs/Heads/captain.yml index b59f044144..8b4d785476 100644 --- a/Resources/Prototypes/Loadouts/Jobs/Heads/captain.yml +++ b/Resources/Prototypes/Loadouts/Jobs/Heads/captain.yml @@ -1,7 +1,7 @@ - type: loadout id: LoadoutCommandCapNeckMantle category: JobsCommandCaptain - cost: 2 + cost: 0 exclusive: true requirements: - !type:CharacterJobRequirement @@ -13,7 +13,7 @@ - type: loadout id: LoadoutCommandCapNeckCloak category: JobsCommandCaptain - cost: 2 + cost: 0 exclusive: true requirements: - !type:CharacterJobRequirement @@ -25,7 +25,7 @@ - type: loadout id: LoadoutCommandCapNeckCloakFormal category: JobsCommandCaptain - cost: 2 + cost: 0 exclusive: true requirements: - !type:CharacterJobRequirement @@ -37,7 +37,7 @@ - type: loadout id: LoadoutCommandCapJumpsuitFormal category: JobsCommandCaptain - cost: 3 + cost: 0 exclusive: true requirements: - !type:CharacterJobRequirement @@ -49,7 +49,7 @@ - type: loadout id: LoadoutCommandCapJumpskirtFormal category: JobsCommandCaptain - cost: 3 + cost: 0 exclusive: true requirements: - !type:CharacterJobRequirement @@ -61,7 +61,7 @@ - type: loadout id: LoadoutCommandCapOuterWinter category: JobsCommandCaptain - cost: 2 + cost: 1 requirements: - !type:CharacterJobRequirement jobs: @@ -72,7 +72,7 @@ - type: loadout id: LoadoutCommandCapGloves category: JobsCommandCaptain - cost: 1 + cost: 0 requirements: - !type:CharacterJobRequirement jobs: @@ -83,7 +83,7 @@ - type: loadout id: LoadoutCommandCapHat category: JobsCommandCaptain - cost: 1 + cost: 0 requirements: - !type:CharacterJobRequirement jobs: @@ -94,7 +94,7 @@ - type: loadout id: LoadoutCommandCapHatCapcap category: JobsCommandCaptain - cost: 1 + cost: 0 requirements: - !type:CharacterJobRequirement jobs: @@ -105,7 +105,7 @@ - type: loadout id: LoadoutCommandCapHatBeret category: JobsCommandCaptain - cost: 1 + cost: 0 requirements: - !type:CharacterJobRequirement jobs: @@ -116,7 +116,7 @@ - type: loadout id: LoadoutCommandCapMaskGas category: JobsCommandCaptain - cost: 1 + cost: 0 requirements: - !type:CharacterJobRequirement jobs: @@ -127,7 +127,7 @@ - type: loadout id: LoadoutCommandCapShoesBootsWinter category: JobsCommandCaptain - cost: 1 + cost: 0 exclusive: true requirements: - !type:CharacterJobRequirement diff --git a/Resources/Prototypes/Loadouts/Jobs/Heads/chiefEngineer.yml b/Resources/Prototypes/Loadouts/Jobs/Heads/chiefEngineer.yml index 187c06119e..4ac34495ba 100644 --- a/Resources/Prototypes/Loadouts/Jobs/Heads/chiefEngineer.yml +++ b/Resources/Prototypes/Loadouts/Jobs/Heads/chiefEngineer.yml @@ -1,7 +1,7 @@ - type: loadout id: LoadoutCommandCENeckMantle category: JobsCommandCE - cost: 2 + cost: 0 exclusive: true requirements: - !type:CharacterJobRequirement @@ -13,7 +13,7 @@ - type: loadout id: LoadoutCommandCENeckCloak category: JobsCommandCE - cost: 2 + cost: 0 exclusive: true requirements: - !type:CharacterJobRequirement @@ -25,7 +25,7 @@ - type: loadout id: LoadoutCommandCEOuterWinter category: JobsCommandCE - cost: 2 + cost: 1 requirements: - !type:CharacterJobRequirement jobs: @@ -36,7 +36,7 @@ - type: loadout id: LoadoutCommandCEShoesBootsWinter category: JobsCommandCE - cost: 1 + cost: 0 exclusive: true requirements: - !type:CharacterJobRequirement diff --git a/Resources/Prototypes/Loadouts/Jobs/Heads/chiefMedicalOfficer.yml b/Resources/Prototypes/Loadouts/Jobs/Heads/chiefMedicalOfficer.yml index 8b236a48f4..79d821a8db 100644 --- a/Resources/Prototypes/Loadouts/Jobs/Heads/chiefMedicalOfficer.yml +++ b/Resources/Prototypes/Loadouts/Jobs/Heads/chiefMedicalOfficer.yml @@ -1,7 +1,7 @@ - type: loadout id: LoadoutCommandCMONeckMantle category: JobsCommandCMO - cost: 2 + cost: 0 exclusive: true requirements: - !type:CharacterJobRequirement @@ -13,7 +13,7 @@ - type: loadout id: LoadoutCommandCMONeckCloak category: JobsCommandCMO - cost: 2 + cost: 0 exclusive: true requirements: - !type:CharacterJobRequirement @@ -25,7 +25,7 @@ - type: loadout id: LoadoutCommandCMOOuterWinter category: JobsCommandCMO - cost: 2 + cost: 1 requirements: - !type:CharacterJobRequirement jobs: @@ -36,7 +36,7 @@ - type: loadout id: LoadoutCommandCMOOuterLab category: JobsCommandCMO - cost: 1 + cost: 0 requirements: - !type:CharacterJobRequirement jobs: @@ -47,7 +47,7 @@ - type: loadout id: LoadoutCommandCMOHatBeret category: JobsCommandCMO - cost: 1 + cost: 0 requirements: - !type:CharacterJobRequirement jobs: @@ -58,7 +58,7 @@ - type: loadout id: LoadoutCommandCMOShoesBootsWinter category: JobsCommandCMO - cost: 1 + cost: 0 exclusive: true requirements: - !type:CharacterJobRequirement diff --git a/Resources/Prototypes/Loadouts/Jobs/Heads/headOfPersonnel.yml b/Resources/Prototypes/Loadouts/Jobs/Heads/headOfPersonnel.yml index 44b77d3acd..d17a31bb65 100644 --- a/Resources/Prototypes/Loadouts/Jobs/Heads/headOfPersonnel.yml +++ b/Resources/Prototypes/Loadouts/Jobs/Heads/headOfPersonnel.yml @@ -1,7 +1,7 @@ - type: loadout id: LoadoutCommandHOPNeckMantle category: JobsCommandHOP - cost: 2 + cost: 0 exclusive: true requirements: - !type:CharacterJobRequirement @@ -13,7 +13,7 @@ - type: loadout id: LoadoutCommandHOPNeckCloak category: JobsCommandHOP - cost: 2 + cost: 0 exclusive: true requirements: - !type:CharacterJobRequirement @@ -25,7 +25,7 @@ - type: loadout id: LoadoutCommandHOPJumpsuitTurtleneckBoatswain category: JobsCommandHOP - cost: 2 + cost: 0 exclusive: true requirements: - !type:CharacterJobRequirement @@ -37,7 +37,7 @@ - type: loadout id: LoadoutCommandHOPJumpsuitMess category: JobsCommandHOP - cost: 2 + cost: 0 exclusive: true requirements: - !type:CharacterJobRequirement @@ -49,7 +49,7 @@ - type: loadout id: LoadoutCommandHOPJumpskirtMess category: JobsCommandHOP - cost: 2 + cost: 0 exclusive: true requirements: - !type:CharacterJobRequirement @@ -61,7 +61,7 @@ - type: loadout id: LoadoutcommandHOPOuterCoatFormal category: JobsCommandHOP - cost: 2 + cost: 0 requirements: - !type:CharacterJobRequirement jobs: @@ -72,7 +72,7 @@ - type: loadout id: LoadoutCommandHOPBackIan category: JobsCommandHOP - cost: 4 + cost: 2 requirements: - !type:CharacterJobRequirement jobs: @@ -83,7 +83,7 @@ - type: loadout id: LoadoutCommandHOPHatCap category: JobsCommandHOP - cost: 1 + cost: 0 requirements: - !type:CharacterJobRequirement jobs: @@ -94,7 +94,7 @@ - type: loadout id: LoadoutCommandHOPShoesBootsWinter category: JobsCommandHOP - cost: 1 + cost: 0 exclusive: true requirements: - !type:CharacterJobRequirement @@ -106,7 +106,7 @@ - type: loadout id: LoadoutCommandHOPBedsheetIan category: JobsCommandHOP - cost: 2 + cost: 0 exclusive: true requirements: - !type:CharacterJobRequirement diff --git a/Resources/Prototypes/Loadouts/Jobs/Heads/headOfSecurity.yml b/Resources/Prototypes/Loadouts/Jobs/Heads/headOfSecurity.yml index 89e36caed4..6e53c0195e 100644 --- a/Resources/Prototypes/Loadouts/Jobs/Heads/headOfSecurity.yml +++ b/Resources/Prototypes/Loadouts/Jobs/Heads/headOfSecurity.yml @@ -1,7 +1,7 @@ - type: loadout id: LoadoutCommandHOSNeckMantle category: JobsCommandHOS - cost: 2 + cost: 0 exclusive: true requirements: - !type:CharacterJobRequirement @@ -13,7 +13,7 @@ - type: loadout id: LoadoutCommandHOSNeckCloak category: JobsCommandHOS - cost: 2 + cost: 0 exclusive: true requirements: - !type:CharacterJobRequirement @@ -25,7 +25,7 @@ - type: loadout id: LoadoutCommandHOSJumpsuitAlt category: JobsCommandHOS - cost: 2 + cost: 0 exclusive: true requirements: - !type:CharacterJobRequirement @@ -37,7 +37,7 @@ - type: loadout id: LoadoutCommandHOSJumpsuitBlue category: JobsCommandHOS - cost: 2 + cost: 0 exclusive: true requirements: - !type:CharacterJobRequirement @@ -49,7 +49,7 @@ - type: loadout id: LoadoutCommandHOSJumpsuitGrey category: JobsCommandHOS - cost: 2 + cost: 0 exclusive: true requirements: - !type:CharacterJobRequirement @@ -61,7 +61,7 @@ - type: loadout id: LoadoutCommandHOSJumpsuitParade category: JobsCommandHOS - cost: 3 + cost: 0 exclusive: true requirements: - !type:CharacterJobRequirement @@ -73,7 +73,7 @@ - type: loadout id: LoadoutCommandHOSJumpsuitFormal category: JobsCommandHOS - cost: 3 + cost: 0 exclusive: true requirements: - !type:CharacterJobRequirement @@ -85,7 +85,7 @@ - type: loadout id: LoadoutCommandHOSJumpskirtAlt category: JobsCommandHOS - cost: 2 + cost: 0 exclusive: true requirements: - !type:CharacterJobRequirement @@ -97,7 +97,7 @@ - type: loadout id: LoadoutCommandHOSJumpskirtParade category: JobsCommandHOS - cost: 3 + cost: 0 exclusive: true requirements: - !type:CharacterJobRequirement @@ -109,7 +109,7 @@ - type: loadout id: LoadoutCommandHOSJumpskirtFormal category: JobsCommandHOS - cost: 3 + cost: 0 exclusive: true requirements: - !type:CharacterJobRequirement @@ -121,7 +121,7 @@ - type: loadout id: LoadoutCommandHOSOuterWinter category: JobsCommandHOS - cost: 2 + cost: 1 requirements: - !type:CharacterJobRequirement jobs: @@ -132,7 +132,7 @@ - type: loadout id: LoadoutCommandHOSOuterTrench category: JobsCommandHOS - cost: 2 + cost: 1 requirements: - !type:CharacterJobRequirement jobs: @@ -143,7 +143,7 @@ - type: loadout id: LoadoutCommandHOSHatBeret category: JobsCommandHOS - cost: 1 + cost: 0 requirements: - !type:CharacterJobRequirement jobs: @@ -154,7 +154,7 @@ - type: loadout id: LoadoutCommandHOSHatHoshat category: JobsCommandHOS - cost: 1 + cost: 0 requirements: - !type:CharacterJobRequirement jobs: @@ -165,7 +165,7 @@ - type: loadout id: LoadoutCommandHOSShoesBootsWinter category: JobsCommandHOS - cost: 1 + cost: 0 exclusive: true requirements: - !type:CharacterJobRequirement diff --git a/Resources/Prototypes/Loadouts/Jobs/Heads/quarterMaster.yml b/Resources/Prototypes/Loadouts/Jobs/Heads/quarterMaster.yml index 62d872cea2..8064b3105e 100644 --- a/Resources/Prototypes/Loadouts/Jobs/Heads/quarterMaster.yml +++ b/Resources/Prototypes/Loadouts/Jobs/Heads/quarterMaster.yml @@ -14,7 +14,7 @@ - type: loadout id: LoadoutCommandQMNeckCloak category: JobsCommandQM - cost: 2 + cost: 0 exclusive: true requirements: - !type:CharacterJobRequirement @@ -26,7 +26,7 @@ - type: loadout id: LoadoutCommandQMUniformTurtleneck category: JobsCommandQM - cost: 2 + cost: 0 exclusive: true requirements: - !type:CharacterJobRequirement @@ -38,7 +38,7 @@ - type: loadout id: LoadoutCommandQMUniformTurtleneckSkirt category: JobsCommandQM - cost: 2 + cost: 0 exclusive: true requirements: - !type:CharacterJobRequirement @@ -50,7 +50,7 @@ - type: loadout id: LoadoutCommandQMHeadSoft category: JobsCommandQM - cost: 1 + cost: 0 requirements: - !type:CharacterJobRequirement jobs: @@ -61,7 +61,7 @@ - type: loadout id: LoadoutCommandQMShoesBootsWinter category: JobsCommandQM - cost: 1 + cost: 0 exclusive: true requirements: - !type:CharacterJobRequirement diff --git a/Resources/Prototypes/Loadouts/Jobs/Heads/researchDirector.yml b/Resources/Prototypes/Loadouts/Jobs/Heads/researchDirector.yml index 6448f4a151..5d0421fe39 100644 --- a/Resources/Prototypes/Loadouts/Jobs/Heads/researchDirector.yml +++ b/Resources/Prototypes/Loadouts/Jobs/Heads/researchDirector.yml @@ -1,53 +1,97 @@ +# Outer + - type: loadout - id: LoadoutCommandRDNeckMantle + id: LoadoutCommandRDOuterWinter category: JobsCommandRD - cost: 2 + cost: 1 + requirements: + - !type:CharacterJobRequirement + jobs: + - ResearchDirector + items: + - ClothingOuterWinterRD + +- type: loadout + id: LoadoutCommandRDOuterMysta + category: JobsCommandRD + cost: 0 + requirements: + - !type:CharacterJobRequirement + jobs: + - ResearchDirector + items: + - ClothingOuterCoatRndMysta + +# Head + +- type: loadout + id: LoadoutCommandRDHeadHatBeretMysta + category: JobsCommandRD + cost: 0 exclusive: true requirements: - !type:CharacterJobRequirement jobs: - ResearchDirector items: - - ClothingNeckMantleRD + - ClothingHeadHatBeretMysta - type: loadout - id: LoadoutCommandRDNeckCloak + id: LoadoutCommandRDHeadHoodMysta category: JobsCommandRD - cost: 2 + cost: 0 exclusive: true requirements: - !type:CharacterJobRequirement jobs: - ResearchDirector items: - - ClothingNeckCloakRd + - ClothingHeadHoodMysta + +# Neck - type: loadout - id: LoadoutCommandRDOuterWinter + id: LoadoutCommandRDNeckMantle category: JobsCommandRD - cost: 2 + cost: 0 + exclusive: true requirements: - !type:CharacterJobRequirement jobs: - ResearchDirector items: - - ClothingOuterWinterRD + - ClothingNeckMantleRD - type: loadout - id: LoadoutCommandRDOuterMysta + id: LoadoutCommandRDNeckCloak category: JobsCommandRD - cost: 2 + cost: 0 + exclusive: true requirements: - !type:CharacterJobRequirement jobs: - ResearchDirector items: - - ClothingOuterCoatRndMysta + - ClothingNeckCloakRd + +- type: loadout + id: LoadoutCommandRDNeckCloakMystagogue + category: JobsCommandRD + cost: 0 + exclusive: true + requirements: + - !type:CharacterJobRequirement + jobs: + - ResearchDirector + items: + - ClothingNeckCloakMystagogue + +# Shoes - type: loadout id: LoadoutCommandRDShoesBootsWinter category: JobsCommandRD - cost: 1 + cost: 0 exclusive: true requirements: - !type:CharacterJobRequirement diff --git a/Resources/Prototypes/Loadouts/Jobs/cargo.yml b/Resources/Prototypes/Loadouts/Jobs/cargo.yml index 2bec0b7c0a..4558e362bf 100644 --- a/Resources/Prototypes/Loadouts/Jobs/cargo.yml +++ b/Resources/Prototypes/Loadouts/Jobs/cargo.yml @@ -1,10 +1,12 @@ # Cargo technician - type: loadout id: LoadoutCargoOuterWinterCargo - category: JobsAUncategorized - cost: 2 + category: JobsCargo + cost: 1 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutOuterCargo - !type:CharacterJobRequirement jobs: - CargoTechnician @@ -13,10 +15,12 @@ - type: loadout id: LoadoutCargoShoesBootsWinterCargo - category: JobsAUncategorized - cost: 1 + category: JobsCargo + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutShoesCargo - !type:CharacterJobRequirement jobs: - CargoTechnician @@ -27,10 +31,12 @@ - type: loadout id: LoadoutCargoOuterWinterMiner - category: JobsAUncategorized - cost: 2 + category: JobsCargo + cost: 1 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutOuterCargo - !type:CharacterJobRequirement jobs: - SalvageSpecialist @@ -39,10 +45,12 @@ - type: loadout id: LoadoutCargoNeckGoliathCloak - category: JobsAUncategorized - cost: 2 + category: JobsCargo + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutNeckCargo - !type:CharacterJobRequirement jobs: - SalvageSpecialist diff --git a/Resources/Prototypes/Loadouts/Jobs/engineering.yml b/Resources/Prototypes/Loadouts/Jobs/engineering.yml index 94f018e583..2bf857c85f 100644 --- a/Resources/Prototypes/Loadouts/Jobs/engineering.yml +++ b/Resources/Prototypes/Loadouts/Jobs/engineering.yml @@ -1,9 +1,11 @@ - type: loadout id: LoadoutEngineeringUniformHazard - category: JobsAUncategorized - cost: 2 + category: JobsEngineering + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutUniformsEngineering - !type:CharacterJobRequirement jobs: - StationEngineer @@ -12,10 +14,12 @@ - type: loadout id: LoadoutEngineeringOuterHazard - category: JobsAUncategorized - cost: 2 + category: JobsEngineering + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutOuterEngineering - !type:CharacterJobRequirement jobs: - StationEngineer @@ -24,10 +28,12 @@ - type: loadout id: LoadoutEngineeringUniformJumpskirtSenior - category: JobsAUncategorized - cost: 2 + category: JobsEngineering + cost: 1 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutUniformsEngineering - !type:CharacterJobRequirement jobs: - StationEngineer @@ -45,10 +51,12 @@ - type: loadout id: LoadoutEngineeringUniformJumpsuitSenior - category: JobsAUncategorized - cost: 2 + category: JobsEngineering + cost: 1 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutUniformsEngineering - !type:CharacterJobRequirement jobs: - StationEngineer @@ -66,10 +74,12 @@ - type: loadout id: LoadoutEngineeringChickenSuit # :) - category: JobsAUncategorized - cost: 3 + category: JobsEngineering + cost: 1 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutOuterEngineering - !type:CharacterJobRequirement jobs: - AtmosphericTechnician @@ -79,10 +89,12 @@ - type: loadout id: LoadoutEngineeringEyesMeson - category: JobsAUncategorized - cost: 2 + category: JobsEngineering + cost: 1 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutEyesEngineering - !type:CharacterJobRequirement jobs: - StationEngineer @@ -92,10 +104,12 @@ - type: loadout id: LoadoutEngineeringHeadBeret - category: JobsAUncategorized - cost: 1 + category: JobsEngineering + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutHeadEngineering - !type:CharacterJobRequirement jobs: - StationEngineer @@ -106,10 +120,12 @@ - type: loadout id: LoadoutEngineeringHeadHardhatBlue - category: JobsAUncategorized - cost: 2 + category: JobsEngineering + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutHeadEngineering - !type:CharacterJobRequirement jobs: - StationEngineer @@ -119,10 +135,12 @@ - type: loadout id: LoadoutEngineeringHeadHardhatOrange - category: JobsAUncategorized - cost: 2 + category: JobsEngineering + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutHeadEngineering - !type:CharacterJobRequirement jobs: - StationEngineer @@ -132,10 +150,12 @@ - type: loadout id: LoadoutEngineeringHeadHardhatYellow - category: JobsAUncategorized - cost: 2 + category: JobsEngineering + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutHeadEngineering - !type:CharacterJobRequirement jobs: - StationEngineer @@ -145,10 +165,12 @@ - type: loadout id: LoadoutEngineeringHeadHardhatWhite - category: JobsAUncategorized - cost: 2 + category: JobsEngineering + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutHeadEngineering - !type:CharacterJobRequirement jobs: - StationEngineer @@ -158,10 +180,12 @@ - type: loadout id: LoadoutEngineeringHeadHardhatRed - category: JobsAUncategorized - cost: 2 + category: JobsEngineering + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutHeadEngineering - !type:CharacterJobRequirement jobs: - StationEngineer diff --git a/Resources/Prototypes/Loadouts/Jobs/medical.yml b/Resources/Prototypes/Loadouts/Jobs/medical.yml index 33d6ff36da..6a2d5fb9d2 100644 --- a/Resources/Prototypes/Loadouts/Jobs/medical.yml +++ b/Resources/Prototypes/Loadouts/Jobs/medical.yml @@ -1,9 +1,11 @@ - type: loadout id: LoadoutMedicalGlovesNitrile - category: JobsAUncategorized - cost: 1 + category: JobsMedical + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutGlovesMedical - !type:CharacterJobRequirement jobs: - MedicalDoctor @@ -16,10 +18,12 @@ - type: loadout id: LoadoutMedicalOuterLabcoat - category: JobsAUncategorized - cost: 2 + category: JobsMedical + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutOuterMedical - !type:CharacterJobRequirement jobs: - MedicalDoctor @@ -29,10 +33,12 @@ - type: loadout id: LoadoutMedicalNeckStethoscope - category: JobsAUncategorized - cost: 1 + category: JobsMedical + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutNeckMedical - !type:CharacterJobRequirement jobs: - MedicalDoctor @@ -43,10 +49,12 @@ - type: loadout id: LoadoutMedicalUniformScrubsBlue - category: JobsAUncategorized - cost: 2 + category: JobsMedical + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutUniformsMedical - !type:CharacterJobRequirement jobs: - MedicalDoctor @@ -58,10 +66,12 @@ - type: loadout id: LoadoutMedicalUniformScrubsGreen - category: JobsAUncategorized - cost: 2 + category: JobsMedical + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutUniformsMedical - !type:CharacterJobRequirement jobs: - MedicalDoctor @@ -73,10 +83,12 @@ - type: loadout id: LoadoutMedicalUniformScrubsPurple - category: JobsAUncategorized - cost: 2 + category: JobsMedical + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutUniformsMedical - !type:CharacterJobRequirement jobs: - MedicalDoctor @@ -88,10 +100,12 @@ - type: loadout id: LoadoutMedicalUniformScrubsCyan - category: JobsAUncategorized - cost: 2 + category: JobsMedical + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutUniformsMedical - !type:CharacterJobRequirement jobs: - MedicalDoctor @@ -103,10 +117,12 @@ - type: loadout id: LoadoutMedicalUniformScrubsBlack - category: JobsAUncategorized - cost: 2 + category: JobsMedical + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutUniformsMedical - !type:CharacterJobRequirement jobs: - MedicalDoctor @@ -118,10 +134,12 @@ - type: loadout id: LoadoutMedicalUniformScrubsPink - category: JobsAUncategorized - cost: 2 + category: JobsMedical + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutUniformsMedical - !type:CharacterJobRequirement jobs: - MedicalDoctor @@ -133,10 +151,12 @@ - type: loadout id: LoadoutMedicalUniformScrubsCybersun - category: JobsAUncategorized - cost: 3 + category: JobsMedical + cost: 1 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutUniformsMedical - !type:CharacterJobRequirement jobs: - MedicalDoctor @@ -147,10 +167,12 @@ - type: loadout id: LoadoutMedicalOuterCybersunWindbreaker - category: JobsAUncategorized - cost: 5 + category: JobsMedical + cost: 3 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutOuterMedical - !type:CharacterJobRequirement jobs: - MedicalDoctor @@ -161,10 +183,12 @@ - type: loadout id: LoadoutMedicalOuterLabcoatChem - category: JobsAUncategorized - cost: 2 + category: JobsMedical + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutOuterMedical - !type:CharacterJobRequirement jobs: - Chemist @@ -173,7 +197,7 @@ - type: loadout id: LoadoutMedicalItemHandLabeler - category: JobsAUncategorized + category: JobsMedical exclusive: true requirements: - !type:CharacterJobRequirement @@ -184,10 +208,12 @@ - type: loadout id: LoadoutMedicalUniformParamedicJumpsuit - category: JobsAUncategorized - cost: 2 + category: JobsMedical + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutUniformsMedical - !type:CharacterJobRequirement jobs: - Paramedic @@ -196,10 +222,12 @@ - type: loadout id: LoadoutMedicalUniformParamedicJumpskirt - category: JobsAUncategorized - cost: 2 + category: JobsMedical + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutUniformsMedical - !type:CharacterJobRequirement jobs: - Paramedic @@ -208,10 +236,12 @@ - type: loadout id: LoadoutMedicalUniformJumpskirtSenior - category: JobsAUncategorized - cost: 2 + category: JobsMedical + cost: 1 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutUniformsMedical - !type:CharacterJobRequirement jobs: - MedicalDoctor @@ -232,10 +262,12 @@ - type: loadout id: LoadoutMedicalUniformJumpsuitSenior - category: JobsAUncategorized - cost: 2 + category: JobsMedical + cost: 1 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutUniformsMedical - !type:CharacterJobRequirement jobs: - MedicalDoctor @@ -256,10 +288,12 @@ - type: loadout id: LoadoutMedicalHeadNurse - category: JobsAUncategorized - cost: 2 + category: JobsMedical + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutHeadMedical - !type:CharacterJobRequirement jobs: - MedicalDoctor @@ -268,10 +302,12 @@ - type: loadout id: LoadoutMedicalHeadBeretSeniorPhysician - category: JobsAUncategorized - cost: 2 + category: JobsMedical + cost: 1 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutHeadMedical - !type:CharacterJobRequirement jobs: - MedicalDoctor @@ -292,10 +328,12 @@ - type: loadout id: LoadoutMedicalHeadSurgcapBlue - category: JobsAUncategorized - cost: 2 + category: JobsMedical + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutHeadMedical - !type:CharacterJobRequirement jobs: - MedicalDoctor @@ -307,10 +345,12 @@ - type: loadout id: LoadoutMedicalHeadSurgcapPurple - category: JobsAUncategorized - cost: 2 + category: JobsMedical + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutHeadMedical - !type:CharacterJobRequirement jobs: - MedicalDoctor @@ -322,10 +362,12 @@ - type: loadout id: LoadoutMedicalHeadSurgcapGreen - category: JobsAUncategorized - cost: 2 + category: JobsMedical + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutHeadMedical - !type:CharacterJobRequirement jobs: - MedicalDoctor @@ -337,10 +379,12 @@ - type: loadout id: LoadoutMedicalHeadSurgcapCyan - category: JobsAUncategorized - cost: 2 + category: JobsMedical + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutHeadMedical - !type:CharacterJobRequirement jobs: - MedicalDoctor @@ -352,10 +396,12 @@ - type: loadout id: LoadoutMedicalHeadSurgcapBlack - category: JobsAUncategorized - cost: 2 + category: JobsMedical + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutHeadMedical - !type:CharacterJobRequirement jobs: - MedicalDoctor @@ -367,10 +413,12 @@ - type: loadout id: LoadoutMedicalHeadSurgcapPink - category: JobsAUncategorized - cost: 2 + category: JobsMedical + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutHeadMedical - !type:CharacterJobRequirement jobs: - MedicalDoctor @@ -382,10 +430,12 @@ - type: loadout id: LoadoutMedicalHeadSurgcapWhite - category: JobsAUncategorized - cost: 2 + category: JobsMedical + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutHeadMedical - !type:CharacterJobRequirement jobs: - MedicalDoctor @@ -397,10 +447,12 @@ - type: loadout id: LoadoutMedicalHeadSurgcapCybersun - category: JobsAUncategorized - cost: 3 + category: JobsMedical + cost: 1 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutHeadMedical - !type:CharacterJobRequirement jobs: - MedicalDoctor @@ -411,10 +463,12 @@ - type: loadout id: LoadoutMedicalEyesHudMedical - category: JobsAUncategorized - cost: 2 + category: JobsMedical + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutEyesMedical - !type:CharacterJobRequirement jobs: - MedicalDoctor @@ -427,10 +481,12 @@ - type: loadout id: LoadoutMedicalEyesEyepatchHudMedical - category: JobsAUncategorized - cost: 2 + category: JobsMedical + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutEyesMedical - !type:CharacterJobRequirement jobs: - MedicalDoctor @@ -443,10 +499,12 @@ - type: loadout id: LoadoutMedicalEyesHudMedicalPrescription - category: JobsAUncategorized - cost: 2 + category: JobsMedical + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutEyesMedical - !type:CharacterJobRequirement jobs: - MedicalDoctor @@ -462,10 +520,12 @@ - type: loadout id: LoadoutMedicalEyesGlassesChemical - category: JobsAUncategorized - cost: 2 + category: JobsMedical + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutEyesMedical - !type:CharacterJobRequirement jobs: - Chemist @@ -474,10 +534,12 @@ - type: loadout id: LoadoutMedicalBedsheetMedical - category: JobsAUncategorized - cost: 2 + category: JobsMedical + cost: 1 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutNeckMedical - !type:CharacterDepartmentRequirement departments: - Medical @@ -487,10 +549,12 @@ # Chemist PPE gear - type: loadout id: LoadoutMedicalUniformJumpsuitChemShirt - category: JobsAUncategorized - cost: 2 + category: JobsMedical + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutUniformsMedical - !type:CharacterJobRequirement jobs: - Chemist @@ -499,10 +563,12 @@ - type: loadout id: LoadoutMedicalNeckTieChem - category: JobsAUncategorized - cost: 1 + category: JobsMedical + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutNeckMedical - !type:CharacterJobRequirement jobs: - Chemist @@ -511,10 +577,12 @@ - type: loadout id: LoadoutMedicalShoesEnclosedChem - category: JobsAUncategorized - cost: 1 + category: JobsMedical + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutShoesMedical - !type:CharacterJobRequirement jobs: - Chemist @@ -523,10 +591,12 @@ - type: loadout id: LoadoutMedicalOuterApronChemist - category: JobsAUncategorized - cost: 2 + category: JobsMedical + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutOuterMedical - !type:CharacterJobRequirement jobs: - Chemist @@ -535,10 +605,12 @@ - type: loadout id: LoadoutMedicalEyesGlassesChemist - category: JobsAUncategorized - cost: 2 + category: JobsMedical + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutEyesMedical - !type:CharacterJobRequirement jobs: - Chemist @@ -547,10 +619,12 @@ - type: loadout id: LoadoutMedicalHandsGlovesChemist - category: JobsAUncategorized - cost: 1 + category: JobsMedical + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutGlovesMedical - !type:CharacterJobRequirement jobs: - Chemist diff --git a/Resources/Prototypes/Loadouts/Jobs/science.yml b/Resources/Prototypes/Loadouts/Jobs/science.yml index 8a1a2710c2..9a9526f83f 100644 --- a/Resources/Prototypes/Loadouts/Jobs/science.yml +++ b/Resources/Prototypes/Loadouts/Jobs/science.yml @@ -1,9 +1,13 @@ +# Uniforms + - type: loadout id: LoadoutScienceUniformJumpskirtSenior - category: JobsAUncategorized - cost: 2 + category: JobsScience + cost: 1 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutUniformsScience - !type:CharacterJobRequirement jobs: - Scientist @@ -15,10 +19,12 @@ - type: loadout id: LoadoutScienceUniformJumpsuitSenior - category: JobsAUncategorized - cost: 2 + category: JobsScience + cost: 1 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutUniformsScience - !type:CharacterJobRequirement jobs: - Scientist @@ -28,12 +34,72 @@ items: - ClothingUniformJumpsuitSeniorResearcher +- type: loadout + id: LoadoutScienceUniformJumpskirtRoboticist + category: JobsScience + cost: 1 + exclusive: true + requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutUniformsScience + - !type:CharacterJobRequirement + jobs: + - Scientist + items: + - ClothingUniformJumpskirtRoboticist + +- type: loadout + id: LoadoutScienceUniformJumpsuitRoboticist + category: JobsScience + cost: 1 + exclusive: true + requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutUniformsScience + - !type:CharacterJobRequirement + jobs: + - Scientist + items: + - ClothingUniformJumpsuitRoboticist + +- type: loadout + id: LoadoutScienceUniformJumpsuitMonasticRobeDark + category: JobsScience + cost: 0 + exclusive: true + requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutUniformsScience + - !type:CharacterJobRequirement + jobs: + - Chaplain + items: + - ClothingUniformJumpsuitMonasticRobeDark + +- type: loadout + id: LoadoutScienceUniformJumpsuitMonasticRobeLight + category: JobsScience + cost: 0 + exclusive: true + requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutUniformsScience + - !type:CharacterJobRequirement + jobs: + - Chaplain + items: + - ClothingUniformJumpsuitMonasticRobeLight + +# Outer + - type: loadout id: LoadoutScienceOuterCoat - category: JobsAUncategorized - cost: 2 + category: JobsScience + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutOuterScience - !type:CharacterJobRequirement jobs: - Scientist @@ -44,10 +110,12 @@ - type: loadout id: LoadoutScienceOuterLabcoat - category: JobsAUncategorized - cost: 2 + category: JobsScience + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutOuterScience - !type:CharacterJobRequirement jobs: - Scientist @@ -56,12 +124,42 @@ items: - ClothingOuterCoatLab +- type: loadout + id: LoadoutSciencegOuterCoatRobo + category: JobsScience + cost: 0 + exclusive: true + requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutOuterScience + - !type:CharacterJobRequirement + jobs: + - Scientist + items: + - ClothingOuterCoatRobo + +- type: loadout + id: LoadoutScienceOuterWinterSci + category: JobsScience + cost: 1 + exclusive: true + requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutOuterScience + - !type:CharacterJobRequirement + jobs: + - Scientist + items: + - ClothingOuterWinterSci + - type: loadout id: LoadoutScienceOuterLabcoatSeniorResearcher - category: JobsAUncategorized - cost: 2 + category: JobsScience + cost: 1 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutOuterScience - !type:CharacterJobRequirement jobs: - Scientist @@ -73,10 +171,12 @@ - type: loadout id: LoadoutScienceOuterExplorerLabcoat - category: JobsAUncategorized - cost: 2 + category: JobsScience + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutOuterScience - !type:CharacterJobRequirement jobs: - Scientist @@ -86,11 +186,208 @@ - ClothingOuterExplorerCoat - type: loadout - id: LoadoutScienceHatBeret - category: JobsAUncategorized + id: LoadoutScienceOuterPlagueSuit + category: JobsScience + cost: 0 + exclusive: true + requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutOuterScience + - !type:CharacterJobRequirement + jobs: + - Chaplain + items: + - ClothingOuterPlagueSuit + +- type: loadout + id: LoadoutScienceOuterNunRobe + category: JobsScience + cost: 0 + exclusive: true + requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutOuterScience + - !type:CharacterJobRequirement + jobs: + - Chaplain + items: + - ClothingOuterNunRobe + +- type: loadout + id: LoadoutScienceOuterHoodieBlack + category: JobsScience + cost: 0 + exclusive: true + requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutOuterScience + - !type:CharacterJobRequirement + jobs: + - Chaplain + items: + - ClothingOuterHoodieBlack + +- type: loadout + id: LoadoutScienceOuterHoodieChaplain + category: JobsScience + cost: 0 + exclusive: true + requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutOuterScience + - !type:CharacterJobRequirement + jobs: + - Chaplain + items: + - ClothingOuterHoodieChaplain + +- type: loadout + id: LoadoutScienceOuterWinterCoatMantis + category: JobsScience cost: 1 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutOuterScience + - !type:CharacterJobRequirement + jobs: + - ForensicMantis + items: + - ClothingOuterWinterCoatMantis + +# Gloves + +- type: loadout + id: LoadoutScienceHandsGlovesColorPurple + category: JobsScience + cost: 0 + exclusive: true + requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutGlovesScience + - !type:CharacterJobRequirement + jobs: + - Scientist + - ResearchDirector + items: + - ClothingHandsGlovesColorPurple + +- type: loadout + id: LoadoutScienceHandsGlovesLatex + category: JobsScience + cost: 0 + exclusive: true + requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutGlovesScience + - !type:CharacterJobRequirement + jobs: + - Scientist + - ResearchDirector + items: + - ClothingHandsGlovesLatex + +- type: loadout + id: LoadoutScienceHandsGlovesRobohands + category: JobsScience + cost: 0 + exclusive: true + requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutGlovesScience + - !type:CharacterJobRequirement + jobs: + - Scientist + - ResearchDirector + items: + - ClothingHandsGlovesRobohands + +# Neck + +- type: loadout + id: LoadoutScienceNeckTieSci + category: JobsScience + cost: 0 + exclusive: true + requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutNeckScience + - !type:CharacterJobRequirement + jobs: + - Scientist + - ResearchDirector + items: + - ClothingNeckTieSci + +- type: loadout + id: LoadoutScienceNeckScarfStripedPurple + category: JobsScience + cost: 0 + exclusive: true + requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutNeckScience + - !type:CharacterJobRequirement + jobs: + - Scientist + - ResearchDirector + items: + - ClothingNeckScarfStripedPurple + +- type: loadout + id: LoadoutScienceNeckStoleChaplain + category: JobsScience + cost: 0 + exclusive: true + requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutNeckScience + - !type:CharacterJobRequirement + jobs: + - Chaplain + items: + - ClothingNeckStoleChaplain + +- type: loadout + id: LoadoutScienceNeckScarfStripedBlack + category: JobsScience + cost: 0 + exclusive: true + requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutNeckScience + - !type:CharacterJobRequirement + jobs: + - Chaplain + items: + - ClothingNeckScarfStripedBlack + +# Mask + +- type: loadout + id: LoadoutScienceMaskPlague + category: JobsScience + cost: 0 + exclusive: true + requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutMaskScience + - !type:CharacterJobRequirement + jobs: + - Chaplain + items: + - ClothingMaskPlague + +# Head + +- type: loadout + id: LoadoutScienceHeadHatBeret + category: JobsScience + cost: 0 + exclusive: true + requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutHeadScience - !type:CharacterJobRequirement jobs: - Scientist @@ -99,12 +396,86 @@ items: - ClothingHeadHatBeretRND +- type: loadout + id: LoadoutScienceHeadHatFez + category: JobsScience + cost: 0 + exclusive: true + requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutHeadScience + - !type:CharacterJobRequirement + jobs: + - Chaplain + items: + - ClothingHeadHatFez + +- type: loadout + id: LoadoutScienceHeadHatHoodNunHood + category: JobsScience + cost: 0 + exclusive: true + requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutHeadScience + - !type:CharacterJobRequirement + jobs: + - Chaplain + items: + - ClothingHeadHatHoodNunHood + +- type: loadout + id: LoadoutScienceHeadHatPlaguedoctor + category: JobsScience + cost: 0 + exclusive: true + requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutHeadScience + - !type:CharacterJobRequirement + jobs: + - Chaplain + items: + - ClothingHeadHatPlaguedoctor + +- type: loadout + id: LoadoutScienceHeadHatWitch + category: JobsScience + cost: 0 + exclusive: true + requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutHeadScience + - !type:CharacterJobRequirement + jobs: + - Chaplain + items: + - ClothingHeadHatWitch + +- type: loadout + id: LoadoutScienceHeadHatWitch1 + category: JobsScience + cost: 0 + exclusive: true + requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutHeadScience + - !type:CharacterJobRequirement + jobs: + - Chaplain + items: + - ClothingHeadHatWitch1 + +# Eyes + - type: loadout id: LoadoutScienceEyesHudDiagnostic - category: JobsAUncategorized - cost: 3 + category: JobsScience + cost: 1 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutEyesScience - !type:CharacterJobRequirement jobs: - Scientist @@ -115,10 +486,12 @@ - type: loadout id: LoadoutScienceEyesEyepatchHudDiag - category: JobsAUncategorized - cost: 3 + category: JobsScience + cost: 1 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutEyesScience - !type:CharacterJobRequirement jobs: - Scientist @@ -127,14 +500,35 @@ items: - ClothingEyesEyepatchHudDiag +# Shoes + +- type: loadout + id: LoadoutScienceShoesBootsWinterSci + category: JobsScience + cost: 0 + exclusive: true + requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutShoesScience + - !type:CharacterJobRequirement + jobs: + - Scientist + - ResearchAssistant + - ResearchDirector + items: + - ClothingShoesBootsWinterSci + # Robes + - type: loadout id: LoadoutOuterRobeTechPriest category: Outer - cost: 2 + cost: 0 items: - ClothingOuterRobeTechPriest requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutOuterScience - !type:CharacterJobRequirement jobs: - Scientist @@ -144,11 +538,13 @@ - type: loadout id: LoadoutHeadHoodTechPriest category: Head - cost: 1 + cost: 0 exclusive: true items: - ClothingHeadTechPriest requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutHeadScience - !type:CharacterJobRequirement jobs: - Scientist diff --git a/Resources/Prototypes/Loadouts/Jobs/security.yml b/Resources/Prototypes/Loadouts/Jobs/security.yml index 13d11b13fa..db11903313 100644 --- a/Resources/Prototypes/Loadouts/Jobs/security.yml +++ b/Resources/Prototypes/Loadouts/Jobs/security.yml @@ -1,10 +1,12 @@ # Uniforms - type: loadout id: LoadoutSecurityUniformJumpsuitBlue - category: JobsAUncategorized - cost: 1 + category: JobsSecurity + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutUniformsSecurity - !type:CharacterDepartmentRequirement departments: - Security @@ -13,10 +15,12 @@ - type: loadout id: LoadoutSecurityUniformJumpsuitGrey - category: JobsAUncategorized - cost: 1 + category: JobsSecurity + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutUniformsSecurity - !type:CharacterDepartmentRequirement departments: - Security @@ -25,10 +29,12 @@ - type: loadout id: LoadoutSecurityUniformJumpskirtGrey - category: JobsAUncategorized - cost: 1 + category: JobsSecurity + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutUniformsSecurity - !type:CharacterDepartmentRequirement departments: - Security @@ -37,10 +43,12 @@ - type: loadout id: LoadoutSecurityUniformJumpskirtBlue - category: JobsAUncategorized - cost: 1 + category: JobsSecurity + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutUniformsSecurity - !type:CharacterDepartmentRequirement departments: - Security @@ -49,10 +57,12 @@ - type: loadout id: LoadoutSecurityUniformJumpskirtSenior - category: JobsAUncategorized - cost: 2 + category: JobsSecurity + cost: 1 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutUniformsSecurity - !type:CharacterJobRequirement jobs: - SecurityOfficer @@ -73,10 +83,12 @@ - type: loadout id: LoadoutSecurityUniformJumpsuitSenior - category: JobsAUncategorized - cost: 2 + category: JobsSecurity + cost: 1 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutUniformsSecurity - !type:CharacterJobRequirement jobs: - SecurityOfficer @@ -97,10 +109,12 @@ - type: loadout id: LoadoutUniformJumpsuitWardenBlue - category: JobsAUncategorized - cost: 2 + category: JobsSecurity + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutUniformsSecurity - !type:CharacterJobRequirement jobs: - Warden @@ -109,10 +123,12 @@ - type: loadout id: LoadoutUniformJumpsuitWardenGrey - category: JobsAUncategorized - cost: 2 + category: JobsSecurity + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutUniformsSecurity - !type:CharacterJobRequirement jobs: - Warden @@ -121,10 +137,12 @@ - type: loadout id: LoadoutUniformJumpskirtWardenBlue - category: JobsAUncategorized - cost: 2 + category: JobsSecurity + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutUniformsSecurity - !type:CharacterJobRequirement jobs: - Warden @@ -133,10 +151,12 @@ - type: loadout id: LoadoutUniformJumpskirtWardenGrey - category: JobsAUncategorized - cost: 2 + category: JobsSecurity + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutUniformsSecurity - !type:CharacterJobRequirement jobs: - Warden @@ -145,10 +165,12 @@ - type: loadout id: LoadoutUniformJumpskirtHoSBlue - category: JobsAUncategorized - cost: 2 + category: JobsSecurity + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutUniformsSecurity - !type:CharacterJobRequirement jobs: - HeadOfSecurity @@ -157,10 +179,12 @@ - type: loadout id: LoadoutUniformJumpskirtHoSGrey - category: JobsAUncategorized - cost: 2 + category: JobsSecurity + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutUniformsSecurity - !type:CharacterJobRequirement jobs: - HeadOfSecurity @@ -169,10 +193,12 @@ - type: loadout id: LoadoutUniformJumpsuitSecFormal - category: JobsAUncategorized - cost: 1 + category: JobsSecurity + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutUniformsSecurity - !type:CharacterDepartmentRequirement departments: - Security @@ -181,10 +207,12 @@ - type: loadout id: LoadoutUniformJumpsuitSecSummer - category: JobsAUncategorized - cost: 1 + category: JobsSecurity + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutUniformsSecurity - !type:CharacterDepartmentRequirement departments: - Security @@ -194,10 +222,12 @@ # Mask - type: loadout id: LoadoutSecurityMaskGasSwat - category: JobsAUncategorized - cost: 2 + category: JobsSecurity + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutMaskSecurity - !type:CharacterJobRequirement jobs: - Warden @@ -208,9 +238,11 @@ # Shoes - type: loadout id: LoadoutSecurityShoesJackboots - category: JobsAUncategorized - cost: 1 + category: JobsSecurity + cost: 0 requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutShoesSecurity - !type:CharacterDepartmentRequirement departments: - Security @@ -219,9 +251,11 @@ - type: loadout id: LoadoutClothingShoesBootsCombat - category: JobsAUncategorized - cost: 1 + category: JobsSecurity + cost: 0 requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutShoesSecurity - !type:CharacterDepartmentRequirement departments: - Security @@ -231,10 +265,12 @@ # Eyes - type: loadout id: LoadoutSecurityEyesHudSecurity - category: JobsAUncategorized + category: JobsSecurity cost: 1 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutEyesSecurity - !type:CharacterDepartmentRequirement departments: - Security @@ -243,10 +279,12 @@ - type: loadout id: ClothingEyesGlassesSunglasses - category: JobsAUncategorized - cost: 1 + category: JobsSecurity + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutEyesSecurity - !type:CharacterDepartmentRequirement departments: - Security @@ -255,10 +293,12 @@ - type: loadout id: LoadoutSecurityEyesEyepatchHudSecurity - category: JobsAUncategorized + category: JobsSecurity cost: 1 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutEyesSecurity - !type:CharacterDepartmentRequirement departments: - Security @@ -267,10 +307,12 @@ - type: loadout id: LoadoutSecurityEyesHudSecurityPrescription - category: JobsAUncategorized + category: JobsSecurity cost: 1 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutEyesSecurity - !type:CharacterDepartmentRequirement departments: - Security @@ -282,10 +324,12 @@ - type: loadout id: LoadoutClothingEyesGlassesSecurity - category: JobsAUncategorized - cost: 4 + category: JobsSecurity + cost: 2 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutEyesSecurity - !type:CharacterDepartmentRequirement departments: - Security @@ -298,10 +342,12 @@ # Head - type: loadout id: LoadoutSecurityHeadHatBeret - category: JobsAUncategorized - cost: 1 + category: JobsSecurity + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutHeadSecurity - !type:CharacterDepartmentRequirement departments: - Security @@ -310,10 +356,12 @@ - type: loadout id: LoadoutClothingHeadHelmetBasic - category: JobsAUncategorized - cost: 2 + category: JobsSecurity + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutHeadSecurity - !type:CharacterDepartmentRequirement departments: - Security @@ -322,10 +370,12 @@ - type: loadout id: LoadoutClothingHeadHatBeretBrigmedic - category: JobsAUncategorized - cost: 1 + category: JobsSecurity + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutHeadSecurity - !type:CharacterJobRequirement jobs: - Brigmedic @@ -334,10 +384,12 @@ - type: loadout id: LoadoutClothingHeadHatBeretCorpsman - category: JobsAUncategorized - cost: 1 + category: JobsSecurity + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutHeadSecurity - !type:CharacterJobRequirement jobs: - Brigmedic @@ -346,10 +398,12 @@ - type: loadout id: LoadoutClothingHeadHatBeretWarden - category: JobsAUncategorized - cost: 1 + category: JobsSecurity + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutHeadSecurity - !type:CharacterJobRequirement jobs: - Warden @@ -358,10 +412,12 @@ - type: loadout id: LoadoutClothingHeadHatBeretHoS - category: JobsAUncategorized - cost: 1 + category: JobsSecurity + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutHeadSecurity - !type:CharacterJobRequirement jobs: - HeadOfSecurity @@ -370,9 +426,11 @@ - type: loadout id: LoadoutSecurityHeadHelmetInsulated - category: JobsAUncategorized - cost: 2 + category: JobsSecurity + cost: 1 requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutHeadSecurity - !type:CharacterDepartmentRequirement departments: - Security @@ -382,10 +440,12 @@ # Belt - type: loadout id: LoadoutSecurityBeltWebbing - category: JobsAUncategorized - cost: 1 + category: JobsSecurity + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutBeltSecurity - !type:CharacterDepartmentRequirement departments: - Security @@ -394,10 +454,12 @@ - type: loadout id: LoadoutClothingBeltCorpsmanWebbing - category: JobsAUncategorized - cost: 1 + category: JobsSecurity + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutBeltSecurity - !type:CharacterJobRequirement jobs: - Brigmedic @@ -406,10 +468,12 @@ - type: loadout id: LoadoutClothingBeltSecurity - category: JobsAUncategorized - cost: 1 + category: JobsSecurity + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutBeltSecurity - !type:CharacterDepartmentRequirement departments: - Security @@ -420,22 +484,28 @@ - type: loadout id: LoadoutClothingHandsGlovesNitrile - category: JobsAUncategorized - cost: 1 + category: JobsSecurity + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutGlovesSecurity - !type:CharacterJobRequirement jobs: - Brigmedic items: - ClothingHandsGlovesNitrile +# Outerwear + - type: loadout id: LoadoutClothingOuterArmorPlateCarrier - category: JobsAUncategorized - cost: 2 + category: JobsSecurity + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutOuterSecurity - !type:CharacterDepartmentRequirement departments: - Security @@ -444,10 +514,12 @@ - type: loadout id: LoadoutClothingOuterArmorDuraVest - category: JobsAUncategorized - cost: 2 + category: JobsSecurity + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutOuterSecurity - !type:CharacterDepartmentRequirement departments: - Security @@ -456,10 +528,12 @@ - type: loadout id: LoadoutClothingOuterCoatDetective - category: JobsAUncategorized - cost: 2 + category: JobsSecurity + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutOuterSecurity - !type:CharacterJobRequirement jobs: - Detective @@ -468,10 +542,12 @@ - type: loadout id: LoadoutOuterVestDetective - category: JobsAUncategorized - cost: 2 + category: JobsSecurity + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutOuterSecurity - !type:CharacterJobRequirement jobs: - Detective @@ -480,10 +556,12 @@ - type: loadout id: LoadoutClothingOuterCoatWarden - category: JobsAUncategorized - cost: 2 + category: JobsSecurity + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutOuterSecurity - !type:CharacterJobRequirement jobs: - Warden @@ -492,10 +570,12 @@ - type: loadout id: LoadoutClothingOuterCoatHoSTrench - category: JobsAUncategorized - cost: 2 + category: JobsSecurity + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutOuterSecurity - !type:CharacterJobRequirement jobs: - HeadOfSecurity @@ -504,10 +584,12 @@ - type: loadout id: LoadoutClothingOuterWinterHoS - category: JobsAUncategorized - cost: 2 + category: JobsSecurity + cost: 1 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutOuterSecurity - !type:CharacterJobRequirement jobs: - HeadOfSecurity @@ -517,10 +599,12 @@ # Neck - type: loadout id: LoadoutClothingNeckCloakHos - category: JobsAUncategorized - cost: 1 + category: JobsSecurity + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutNeckSecurity - !type:CharacterJobRequirement jobs: - HeadOfSecurity @@ -529,10 +613,12 @@ - type: loadout id: LoadoutClothingNeckMantleHOS - category: JobsAUncategorized - cost: 1 + category: JobsSecurity + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutNeckSecurity - !type:CharacterJobRequirement jobs: - HeadOfSecurity @@ -541,23 +627,26 @@ - type: loadout id: LoadoutBedsheetBrigmedic - category: JobsAUncategorized - cost: 1 + category: JobsSecurity + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutNeckSecurity - !type:CharacterJobRequirement jobs: - Brigmedic items: - BedsheetBrigmedic - # Equipment - type: loadout id: LoadoutSecurityCombatKnife - category: JobsAUncategorized - cost: 2 + category: JobsSecurity + cost: 1 requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutEquipmentSecurity - !type:CharacterDepartmentRequirement departments: - Security @@ -566,7 +655,7 @@ - type: loadout id: LoadoutSecurityFlash - category: JobsAUncategorized + category: JobsSecurity cost: 1 requirements: - !type:CharacterDepartmentRequirement @@ -577,8 +666,8 @@ - type: loadout id: LoadoutSecurityDisabler - category: JobsAUncategorized - cost: 2 + category: JobsSecurity + cost: 1 requirements: - !type:CharacterDepartmentRequirement departments: @@ -588,8 +677,8 @@ - type: loadout id: LoadoutMagazinePistolRubber - category: JobsAUncategorized - cost: 2 + category: JobsSecurity + cost: 1 requirements: - !type:CharacterDepartmentRequirement departments: @@ -599,8 +688,8 @@ - type: loadout id: LoadoutSpeedLoaderMagnumRubber - category: JobsAUncategorized - cost: 2 + category: JobsSecurity + cost: 1 exclusive: true requirements: - !type:CharacterJobRequirement @@ -613,7 +702,7 @@ # # Species # - type: loadout # id: LoadoutSecurityEquipmentTruncheon -# category: JobsAUncategorized +# category: JobsSecurity # cost: 8 # requirements: # - !type:CharacterJobRequirement diff --git a/Resources/Prototypes/Loadouts/Jobs/service.yml b/Resources/Prototypes/Loadouts/Jobs/service.yml index 815138e393..bdfa3d8165 100644 --- a/Resources/Prototypes/Loadouts/Jobs/service.yml +++ b/Resources/Prototypes/Loadouts/Jobs/service.yml @@ -1,10 +1,12 @@ # Clown - type: loadout id: LoadoutServiceClownOutfitJester - category: JobsAUncategorized - cost: 3 + category: JobsServiceUncategorized + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutUniformsService - !type:CharacterJobRequirement jobs: - Clown @@ -15,10 +17,12 @@ - type: loadout id: LoadoutServiceClownOutfitJesterAlt - category: JobsAUncategorized - cost: 3 + category: JobsServiceUncategorized + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutUniformsService - !type:CharacterJobRequirement jobs: - Clown @@ -29,10 +33,12 @@ - type: loadout id: LoadoutServiceClownOuterWinter - category: JobsAUncategorized - cost: 2 + category: JobsServiceUncategorized + cost: 1 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutOuterService - !type:CharacterJobRequirement jobs: - Clown @@ -41,10 +47,12 @@ - type: loadout id: LoadoutServiceClownOuterClownPriest - category: JobsAUncategorized - cost: 2 + category: JobsServiceUncategorized + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutOuterService - !type:CharacterJobRequirement jobs: - Clown @@ -53,10 +61,12 @@ - type: loadout id: LoadoutServiceClownBootsWinter - category: JobsAUncategorized - cost: 1 + category: JobsServiceUncategorized + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutShoesService - !type:CharacterJobRequirement jobs: - Clown @@ -65,10 +75,12 @@ - type: loadout id: LoadoutServiceClownMaskSexy - category: JobsAUncategorized - cost: 1 + category: JobsServiceUncategorized + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutMaskService - !type:CharacterJobRequirement jobs: - Clown @@ -77,21 +89,28 @@ - type: loadout id: LoadoutServiceClownBedsheetClown - category: JobsAUncategorized - cost: 2 + category: JobsServiceUncategorized + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutNeckService - !type:CharacterJobRequirement jobs: - Clown items: - BedsheetClown +# For the most part we dont want people to take this item, so its used as an example of all the things +# you can do with requirements. Point someone to this thing if they ask "how tf do loadout requirements work?" + - type: loadout id: LoadoutServiceClownCowToolboxFilled - category: JobsAUncategorized - cost: 3 + category: JobsServiceUncategorized + cost: 2 requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutEquipmentService - !type:CharacterLogicXorRequirement requirements: - !type:CharacterLogicAndRequirement @@ -121,7 +140,7 @@ - !type:CharacterSexRequirement sex: Male - !type:CharacterJobRequirement - inverted: true + inverted: true # This is the equivalent of !(condition) jobs: - Clown - !type:CharacterJobRequirement @@ -133,10 +152,12 @@ # Mime - type: loadout id: LoadoutServiceMimeOuterWinter - category: JobsAUncategorized - cost: 2 + category: JobsServiceUncategorized + cost: 1 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutOuterService - !type:CharacterJobRequirement jobs: - Mime @@ -145,10 +166,12 @@ - type: loadout id: LoadoutServiceMimeMaskSad - category: JobsAUncategorized - cost: 1 + category: JobsServiceUncategorized + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutMaskService - !type:CharacterJobRequirement jobs: - Mime @@ -157,10 +180,12 @@ - type: loadout id: LoadoutServiceMimeMaskScared - category: JobsAUncategorized - cost: 1 + category: JobsServiceUncategorized + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutMaskService - !type:CharacterJobRequirement jobs: - Mime @@ -169,10 +194,12 @@ - type: loadout id: LoadoutServiceMimeMaskSexy - category: JobsAUncategorized - cost: 1 + category: JobsServiceUncategorized + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutMaskService - !type:CharacterJobRequirement jobs: - Mime @@ -181,10 +208,12 @@ - type: loadout id: LoadoutServiceMimeShoesBootsWinter - category: JobsAUncategorized - cost: 1 + category: JobsServiceUncategorized + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutShoesService - !type:CharacterJobRequirement jobs: - Mime @@ -193,10 +222,12 @@ - type: loadout id: LoadoutServiceMimeBedsheetMime - category: JobsAUncategorized - cost: 2 + category: JobsServiceUncategorized + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutNeckService - !type:CharacterJobRequirement jobs: - Mime @@ -206,23 +237,97 @@ # Bartender - type: loadout id: LoadoutServiceBartenderUniformPurple - category: JobsAUncategorized - cost: 2 + category: JobsServiceBartender + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutUniformsService - !type:CharacterJobRequirement jobs: - Bartender items: - ClothingUniformJumpsuitBartenderPurple +- type: loadout + id: LoadoutServiceBartenderArmorDuraVest + category: JobsServiceBartender + cost: 0 + exclusive: true + requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutBartenderOuterwear + - !type:CharacterJobRequirement + jobs: + - Bartender + items: + - ClothingOuterArmorDuraVest + +- type: loadout + id: LoadoutServiceBartenderBoxBeanbags + category: JobsServiceBartender + cost: 0 + exclusive: true + requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutBartenderAmmo + - !type:CharacterJobRequirement + jobs: + - Bartender + items: + - BoxBeanbag + +- type: loadout + id: LoadoutServiceBartenderBoxLightRifleRubber + category: JobsServiceBartender + cost: 1 + exclusive: true + requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutBartenderAmmo + - !type:CharacterJobRequirement + jobs: + - Bartender + items: + - MagazineBoxLightRifleRubber + +- type: loadout + id: LoadoutServiceBartenderShotgunDoubleBarreledRubber + category: JobsServiceBartender + cost: 0 + exclusive: true + requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutBartenderWeapon + - !type:CharacterJobRequirement + jobs: + - Bartender + items: + - WeaponShotgunDoubleBarreledRubber + +- type: loadout + id: LoadoutServiceBartenderMosinRubber + category: JobsServiceBartender + cost: 3 + exclusive: true + requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutBartenderWeapon + - !type:CharacterJobRequirement + jobs: + - Bartender + items: + - WeaponSniperMosinRubber + # Botanist - type: loadout id: LoadoutServiceBotanistUniformOveralls - category: JobsAUncategorized - cost: 2 + category: JobsServiceUncategorized + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutUniformsService - !type:CharacterJobRequirement jobs: - Botanist @@ -232,10 +337,12 @@ # Lawyer - type: loadout id: LoadoutServiceLawyerUniformBlueSuit - category: JobsAUncategorized - cost: 2 + category: JobsServiceUncategorized + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutUniformsService - !type:CharacterJobRequirement jobs: - Lawyer @@ -244,10 +351,12 @@ - type: loadout id: LoadoutServiceLawyerUniformBlueSkirt - category: JobsAUncategorized - cost: 2 + category: JobsServiceUncategorized + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutUniformsService - !type:CharacterJobRequirement jobs: - Lawyer @@ -256,10 +365,12 @@ - type: loadout id: LoadoutServiceLawyerUniformRedSuit - category: JobsAUncategorized - cost: 2 + category: JobsServiceUncategorized + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutUniformsService - !type:CharacterJobRequirement jobs: - Lawyer @@ -268,10 +379,12 @@ - type: loadout id: LoadoutServiceLawyerUniformRedSkirt - category: JobsAUncategorized - cost: 2 + category: JobsServiceUncategorized + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutUniformsService - !type:CharacterJobRequirement jobs: - Lawyer @@ -280,10 +393,12 @@ - type: loadout id: LoadoutServiceLawyerUniformPurpleSuit - category: JobsAUncategorized - cost: 2 + category: JobsServiceUncategorized + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutUniformsService - !type:CharacterJobRequirement jobs: - Lawyer @@ -292,10 +407,12 @@ - type: loadout id: LoadoutServiceLawyerUniformPurpleSkirt - category: JobsAUncategorized - cost: 2 + category: JobsServiceUncategorized + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutUniformsService - !type:CharacterJobRequirement jobs: - Lawyer @@ -304,10 +421,12 @@ - type: loadout id: LoadoutServiceLawyerUniformGoodSuit - category: JobsAUncategorized - cost: 2 + category: JobsServiceUncategorized + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutUniformsService - !type:CharacterJobRequirement jobs: - Lawyer @@ -316,10 +435,12 @@ - type: loadout id: LoadoutServiceLawyerUniformGoodSkirt - category: JobsAUncategorized - cost: 2 + category: JobsServiceUncategorized + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutUniformsService - !type:CharacterJobRequirement jobs: - Lawyer @@ -328,10 +449,12 @@ - type: loadout id: LoadoutServiceReporterUniformJournalist - category: JobsAUncategorized - cost: 2 + category: JobsServiceUncategorized + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutUniformsService - !type:CharacterJobRequirement jobs: - Reporter @@ -341,10 +464,12 @@ # Reporter - type: loadout id: LoadoutServiceReporterUniformDetectivesuit - category: JobsAUncategorized - cost: 2 + category: JobsServiceUncategorized + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutUniformsService - !type:CharacterJobRequirement jobs: - Reporter @@ -353,10 +478,12 @@ - type: loadout id: LoadoutServiceReporterUniformDetectiveskirt - category: JobsAUncategorized - cost: 2 + category: JobsServiceUncategorized + cost: 0 exclusive: true requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutUniformsService - !type:CharacterJobRequirement jobs: - Reporter @@ -365,12 +492,170 @@ # Musician - type: loadout - id: LoadoutItemSynthesizerInstrument - category: JobsAUncategorized - cost: 8 + id: LoadoutItemSynthesizerInstrumentMusician + category: JobsServiceUncategorized + cost: 2 requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutMusicianInstruments - !type:CharacterJobRequirement jobs: - Musician items: - SynthesizerInstrument + +- type: loadout + id: LoadoutItemMicrophoneInstrumentMusician + category: JobsServiceUncategorized + cost: 0 + requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutMusicianInstruments + - !type:CharacterJobRequirement + jobs: + - Musician + items: + - MicrophoneInstrument + +- type: loadout + id: LoadoutItemKalimbaInstrumentMusician + category: Items + cost: 0 + requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutMusicianInstruments + - !type:CharacterJobRequirement + jobs: + - Musician + items: + - KalimbaInstrument + +- type: loadout + id: LoadoutItemTrumpetInstrumentMusician + category: Items + cost: 2 + requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutMusicianInstruments + - !type:CharacterJobRequirement + jobs: + - Musician + items: + - TrumpetInstrument + +- type: loadout + id: LoadoutItemElectricGuitarInstrumentMusician + category: Items + cost: 2 + requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutMusicianInstruments + - !type:CharacterJobRequirement + jobs: + - Musician + items: + - ElectricGuitarInstrument + +- type: loadout + id: LoadoutItemBassGuitarInstrumentMusician + category: Items + cost: 2 + requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutMusicianInstruments + - !type:CharacterJobRequirement + jobs: + - Musician + items: + - BassGuitarInstrument + +- type: loadout + id: LoadoutItemRockGuitarInstrumentMusician + category: Items + cost: 2 + requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutMusicianInstruments + - !type:CharacterJobRequirement + jobs: + - Musician + items: + - RockGuitarInstrument + +- type: loadout + id: LoadoutItemAcousticGuitarInstrumentMusician + category: Items + cost: 2 + requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutMusicianInstruments + - !type:CharacterJobRequirement + jobs: + - Musician + items: + - AcousticGuitarInstrument + +- type: loadout + id: LoadoutItemViolinInstrumentMusician + category: Items + cost: 2 + requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutMusicianInstruments + - !type:CharacterJobRequirement + jobs: + - Musician + items: + - ViolinInstrument + +- type: loadout + id: LoadoutItemHarmonicaInstrumentMusician + category: Items + cost: 0 + requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutMusicianInstruments + - !type:CharacterJobRequirement + jobs: + - Musician + items: + - HarmonicaInstrument + +- type: loadout + id: LoadoutItemAccordionInstrumentMusician + category: Items + cost: 0 + requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutMusicianInstruments + - !type:CharacterJobRequirement + jobs: + - Musician + items: + - AccordionInstrument + +- type: loadout + id: LoadoutItemFluteInstrumentMusician + category: Items + cost: 0 + requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutMusicianInstruments + - !type:CharacterJobRequirement + jobs: + - Musician + items: + - FluteInstrument + +- type: loadout + id: LoadoutItemOcarinaInstrumentMusician + category: Items + cost: 0 + requirements: + - !type:CharacterItemGroupRequirement + group: LoadoutMusicianInstruments + - !type:CharacterJobRequirement + jobs: + - Musician + items: + - OcarinaInstrument \ No newline at end of file diff --git a/Resources/Prototypes/Loadouts/items.yml b/Resources/Prototypes/Loadouts/items.yml index 97a3ed2fdc..12fc1cdf85 100644 --- a/Resources/Prototypes/Loadouts/items.yml +++ b/Resources/Prototypes/Loadouts/items.yml @@ -139,6 +139,10 @@ requirements: - !type:CharacterItemGroupRequirement group: LoadoutInstrumentsAny + - !type:CharacterJobRequirement + inverted: true + jobs: + - Musician - type: loadout id: LoadoutItemKalimbaInstrument @@ -149,6 +153,10 @@ requirements: - !type:CharacterItemGroupRequirement group: LoadoutInstrumentsAny + - !type:CharacterJobRequirement + inverted: true + jobs: + - Musician - type: loadout id: LoadoutItemTrumpetInstrument @@ -159,6 +167,10 @@ requirements: - !type:CharacterItemGroupRequirement group: LoadoutInstrumentsAny + - !type:CharacterJobRequirement + inverted: true + jobs: + - Musician - type: loadout id: LoadoutItemElectricGuitar @@ -169,6 +181,10 @@ requirements: - !type:CharacterItemGroupRequirement group: LoadoutInstrumentsAny + - !type:CharacterJobRequirement + inverted: true + jobs: + - Musician - type: loadout id: LoadoutItemBassGuitar @@ -179,6 +195,10 @@ requirements: - !type:CharacterItemGroupRequirement group: LoadoutInstrumentsAny + - !type:CharacterJobRequirement + inverted: true + jobs: + - Musician - type: loadout id: LoadoutItemRockGuitar @@ -189,6 +209,10 @@ requirements: - !type:CharacterItemGroupRequirement group: LoadoutInstrumentsAny + - !type:CharacterJobRequirement + inverted: true + jobs: + - Musician - type: loadout id: LoadoutItemAcousticGuitar @@ -199,6 +223,10 @@ requirements: - !type:CharacterItemGroupRequirement group: LoadoutInstrumentsAny + - !type:CharacterJobRequirement + inverted: true + jobs: + - Musician - type: loadout id: LoadoutItemViolin @@ -209,6 +237,10 @@ requirements: - !type:CharacterItemGroupRequirement group: LoadoutInstrumentsAny + - !type:CharacterJobRequirement + inverted: true + jobs: + - Musician - type: loadout id: LoadoutItemHarmonica @@ -219,6 +251,10 @@ requirements: - !type:CharacterItemGroupRequirement group: LoadoutInstrumentsAny + - !type:CharacterJobRequirement + inverted: true + jobs: + - Musician - type: loadout id: LoadoutItemAccordion @@ -229,6 +265,10 @@ requirements: - !type:CharacterItemGroupRequirement group: LoadoutInstrumentsAny + - !type:CharacterJobRequirement + inverted: true + jobs: + - Musician - type: loadout id: LoadoutItemFlute @@ -239,6 +279,10 @@ requirements: - !type:CharacterItemGroupRequirement group: LoadoutInstrumentsAny + - !type:CharacterJobRequirement + inverted: true + jobs: + - Musician - type: loadout id: LoadoutItemOcarina @@ -249,6 +293,10 @@ requirements: - !type:CharacterItemGroupRequirement group: LoadoutInstrumentsAny + - !type:CharacterJobRequirement + inverted: true + jobs: + - Musician # Survival Kit - type: loadout diff --git a/Resources/Prototypes/Mood/drugs.yml b/Resources/Prototypes/Mood/drugs.yml new file mode 100644 index 0000000000..470abc5e3d --- /dev/null +++ b/Resources/Prototypes/Mood/drugs.yml @@ -0,0 +1,34 @@ +# Drugs should be paired up in Trios of "Bonus, Penalty, Category" + +# Lotophagoi Oil +- type: moodEffect + id: LotoTranscendence + moodChange: 30 + timeout: 900 #15 minutes + moodletOnEnd: LotoEnthrallment + category: "LotophagoiAddiction" + +- type: moodEffect + id: LotoEnthrallment + moodChange: -30 + timeout: 7200 #2 hours + category: "LotophagoiAddiction" + +- type: moodCategory + id: LotophagoiAddiction + +# Nicotine +- type: moodEffect + id: NicotineBenefit + moodChange: 5 + timeout: 600 #10 minutes + moodletOnEnd: NicotineWithdrawal + category: "NicotineAddiction" + +- type: moodEffect + id: NicotineWithdrawal + moodChange: -7 #No timeout + category: "NicotineAddiction" + +- type: moodCategory + id: NicotineAddiction \ No newline at end of file diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Objects/Devices/CircuitBoards/production.yml b/Resources/Prototypes/Nyanotrasen/Entities/Objects/Devices/CircuitBoards/production.yml index 6e80ec7c4e..2ed4a594e3 100644 --- a/Resources/Prototypes/Nyanotrasen/Entities/Objects/Devices/CircuitBoards/production.yml +++ b/Resources/Prototypes/Nyanotrasen/Entities/Objects/Devices/CircuitBoards/production.yml @@ -12,9 +12,8 @@ MatterBin: 1 Manipulator: 1 materialRequirements: - Glass: 1 Cable: 1 - Diamond: 10 + PlasmaGlass: 5 tagRequirements: BorgArm: Amount: 3 diff --git a/Resources/Prototypes/Nyanotrasen/GameRules/events.yml b/Resources/Prototypes/Nyanotrasen/GameRules/events.yml index 43347ca7d0..524bf4d4b7 100644 --- a/Resources/Prototypes/Nyanotrasen/GameRules/events.yml +++ b/Resources/Prototypes/Nyanotrasen/GameRules/events.yml @@ -24,13 +24,13 @@ earliestStart: 25 - type: MidRoundAntagRule -#- type: entity -# noSpawn: true -# parent: BaseMidRoundAntag -# id: RatKingSpawn -# components: -# - type: MidRoundAntagRule -# spawner: SpawnPointGhostRatKing +- type: entity + noSpawn: true + parent: BaseMidRoundAntag + id: RatKingSpawn + components: + - type: MidRoundAntagRule + spawner: SpawnPointGhostRatKing - type: entity noSpawn: true diff --git a/Resources/Prototypes/Nyanotrasen/Reagents/Consumable/Drink/alcohol.yml b/Resources/Prototypes/Nyanotrasen/Reagents/Consumable/Drink/alcohol.yml index 972fc08239..19d49b913a 100644 --- a/Resources/Prototypes/Nyanotrasen/Reagents/Consumable/Drink/alcohol.yml +++ b/Resources/Prototypes/Nyanotrasen/Reagents/Consumable/Drink/alcohol.yml @@ -19,7 +19,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.07 + amount: 0.15 - type: reagent id: Soju @@ -42,7 +42,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.15 + amount: 0.2 - type: reagent id: OrangeCreamice @@ -65,7 +65,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.05 + amount: 0.1 - type: reagent id: Silverjack @@ -88,7 +88,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.0625 + amount: 0.1375 - type: reagent id: Brainbomb @@ -118,7 +118,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.085 + amount: 0.13 - !type:AdjustReagent reagent: THC amount: 0.33 @@ -147,7 +147,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.025 + amount: 0.08 - type: reagent id: CircusJuice @@ -170,7 +170,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.0625 + amount: 0.12 - !type:Emote #It's very funny emote: Laugh probability: 0.15 @@ -196,7 +196,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.065 + amount: 0.1125 - !type:AdjustTemperature amount: 75 # thermal energy, not temperature! @@ -221,4 +221,4 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.03 + amount: 0.12 diff --git a/Resources/Prototypes/Nyanotrasen/Recipes/Lathes/electronics.yml b/Resources/Prototypes/Nyanotrasen/Recipes/Lathes/electronics.yml index 1e53c715af..695fb42150 100644 --- a/Resources/Prototypes/Nyanotrasen/Recipes/Lathes/electronics.yml +++ b/Resources/Prototypes/Nyanotrasen/Recipes/Lathes/electronics.yml @@ -4,7 +4,7 @@ completetime: 4 materials: Steel: 100 - Glass: 900 + Glass: 700 Gold: 100 - type: latheRecipe @@ -13,7 +13,7 @@ completetime: 4 materials: Steel: 100 - Glass: 900 + Glass: 700 Gold: 100 - type: latheRecipe @@ -21,8 +21,8 @@ result: CrewMonitoringComputerCircuitboard completetime: 4 materials: - Steel: 100 - Glass: 900 + Steel: 100 + Glass: 700 - type: latheRecipe id: ClothingEyesHudMedical @@ -41,4 +41,4 @@ completetime: 4 materials: Steel: 100 - Glass: 900 + Glass: 700 diff --git a/Resources/Prototypes/Reagents/Consumable/Drink/alcohol.yml b/Resources/Prototypes/Reagents/Consumable/Drink/alcohol.yml index e31087c309..d9e57d5b80 100644 --- a/Resources/Prototypes/Reagents/Consumable/Drink/alcohol.yml +++ b/Resources/Prototypes/Reagents/Consumable/Drink/alcohol.yml @@ -22,7 +22,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.3 + amount: 0.7 - type: reagent id: Ale @@ -77,7 +77,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.1 + amount: 0.25 - type: reagent id: BlueHawaiian @@ -97,7 +97,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.2 + amount: 0.154 - type: reagent id: Cognac @@ -121,7 +121,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.2 + amount: 0.4 - type: reagent id: DeadRum @@ -144,7 +144,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.2 + amount: 0.6 - type: reagent id: Ethanol @@ -163,7 +163,7 @@ - !type:HealthChange conditions: - !type:ReagentThreshold - min: 15 + min: 45 damage: types: Poison: 1 @@ -278,7 +278,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.2 + amount: 0.45 - type: reagent id: CoffeeLiqueur @@ -294,6 +294,13 @@ metamorphicMaxFillLevels: 3 metamorphicFillBaseName: fill- metamorphicChangeColor: true + metabolisms: + Drink: + effects: + - !type:AdjustReagent + reagent: Ethanol + amount: 0.20 + - type: reagent id: MelonLiquor @@ -309,6 +316,12 @@ metamorphicMaxFillLevels: 5 metamorphicFillBaseName: fill- metamorphicChangeColor: true + metabolisms: + Drink: + effects: + - !type:AdjustReagent + reagent: Ethanol + amount: 0.20 - type: reagent id: NTCahors @@ -324,6 +337,12 @@ metamorphicMaxFillLevels: 5 metamorphicFillBaseName: fill- metamorphicChangeColor: true + metabolisms: + Drink: + effects: + - !type:AdjustReagent + reagent: Ethanol + amount: 0.17 - type: reagent id: PoisonWine @@ -346,7 +365,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.05 + amount: 0.11 Poison: effects: - !type:HealthChange @@ -376,7 +395,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.2 + amount: 0.40 ##Commented out in favor of Nyano sake/soju #- type: reagent @@ -409,7 +428,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.2 + amount: 0.40 - type: reagent id: Vermouth @@ -425,6 +444,12 @@ metamorphicMaxFillLevels: 4 metamorphicFillBaseName: fill- metamorphicChangeColor: false + metabolisms: + Drink: + effects: + - !type:AdjustReagent + reagent: Ethanol + amount: 0.16 - type: reagent id: Vodka @@ -448,7 +473,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.2 + amount: 0.40 - type: reagent id: Whiskey @@ -472,7 +497,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.2 + amount: 0.40 - type: reagent id: Wine @@ -489,6 +514,14 @@ metamorphicMaxFillLevels: 5 metamorphicFillBaseName: fill- metamorphicChangeColor: true + metabolisms: + Drink: + effects: + - !type:SatiateThirst + factor: 2 + - !type:AdjustReagent + reagent: Ethanol + amount: 0.11 - type: reagent id: Champagne @@ -512,7 +545,7 @@ factor: 3 - !type:AdjustReagent reagent: Ethanol - amount: 0.3 + amount: 0.12 # Mixed Alcohol @@ -530,6 +563,14 @@ metamorphicMaxFillLevels: 5 metamorphicFillBaseName: fill- metamorphicChangeColor: false + metabolisms: + Drink: + effects: + - !type:SatiateThirst + factor: 1 + - !type:AdjustReagent + reagent: Ethanol + amount: 0.073 - type: reagent id: AlliesCocktail @@ -545,6 +586,14 @@ metamorphicMaxFillLevels: 4 metamorphicFillBaseName: fill- metamorphicChangeColor: false + metabolisms: + Drink: + effects: + - !type:SatiateThirst + factor: 2 + - !type:AdjustReagent + reagent: Ethanol + amount: 0.37 - type: reagent id: Aloe @@ -575,6 +624,14 @@ metamorphicMaxFillLevels: 5 metamorphicFillBaseName: fill- metamorphicChangeColor: false + metabolisms: + Drink: + effects: + - !type:SatiateThirst + factor: 2 + - !type:AdjustReagent + reagent: Ethanol + amount: 0.204 - type: reagent id: Andalusia @@ -590,6 +647,14 @@ metamorphicMaxFillLevels: 4 metamorphicFillBaseName: fill- metamorphicChangeColor: false + metabolisms: + Drink: + effects: + - !type:SatiateThirst + factor: 2 + - !type:AdjustReagent + reagent: Ethanol + amount: 0.27 - type: reagent id: Antifreeze @@ -612,7 +677,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.15 + amount: 0.2 - type: reagent id: AtomicBomb @@ -635,7 +700,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.15 + amount: 0.254 - !type:AdjustReagent reagent: Uranium amount: 0.05 @@ -661,7 +726,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.15 + amount: 0.28 - type: reagent id: BahamaMama @@ -677,6 +742,14 @@ metamorphicMaxFillLevels: 5 metamorphicFillBaseName: fill- metamorphicChangeColor: true + metabolisms: + Drink: + effects: + - !type:SatiateThirst + factor: 2 + - !type:AdjustReagent + reagent: Ethanol + amount: 0.11 - type: reagent id: BananaHonk @@ -707,6 +780,14 @@ metamorphicMaxFillLevels: 3 metamorphicFillBaseName: fill- metamorphicChangeColor: true + metabolisms: + Drink: + effects: + - !type:SatiateThirst + factor: 2 + - !type:AdjustReagent + reagent: Ethanol + amount: 0.05 - type: reagent id: BeepskySmash @@ -729,7 +810,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.15 + amount: 0.13 - type: reagent id: BlackRussian @@ -752,7 +833,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.2 + amount: 0.33 - type: reagent id: BloodyMary @@ -768,6 +849,14 @@ metamorphicMaxFillLevels: 5 metamorphicFillBaseName: fill- metamorphicChangeColor: true + metabolisms: + Drink: + effects: + - !type:SatiateThirst + factor: 2 + - !type:AdjustReagent + reagent: Ethanol + amount: 0.13 - type: reagent id: Booger @@ -783,6 +872,14 @@ metamorphicMaxFillLevels: 5 metamorphicFillBaseName: fill- metamorphicChangeColor: true + metabolisms: + Drink: + effects: + - !type:SatiateThirst + factor: 2 + - !type:AdjustReagent + reagent: Ethanol + amount: 0.08 - type: reagent id: BraveBull @@ -805,7 +902,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.2 + amount: 0.33 - type: reagent id: CoconutRum @@ -825,7 +922,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.2 + amount: 0.26 - type: reagent id: Cosmopolitan @@ -845,7 +942,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.15 + amount: 0.13 - type: reagent id: CubaLibre @@ -868,7 +965,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.07 + amount: 0.13 - type: reagent id: DemonsBlood @@ -884,6 +981,14 @@ metamorphicMaxFillLevels: 4 metamorphicFillBaseName: fill- metamorphicChangeColor: true + metabolisms: + Drink: + effects: + - !type:SatiateThirst + factor: 2 + - !type:AdjustReagent + reagent: Ethanol + amount: 0.10 - type: reagent id: DevilsKiss @@ -899,6 +1004,14 @@ metamorphicMaxFillLevels: 3 metamorphicFillBaseName: fill- metamorphicChangeColor: true + metabolisms: + Drink: + effects: + - !type:SatiateThirst + factor: 2 + - !type:AdjustReagent + reagent: Ethanol + amount: 0.20 - type: reagent id: DoctorsDelight @@ -921,9 +1034,6 @@ factor: 2 - !type:SatiateHunger factor: -2 - - !type:AdjustReagent - reagent: Ethanol - amount: 0.05 Medicine: effects: - !type:HealthChange @@ -955,7 +1065,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.15 + amount: 0.225 - type: reagent id: ErikaSurprise @@ -971,6 +1081,14 @@ metamorphicMaxFillLevels: 5 metamorphicFillBaseName: fill- metamorphicChangeColor: true + metabolisms: + Drink: + effects: + - !type:SatiateThirst + factor: 2 + - !type:AdjustReagent + reagent: Ethanol + amount: 0.02 - type: reagent id: GargleBlaster @@ -993,7 +1111,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.2 + amount: 0.32 - type: reagent id: GinFizz @@ -1016,7 +1134,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.07 + amount: 0.15 - type: reagent id: GinTonic @@ -1039,7 +1157,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.07 + amount: 0.15 - type: reagent id: Gildlager @@ -1062,7 +1180,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.2 + amount: 0.363 - type: reagent id: Grog @@ -1078,6 +1196,14 @@ metamorphicMaxFillLevels: 5 metamorphicFillBaseName: fill- metamorphicChangeColor: true + metabolisms: + Drink: + effects: + - !type:SatiateThirst + factor: 2 + - !type:AdjustReagent + reagent: Ethanol + amount: 0.10 - type: reagent id: HippiesDelight @@ -1093,6 +1219,14 @@ metamorphicMaxFillLevels: 6 metamorphicFillBaseName: fill- metamorphicChangeColor: false + metabolisms: + Drink: + effects: + - !type:SatiateThirst + factor: 2 + - !type:AdjustReagent + reagent: Ethanol + amount: 0.16 - type: reagent id: Hooch @@ -1102,6 +1236,14 @@ physicalDesc: reagent-physical-desc-strong-smelling flavor: alcohol color: "#664e00" + metabolisms: + Drink: + effects: + - !type:SatiateThirst + factor: 2 + - !type:AdjustReagent + reagent: Ethanol + amount: 0.50 - type: reagent id: IcedBeer @@ -1139,7 +1281,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.15 + amount: 0.16 - type: reagent id: IrishCream @@ -1162,7 +1304,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.2 + amount: 0.266 - type: reagent id: IrishCoffee @@ -1185,7 +1327,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.15 + amount: 0.133 - type: reagent id: LongIslandIcedTea @@ -1208,7 +1350,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.15 + amount: 0.273 - type: reagent id: Manhattan @@ -1224,6 +1366,14 @@ metamorphicMaxFillLevels: 3 metamorphicFillBaseName: fill- metamorphicChangeColor: false + metabolisms: + Drink: + effects: + - !type:SatiateThirst + factor: 2 + - !type:AdjustReagent + reagent: Ethanol + amount: 0.32 - type: reagent id: ManhattanProject @@ -1239,6 +1389,14 @@ metamorphicMaxFillLevels: 3 metamorphicFillBaseName: fill- metamorphicChangeColor: false + metabolisms: + Drink: + effects: + - !type:SatiateThirst + factor: 2 + - !type:AdjustReagent + reagent: Ethanol + amount: 0.363 - type: reagent id: ManlyDorf @@ -1291,7 +1449,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.15 + amount: 0.353 - type: reagent id: Mead @@ -1322,6 +1480,14 @@ metamorphicMaxFillLevels: 6 metamorphicFillBaseName: fill- metamorphicChangeColor: false + metabolisms: + Drink: + effects: + - !type:SatiateThirst + factor: 2 + - !type:AdjustReagent + reagent: Ethanol + amount: 0.10 - type: reagent id: Moonshine @@ -1338,7 +1504,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.25 + amount: 0.40 - type: reagent id: Neurotoxin @@ -1361,7 +1527,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.25 + amount: 0.16 Poison: effects: - !type:HealthChange @@ -1387,7 +1553,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.2 + amount: 0.04 - type: reagent id: Patron @@ -1410,7 +1576,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.2 + amount: 0.50 - type: reagent id: RedMead @@ -1438,6 +1604,14 @@ metamorphicSprite: sprite: Objects/Consumable/Drinks/pinacolada.rsi state: icon + metabolisms: + Drink: + effects: + - !type:SatiateThirst + factor: 2 + - !type:AdjustReagent + reagent: Ethanol + amount: 0.06 - type: reagent id: Sbiten @@ -1453,6 +1627,14 @@ metamorphicMaxFillLevels: 5 metamorphicFillBaseName: fill- metamorphicChangeColor: true + metabolisms: + Drink: + effects: + - !type:SatiateThirst + factor: 2 + - !type:AdjustReagent + reagent: Ethanol + amount: 0.2 - type: reagent id: ScrewdriverCocktail @@ -1475,7 +1657,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.07 + amount: 0.13 - type: reagent id: CogChamp @@ -1501,7 +1683,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.15 + amount: 0.176 - type: reagent id: Silencer @@ -1540,6 +1722,14 @@ metamorphicMaxFillLevels: 5 metamorphicFillBaseName: fill- metamorphicChangeColor: false + metabolisms: + Drink: + effects: + - !type:SatiateThirst + factor: 2 + - !type:AdjustReagent + reagent: Ethanol + amount: 0.23 - type: reagent id: SnowWhite @@ -1555,6 +1745,14 @@ metamorphicMaxFillLevels: 6 metamorphicFillBaseName: fill- metamorphicChangeColor: true + metabolisms: + Drink: + effects: + - !type:SatiateThirst + factor: 2 + - !type:AdjustReagent + reagent: Ethanol + amount: 0.03 - type: reagent id: SuiDream @@ -1570,6 +1768,14 @@ metamorphicMaxFillLevels: 5 metamorphicFillBaseName: fill- metamorphicChangeColor: false + metabolisms: + Drink: + effects: + - !type:SatiateThirst + factor: 2 + - !type:AdjustReagent + reagent: Ethanol + amount: 0.13 - type: reagent id: SyndicateBomb @@ -1585,6 +1791,14 @@ metamorphicMaxFillLevels: 6 metamorphicFillBaseName: fill- metamorphicChangeColor: true + metabolisms: + Drink: + effects: + - !type:SatiateThirst + factor: 2 + - !type:AdjustReagent + reagent: Ethanol + amount: 0.095 - type: reagent id: TequilaSunrise @@ -1607,7 +1821,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.15 + amount: 0.26 - type: reagent id: TheMartinez @@ -1623,6 +1837,14 @@ metamorphicMaxFillLevels: 3 metamorphicFillBaseName: fill- metamorphicChangeColor: false + metabolisms: + Drink: + effects: + - !type:SatiateThirst + factor: 2 + - !type:AdjustReagent + reagent: Ethanol + amount: 0.13 - type: reagent id: ThreeMileIsland @@ -1645,7 +1867,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.15 + amount: 0.273 - !type:AdjustReagent reagent: Uranium amount: 0.05 @@ -1664,6 +1886,14 @@ metamorphicMaxFillLevels: 4 metamorphicFillBaseName: fill- metamorphicChangeColor: false + metabolisms: + Drink: + effects: + - !type:SatiateThirst + factor: 2 + - !type:AdjustReagent + reagent: Ethanol + amount: 0.112 - type: reagent id: VodkaMartini @@ -1686,7 +1916,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.15 + amount: 0.32 - type: reagent id: VodkaTonic @@ -1709,7 +1939,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.07 + amount: 0.13 - type: reagent id: WhiskeyCola @@ -1732,7 +1962,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.07 + amount: 0.013 - type: reagent id: WhiskeySoda @@ -1755,7 +1985,7 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.07 + amount: 0.13 - type: reagent id: WhiteGilgamesh @@ -1772,7 +2002,7 @@ factor: 1 - !type:AdjustReagent reagent: Ethanol - amount: 0.15 + amount: 0.04 - type: reagent id: WhiteRussian @@ -1795,4 +2025,4 @@ factor: 2 - !type:AdjustReagent reagent: Ethanol - amount: 0.15 + amount: 0.33 diff --git a/Resources/Prototypes/Reagents/narcotics.yml b/Resources/Prototypes/Reagents/narcotics.yml index 2ab323c309..ca85fd15b3 100644 --- a/Resources/Prototypes/Reagents/narcotics.yml +++ b/Resources/Prototypes/Reagents/narcotics.yml @@ -212,6 +212,11 @@ plantMetabolism: - !type:PlantAdjustHealth amount: -5 + metabolisms: + Narcotic: + effects: + - !type:ChemAddMoodlet + moodPrototype: NicotineBenefit # TODO: Replace these nonstandardized effects with generic brain damage - type: reagent @@ -260,7 +265,7 @@ type: Add time: 5 refresh: false - - !type:ChemRerollPsionic #Nyano - Summary: lets the imbiber become psionic. + - !type:ChemRerollPsionic #Nyano - Summary: lets the imbiber become psionic. conditions: - !type:ReagentThreshold reagent: SpaceDrugs diff --git a/Resources/Prototypes/Reagents/psionic.yml b/Resources/Prototypes/Reagents/psionic.yml index 3e8415fc0e..f17a84047a 100644 --- a/Resources/Prototypes/Reagents/psionic.yml +++ b/Resources/Prototypes/Reagents/psionic.yml @@ -92,6 +92,12 @@ - !type:GenericStatusEffect key: SlurredSpeech component: TelepathicRepeater + - !type:ChemAddMoodlet + moodPrototype: LotoTranscendence + conditions: + - !type:ReagentThreshold + reagent: LotophagoiOil + min: 5 - type: reagent id: Ectoplasm diff --git a/Resources/Prototypes/Recipes/Reactions/drinks.yml b/Resources/Prototypes/Recipes/Reactions/drinks.yml index c810ebb0ce..812cded972 100644 --- a/Resources/Prototypes/Recipes/Reactions/drinks.yml +++ b/Resources/Prototypes/Recipes/Reactions/drinks.yml @@ -857,7 +857,7 @@ LemonLime: amount: 1 products: - SnowWhite: 3 + SnowWhite: 2 - type: reaction id: SoyLatte diff --git a/Resources/Prototypes/Research/experimental.yml b/Resources/Prototypes/Research/experimental.yml index 0dbcded546..d46e1db144 100644 --- a/Resources/Prototypes/Research/experimental.yml +++ b/Resources/Prototypes/Research/experimental.yml @@ -56,6 +56,7 @@ cost: 5000 recipeUnlocks: - TechDiskComputerCircuitboard + - ReverseEngineeringMachineCircuitboard #DeltaV - type: technology id: MagnetsTech diff --git a/Resources/Prototypes/Roles/Jobs/Civilian/lawyer.yml b/Resources/Prototypes/Roles/Jobs/Civilian/lawyer.yml index b7e3cc2223..c05d861280 100644 --- a/Resources/Prototypes/Roles/Jobs/Civilian/lawyer.yml +++ b/Resources/Prototypes/Roles/Jobs/Civilian/lawyer.yml @@ -20,7 +20,7 @@ shoes: ClothingShoesBootsLaceup id: LawyerPDA ears: ClothingHeadsetSecurity - # TODO add copy of space law + pocket1: BookSecurity inhand: - BriefcaseBrownFilled innerClothingSkirt: ClothingUniformJumpskirtLawyerBlack diff --git a/Resources/Prototypes/Roles/Jobs/Engineering/atmospheric_technician.yml b/Resources/Prototypes/Roles/Jobs/Engineering/atmospheric_technician.yml index 6371978425..aeca27189c 100644 --- a/Resources/Prototypes/Roles/Jobs/Engineering/atmospheric_technician.yml +++ b/Resources/Prototypes/Roles/Jobs/Engineering/atmospheric_technician.yml @@ -17,12 +17,12 @@ id: AtmosphericTechnicianGear equipment: jumpsuit: ClothingUniformJumpsuitAtmos - back: ClothingBackpackAtmosphericsFilled + back: ClothingBackpackEngineeringFilled shoes: ClothingShoesColorWhite eyes: ClothingEyesGlassesMeson id: AtmosPDA belt: ClothingBeltUtilityEngineering ears: ClothingHeadsetEngineering innerClothingSkirt: ClothingUniformJumpskirtAtmos - satchel: ClothingBackpackSatchelAtmosphericsFilled - duffelbag: ClothingBackpackDuffelAtmosphericsFilled + satchel: ClothingBackpackSatchelEngineeringFilled + duffelbag: ClothingBackpackDuffelEngineeringFilled diff --git a/Resources/Prototypes/Shaders/shaders.yml b/Resources/Prototypes/Shaders/shaders.yml index b495490201..3f0cb5ae1f 100644 --- a/Resources/Prototypes/Shaders/shaders.yml +++ b/Resources/Prototypes/Shaders/shaders.yml @@ -104,3 +104,10 @@ id: SaturationScale kind: source path: "/Textures/Shaders/saturationscale.swsl" + + # Flight shaders + +- type: shader + id: Flap + kind: source + path: "/Textures/Shaders/flap.swsl" \ No newline at end of file diff --git a/Resources/Prototypes/SoundCollections/flight.yml b/Resources/Prototypes/SoundCollections/flight.yml new file mode 100644 index 0000000000..cca2cfb014 --- /dev/null +++ b/Resources/Prototypes/SoundCollections/flight.yml @@ -0,0 +1,6 @@ +- type: soundCollection + id: WingFlaps + files: + - /Audio/Effects/Flight/wingflap1.ogg + - /Audio/Effects/Flight/wingflap2.ogg + - /Audio/Effects/Flight/wingflap3.ogg diff --git a/Resources/Prototypes/Traits/disabilities.yml b/Resources/Prototypes/Traits/disabilities.yml index c0b942ea66..c24e892769 100644 --- a/Resources/Prototypes/Traits/disabilities.yml +++ b/Resources/Prototypes/Traits/disabilities.yml @@ -65,7 +65,7 @@ - type: trait id: Uncloneable category: Physical - points: 4 + points: 1 requirements: - !type:CharacterJobRequirement inverted: true @@ -168,8 +168,8 @@ species: - IPC components: - - type: BloodDeficiency # 0.07 = start taking bloodloss damage at around ~21.4 minutes, - bloodLossAmount: 0.07 # then become crit ~10 minutes later + - type: BloodDeficiency # by default, start taking bloodloss damage at around ~21.4 minutes, + bloodLossPercentage: 0.0002333333 # then become crit ~10 minutes - type: trait id: Hemophilia diff --git a/Resources/Prototypes/Traits/neutral.yml b/Resources/Prototypes/Traits/neutral.yml index b9f988106d..a103f5abee 100644 --- a/Resources/Prototypes/Traits/neutral.yml +++ b/Resources/Prototypes/Traits/neutral.yml @@ -54,9 +54,8 @@ inverted: true traits: - Sanguine - components: - - type: MoodModifyTrait - moodId: TraitSaturnine + moodEffects: + - TraitSaturnine - type: trait id: Sanguine @@ -72,6 +71,22 @@ inverted: true traits: - Saturnine - components: - - type: MoodModifyTrait - moodId: TraitSanguine \ No newline at end of file + moodEffects: + - TraitSanguine + +- type: trait + id: AddictionNicotine + category: Mental + points: 1 + requirements: + - !type:CharacterJobRequirement + inverted: true + jobs: + - Borg + - MedicalBorg + - !type:CharacterSpeciesRequirement + inverted: true + species: + - IPC + moodEffects: + - NicotineWithdrawal \ No newline at end of file diff --git a/Resources/Prototypes/Wires/layouts.yml b/Resources/Prototypes/Wires/layouts.yml index 8d6be674e8..cf76e0ea61 100644 --- a/Resources/Prototypes/Wires/layouts.yml +++ b/Resources/Prototypes/Wires/layouts.yml @@ -1,6 +1,7 @@ - type: wireLayout id: Airlock wires: + - !type:AccessWireAction - !type:PowerWireAction - !type:PowerWireAction pulseTimeout: 15 @@ -44,6 +45,7 @@ - type: wireLayout id: HighSec wires: + - !type:AccessWireAction - !type:PowerWireAction pulseTimeout: 10 - !type:DoorBoltWireAction diff --git a/Resources/ServerInfo/Guidebook/Service/FoodRecipes.xml b/Resources/ServerInfo/Guidebook/Service/FoodRecipes.xml index 797591dd78..c74b947dbf 100644 --- a/Resources/ServerInfo/Guidebook/Service/FoodRecipes.xml +++ b/Resources/ServerInfo/Guidebook/Service/FoodRecipes.xml @@ -1,88 +1,9 @@ -## Starting Out -This is not an extensive list of recipes, these listings are to showcase the basics. +## Recipe list +Note: Only solid foods are listed here! To learn recipes for liquid ingredients, check the chemistry guidebook. -Mixes are done in a Beaker, foods are cooked in a Microwave. Cook times will be listed. +This list is auto-generated and contains all known foods. -WARNING: This is not an automatically generated list, things here may become outdated. The wiki has much more than is listed here. - -## The Basics: Mixing - -- Dough = 15 Flour, 10 Water -- Cornmeal Dough = 1 Egg (6u), 10 Milk, 15 Cornmeal -- Tortila Dough = 15 Cornmeal, 10 Water -- Tofu = 5 Enzyme (Catalyst), 30 Soy Milk -- Pie Dough = 2 Eggs (12u), 15 Flour, 5 Table Salt -- Cake Batter = 2 Eggs(12u), 15 flour, 5 Sugar -- Vegan Cake Batter = 15 Soy Milk, 15 Flour, 5 Sugar -- Butter = 30 Milk, 5 Table Salt (Catalyst) -- Cheese Wheel = 5 Enzyme (Catalyst), 40 Milk -- Chèvre Log = 5 Enzyme (Catalyst), 10 Goat Milk -- Meatball = 1 Egg (6u), 5 Flour, 5 Uncooked Animal Proteins -- Chocolate = 6 Cocoa Powder, 2 Milk, 2 Sugar -- Uncooked Animal Protein: Grind Raw Meat - - - - - - - - - - - - - - - - - - - -## Secondary Products - -- Dough Slice: Cut Dough -- Bun: Microwave Dough Slice for 5 Seconds -- Cutlet: Slice Raw Meat -- Cheese Wedge: Slice Cheese Wheel -- Flat Dough: Use a rolling pin or a round object (fire extinguisher, soda can, bottle) on Dough. -- Tortilla Dough Slice: cut Tortilla Dough -- Flat Tortilla Dough: Use a rolling pin or a round object (fire extinguisher, soda can, bottle) on Tortilla Dough Slice -- Taco Shell: Microwave Flat Tortilla Dough for 5 Seconds - -## Food Examples - -- Bread: Microwave Dough for 10 Seconds -- Plain Burger: Microwave 1 Bun and 1 Raw Meat for 10 Seconds -- Tomato Soup: 10u Water, 1 Bowl, and 2 Tomatoes for 10 Seconds -- Citrus Salad: 1 Bowl, 1 Lemon, 1 Lime, 1 Orange for 5 Seconds -- Margherita Pizza: Microwave 1 Flat Dough, 1 Cheese Wedge, and 4 Tomatoes for 30 Seconds -- Cake: 1 Cake Batter for 15 Seconds -- Apple Pie: 1 Pie Dough, 3 Apples, and 1 Pie Tin for 15 Seconds -- Beef Taco: Microwave 1 Taco Shell, 1 Raw Meat Cutlet, 1 Cheese Wedge for 10 Seconds -- Cuban Carp : Microwave 1 Dough, 1 Cheese Wedge, 1 Chili, 1 Carp Meat for 15 Seconds -- Banana Cream Pie : Microwave 1 Pie Dough, 3 Bananas, and 1 Pie Tin for 15 Seconds -- Carrot Fries : Microwave 1 Carrot, 15u Salt for 15 Seconds -- Pancake : Microwave 5u Flour, 5u Milk, 1 Egg (6u) for 5 Seconds - - - - - - - - - - - - - - - - - - - + diff --git a/Resources/Textures/Interface/Actions/flight.rsi/flight_off.png b/Resources/Textures/Interface/Actions/flight.rsi/flight_off.png new file mode 100644 index 0000000000..852dd300e9 Binary files /dev/null and b/Resources/Textures/Interface/Actions/flight.rsi/flight_off.png differ diff --git a/Resources/Textures/Interface/Actions/flight.rsi/flight_on.png b/Resources/Textures/Interface/Actions/flight.rsi/flight_on.png new file mode 100644 index 0000000000..c47b923a68 Binary files /dev/null and b/Resources/Textures/Interface/Actions/flight.rsi/flight_on.png differ diff --git a/Resources/Textures/Interface/Actions/flight.rsi/meta.json b/Resources/Textures/Interface/Actions/flight.rsi/meta.json new file mode 100644 index 0000000000..b4a013190d --- /dev/null +++ b/Resources/Textures/Interface/Actions/flight.rsi/meta.json @@ -0,0 +1,17 @@ +{ + "copyright" : "Made by dootythefrooty (273243513800622090)", + "license" : "CC-BY-SA-3.0", + "version": 1, + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "flight_off" + }, + { + "name": "flight_on" + } + ] + } \ No newline at end of file diff --git a/Resources/Textures/Markers/environment.rsi/base-blue.png b/Resources/Textures/Markers/environment.rsi/base-blue.png new file mode 100644 index 0000000000..ee77bb448a Binary files /dev/null and b/Resources/Textures/Markers/environment.rsi/base-blue.png differ diff --git a/Resources/Textures/Markers/environment.rsi/base-green.png b/Resources/Textures/Markers/environment.rsi/base-green.png new file mode 100644 index 0000000000..a39bca9cdc Binary files /dev/null and b/Resources/Textures/Markers/environment.rsi/base-green.png differ diff --git a/Resources/Textures/Markers/environment.rsi/base-red.png b/Resources/Textures/Markers/environment.rsi/base-red.png new file mode 100644 index 0000000000..e0d68f8b9e Binary files /dev/null and b/Resources/Textures/Markers/environment.rsi/base-red.png differ diff --git a/Resources/Textures/Markers/environment.rsi/fire.png b/Resources/Textures/Markers/environment.rsi/fire.png new file mode 100644 index 0000000000..71abc46e81 Binary files /dev/null and b/Resources/Textures/Markers/environment.rsi/fire.png differ diff --git a/Resources/Textures/Markers/environment.rsi/meta.json b/Resources/Textures/Markers/environment.rsi/meta.json new file mode 100644 index 0000000000..6fc7decc8b --- /dev/null +++ b/Resources/Textures/Markers/environment.rsi/meta.json @@ -0,0 +1,32 @@ +{ + "version": 1, + "license": "CC-BY-NC-SA-3.0", + "copyright": "Nuclear14", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "base-blue" + }, + { + "name": "base-red" + }, + { + "name": "base-green" + }, + { + "name": "fire" + }, + { + "name": "rad" + }, + { + "name": "wall" + }, + { + "name": "weather" + } + ] +} diff --git a/Resources/Textures/Markers/environment.rsi/rad.png b/Resources/Textures/Markers/environment.rsi/rad.png new file mode 100644 index 0000000000..ae01d87143 Binary files /dev/null and b/Resources/Textures/Markers/environment.rsi/rad.png differ diff --git a/Resources/Textures/Markers/environment.rsi/wall.png b/Resources/Textures/Markers/environment.rsi/wall.png new file mode 100644 index 0000000000..2aaeaaf014 Binary files /dev/null and b/Resources/Textures/Markers/environment.rsi/wall.png differ diff --git a/Resources/Textures/Markers/environment.rsi/weather.png b/Resources/Textures/Markers/environment.rsi/weather.png new file mode 100644 index 0000000000..adb9f53a47 Binary files /dev/null and b/Resources/Textures/Markers/environment.rsi/weather.png differ diff --git a/Resources/Textures/Shaders/flap.swsl b/Resources/Textures/Shaders/flap.swsl new file mode 100644 index 0000000000..3082e19b49 --- /dev/null +++ b/Resources/Textures/Shaders/flap.swsl @@ -0,0 +1,35 @@ +preset raw; + +varying highp vec4 VtxModulate; +varying highp vec2 Pos; + +uniform highp float Speed; +uniform highp float Multiplier; +uniform highp float Offset; + +void fragment() { + highp vec4 texColor = zTexture(UV); + lowp vec3 lightSample = texture2D(lightMap, Pos).rgb; + COLOR = texColor * VtxModulate * vec4(lightSample, 1.0); +} + +void vertex() { + vec2 pos = aPos; + + // Apply MVP transformation first + vec2 transformedPos = apply_mvp(pos); + + // Calculate vertical movement in screen space + float verticalOffset = (sin(TIME * Speed) + Offset) * Multiplier; + + // Apply vertical movement after MVP transformation + transformedPos.y += verticalOffset; + + // Assign the final position + VERTEX = transformedPos; + + // Keep the original UV coordinates + UV = mix(modifyUV.xy, modifyUV.zw, tCoord); + Pos = (VERTEX + 1.0) / 2.0; + VtxModulate = zFromSrgb(modulate); +} \ No newline at end of file