diff --git a/Content.Client/Administration/UI/Tabs/PlayerTab/PlayerTab.xaml.cs b/Content.Client/Administration/UI/Tabs/PlayerTab/PlayerTab.xaml.cs index e6a64fc48d4..4f77369b57b 100644 --- a/Content.Client/Administration/UI/Tabs/PlayerTab/PlayerTab.xaml.cs +++ b/Content.Client/Administration/UI/Tabs/PlayerTab/PlayerTab.xaml.cs @@ -150,7 +150,7 @@ private int Compare(PlayerInfo x, PlayerInfo y) Header.Character => Compare(x.CharacterName, y.CharacterName), Header.Job => Compare(x.StartingJob, y.StartingJob), Header.Antagonist => x.Antag.CompareTo(y.Antag), - Header.Playtime => Compare(x.PlaytimeString, y.PlaytimeString), + Header.Playtime => TimeSpan.Compare(x.OverallPlaytime ?? default, y.OverallPlaytime ?? default), _ => 1 }; } diff --git a/Content.Client/Antag/AntagStatusIconSystem.cs b/Content.Client/Antag/AntagStatusIconSystem.cs index 3c1c72d03b9..bf3955b49ab 100644 --- a/Content.Client/Antag/AntagStatusIconSystem.cs +++ b/Content.Client/Antag/AntagStatusIconSystem.cs @@ -1,8 +1,8 @@ +using Content.Shared.Ghost; using Content.Shared.StatusIcon; using Content.Shared.StatusIcon.Components; -using Robust.Shared.Prototypes; -using Content.Shared.Ghost; using Robust.Client.Player; +using Robust.Shared.Prototypes; namespace Content.Client.Antag; @@ -10,7 +10,7 @@ namespace Content.Client.Antag; /// Used for assigning specified icons for antags. /// public abstract class AntagStatusIconSystem : SharedStatusIconSystem - where T : Component + where T : IComponent { [Dependency] private readonly IPrototypeManager _prototype = default!; [Dependency] private readonly IPlayerManager _player = default!; diff --git a/Content.Client/Eye/EyeLerpingSystem.cs b/Content.Client/Eye/EyeLerpingSystem.cs index 79af9e719b8..8e54196b81d 100644 --- a/Content.Client/Eye/EyeLerpingSystem.cs +++ b/Content.Client/Eye/EyeLerpingSystem.cs @@ -132,7 +132,7 @@ private Vector2 UpdateZoom(EntityUid uid, float frameTime, EyeComponent? eye = n return content.TargetZoom; } - var change = diff * 8f * frameTime; + var change = diff * Math.Min(8f * frameTime, 1); return eye.Zoom + change; } diff --git a/Content.Client/Guidebook/Controls/GuideTechDisciplineEmbed.xaml b/Content.Client/Guidebook/Controls/GuideTechDisciplineEmbed.xaml new file mode 100644 index 00000000000..0878951af86 --- /dev/null +++ b/Content.Client/Guidebook/Controls/GuideTechDisciplineEmbed.xaml @@ -0,0 +1,4 @@ + + + diff --git a/Content.Client/Guidebook/Controls/GuideTechDisciplineEmbed.xaml.cs b/Content.Client/Guidebook/Controls/GuideTechDisciplineEmbed.xaml.cs new file mode 100644 index 00000000000..88d264cb059 --- /dev/null +++ b/Content.Client/Guidebook/Controls/GuideTechDisciplineEmbed.xaml.cs @@ -0,0 +1,60 @@ +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using Content.Client.Guidebook.Richtext; +using Content.Shared.Research.Prototypes; +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; + +/// +/// Control for embedding all the technologies in a discipline into a guidebook. +/// +[UsedImplicitly, GenerateTypedNameReferences] +public sealed partial class GuideTechDisciplineEmbed : BoxContainer, IDocumentTag +{ + [Dependency] private readonly IPrototypeManager _prototype = default!; + + public GuideTechDisciplineEmbed() + { + RobustXamlLoader.Load(this); + IoCManager.InjectDependencies(this); + MouseFilter = MouseFilterMode.Stop; + } + + public GuideTechDisciplineEmbed(string group) : this() + { + var prototypes = _prototype.EnumeratePrototypes() + .Where(p => p.Discipline.Equals(group)).OrderBy(p => p.Tier).ThenBy(p => Loc.GetString(p.Name)); + foreach (var tech in prototypes) + { + var embed = new GuideTechnologyEmbed(tech); + DisciplineContainer.AddChild(embed); + } + } + + public bool TryParseTag(Dictionary args, [NotNullWhen(true)] out Control? control) + { + control = null; + if (!args.TryGetValue("Discipline", out var group)) + { + Logger.Error("Technology discipline embed tag is missing discipline argument"); + return false; + } + + var prototypes = _prototype.EnumeratePrototypes() + .Where(p => p.Discipline.Equals(group)).OrderBy(p => p.Tier).ThenBy(p => Loc.GetString(p.Name)); + foreach (var tech in prototypes) + { + var embed = new GuideTechnologyEmbed(tech); + DisciplineContainer.AddChild(embed); + } + + control = this; + return true; + } +} diff --git a/Content.Client/Guidebook/Controls/GuideTechnologyEmbed.xaml b/Content.Client/Guidebook/Controls/GuideTechnologyEmbed.xaml new file mode 100644 index 00000000000..6d96f19972e --- /dev/null +++ b/Content.Client/Guidebook/Controls/GuideTechnologyEmbed.xaml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + diff --git a/Content.Client/Guidebook/Controls/GuideTechnologyEmbed.xaml.cs b/Content.Client/Guidebook/Controls/GuideTechnologyEmbed.xaml.cs new file mode 100644 index 00000000000..d61cc2d961c --- /dev/null +++ b/Content.Client/Guidebook/Controls/GuideTechnologyEmbed.xaml.cs @@ -0,0 +1,93 @@ +using System.Diagnostics.CodeAnalysis; +using Content.Client.Guidebook.Richtext; +using Content.Client.Message; +using Content.Client.Research; +using Content.Client.UserInterface.ControlExtensions; +using Content.Shared.Research.Prototypes; +using JetBrains.Annotations; +using Robust.Client.AutoGenerated; +using Robust.Client.GameObjects; +using Robust.Client.Graphics; +using Robust.Client.UserInterface; +using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.XAML; +using Robust.Shared.Prototypes; + +namespace Content.Client.Guidebook.Controls; + +/// +/// Control for embedding a research technology into a guidebook. +/// +[UsedImplicitly, GenerateTypedNameReferences] +public sealed partial class GuideTechnologyEmbed : BoxContainer, IDocumentTag, ISearchableControl +{ + [Dependency] private readonly IEntitySystemManager _systemManager = default!; + [Dependency] private readonly IPrototypeManager _prototype = default!; + + private readonly ResearchSystem _research; + private readonly SpriteSystem _sprite; + + public GuideTechnologyEmbed() + { + RobustXamlLoader.Load(this); + IoCManager.InjectDependencies(this); + _research = _systemManager.GetEntitySystem(); + _sprite = _systemManager.GetEntitySystem(); + MouseFilter = MouseFilterMode.Stop; + } + + public GuideTechnologyEmbed(string technology) : this() + { + GenerateControl(_prototype.Index(technology)); + } + + public GuideTechnologyEmbed(TechnologyPrototype technology) : this() + { + GenerateControl(technology); + } + + public bool CheckMatchesSearch(string query) + { + return this.ChildrenContainText(query); + } + + 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("Technology", out var id)) + { + Logger.Error("Technology embed tag is missing technology prototype argument"); + return false; + } + + if (!_prototype.TryIndex(id, out var technology)) + { + Logger.Error($"Specified technology prototype \"{id}\" is not a valid technology prototype"); + return false; + } + + GenerateControl(technology); + + control = this; + return true; + } + + private void GenerateControl(TechnologyPrototype technology) + { + var discipline = _prototype.Index(technology.Discipline); + + NameLabel.SetMarkup($"[bold]{Loc.GetString(technology.Name)}[/bold]"); + DescriptionLabel.SetMessage(_research.GetTechnologyDescription(technology, includePrereqs: true, disciplinePrototype: discipline)); + TechTexture.Texture = _sprite.Frame0(technology.Icon); + + DisciplineColorBackground.PanelOverride = new StyleBoxFlat + { + BackgroundColor = discipline.Color + }; + } +} diff --git a/Content.Client/Research/UI/MiniTechnologyCardControl.xaml.cs b/Content.Client/Research/UI/MiniTechnologyCardControl.xaml.cs index 8b1a583c24a..5af1159c935 100644 --- a/Content.Client/Research/UI/MiniTechnologyCardControl.xaml.cs +++ b/Content.Client/Research/UI/MiniTechnologyCardControl.xaml.cs @@ -2,6 +2,7 @@ using Robust.Client.AutoGenerated; using Robust.Client.GameObjects; using Robust.Client.UserInterface; +using Robust.Client.UserInterface.CustomControls; using Robust.Client.UserInterface.XAML; using Robust.Shared.Prototypes; using Robust.Shared.Utility; @@ -15,10 +16,13 @@ public MiniTechnologyCardControl(TechnologyPrototype technology, IPrototypeManag { RobustXamlLoader.Load(this); - var discipline = prototypeManager.Index(technology.Discipline); + var discipline = prototypeManager.Index(technology.Discipline); Background.ModulateSelfOverride = discipline.Color; Texture.Texture = spriteSys.Frame0(technology.Icon); NameLabel.SetMessage(Loc.GetString(technology.Name)); - Main.ToolTip = description.ToString(); + + var tooltip = new Tooltip(); + tooltip.SetMessage(description); + Main.TooltipSupplier = _ => tooltip; } } diff --git a/Content.Client/Research/UI/ResearchConsoleMenu.xaml.cs b/Content.Client/Research/UI/ResearchConsoleMenu.xaml.cs index c2b23f7341d..a20509202fd 100644 --- a/Content.Client/Research/UI/ResearchConsoleMenu.xaml.cs +++ b/Content.Client/Research/UI/ResearchConsoleMenu.xaml.cs @@ -27,7 +27,7 @@ public sealed partial class ResearchConsoleMenu : FancyWindow private readonly TechnologyDatabaseComponent? _technologyDatabase; private readonly ResearchSystem _research; private readonly SpriteSystem _sprite; - private readonly AccessReaderSystem _accessReader = default!; + private readonly AccessReaderSystem _accessReader; public readonly EntityUid Entity; @@ -55,7 +55,7 @@ public void UpdatePanels(ResearchConsoleBoundInterfaceState state) foreach (var tech in allTech) { - var mini = new MiniTechnologyCardControl(tech, _prototype, _sprite, GetTechnologyDescription(tech, false)); + var mini = new MiniTechnologyCardControl(tech, _prototype, _sprite, _research.GetTechnologyDescription(tech)); AvailableCardsContainer.AddChild(mini); } @@ -74,7 +74,7 @@ public void UpdatePanels(ResearchConsoleBoundInterfaceState state) foreach (var techId in _technologyDatabase.CurrentTechnologyCards) { var tech = _prototype.Index(techId); - var cardControl = new TechnologyCardControl(tech, _prototype, _sprite, GetTechnologyDescription(tech), state.Points, hasAccess); + var cardControl = new TechnologyCardControl(tech, _prototype, _sprite, _research.GetTechnologyDescription(tech, includeTier: false), state.Points, hasAccess); cardControl.OnPressed += () => OnTechnologyCardPressed?.Invoke(techId); TechnologyCardsContainer.AddChild(cardControl); } @@ -82,37 +82,11 @@ public void UpdatePanels(ResearchConsoleBoundInterfaceState state) foreach (var unlocked in _technologyDatabase.UnlockedTechnologies) { var tech = _prototype.Index(unlocked); - var cardControl = new MiniTechnologyCardControl(tech, _prototype, _sprite, GetTechnologyDescription(tech, false)); + var cardControl = new MiniTechnologyCardControl(tech, _prototype, _sprite, _research.GetTechnologyDescription(tech, false)); UnlockedCardsContainer.AddChild(cardControl); } } - public FormattedMessage GetTechnologyDescription(TechnologyPrototype technology, bool includeCost = true) - { - var description = new FormattedMessage(); - if (includeCost) - { - description.AddMarkup(Loc.GetString("research-console-cost", ("amount", technology.Cost))); - description.PushNewline(); - } - description.AddMarkup(Loc.GetString("research-console-unlocks-list-start")); - foreach (var recipe in technology.RecipeUnlocks) - { - var recipeProto = _prototype.Index(recipe); - description.PushNewline(); - description.AddMarkup(Loc.GetString("research-console-unlocks-list-entry", - ("name",recipeProto.Name))); - } - foreach (var generic in technology.GenericUnlocks) - { - description.PushNewline(); - description.AddMarkup(Loc.GetString("research-console-unlocks-list-entry-generic", - ("name", Loc.GetString(generic.UnlockDescription)))); - } - - return description; - } - public void UpdateInformationPanel(ResearchConsoleBoundInterfaceState state) { var amountMsg = new FormattedMessage(); diff --git a/Content.Client/Weapons/Melee/MeleeWeaponSystem.Effects.cs b/Content.Client/Weapons/Melee/MeleeWeaponSystem.Effects.cs index 79a6529a4dd..0dd207fbb19 100644 --- a/Content.Client/Weapons/Melee/MeleeWeaponSystem.Effects.cs +++ b/Content.Client/Weapons/Melee/MeleeWeaponSystem.Effects.cs @@ -1,5 +1,6 @@ using System.Numerics; using Content.Client.Weapons.Melee.Components; +using Content.Shared.Weapons.Melee; using Robust.Client.Animations; using Robust.Client.GameObjects; using Robust.Shared.Animations; @@ -16,7 +17,7 @@ public sealed partial class MeleeWeaponSystem /// /// Does all of the melee effects for a player that are predicted, i.e. character lunge and weapon animation. /// - public override void DoLunge(EntityUid user, Angle angle, Vector2 localPos, string? animation, bool predicted = true) + public override void DoLunge(EntityUid user, EntityUid weapon, Angle angle, Vector2 localPos, string? animation, bool predicted = true) { if (!Timing.IsFirstTimePredicted) return; @@ -41,6 +42,19 @@ public override void DoLunge(EntityUid user, Angle angle, Vector2 localPos, stri return; } + var spriteRotation = Angle.Zero; + if (arcComponent.Animation != WeaponArcAnimation.None + && TryComp(weapon, out MeleeWeaponComponent? meleeWeaponComponent)) + { + if (user == weapon + && TryComp(weapon, out SpriteComponent? weaponSpriteComponent)) + sprite.CopyFrom(weaponSpriteComponent); + + spriteRotation = meleeWeaponComponent.WideAnimationRotation; + + if (meleeWeaponComponent.SwingLeft) + angle *= -1; + } sprite.NoRotation = true; sprite.Rotation = localPos.ToWorldAngle(); var distance = Math.Clamp(localPos.Length() / 2f, 0.2f, 1f); @@ -50,13 +64,13 @@ public override void DoLunge(EntityUid user, Angle angle, Vector2 localPos, stri switch (arcComponent.Animation) { case WeaponArcAnimation.Slash: - _animation.Play(animationUid, GetSlashAnimation(sprite, angle), SlashAnimationKey); + _animation.Play(animationUid, GetSlashAnimation(sprite, angle, spriteRotation), SlashAnimationKey); TransformSystem.SetParent(animationUid, xform, user, userXform); if (arcComponent.Fadeout) _animation.Play(animationUid, GetFadeAnimation(sprite, 0.065f, 0.065f + 0.05f), FadeAnimationKey); break; case WeaponArcAnimation.Thrust: - _animation.Play(animationUid, GetThrustAnimation(sprite, distance), ThrustAnimationKey); + _animation.Play(animationUid, GetThrustAnimation(sprite, distance, spriteRotation), ThrustAnimationKey); TransformSystem.SetParent(animationUid, xform, user, userXform); if (arcComponent.Fadeout) _animation.Play(animationUid, GetFadeAnimation(sprite, 0.05f, 0.15f), FadeAnimationKey); @@ -73,13 +87,17 @@ public override void DoLunge(EntityUid user, Angle angle, Vector2 localPos, stri } } - private Animation GetSlashAnimation(SpriteComponent sprite, Angle arc) + private Animation GetSlashAnimation(SpriteComponent sprite, Angle arc, Angle spriteRotation) { const float slashStart = 0.03f; const float slashEnd = 0.065f; const float length = slashEnd + 0.05f; - var startRotation = sprite.Rotation - arc / 2; - var endRotation = sprite.Rotation + arc / 2; + var startRotation = sprite.Rotation + arc / 2; + var endRotation = sprite.Rotation - arc / 2; + var startRotationOffset = startRotation.RotateVec(new Vector2(0f, -1f)); + var endRotationOffset = endRotation.RotateVec(new Vector2(0f, -1f)); + startRotation += spriteRotation; + endRotation += spriteRotation; sprite.NoRotation = true; return new Animation() @@ -104,19 +122,21 @@ private Animation GetSlashAnimation(SpriteComponent sprite, Angle arc) Property = nameof(SpriteComponent.Offset), KeyFrames = { - new AnimationTrackProperty.KeyFrame(startRotation.RotateVec(new Vector2(0f, -1f)), 0f), - new AnimationTrackProperty.KeyFrame(startRotation.RotateVec(new Vector2(0f, -1f)), slashStart), - new AnimationTrackProperty.KeyFrame(endRotation.RotateVec(new Vector2(0f, -1f)), slashEnd) + new AnimationTrackProperty.KeyFrame(startRotationOffset, 0f), + new AnimationTrackProperty.KeyFrame(startRotationOffset, slashStart), + new AnimationTrackProperty.KeyFrame(endRotationOffset, slashEnd) } }, } }; } - private Animation GetThrustAnimation(SpriteComponent sprite, float distance) + private Animation GetThrustAnimation(SpriteComponent sprite, float distance, Angle spriteRotation) { const float thrustEnd = 0.05f; const float length = 0.15f; + var startOffset = sprite.Rotation.RotateVec(new Vector2(0f, -distance / 5f)); + var endOffset = sprite.Rotation.RotateVec(new Vector2(0f, -distance)); return new Animation() { @@ -129,9 +149,9 @@ private Animation GetThrustAnimation(SpriteComponent sprite, float distance) Property = nameof(SpriteComponent.Offset), KeyFrames = { - new AnimationTrackProperty.KeyFrame(sprite.Rotation.RotateVec(new Vector2(0f, -distance / 5f)), 0f), - new AnimationTrackProperty.KeyFrame(sprite.Rotation.RotateVec(new Vector2(0f, -distance)), thrustEnd), - new AnimationTrackProperty.KeyFrame(sprite.Rotation.RotateVec(new Vector2(0f, -distance)), length), + new AnimationTrackProperty.KeyFrame(startOffset, 0f), + new AnimationTrackProperty.KeyFrame(endOffset, thrustEnd), + new AnimationTrackProperty.KeyFrame(endOffset, length), } }, } diff --git a/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs b/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs index 36fe75fad7f..397032cd154 100644 --- a/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs +++ b/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs @@ -17,8 +17,6 @@ using Robust.Shared.Map; using Robust.Shared.Player; using Robust.Shared.Players; -using Robust.Shared.Prototypes; -using Robust.Shared.Timing; namespace Content.Client.Weapons.Melee; @@ -235,9 +233,10 @@ private void ClientHeavyAttack(EntityUid user, EntityCoordinates coordinates, En private void OnMeleeLunge(MeleeLungeEvent ev) { var ent = GetEntity(ev.Entity); + var entWeapon = GetEntity(ev.Weapon); // Entity might not have been sent by PVS. - if (Exists(ent)) - DoLunge(ent, ev.Angle, ev.LocalPos, ev.Animation); + if (Exists(ent) && Exists(entWeapon)) + DoLunge(ent, entWeapon, ev.Angle, ev.LocalPos, ev.Animation); } } diff --git a/Content.IntegrationTests/PoolManager.cs b/Content.IntegrationTests/PoolManager.cs index 3f8d261e8dd..a2015f3fdba 100644 --- a/Content.IntegrationTests/PoolManager.cs +++ b/Content.IntegrationTests/PoolManager.cs @@ -428,7 +428,7 @@ public static async Task WaitUntil(RobustIntegrationTest.IntegrationInstance ins /// /// Helper method that retrieves all entity prototypes that have some component. /// - public static List GetPrototypesWithComponent(RobustIntegrationTest.IntegrationInstance instance) where T : Component + public static List GetPrototypesWithComponent(RobustIntegrationTest.IntegrationInstance instance) where T : IComponent { var protoMan = instance.ResolveDependency(); var compFact = instance.ResolveDependency(); diff --git a/Content.IntegrationTests/Tests/EntityTest.cs b/Content.IntegrationTests/Tests/EntityTest.cs index 453796b9165..042db1deb3c 100644 --- a/Content.IntegrationTests/Tests/EntityTest.cs +++ b/Content.IntegrationTests/Tests/EntityTest.cs @@ -1,6 +1,8 @@ using System.Collections.Generic; using System.Linq; +using Content.Server.Humanoid.Components; using Content.Shared.Coordinates; +using Content.Shared.Prototypes; using Robust.Shared; using Robust.Shared.Configuration; using Robust.Shared.GameObjects; @@ -183,7 +185,7 @@ await server.WaitPost(() => var query = entityMan.AllEntityQueryEnumerator(); while (query.MoveNext(out var uid, out var meta)) yield return (uid, meta); - }; + } var entityMetas = Query(sEntMan).ToList(); foreach (var (uid, meta) in entityMetas) @@ -198,6 +200,100 @@ await server.WaitPost(() => await pair.CleanReturnAsync(); } + /// + /// This test checks that spawning and deleting an entity doesn't somehow create other unrelated entities. + /// + /// + /// Unless an entity is intentionally designed to spawn other entities (e.g., mob spawners), they should + /// generally not spawn unrelated / detached entities. Any entities that do get spawned should be parented to + /// the spawned entity (e.g., in a container). If an entity needs to spawn an entity somewhere in null-space, + /// it should delete that entity when it is no longer required. This test mainly exists to prevent "entity leak" + /// bugs, where spawning some entity starts spawning unrelated entities in null space. + /// + [Test] + public async Task SpawnAndDeleteEntityCountTest() + { + var settings = new PoolSettings { Connected = true, Dirty = true }; + await using var pair = await PoolManager.GetServerClient(settings); + var server = pair.Server; + var client = pair.Client; + + var excluded = new[] + { + "MapGrid", + "StationEvent", + "TimedDespawn", + + // Spawner entities + "DragonRift", + "RandomHumanoidSpawner", + "RandomSpawner", + "ConditionalSpawner", + "GhostRoleMobSpawner", + "NukeOperativeSpawner", + "TimedSpawner", + }; + + Assert.That(server.CfgMan.GetCVar(CVars.NetPVS), Is.False); + + var protoIds = server.ProtoMan + .EnumeratePrototypes() + .Where(p => !p.Abstract) + .Where(p => !pair.IsTestPrototype(p)) + .Where(p => !excluded.Any(p.Components.ContainsKey)) + .Select(p => p.ID) + .ToList(); + + MapCoordinates coords = default; + await server.WaitPost(() => + { + var map = server.MapMan.CreateMap(); + coords = new MapCoordinates(default, map); + }); + + await pair.RunTicksSync(3); + + List badPrototypes = new(); + foreach (var protoId in protoIds) + { + // TODO fix ninja + // Currently ninja fails to equip their own loadout. + if (protoId == "MobHumanSpaceNinja") + continue; + + var count = server.EntMan.EntityCount; + var clientCount = client.EntMan.EntityCount; + EntityUid uid = default; + await server.WaitPost(() => uid = server.EntMan.SpawnEntity(protoId, coords)); + await pair.RunTicksSync(3); + + // If the entity deleted itself, check that it didn't spawn other entities + if (!server.EntMan.EntityExists(uid)) + { + if (server.EntMan.EntityCount != count || client.EntMan.EntityCount != clientCount) + badPrototypes.Add(protoId); + continue; + } + + // Check that the number of entities has increased. + if (server.EntMan.EntityCount <= count || client.EntMan.EntityCount <= clientCount) + { + badPrototypes.Add(protoId); + continue; + } + + await server.WaitPost(() => server.EntMan.DeleteEntity(uid)); + await pair.RunTicksSync(3); + + // Check that the number of entities has gone back to the original value. + if (server.EntMan.EntityCount != count || client.EntMan.EntityCount != clientCount) + badPrototypes.Add(protoId); + } + + Assert.That(badPrototypes, Is.Empty); + await pair.CleanReturnAsync(); + } + [Test] public async Task AllComponentsOneToOneDeleteTest() { diff --git a/Content.Server/Administration/Commands/WarpCommand.cs b/Content.Server/Administration/Commands/WarpCommand.cs index 5c61208b5b2..30a6d127aa3 100644 --- a/Content.Server/Administration/Commands/WarpCommand.cs +++ b/Content.Server/Administration/Commands/WarpCommand.cs @@ -59,9 +59,7 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) var currentMap = _entManager.GetComponent(playerEntity).MapID; var currentGrid = _entManager.GetComponent(playerEntity).GridUid; - var found = _entManager.EntityQuery(true) - .Where(p => p.Location == location) - .Select(p => (_entManager.GetComponent(p.Owner).Coordinates, p.Follow)) + var found = GetWarpPointByName(location) .OrderBy(p => p.Item1, Comparer.Create((a, b) => { // Sort so that warp points on the same grid/map are first. @@ -133,11 +131,28 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) private IEnumerable GetWarpPointNames() { - return _entManager.EntityQuery(true) - .Select(p => p.Location) - .Where(p => p != null) - .OrderBy(p => p) - .Distinct()!; + List points = new(_entManager.Count()); + var query = _entManager.AllEntityQueryEnumerator(); + while (query.MoveNext(out _, out var warp, out var meta)) + { + points.Add(warp.Location ?? meta.EntityName); + } + + points.Sort(); + return points; + } + + private List<(EntityCoordinates, bool)> GetWarpPointByName(string name) + { + List<(EntityCoordinates, bool)> points = new(); + var query = _entManager.AllEntityQueryEnumerator(); + while (query.MoveNext(out var uid, out var warp, out var meta, out var xform)) + { + if (name == (warp.Location ?? meta.EntityName)) + points.Add((xform.Coordinates, warp.Follow)); + } + + return points; } public CompletionResult GetCompletion(IConsoleShell shell, string[] args) diff --git a/Content.Server/Administration/Systems/AdminVerbSystem.cs b/Content.Server/Administration/Systems/AdminVerbSystem.cs index 3a419b93f6f..c7e23374a3c 100644 --- a/Content.Server/Administration/Systems/AdminVerbSystem.cs +++ b/Content.Server/Administration/Systems/AdminVerbSystem.cs @@ -59,6 +59,7 @@ public sealed partial class AdminVerbSystem : EntitySystem [Dependency] private readonly SharedMindSystem _mindSystem = default!; [Dependency] private readonly ToolshedManager _toolshed = default!; [Dependency] private readonly RejuvenateSystem _rejuvenate = default!; + [Dependency] private readonly SharedPopupSystem _popup = default!; private readonly Dictionary _openSolutionUis = new(); @@ -357,7 +358,8 @@ private void AddDebugVerbs(GetVerbsEvent args) var message = ExamineSystemShared.InRangeUnOccluded(args.User, args.Target) ? Loc.GetString("in-range-unoccluded-verb-on-activate-not-occluded") : Loc.GetString("in-range-unoccluded-verb-on-activate-occluded"); - args.Target.PopupMessage(args.User, message); + + _popup.PopupEntity(message, args.Target, args.User); } }; args.Verbs.Add(verb); diff --git a/Content.Server/Atmos/EntitySystems/FlammableSystem.cs b/Content.Server/Atmos/EntitySystems/FlammableSystem.cs index 2adec63db56..b2f62572bff 100644 --- a/Content.Server/Atmos/EntitySystems/FlammableSystem.cs +++ b/Content.Server/Atmos/EntitySystems/FlammableSystem.cs @@ -37,6 +37,7 @@ public sealed class FlammableSystem : EntitySystem [Dependency] private readonly EntityLookupSystem _lookup = default!; [Dependency] private readonly IAdminLogManager _adminLogger = default!; [Dependency] private readonly SharedAppearanceSystem _appearance = default!; + [Dependency] private readonly SharedPopupSystem _popup = default!; public const float MinimumFireStacks = -10f; public const float MaximumFireStacks = 20f; @@ -45,7 +46,7 @@ public sealed class FlammableSystem : EntitySystem public const float MinIgnitionTemperature = 373.15f; public const string FlammableFixtureID = "flammable"; - private float _timer = 0f; + private float _timer; private Dictionary _fireEvents = new(); @@ -191,8 +192,7 @@ private void OnTileFire(EntityUid uid, FlammableComponent flammable, ref TileFir { var tempDelta = args.Temperature - MinIgnitionTemperature; - var maxTemp = 0f; - _fireEvents.TryGetValue(flammable, out maxTemp); + _fireEvents.TryGetValue(flammable, out var maxTemp); if (tempDelta > maxTemp) _fireEvents[flammable] = tempDelta; @@ -233,7 +233,7 @@ public void Extinguish(EntityUid uid, FlammableComponent? flammable = null) if (!flammable.OnFire || !flammable.CanExtinguish) return; - _adminLogger.Add(LogType.Flammable, $"{ToPrettyString(flammable.Owner):entity} stopped being on fire damage"); + _adminLogger.Add(LogType.Flammable, $"{ToPrettyString(uid):entity} stopped being on fire damage"); flammable.OnFire = false; flammable.FireStacks = 0; @@ -271,16 +271,16 @@ public void Resist(EntityUid uid, if (!Resolve(uid, ref flammable)) return; - if (!flammable.OnFire || !_actionBlockerSystem.CanInteract(flammable.Owner, null) || flammable.Resisting) + if (!flammable.OnFire || !_actionBlockerSystem.CanInteract(uid, null) || flammable.Resisting) return; flammable.Resisting = true; - flammable.Owner.PopupMessage(Loc.GetString("flammable-component-resist-message")); + _popup.PopupEntity(Loc.GetString("flammable-component-resist-message"), uid, uid); _stunSystem.TryParalyze(uid, TimeSpan.FromSeconds(2f), true); // TODO FLAMMABLE: Make this not use TimerComponent... - flammable.Owner.SpawnTimer(2000, () => + uid.SpawnTimer(2000, () => { flammable.Resisting = false; flammable.FireStacks -= 1f; @@ -329,7 +329,7 @@ public override void Update(float frameTime) continue; } - _alertsSystem.ShowAlert(uid, AlertType.Fire, null, null); + _alertsSystem.ShowAlert(uid, AlertType.Fire); if (flammable.FireStacks > 0) { diff --git a/Content.Server/Atmos/Piping/Binary/EntitySystems/GasPressurePumpSystem.cs b/Content.Server/Atmos/Piping/Binary/EntitySystems/GasPressurePumpSystem.cs index e193de4b3db..e857b02b944 100644 --- a/Content.Server/Atmos/Piping/Binary/EntitySystems/GasPressurePumpSystem.cs +++ b/Content.Server/Atmos/Piping/Binary/EntitySystems/GasPressurePumpSystem.cs @@ -27,6 +27,7 @@ public sealed class GasPressurePumpSystem : EntitySystem [Dependency] private readonly SharedAmbientSoundSystem _ambientSoundSystem = default!; [Dependency] private readonly SharedAppearanceSystem _appearance = default!; [Dependency] private readonly NodeContainerSystem _nodeContainer = default!; + [Dependency] private readonly SharedPopupSystem _popup = default!; public override void Initialize() { @@ -49,14 +50,16 @@ private void OnInit(EntityUid uid, GasPressurePumpComponent pump, ComponentInit private void OnExamined(EntityUid uid, GasPressurePumpComponent pump, ExaminedEvent args) { - if (!EntityManager.GetComponent(pump.Owner).Anchored || !args.IsInDetailsRange) // Not anchored? Out of range? No status. + if (!EntityManager.GetComponent(uid).Anchored || !args.IsInDetailsRange) // Not anchored? Out of range? No status. return; if (Loc.TryGetString("gas-pressure-pump-system-examined", out var str, - ("statusColor", "lightblue"), // TODO: change with pressure? - ("pressure", pump.TargetPressure) - )) + ("statusColor", "lightblue"), // TODO: change with pressure? + ("pressure", pump.TargetPressure) + )) + { args.PushMarkup(str); + } } private void OnPumpUpdated(EntityUid uid, GasPressurePumpComponent pump, AtmosDeviceUpdateEvent args) @@ -66,7 +69,7 @@ private void OnPumpUpdated(EntityUid uid, GasPressurePumpComponent pump, AtmosDe || !_nodeContainer.TryGetNode(nodeContainer, pump.InletName, out PipeNode? inlet) || !_nodeContainer.TryGetNode(nodeContainer, pump.OutletName, out PipeNode? outlet)) { - _ambientSoundSystem.SetAmbience(pump.Owner, false); + _ambientSoundSystem.SetAmbience(uid, false); return; } @@ -74,7 +77,7 @@ private void OnPumpUpdated(EntityUid uid, GasPressurePumpComponent pump, AtmosDe if (outputStartingPressure >= pump.TargetPressure) { - _ambientSoundSystem.SetAmbience(pump.Owner, false); + _ambientSoundSystem.SetAmbience(uid, false); return; // No need to pump gas if target has been reached. } @@ -86,7 +89,7 @@ private void OnPumpUpdated(EntityUid uid, GasPressurePumpComponent pump, AtmosDe var removed = inlet.Air.Remove(transferMoles); _atmosphereSystem.Merge(outlet.Air, removed); - _ambientSoundSystem.SetAmbience(pump.Owner, removed.TotalMoles > 0f); + _ambientSoundSystem.SetAmbience(uid, removed.TotalMoles > 0f); } } @@ -104,14 +107,14 @@ private void OnPumpActivate(EntityUid uid, GasPressurePumpComponent pump, Activa if (!EntityManager.TryGetComponent(args.User, out ActorComponent? actor)) return; - if (EntityManager.GetComponent(pump.Owner).Anchored) + if (Transform(uid).Anchored) { _userInterfaceSystem.TryOpen(uid, GasPressurePumpUiKey.Key, actor.PlayerSession); DirtyUI(uid, pump); } else { - args.User.PopupMessageCursor(Loc.GetString("comp-gas-pump-ui-needs-anchor")); + _popup.PopupCursor(Loc.GetString("comp-gas-pump-ui-needs-anchor"), args.User); } args.Handled = true; @@ -141,7 +144,7 @@ private void DirtyUI(EntityUid uid, GasPressurePumpComponent? pump) return; _userInterfaceSystem.TrySetUiState(uid, GasPressurePumpUiKey.Key, - new GasPressurePumpBoundUserInterfaceState(EntityManager.GetComponent(pump.Owner).EntityName, pump.TargetPressure, pump.Enabled)); + new GasPressurePumpBoundUserInterfaceState(EntityManager.GetComponent(uid).EntityName, pump.TargetPressure, pump.Enabled)); } private void UpdateAppearance(EntityUid uid, GasPressurePumpComponent? pump = null, AppearanceComponent? appearance = null) diff --git a/Content.Server/Atmos/Piping/Binary/EntitySystems/GasVolumePumpSystem.cs b/Content.Server/Atmos/Piping/Binary/EntitySystems/GasVolumePumpSystem.cs index 5b8035681e0..19ad8175aad 100644 --- a/Content.Server/Atmos/Piping/Binary/EntitySystems/GasVolumePumpSystem.cs +++ b/Content.Server/Atmos/Piping/Binary/EntitySystems/GasVolumePumpSystem.cs @@ -9,9 +9,7 @@ using Content.Server.NodeContainer; using Content.Server.NodeContainer.EntitySystems; using Content.Server.NodeContainer.Nodes; -using Content.Shared.Atmos.Piping; using Content.Shared.Atmos.Piping.Binary.Components; -using Content.Shared.Atmos.Piping.Unary.Components; using Content.Shared.Atmos.Visuals; using Content.Shared.Audio; using Content.Shared.Database; @@ -34,6 +32,7 @@ public sealed class GasVolumePumpSystem : EntitySystem [Dependency] private readonly SharedAppearanceSystem _appearance = default!; [Dependency] private readonly NodeContainerSystem _nodeContainer = default!; [Dependency] private readonly DeviceNetworkSystem _deviceNetwork = default!; + [Dependency] private readonly SharedPopupSystem _popup = default!; public override void Initialize() @@ -59,7 +58,7 @@ private void OnInit(EntityUid uid, GasVolumePumpComponent pump, ComponentInit ar private void OnExamined(EntityUid uid, GasVolumePumpComponent pump, ExaminedEvent args) { - if (!EntityManager.GetComponent(pump.Owner).Anchored || !args.IsInDetailsRange) // Not anchored? Out of range? No status. + if (!EntityManager.GetComponent(uid).Anchored || !args.IsInDetailsRange) // Not anchored? Out of range? No status. return; if (Loc.TryGetString("gas-volume-pump-system-examined", out var str, @@ -98,14 +97,14 @@ private void OnVolumePumpUpdated(EntityUid uid, GasVolumePumpComponent pump, Atm { pump.Blocked = true; } - + if (previouslyBlocked != pump.Blocked) UpdateAppearance(uid, pump); if (pump.Blocked) return; // We multiply the transfer rate in L/s by the seconds passed since the last process to get the liters. - var removed = inlet.Air.RemoveVolume((float)(pump.TransferRate * args.dt)); + var removed = inlet.Air.RemoveVolume(pump.TransferRate * args.dt); // Some of the gas from the mixture leaks when overclocked. if (pump.Overclocked) @@ -141,14 +140,14 @@ private void OnPumpActivate(EntityUid uid, GasVolumePumpComponent pump, Activate if (!EntityManager.TryGetComponent(args.User, out ActorComponent? actor)) return; - if (EntityManager.GetComponent(pump.Owner).Anchored) + if (Transform(uid).Anchored) { _userInterfaceSystem.TryOpen(uid, GasVolumePumpUiKey.Key, actor.PlayerSession); DirtyUI(uid, pump); } else { - args.User.PopupMessageCursor(Loc.GetString("comp-gas-pump-ui-needs-anchor")); + _popup.PopupCursor(Loc.GetString("comp-gas-pump-ui-needs-anchor"), args.User); } args.Handled = true; @@ -177,7 +176,7 @@ private void DirtyUI(EntityUid uid, GasVolumePumpComponent? pump) return; _userInterfaceSystem.TrySetUiState(uid, GasVolumePumpUiKey.Key, - new GasVolumePumpBoundUserInterfaceState(EntityManager.GetComponent(pump.Owner).EntityName, pump.TransferRate, pump.Enabled)); + new GasVolumePumpBoundUserInterfaceState(Name(uid), pump.TransferRate, pump.Enabled)); } private void UpdateAppearance(EntityUid uid, GasVolumePumpComponent? pump = null, AppearanceComponent? appearance = null) diff --git a/Content.Server/Atmos/Piping/Trinary/EntitySystems/GasMixerSystem.cs b/Content.Server/Atmos/Piping/Trinary/EntitySystems/GasMixerSystem.cs index 0780ff035f1..ce2213d535b 100644 --- a/Content.Server/Atmos/Piping/Trinary/EntitySystems/GasMixerSystem.cs +++ b/Content.Server/Atmos/Piping/Trinary/EntitySystems/GasMixerSystem.cs @@ -26,6 +26,7 @@ public sealed class GasMixerSystem : EntitySystem [Dependency] private readonly SharedAmbientSoundSystem _ambientSoundSystem = default!; [Dependency] private readonly SharedAppearanceSystem _appearance = default!; [Dependency] private readonly NodeContainerSystem _nodeContainer = default!; + [Dependency] private readonly SharedPopupSystem _popup = default!; public override void Initialize() { @@ -54,7 +55,7 @@ private void OnMixerUpdated(EntityUid uid, GasMixerComponent mixer, AtmosDeviceU if (!mixer.Enabled) { - _ambientSoundSystem.SetAmbience(mixer.Owner, false); + _ambientSoundSystem.SetAmbience(uid, false); return; } @@ -65,7 +66,7 @@ private void OnMixerUpdated(EntityUid uid, GasMixerComponent mixer, AtmosDeviceU || !_nodeContainer.TryGetNode(nodeContainer, mixer.InletTwoName, out PipeNode? inletTwo) || !_nodeContainer.TryGetNode(nodeContainer, mixer.OutletName, out PipeNode? outlet)) { - _ambientSoundSystem.SetAmbience(mixer.Owner, false); + _ambientSoundSystem.SetAmbience(uid, false); return; } @@ -103,7 +104,7 @@ private void OnMixerUpdated(EntityUid uid, GasMixerComponent mixer, AtmosDeviceU if (transferMolesOne <= 0 || transferMolesTwo <= 0) { - _ambientSoundSystem.SetAmbience(mixer.Owner, false); + _ambientSoundSystem.SetAmbience(uid, false); return; } @@ -133,7 +134,7 @@ private void OnMixerUpdated(EntityUid uid, GasMixerComponent mixer, AtmosDeviceU } if (transferred) - _ambientSoundSystem.SetAmbience(mixer.Owner, true); + _ambientSoundSystem.SetAmbience(uid, true); } private void OnMixerLeaveAtmosphere(EntityUid uid, GasMixerComponent mixer, AtmosDeviceDisabledEvent args) @@ -150,14 +151,14 @@ private void OnMixerInteractHand(EntityUid uid, GasMixerComponent mixer, Interac if (!EntityManager.TryGetComponent(args.User, out ActorComponent? actor)) return; - if (EntityManager.GetComponent(mixer.Owner).Anchored) + if (Transform(uid).Anchored) { _userInterfaceSystem.TryOpen(uid, GasMixerUiKey.Key, actor.PlayerSession); DirtyUI(uid, mixer); } else { - args.User.PopupMessageCursor(Loc.GetString("comp-gas-mixer-ui-needs-anchor")); + _popup.PopupCursor(Loc.GetString("comp-gas-mixer-ui-needs-anchor"), args.User); } args.Handled = true; @@ -169,7 +170,7 @@ private void DirtyUI(EntityUid uid, GasMixerComponent? mixer) return; _userInterfaceSystem.TrySetUiState(uid, GasMixerUiKey.Key, - new GasMixerBoundUserInterfaceState(EntityManager.GetComponent(mixer.Owner).EntityName, mixer.TargetPressure, mixer.Enabled, mixer.InletOneConcentration)); + new GasMixerBoundUserInterfaceState(EntityManager.GetComponent(uid).EntityName, mixer.TargetPressure, mixer.Enabled, mixer.InletOneConcentration)); } private void UpdateAppearance(EntityUid uid, GasMixerComponent? mixer = null, AppearanceComponent? appearance = null) diff --git a/Content.Server/Botany/Systems/BotanySystem.Seed.cs b/Content.Server/Botany/Systems/BotanySystem.Seed.cs index 752d8e40043..02fb1060f31 100644 --- a/Content.Server/Botany/Systems/BotanySystem.Seed.cs +++ b/Content.Server/Botany/Systems/BotanySystem.Seed.cs @@ -9,6 +9,7 @@ using Content.Shared.Hands.EntitySystems; using Content.Shared.Physics; using Content.Shared.Popups; +using Content.Shared.Random; using Content.Shared.Random.Helpers; using Content.Shared.Slippery; using Content.Shared.StepTrigger.Components; @@ -34,6 +35,7 @@ public sealed partial class BotanySystem : EntitySystem [Dependency] private readonly MetaDataSystem _metaData = default!; [Dependency] private readonly FixtureSystem _fixtureSystem = default!; [Dependency] private readonly CollisionWakeSystem _colWakeSystem = default!; + [Dependency] private readonly RandomHelperSystem _randomHelper = default!; public override void Initialize() { @@ -160,7 +162,7 @@ public IEnumerable GenerateProduct(SeedData proto, EntityCoordinates var product = _robustRandom.Pick(proto.ProductPrototypes); var entity = Spawn(product, position); - entity.RandomOffset(0.25f); + _randomHelper.RandomOffset(entity, 0.25f); products.Add(entity); var produce = EnsureComp(entity); diff --git a/Content.Server/Botany/Systems/LogSystem.cs b/Content.Server/Botany/Systems/LogSystem.cs index e9ac926d8a5..b6cb0dedaf4 100644 --- a/Content.Server/Botany/Systems/LogSystem.cs +++ b/Content.Server/Botany/Systems/LogSystem.cs @@ -2,6 +2,7 @@ using Content.Server.Kitchen.Components; using Content.Shared.Hands.EntitySystems; using Content.Shared.Interaction; +using Content.Shared.Random; using Content.Shared.Random.Helpers; using Robust.Shared.Containers; @@ -11,6 +12,7 @@ public sealed class LogSystem : EntitySystem { [Dependency] private readonly SharedHandsSystem _handsSystem = default!; [Dependency] private readonly SharedContainerSystem _containerSystem = default!; + [Dependency] private readonly RandomHelperSystem _randomHelper = default!; public override void Initialize() { @@ -39,7 +41,7 @@ private void OnInteractUsing(EntityUid uid, LogComponent component, InteractUsin var xform = Transform(plank); _containerSystem.AttachParentToContainerOrGrid(xform); xform.LocalRotation = 0; - plank.RandomOffset(0.25f); + _randomHelper.RandomOffset(plank, 0.25f); } } diff --git a/Content.Server/Botany/Systems/PlantHolderSystem.cs b/Content.Server/Botany/Systems/PlantHolderSystem.cs index 506b88f78b8..c3d57c4ad85 100644 --- a/Content.Server/Botany/Systems/PlantHolderSystem.cs +++ b/Content.Server/Botany/Systems/PlantHolderSystem.cs @@ -15,7 +15,7 @@ using Content.Shared.IdentityManagement; using Content.Shared.Interaction; using Content.Shared.Popups; -using Content.Shared.Random.Helpers; +using Content.Shared.Random; using Content.Shared.Tag; using Robust.Server.GameObjects; using Robust.Shared.Audio; @@ -39,6 +39,7 @@ public sealed class PlantHolderSystem : EntitySystem [Dependency] private readonly SharedPointLightSystem _pointLight = default!; [Dependency] private readonly SolutionContainerSystem _solutionSystem = default!; [Dependency] private readonly TagSystem _tagSystem = default!; + [Dependency] private readonly RandomHelperSystem _randomHelper = default!; [Dependency] private readonly IRobustRandom _random = default!; @@ -253,7 +254,7 @@ private void OnInteractUsing(EntityUid uid, PlantHolderComponent component, Inte component.Seed.Unique = false; var seed = _botany.SpawnSeedPacket(component.Seed, Transform(args.User).Coordinates, args.User); - seed.RandomOffset(0.25f); + _randomHelper.RandomOffset(seed, 0.25f); var displayName = Loc.GetString(component.Seed.DisplayName); _popup.PopupCursor(Loc.GetString("plant-holder-component-take-sample-message", ("seedName", displayName)), args.User); diff --git a/Content.Server/Chat/Managers/ChatSanitizationManager.cs b/Content.Server/Chat/Managers/ChatSanitizationManager.cs index c21a2ab03c4..01c02a270a6 100644 --- a/Content.Server/Chat/Managers/ChatSanitizationManager.cs +++ b/Content.Server/Chat/Managers/ChatSanitizationManager.cs @@ -90,7 +90,8 @@ public sealed class ChatSanitizationManager : IChatSanitizationManager { "kek.", "chatsan-laughs" }, { "o7", "chatsan-salutes" }, { ";_;7", "chatsan-tearfully-salutes"}, - { "idk", "chatsan-shrugs" } + { "idk", "chatsan-shrugs" }, + { "idk.", "chatsan-shrugs" } }; private bool _doSanitize; diff --git a/Content.Server/Chat/SuicideSystem.cs b/Content.Server/Chat/SuicideSystem.cs index 2f6ac51d724..131d19c5235 100644 --- a/Content.Server/Chat/SuicideSystem.cs +++ b/Content.Server/Chat/SuicideSystem.cs @@ -10,6 +10,7 @@ using Content.Shared.Mobs.Systems; using Content.Shared.Popups; using Content.Shared.Tag; +using Robust.Shared.Player; using Robust.Shared.Prototypes; namespace Content.Server.Chat @@ -22,6 +23,7 @@ public sealed class SuicideSystem : EntitySystem [Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly TagSystem _tagSystem = default!; [Dependency] private readonly MobStateSystem _mobState = default!; + [Dependency] private readonly SharedPopupSystem _popup = default!; public bool Suicide(EntityUid victim) { @@ -67,10 +69,10 @@ private void DefaultSuicideHandler(EntityUid victim, SuicideEvent suicideEvent) return; var othersMessage = Loc.GetString("suicide-command-default-text-others", ("name", victim)); - victim.PopupMessageOtherClients(othersMessage); + _popup.PopupEntity(othersMessage, victim, Filter.PvsExcept(victim), true); var selfMessage = Loc.GetString("suicide-command-default-text-self"); - victim.PopupMessage(selfMessage); + _popup.PopupEntity(selfMessage, victim, victim); suicideEvent.SetHandled(SuicideKind.Bloodloss); } @@ -112,7 +114,7 @@ private bool EnvironmentSuicideHandler(EntityUid victim, SuicideEvent suicideEve if (itemQuery.HasComponent(entity)) continue; - RaiseLocalEvent(entity, suicideEvent, false); + RaiseLocalEvent(entity, suicideEvent); if (suicideEvent.Handled) return true; @@ -129,7 +131,7 @@ private void ApplyDeath(EntityUid target, SuicideKind kind) if (!_prototypeManager.TryIndex(kind.ToString(), out var damagePrototype)) { const SuicideKind fallback = SuicideKind.Blunt; - Logger.Error($"{nameof(SuicideSystem)} could not find the damage type prototype associated with {kind}. Falling back to {fallback}"); + Log.Error($"{nameof(SuicideSystem)} could not find the damage type prototype associated with {kind}. Falling back to {fallback}"); damagePrototype = _prototypeManager.Index(fallback.ToString()); } const int lethalAmountOfDamage = 200; // TODO: Would be nice to get this number from somewhere else diff --git a/Content.Server/Coordinates/SpawnRandomOffsetSystem.cs b/Content.Server/Coordinates/SpawnRandomOffsetSystem.cs index f664ec12255..5643681f4eb 100644 --- a/Content.Server/Coordinates/SpawnRandomOffsetSystem.cs +++ b/Content.Server/Coordinates/SpawnRandomOffsetSystem.cs @@ -1,9 +1,13 @@ +using Content.Shared.Random; using Content.Shared.Random.Helpers; +using Robust.Shared.Random; namespace Content.Server.Coordinates; public sealed class SpawnRandomOffsetSystem : EntitySystem { + [Dependency] private readonly RandomHelperSystem _randomHelper = default!; + public override void Initialize() { base.Initialize(); @@ -13,8 +17,7 @@ public override void Initialize() private void OnMapInit(EntityUid uid, SpawnRandomOffsetComponent component, MapInitEvent args) { - // TODO: Kill this extension with fire, thanks - uid.RandomOffset(component.Offset); + _randomHelper.RandomOffset(uid, component.Offset); EntityManager.RemoveComponentDeferred(uid, component); } } diff --git a/Content.Server/Fluids/EntitySystems/AbsorbentSystem.cs b/Content.Server/Fluids/EntitySystems/AbsorbentSystem.cs index bf54a18f1af..facc39f1461 100644 --- a/Content.Server/Fluids/EntitySystems/AbsorbentSystem.cs +++ b/Content.Server/Fluids/EntitySystems/AbsorbentSystem.cs @@ -207,9 +207,6 @@ private bool TryTransferAbsorber(EntityUid user, EntityUid used, EntityUid targe _audio.PlayPvs(component.TransferSound, target); _useDelay.BeginDelay(used); return true; - _audio.PlayPvs(component.TransferSound, target); - _useDelay.BeginDelay(used); - return true; } /// @@ -259,7 +256,7 @@ private bool TryPuddleInteract(EntityUid user, EntityUid used, EntityUid target, var localPos = _transform.GetInvWorldMatrix(userXform).Transform(targetPos); localPos = userXform.LocalRotation.RotateVec(localPos); - _melee.DoLunge(user, Angle.Zero, localPos, null, false); + _melee.DoLunge(user, used, Angle.Zero, localPos, null, false); return true; } diff --git a/Content.Server/GameTicking/Rules/DeathMatchRuleSystem.cs b/Content.Server/GameTicking/Rules/DeathMatchRuleSystem.cs index 042455e75df..82ac755592e 100644 --- a/Content.Server/GameTicking/Rules/DeathMatchRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/DeathMatchRuleSystem.cs @@ -1,3 +1,4 @@ +using System.Linq; using Content.Server.Administration.Commands; using Content.Server.GameTicking.Rules.Components; using Content.Server.KillTracking; @@ -95,7 +96,7 @@ private void OnKillReported(ref KillReportedEvent ev) if (ev.Assist is KillPlayerSource assist && dm.Victor == null) _point.AdjustPointValue(assist.PlayerId, 1, uid, point); - var spawns = EntitySpawnCollection.GetSpawns(dm.RewardSpawns); + var spawns = EntitySpawnCollection.GetSpawns(dm.RewardSpawns).Cast().ToList(); EntityManager.SpawnEntities(Transform(ev.Entity).MapPosition, spawns); } } diff --git a/Content.Server/GameTicking/Rules/GameRuleSystem.cs b/Content.Server/GameTicking/Rules/GameRuleSystem.cs index b13f00f3638..ba781e32e29 100644 --- a/Content.Server/GameTicking/Rules/GameRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/GameRuleSystem.cs @@ -3,7 +3,7 @@ namespace Content.Server.GameTicking.Rules; -public abstract partial class GameRuleSystem : EntitySystem where T : Component +public abstract partial class GameRuleSystem : EntitySystem where T : IComponent { [Dependency] protected readonly IChatManager ChatManager = default!; [Dependency] protected readonly GameTicker GameTicker = default!; diff --git a/Content.Server/Gatherable/GatherableSystem.cs b/Content.Server/Gatherable/GatherableSystem.cs index 5eaff020d5e..4f7d19b0a8b 100644 --- a/Content.Server/Gatherable/GatherableSystem.cs +++ b/Content.Server/Gatherable/GatherableSystem.cs @@ -70,7 +70,7 @@ public void Gather(EntityUid gatheredUid, EntityUid? gatherer = null, Gatherable continue; } var getLoot = _prototypeManager.Index(table); - var spawnLoot = getLoot.GetSpawns(); + var spawnLoot = getLoot.GetSpawns(_random); var spawnPos = pos.Offset(_random.NextVector2(0.3f)); Spawn(spawnLoot[0], spawnPos); } diff --git a/Content.Server/Ghost/GhostSystem.cs b/Content.Server/Ghost/GhostSystem.cs index 78818039017..064e25957a1 100644 --- a/Content.Server/Ghost/GhostSystem.cs +++ b/Content.Server/Ghost/GhostSystem.cs @@ -297,8 +297,7 @@ private IEnumerable GetLocationWarps() while (allQuery.MoveNext(out var uid, out var warp)) { - if (warp.Location != null) - yield return new GhostWarp(GetNetEntity(uid), warp.Location, true); + yield return new GhostWarp(GetNetEntity(uid), warp.Location ?? Name(uid), true); } } diff --git a/Content.Server/IdentityManagement/IdentitySystem.cs b/Content.Server/IdentityManagement/IdentitySystem.cs index 6be3a964335..3d4be31435e 100644 --- a/Content.Server/IdentityManagement/IdentitySystem.cs +++ b/Content.Server/IdentityManagement/IdentitySystem.cs @@ -35,6 +35,7 @@ public override void Initialize() SubscribeLocalEvent((uid, _, _) => QueueIdentityUpdate(uid)); SubscribeLocalEvent((uid, _, _) => QueueIdentityUpdate(uid)); SubscribeLocalEvent((uid, _, _) => QueueIdentityUpdate(uid)); + SubscribeLocalEvent(OnMapInit); } public override void Update(float frameTime) @@ -53,10 +54,8 @@ public override void Update(float frameTime) } // This is where the magic happens - protected override void OnComponentInit(EntityUid uid, IdentityComponent component, ComponentInit args) + private void OnMapInit(EntityUid uid, IdentityComponent component, MapInitEvent args) { - base.OnComponentInit(uid, component, args); - var ident = Spawn(null, Transform(uid).Coordinates); QueueIdentityUpdate(uid); diff --git a/Content.Server/Kitchen/EntitySystems/KitchenSpikeSystem.cs b/Content.Server/Kitchen/EntitySystems/KitchenSpikeSystem.cs index 04a224a3a74..6e563ff45fd 100644 --- a/Content.Server/Kitchen/EntitySystems/KitchenSpikeSystem.cs +++ b/Content.Server/Kitchen/EntitySystems/KitchenSpikeSystem.cs @@ -110,7 +110,8 @@ private void OnInteractHand(EntityUid uid, KitchenSpikeComponent component, Inte if (args.Handled) return; - if (component.PrototypesToSpawn?.Count > 0) { + if (component.PrototypesToSpawn?.Count > 0) + { _popupSystem.PopupEntity(Loc.GetString("comp-kitchen-spike-knife-needed"), uid, args.User); args.Handled = true; } diff --git a/Content.Server/Kitchen/EntitySystems/ReagentGrinderSystem.cs b/Content.Server/Kitchen/EntitySystems/ReagentGrinderSystem.cs index 2f34b4285d1..d50ce8df1fd 100644 --- a/Content.Server/Kitchen/EntitySystems/ReagentGrinderSystem.cs +++ b/Content.Server/Kitchen/EntitySystems/ReagentGrinderSystem.cs @@ -11,6 +11,7 @@ using Content.Shared.Interaction; using Content.Shared.Kitchen; using Content.Shared.Popups; +using Content.Shared.Random; using Content.Shared.Random.Helpers; using Content.Shared.Stacks; using JetBrains.Annotations; @@ -33,6 +34,7 @@ internal sealed class ReagentGrinderSystem : EntitySystem [Dependency] private readonly SharedAudioSystem _audioSystem = default!; [Dependency] private readonly SharedAppearanceSystem _appearanceSystem = default!; [Dependency] private readonly SharedContainerSystem _containerSystem = default!; + [Dependency] private readonly RandomHelperSystem _randomHelper = default!; public override void Initialize() { @@ -230,7 +232,7 @@ private void OnEjectChamberAllMessage(EntityUid uid, ReagentGrinderComponent rea foreach (var entity in inputContainer.ContainedEntities.ToList()) { inputContainer.Remove(entity); - entity.RandomOffset(0.4f); + _randomHelper.RandomOffset(entity, 0.4f); } UpdateUiState(uid); } @@ -245,7 +247,7 @@ private void OnEjectChamberContentMessage(EntityUid uid, ReagentGrinderComponent if (inputContainer.Remove(ent)) { - ent.RandomOffset(0.4f); + _randomHelper.RandomOffset(ent, 0.4f); ClickSound(uid, reagentGrinder); UpdateUiState(uid); } diff --git a/Content.Server/Materials/MaterialReclaimerSystem.cs b/Content.Server/Materials/MaterialReclaimerSystem.cs index ce1f285fcf6..2f8b43e8328 100644 --- a/Content.Server/Materials/MaterialReclaimerSystem.cs +++ b/Content.Server/Materials/MaterialReclaimerSystem.cs @@ -166,13 +166,17 @@ public override void Reclaim(EntityUid uid, var xform = Transform(uid); SpawnMaterialsFromComposition(uid, item, completion * component.Efficiency, xform: xform); - SpawnChemicalsFromComposition(uid, item, completion, component, xform); if (CanGib(uid, item, component)) { + SpawnChemicalsFromComposition(uid, item, completion, false, component, xform); _body.GibBody(item, true); _appearance.SetData(uid, RecyclerVisuals.Bloody, true); } + else + { + SpawnChemicalsFromComposition(uid, item, completion, true, component, xform); + } QueueDel(item); } @@ -213,6 +217,7 @@ private void SpawnMaterialsFromComposition(EntityUid reclaimer, private void SpawnChemicalsFromComposition(EntityUid reclaimer, EntityUid item, float efficiency, + bool sound = true, MaterialReclaimerComponent? reclaimerComponent = null, TransformComponent? xform = null, PhysicalCompositionComponent? composition = null) @@ -248,7 +253,7 @@ private void SpawnChemicalsFromComposition(EntityUid reclaimer, _solutionContainer.TryTransferSolution(reclaimer, reclaimerComponent.OutputSolution, totalChemicals, totalChemicals.Volume); if (totalChemicals.Volume > 0) { - _puddle.TrySpillAt(reclaimer, totalChemicals, out _, transformComponent: xform); + _puddle.TrySpillAt(reclaimer, totalChemicals, out _, sound, transformComponent: xform); } } } diff --git a/Content.Server/Ninja/Systems/SpaceNinjaSystem.cs b/Content.Server/Ninja/Systems/SpaceNinjaSystem.cs index 8f19850c70c..6de2d7dee00 100644 --- a/Content.Server/Ninja/Systems/SpaceNinjaSystem.cs +++ b/Content.Server/Ninja/Systems/SpaceNinjaSystem.cs @@ -170,12 +170,10 @@ private void OnNinjaCreated(EntityUid uid, SpaceNinjaComponent comp, ref Generic // choose spider charge detonation point var warps = new List(); - var query = EntityQueryEnumerator(); - var map = Transform(uid).MapID; - while (query.MoveNext(out var warpUid, out _, out var warp, out var xform)) + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var warpUid, out _, out var warp)) { - if (warp.Location != null) - warps.Add(warpUid); + warps.Add(warpUid); } if (warps.Count > 0) diff --git a/Content.Server/Objectives/Systems/NinjaConditionsSystem.cs b/Content.Server/Objectives/Systems/NinjaConditionsSystem.cs index eaf97e97e01..24eeb0542ec 100644 --- a/Content.Server/Objectives/Systems/NinjaConditionsSystem.cs +++ b/Content.Server/Objectives/Systems/NinjaConditionsSystem.cs @@ -58,14 +58,13 @@ private string SpiderChargeTitle(EntityUid mindId) { if (!TryComp(mindId, out var role) || role.SpiderChargeTarget == null || - !TryComp(role.SpiderChargeTarget, out var warp) || - warp.Location == null) + !TryComp(role.SpiderChargeTarget, out var warp)) { // this should never really happen but eh return Loc.GetString("objective-condition-spider-charge-title-no-target"); } - return Loc.GetString("objective-condition-spider-charge-title", ("location", warp.Location)); + return Loc.GetString("objective-condition-spider-charge-title", ("location", warp.Location ?? Name(role.SpiderChargeTarget.Value))); } // steal research diff --git a/Content.Server/ParticleAccelerator/EntitySystems/ParticleAcceleratorSystem.Emitter.cs b/Content.Server/ParticleAccelerator/EntitySystems/ParticleAcceleratorSystem.Emitter.cs index dbe55bb6e5c..7fad69e349f 100644 --- a/Content.Server/ParticleAccelerator/EntitySystems/ParticleAcceleratorSystem.Emitter.cs +++ b/Content.Server/ParticleAccelerator/EntitySystems/ParticleAcceleratorSystem.Emitter.cs @@ -38,7 +38,7 @@ private void FireEmitter(EntityUid uid, ParticleAcceleratorPowerState strength, } if (TryComp(emitted, out var proj)) - _projectileSystem.SetShooter(proj, uid); + _projectileSystem.SetShooter(emitted, proj, uid); if (TryComp(emitted, out var food)) { diff --git a/Content.Server/ParticleAccelerator/EntitySystems/ParticleAcceleratorSystem.Parts.cs b/Content.Server/ParticleAccelerator/EntitySystems/ParticleAcceleratorSystem.Parts.cs index 860fbdcefe3..271d17a0c49 100644 --- a/Content.Server/ParticleAccelerator/EntitySystems/ParticleAcceleratorSystem.Parts.cs +++ b/Content.Server/ParticleAccelerator/EntitySystems/ParticleAcceleratorSystem.Parts.cs @@ -1,10 +1,10 @@ +using System.Diagnostics.CodeAnalysis; +using System.Numerics; using Content.Server.ParticleAccelerator.Components; using JetBrains.Annotations; using Robust.Server.Player; using Robust.Shared.Map.Components; using Robust.Shared.Physics.Events; -using System.Diagnostics.CodeAnalysis; -using System.Numerics; namespace Content.Server.ParticleAccelerator.EntitySystems; @@ -127,12 +127,12 @@ public void RescanParts(EntityUid uid, IPlayerSession? user = null, ParticleAcce } private bool ScanPart(EntityUid uid, Vector2i coordinates, Angle? rotation, [NotNullWhen(true)] out EntityUid? part, [NotNullWhen(true)] out T? comp, MapGridComponent? grid = null) - where T : Component + where T : IComponent { if (!Resolve(uid, ref grid)) { part = null; - comp = null; + comp = default; return false; } @@ -149,7 +149,7 @@ private bool ScanPart(EntityUid uid, Vector2i coordinates, Angle? rotation, [ } part = null; - comp = null; + comp = default; return false; } diff --git a/Content.Server/Popups/PopupExtensions.cs b/Content.Server/Popups/PopupExtensions.cs deleted file mode 100644 index 1419ef46fcf..00000000000 --- a/Content.Server/Popups/PopupExtensions.cs +++ /dev/null @@ -1,53 +0,0 @@ -using Content.Shared.Popups; -using Robust.Server.Player; -using Robust.Shared.Player; - -namespace Content.Server.Popups -{ - public static class PopupExtensions - { - /// - /// Pops up a message for every player around to see, - /// except for itself. - /// - /// The entity on which to popup the message. - /// The message to show. - [Obsolete("Use PopupSystem.PopupEntity instead")] - public static void PopupMessageOtherClients(this EntityUid source, string message) - { - var viewers = Filter.Empty() - .AddPlayersByPvs(source) - .Recipients; - - foreach (var viewer in viewers) - { - if (viewer.AttachedEntity is not {Valid: true} viewerEntity || source == viewerEntity || viewer.AttachedEntity == null) - { - continue; - } - - source.PopupMessage(viewerEntity, message); - } - } - - /// - /// Pops up a message at the given entity's location for everyone, - /// including itself, to see. - /// - /// The entity above which to show the message. - /// The message to be seen. - /// - /// The instance of player manager to use, will be resolved automatically - /// if null. - /// - /// - /// The range in which to search for players, defaulting to one screen. - /// - [Obsolete("Use PopupSystem.PopupEntity instead")] - public static void PopupMessageEveryone(this EntityUid source, string message, IPlayerManager? playerManager = null, int range = 15) - { - source.PopupMessage(message); - source.PopupMessageOtherClients(message); - } - } -} diff --git a/Content.Server/Popups/PopupMsgCommand.cs b/Content.Server/Popups/PopupMsgCommand.cs deleted file mode 100644 index 8e4294c7fd3..00000000000 --- a/Content.Server/Popups/PopupMsgCommand.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Content.Server.Administration; -using Content.Shared.Administration; -using Content.Shared.Popups; -using Robust.Shared.Console; - -namespace Content.Server.Popups -{ - [AdminCommand(AdminFlags.Debug)] - public sealed class PopupMsgCommand : IConsoleCommand - { - public string Command => "srvpopupmsg"; - public string Description => ""; - public string Help => ""; - - public void Execute(IConsoleShell shell, string argStr, string[] args) - { - var source = EntityUid.Parse(args[0]); - var viewer = EntityUid.Parse(args[1]); - var msg = args[2]; - - source.PopupMessage(viewer, msg); - } - } -} diff --git a/Content.Server/Popups/PopupSystem.cs b/Content.Server/Popups/PopupSystem.cs index 407d2c49aa4..483d4f3d3f7 100644 --- a/Content.Server/Popups/PopupSystem.cs +++ b/Content.Server/Popups/PopupSystem.cs @@ -12,6 +12,7 @@ public sealed class PopupSystem : SharedPopupSystem { [Dependency] private readonly IPlayerManager _player = default!; [Dependency] private readonly IConfigurationManager _cfg = default!; + [Dependency] private readonly TransformSystem _xform = default!; public override void PopupCursor(string message, PopupType type = PopupType.Small) { @@ -36,7 +37,7 @@ public override void PopupCoordinates(string message, EntityCoordinates coordina public override void PopupCoordinates(string message, EntityCoordinates coordinates, PopupType type = PopupType.Small) { - var mapPos = coordinates.ToMap(EntityManager); + var mapPos = coordinates.ToMap(EntityManager, _xform); var filter = Filter.Empty().AddPlayersByPvs(mapPos, entManager: EntityManager, playerMan: _player, cfgMan: _cfg); RaiseNetworkEvent(new PopupCoordinatesEvent(message, type, GetNetCoordinates(coordinates)), filter); } diff --git a/Content.Server/Power/Components/ApcPowerReceiverComponent.cs b/Content.Server/Power/Components/ApcPowerReceiverComponent.cs index ae4d7394304..b8340d0be4b 100644 --- a/Content.Server/Power/Components/ApcPowerReceiverComponent.cs +++ b/Content.Server/Power/Components/ApcPowerReceiverComponent.cs @@ -59,13 +59,6 @@ public bool PowerDisabled { }; public float PowerReceived => NetworkLoad.ReceivingPower; - - protected override void OnRemove() - { - Provider?.RemoveReceiver(this); - - base.OnRemove(); - } } /// diff --git a/Content.Server/Power/Components/BaseNetConnectorComponent.cs b/Content.Server/Power/Components/BaseNetConnectorComponent.cs index 551b5f3621f..f2a1372dbc9 100644 --- a/Content.Server/Power/Components/BaseNetConnectorComponent.cs +++ b/Content.Server/Power/Components/BaseNetConnectorComponent.cs @@ -33,12 +33,6 @@ public abstract partial class BaseNetConnectorComponent : Component, I [DataField("node")] public string? NodeId { get; set; } - protected override void OnRemove() - { - ClearNet(); - base.OnRemove(); - } - public void TryFindAndSetNet() { if (TryFindNet(out var net)) diff --git a/Content.Server/Power/EntitySystems/PowerNetConnectorSystem.cs b/Content.Server/Power/EntitySystems/PowerNetConnectorSystem.cs index df38c2f17a2..8738f493ac7 100644 --- a/Content.Server/Power/EntitySystems/PowerNetConnectorSystem.cs +++ b/Content.Server/Power/EntitySystems/PowerNetConnectorSystem.cs @@ -12,6 +12,21 @@ public override void Initialize() SubscribeLocalEvent(OnApcPowerProviderInit); SubscribeLocalEvent(OnBatteryChargerInit); SubscribeLocalEvent(OnBatteryDischargerInit); + + // TODO please end my life + SubscribeLocalEvent(OnRemove); + SubscribeLocalEvent(OnRemove); + SubscribeLocalEvent(OnRemove); + SubscribeLocalEvent(OnRemove); + SubscribeLocalEvent(OnRemove); + SubscribeLocalEvent(OnRemove); + } + + private void OnRemove(EntityUid uid, TComp component, ComponentRemove args) + where TComp : BaseNetConnectorComponent + where TNet : class + { + component.ClearNet(); } private void OnPowerSupplierInit(EntityUid uid, PowerSupplierComponent component, ComponentInit args) diff --git a/Content.Server/Power/EntitySystems/PowerNetSystem.cs b/Content.Server/Power/EntitySystems/PowerNetSystem.cs index a3aa1caee2e..425f4637aff 100644 --- a/Content.Server/Power/EntitySystems/PowerNetSystem.cs +++ b/Content.Server/Power/EntitySystems/PowerNetSystem.cs @@ -3,8 +3,8 @@ using Content.Server.Power.Components; using Content.Server.Power.NodeGroups; using Content.Server.Power.Pow3r; -using JetBrains.Annotations; using Content.Shared.Power; +using JetBrains.Annotations; using Robust.Server.GameObjects; using Robust.Shared.Threading; @@ -34,6 +34,7 @@ public override void Initialize() SubscribeLocalEvent(ApcPowerReceiverInit); SubscribeLocalEvent(ApcPowerReceiverShutdown); + SubscribeLocalEvent(ApcPowerReceiverRemove); SubscribeLocalEvent(ApcPowerReceiverPaused); SubscribeLocalEvent(ApcPowerReceiverUnpaused); @@ -64,6 +65,11 @@ private void ApcPowerReceiverShutdown(EntityUid uid, ApcPowerReceiverComponent c _powerState.Loads.Free(component.NetworkLoad.Id); } + private void ApcPowerReceiverRemove(EntityUid uid, ApcPowerReceiverComponent component, ComponentRemove args) + { + component.Provider?.RemoveReceiver(component); + } + private static void ApcPowerReceiverPaused( EntityUid uid, ApcPowerReceiverComponent component, diff --git a/Content.Server/Projectiles/ProjectileSystem.cs b/Content.Server/Projectiles/ProjectileSystem.cs index c52e712e741..b8a6b8c5b26 100644 --- a/Content.Server/Projectiles/ProjectileSystem.cs +++ b/Content.Server/Projectiles/ProjectileSystem.cs @@ -4,11 +4,10 @@ using Content.Shared.Camera; using Content.Shared.Damage; using Content.Shared.Database; -using Content.Shared.FixedPoint; using Content.Shared.Projectiles; using Robust.Server.GameObjects; -using Robust.Shared.Player; using Robust.Shared.Physics.Events; +using Robust.Shared.Player; namespace Content.Server.Projectiles; @@ -39,7 +38,7 @@ private void OnStartCollide(EntityUid uid, ProjectileComponent component, ref St RaiseLocalEvent(target, ref attemptEv); if (attemptEv.Cancelled) { - SetShooter(component, target); + SetShooter(uid, component, target); return; } diff --git a/Content.Server/Repairable/RepairableSystem.cs b/Content.Server/Repairable/RepairableSystem.cs index 8d9833a66f4..486ac756e3a 100644 --- a/Content.Server/Repairable/RepairableSystem.cs +++ b/Content.Server/Repairable/RepairableSystem.cs @@ -1,12 +1,10 @@ using Content.Server.Administration.Logs; using Content.Shared.Damage; using Content.Shared.Database; -using Content.Shared.DoAfter; using Content.Shared.Interaction; using Content.Shared.Popups; using Content.Shared.Repairable; using Content.Shared.Tools; -using Content.Shared.Tools.Components; namespace Content.Server.Repairable { @@ -14,6 +12,7 @@ public sealed class RepairableSystem : SharedRepairableSystem { [Dependency] private readonly SharedToolSystem _toolSystem = default!; [Dependency] private readonly DamageableSystem _damageableSystem = default!; + [Dependency] private readonly SharedPopupSystem _popup = default!; [Dependency] private readonly IAdminLogManager _adminLogger= default!; public override void Initialize() @@ -33,7 +32,7 @@ private void OnRepairFinished(EntityUid uid, RepairableComponent component, Repa if (component.Damage != null) { var damageChanged = _damageableSystem.TryChangeDamage(uid, component.Damage, true, false, origin: args.User); - _adminLogger.Add(LogType.Healed, $"{ToPrettyString(args.User):user} repaired {ToPrettyString(uid):target} by {damageChanged?.Total}"); + _adminLogger.Add(LogType.Healed, $"{ToPrettyString(args.User):user} repaired {ToPrettyString(uid):target} by {damageChanged?.GetTotal()}"); } else @@ -43,10 +42,10 @@ private void OnRepairFinished(EntityUid uid, RepairableComponent component, Repa _adminLogger.Add(LogType.Healed, $"{ToPrettyString(args.User):user} repaired {ToPrettyString(uid):target} back to full health"); } - uid.PopupMessage(args.User, - Loc.GetString("comp-repairable-repair", - ("target", uid), - ("tool", args.Used!))); + var str = Loc.GetString("comp-repairable-repair", + ("target", uid), + ("tool", args.Used!)); + _popup.PopupEntity(str, uid, args.User); } public async void Repair(EntityUid uid, RepairableComponent component, InteractUsingEvent args) diff --git a/Content.Server/Research/TechnologyDisk/Systems/TechnologyDiskSystem.cs b/Content.Server/Research/TechnologyDisk/Systems/TechnologyDiskSystem.cs index d886493e3f3..176b2b68bc9 100644 --- a/Content.Server/Research/TechnologyDisk/Systems/TechnologyDiskSystem.cs +++ b/Content.Server/Research/TechnologyDisk/Systems/TechnologyDiskSystem.cs @@ -72,7 +72,7 @@ private void OnMapInit(EntityUid uid, TechnologyDiskComponent component, MapInit var tier = int.Parse(weightedRandom.Pick(_random)); //get a list of every distinct recipe in all the technologies. - var techs = new List(); + var techs = new List>(); foreach (var tech in _prototype.EnumeratePrototypes()) { if (tech.Tier != tier) diff --git a/Content.Server/Singularity/EntitySystems/EmitterSystem.cs b/Content.Server/Singularity/EntitySystems/EmitterSystem.cs index e737cd0a8d7..652ca236e44 100644 --- a/Content.Server/Singularity/EntitySystems/EmitterSystem.cs +++ b/Content.Server/Singularity/EntitySystems/EmitterSystem.cs @@ -291,7 +291,7 @@ private void Fire(EntityUid uid, EmitterComponent component) var xform = Transform(uid); var ent = Spawn(component.BoltType, xform.Coordinates); var proj = EnsureComp(ent); - _projectile.SetShooter(proj, uid); + _projectile.SetShooter(ent, proj, uid); var targetPos = new EntityCoordinates(uid, new Vector2(0, -1)); diff --git a/Content.Server/StationEvents/Events/StationEventSystem.cs b/Content.Server/StationEvents/Events/StationEventSystem.cs index c647c965064..41a7b153f58 100644 --- a/Content.Server/StationEvents/Events/StationEventSystem.cs +++ b/Content.Server/StationEvents/Events/StationEventSystem.cs @@ -1,5 +1,4 @@ using System.Diagnostics.CodeAnalysis; -using System.Linq; using Content.Server.Administration.Logs; using Content.Server.Atmos.EntitySystems; using Content.Server.Chat.Systems; @@ -22,7 +21,7 @@ namespace Content.Server.StationEvents.Events; /// /// An abstract entity system inherited by all station events for their behavior. /// -public abstract partial class StationEventSystem : GameRuleSystem where T : Component +public abstract partial class StationEventSystem : GameRuleSystem where T : IComponent { [Dependency] protected readonly IAdminLogManager AdminLogManager = default!; [Dependency] private readonly IGameTiming _timing = default!; @@ -136,12 +135,7 @@ protected void ForceEndSelf(EntityUid uid, GameRuleComponent? component = null) protected bool TryGetRandomStation([NotNullWhen(true)] out EntityUid? station, Func? filter = null) { - var stations = new ValueList(); - - if (filter == null) - { - stations.EnsureCapacity(Count()); - } + var stations = new ValueList(Count()); filter ??= _ => true; var query = AllEntityQuery(); diff --git a/Content.Server/Storage/EntitySystems/StorageSystem.Fill.cs b/Content.Server/Storage/EntitySystems/StorageSystem.Fill.cs index e05a8f49ff0..902ab471f18 100644 --- a/Content.Server/Storage/EntitySystems/StorageSystem.Fill.cs +++ b/Content.Server/Storage/EntitySystems/StorageSystem.Fill.cs @@ -1,6 +1,10 @@ +using Content.Server.Spawners.Components; using Content.Server.Storage.Components; +using Content.Shared.Prototypes; using Content.Shared.Storage; using Content.Shared.Storage.Components; +using Robust.Shared.Prototypes; +using Robust.Shared.Utility; namespace Content.Server.Storage.EntitySystems; @@ -25,10 +29,13 @@ private void OnStorageFillMapInit(EntityUid uid, StorageFillComponent component, var spawnItems = EntitySpawnCollection.GetSpawns(component.Contents, Random); foreach (var item in spawnItems) { + // No, you are not allowed to fill a container with entity spawners. + DebugTools.Assert(!_prototype.Index(item) + .HasComponent(typeof(RandomSpawnerComponent))); var ent = EntityManager.SpawnEntity(item, coordinates); // handle depending on storage component, again this should be unified after ECS - if (entityStorageComp != null && EntityStorage.Insert(ent, uid)) + if (entityStorageComp != null && EntityStorage.Insert(ent, uid, entityStorageComp)) continue; if (storageComp != null && Insert(uid, ent, out _, storageComp: storageComp, playSound: false)) diff --git a/Content.Server/Storage/EntitySystems/StorageSystem.cs b/Content.Server/Storage/EntitySystems/StorageSystem.cs index b2d940ffe1c..3430449957e 100644 --- a/Content.Server/Storage/EntitySystems/StorageSystem.cs +++ b/Content.Server/Storage/EntitySystems/StorageSystem.cs @@ -12,7 +12,7 @@ using Robust.Server.Player; using Robust.Shared.Map; using Robust.Shared.Player; -using Robust.Shared.Players; +using Robust.Shared.Prototypes; using Robust.Shared.Utility; namespace Content.Server.Storage.EntitySystems; @@ -20,6 +20,7 @@ namespace Content.Server.Storage.EntitySystems; public sealed partial class StorageSystem : SharedStorageSystem { [Dependency] private readonly IAdminManager _admin = default!; + [Dependency] private readonly IPrototypeManager _prototype = default!; [Dependency] private readonly UserInterfaceSystem _uiSystem = default!; public override void Initialize() diff --git a/Content.Server/Stunnable/Systems/StunbatonSystem.cs b/Content.Server/Stunnable/Systems/StunbatonSystem.cs index 7a801765d85..f4a7448fa24 100644 --- a/Content.Server/Stunnable/Systems/StunbatonSystem.cs +++ b/Content.Server/Stunnable/Systems/StunbatonSystem.cs @@ -11,6 +11,7 @@ using Content.Shared.Popups; using Content.Shared.Stunnable; using Content.Shared.Toggleable; +using Robust.Server.GameObjects; using Robust.Shared.Audio; using Robust.Shared.Player; @@ -21,6 +22,9 @@ public sealed class StunbatonSystem : SharedStunbatonSystem [Dependency] private readonly SharedItemSystem _item = default!; [Dependency] private readonly SharedAppearanceSystem _appearance = default!; [Dependency] private readonly RiggableSystem _riggableSystem = default!; + [Dependency] private readonly SharedPopupSystem _popup = default!; + [Dependency] private readonly BatterySystem _battery = default!; + [Dependency] private readonly AudioSystem _audio = default!; public override void Initialize() { @@ -35,7 +39,7 @@ public override void Initialize() private void OnStaminaHitAttempt(EntityUid uid, StunbatonComponent component, ref StaminaDamageOnHitAttemptEvent args) { if (!component.Activated || - !TryComp(uid, out var battery) || !battery.TryUseCharge(component.EnergyPerUse)) + !TryComp(uid, out var battery) || !_battery.TryUseCharge(uid, component.EnergyPerUse, battery)) { args.Cancelled = true; return; @@ -43,7 +47,7 @@ private void OnStaminaHitAttempt(EntityUid uid, StunbatonComponent component, re if (battery.CurrentCharge < component.EnergyPerUse) { - SoundSystem.Play(component.SparksSound.GetSound(), Filter.Pvs(component.Owner, entityManager: EntityManager), uid, AudioHelpers.WithVariation(0.25f)); + _audio.PlayPvs(component.SparksSound, uid, AudioHelpers.WithVariation(0.25f)); TurnOff(uid, component); } } @@ -66,9 +70,11 @@ private void OnExamined(EntityUid uid, StunbatonComponent comp, ExaminedEvent ar ? Loc.GetString("comp-stunbaton-examined-on") : Loc.GetString("comp-stunbaton-examined-off"); args.PushMarkup(msg); - if(TryComp(uid, out var battery)) + if (TryComp(uid, out var battery)) + { args.PushMarkup(Loc.GetString("stunbaton-component-on-examine-charge", ("charge", (int)((battery.CurrentCharge/battery.MaxCharge) * 100)))); + } } private void TurnOff(EntityUid uid, StunbatonComponent comp) @@ -76,17 +82,17 @@ private void TurnOff(EntityUid uid, StunbatonComponent comp) if (!comp.Activated) return; - if (TryComp(comp.Owner, out var appearance) && - TryComp(comp.Owner, out var item)) + if (TryComp(uid, out var appearance) && + TryComp(uid, out var item)) { - _item.SetHeldPrefix(comp.Owner, "off", item); + _item.SetHeldPrefix(uid, "off", item); _appearance.SetData(uid, ToggleVisuals.Toggled, false, appearance); } - SoundSystem.Play(comp.SparksSound.GetSound(), Filter.Pvs(comp.Owner), comp.Owner, AudioHelpers.WithVariation(0.25f)); + _audio.PlayPvs(comp.SparksSound, uid, AudioHelpers.WithVariation(0.25f)); comp.Activated = false; - Dirty(comp); + Dirty(uid, comp); } private void TurnOn(EntityUid uid, StunbatonComponent comp, EntityUid user) @@ -95,12 +101,11 @@ private void TurnOn(EntityUid uid, StunbatonComponent comp, EntityUid user) if (comp.Activated) return; - var playerFilter = Filter.Pvs(comp.Owner, entityManager: EntityManager); - if (!TryComp(comp.Owner, out var battery) || battery.CurrentCharge < comp.EnergyPerUse) + if (!TryComp(uid, out var battery) || battery.CurrentCharge < comp.EnergyPerUse) { - SoundSystem.Play(comp.TurnOnFailSound.GetSound(), playerFilter, comp.Owner, AudioHelpers.WithVariation(0.25f)); - user.PopupMessage(Loc.GetString("stunbaton-component-low-charge")); + _audio.PlayPvs(comp.TurnOnFailSound, uid, AudioHelpers.WithVariation(0.25f)); + _popup.PopupEntity(Loc.GetString("stunbaton-component-low-charge"), user, user); return; } @@ -110,26 +115,27 @@ private void TurnOn(EntityUid uid, StunbatonComponent comp, EntityUid user) } - if (EntityManager.TryGetComponent(comp.Owner, out var appearance) && - EntityManager.TryGetComponent(comp.Owner, out var item)) + if (EntityManager.TryGetComponent(uid, out var appearance) && + EntityManager.TryGetComponent(uid, out var item)) { - _item.SetHeldPrefix(comp.Owner, "on", item); + _item.SetHeldPrefix(uid, "on", item); _appearance.SetData(uid, ToggleVisuals.Toggled, true, appearance); } - SoundSystem.Play(comp.SparksSound.GetSound(), playerFilter, comp.Owner, AudioHelpers.WithVariation(0.25f)); + _audio.PlayPvs(comp.SparksSound, uid, AudioHelpers.WithVariation(0.25f)); comp.Activated = true; - Dirty(comp); + Dirty(uid, comp); } // https://github.com/space-wizards/space-station-14/pull/17288#discussion_r1241213341 private void OnSolutionChange(EntityUid uid, StunbatonComponent component, SolutionChangedEvent args) { // Explode if baton is activated and rigged. - if (TryComp(uid, out var riggable)) - if (TryComp(uid, out var battery)) - if (component.Activated && riggable.IsRigged) - _riggableSystem.Explode(uid, battery); + if (!TryComp(uid, out var riggable) || !TryComp(uid, out var battery)) + return; + + if (component.Activated && riggable.IsRigged) + _riggableSystem.Explode(uid, battery); } private void SendPowerPulse(EntityUid target, EntityUid? user, EntityUid used) @@ -138,7 +144,7 @@ private void SendPowerPulse(EntityUid target, EntityUid? user, EntityUid used) { Used = used, User = user - }, false); + }); } } } diff --git a/Content.Server/Warps/WarpPointComponent.cs b/Content.Server/Warps/WarpPointComponent.cs index 19c38493ef3..ce169f2e195 100644 --- a/Content.Server/Warps/WarpPointComponent.cs +++ b/Content.Server/Warps/WarpPointComponent.cs @@ -6,12 +6,13 @@ namespace Content.Server.Warps [RegisterComponent] public sealed partial class WarpPointComponent : Component { - [ViewVariables(VVAccess.ReadWrite)] [DataField("location")] public string? Location { get; set; } + [ViewVariables(VVAccess.ReadWrite), DataField] + public string? Location; /// /// If true, ghosts warping to this entity will begin following it. /// - [DataField("follow")] - public bool Follow = false; + [DataField] + public bool Follow; } } diff --git a/Content.Server/Weapons/Melee/MeleeWeaponSystem.cs b/Content.Server/Weapons/Melee/MeleeWeaponSystem.cs index ab7831b2a48..1b6b2ebef1c 100644 --- a/Content.Server/Weapons/Melee/MeleeWeaponSystem.cs +++ b/Content.Server/Weapons/Melee/MeleeWeaponSystem.cs @@ -214,7 +214,7 @@ private float CalculateDisarmChance(EntityUid disarmer, EntityUid disarmed, Enti return Math.Clamp(chance, 0f, 1f); } - public override void DoLunge(EntityUid user, Angle angle, Vector2 localPos, string? animation, bool predicted = true) + public override void DoLunge(EntityUid user, EntityUid weapon, Angle angle, Vector2 localPos, string? animation, bool predicted = true) { Filter filter; @@ -227,7 +227,7 @@ public override void DoLunge(EntityUid user, Angle angle, Vector2 localPos, stri filter = Filter.Pvs(user, entityManager: EntityManager); } - RaiseNetworkEvent(new MeleeLungeEvent(GetNetEntity(user), angle, localPos, animation), filter); + RaiseNetworkEvent(new MeleeLungeEvent(GetNetEntity(user), GetNetEntity(weapon), angle, localPos, animation), filter); } private void OnSpeechHit(EntityUid owner, MeleeSpeechComponent comp, MeleeHitEvent args) diff --git a/Content.Server/Weapons/Ranged/Systems/GunSystem.cs b/Content.Server/Weapons/Ranged/Systems/GunSystem.cs index adda6a94e3c..bbac7acd125 100644 --- a/Content.Server/Weapons/Ranged/Systems/GunSystem.cs +++ b/Content.Server/Weapons/Ranged/Systems/GunSystem.cs @@ -10,13 +10,13 @@ using Content.Shared.Damage.Systems; using Content.Shared.Database; using Content.Shared.Effects; -using Content.Shared.FixedPoint; using Content.Shared.Interaction.Components; using Content.Shared.Projectiles; using Content.Shared.Weapons.Melee; using Content.Shared.Weapons.Ranged; using Content.Shared.Weapons.Ranged.Components; using Content.Shared.Weapons.Ranged.Events; +using Content.Shared.Weapons.Ranged.Systems; using Content.Shared.Weapons.Reflect; using Robust.Server.GameObjects; using Robust.Shared.Audio; @@ -26,7 +26,6 @@ using Robust.Shared.Player; using Robust.Shared.Prototypes; using Robust.Shared.Utility; -using SharedGunSystem = Content.Shared.Weapons.Ranged.Systems.SharedGunSystem; namespace Content.Server.Weapons.Ranged.Systems; @@ -305,7 +304,7 @@ public void ShootProjectile(EntityUid uid, Vector2 direction, Vector2 gunVelocit if (user != null) { var projectile = EnsureComp(uid); - Projectiles.SetShooter(projectile, user.Value); + Projectiles.SetShooter(uid, projectile, user.Value); projectile.Weapon = gunUid; } diff --git a/Content.Shared/Body/Systems/SharedBodySystem.Organs.cs b/Content.Shared/Body/Systems/SharedBodySystem.Organs.cs index d2a7b7256ae..6e392b9892c 100644 --- a/Content.Shared/Body/Systems/SharedBodySystem.Organs.cs +++ b/Content.Shared/Body/Systems/SharedBodySystem.Organs.cs @@ -151,7 +151,7 @@ public bool AddOrganToFirstValidSlot( public List<(T Comp, OrganComponent Organ)> GetBodyOrganComponents( EntityUid uid, BodyComponent? body = null) - where T : Component + where T : IComponent { if (!Resolve(uid, ref body)) return new List<(T Comp, OrganComponent Organ)>(); @@ -180,7 +180,7 @@ public bool TryGetBodyOrganComponents( EntityUid uid, [NotNullWhen(true)] out List<(T Comp, OrganComponent Organ)>? comps, BodyComponent? body = null) - where T : Component + where T : IComponent { if (!Resolve(uid, ref body)) { diff --git a/Content.Shared/Body/Systems/SharedBodySystem.Parts.cs b/Content.Shared/Body/Systems/SharedBodySystem.Parts.cs index 66397017e14..463a4b7661a 100644 --- a/Content.Shared/Body/Systems/SharedBodySystem.Parts.cs +++ b/Content.Shared/Body/Systems/SharedBodySystem.Parts.cs @@ -679,7 +679,7 @@ public bool BodyHasChild( public List<(T Comp, OrganComponent Organ)> GetBodyPartOrganComponents( EntityUid uid, BodyPartComponent? part = null) - where T : Component + where T : IComponent { if (!Resolve(uid, ref part)) return new List<(T Comp, OrganComponent Organ)>(); @@ -709,7 +709,7 @@ public bool TryGetBodyPartOrganComponents( EntityUid uid, [NotNullWhen(true)] out List<(T Comp, OrganComponent Organ)>? comps, BodyPartComponent? part = null) - where T : Component + where T : IComponent { if (!Resolve(uid, ref part)) { @@ -751,7 +751,7 @@ public IEnumerable GetBodyPartAdjacentParts(EntityUid partId, BodyPar public IEnumerable<(EntityUid AdjacentId, T Component)> GetBodyPartAdjacentPartsComponents( EntityUid partId, BodyPartComponent? part = null) - where T : Component + where T : IComponent { if (!Resolve(partId, ref part, false)) yield break; @@ -768,7 +768,7 @@ public bool TryGetBodyPartAdjacentPartsComponents( EntityUid partId, [NotNullWhen(true)] out List<(EntityUid AdjacentId, T Component)>? comps, BodyPartComponent? part = null) - where T : Component + where T : IComponent { if (!Resolve(partId, ref part, false)) { diff --git a/Content.Shared/Climbing/Systems/ClimbSystem.cs b/Content.Shared/Climbing/Systems/ClimbSystem.cs index 4e25fa4ac0d..511149f8f95 100644 --- a/Content.Shared/Climbing/Systems/ClimbSystem.cs +++ b/Content.Shared/Climbing/Systems/ClimbSystem.cs @@ -101,7 +101,7 @@ public override void UpdateBeforeSolve(bool prediction, float frameTime) } var xform = _xformQuery.GetComponent(uid); - _xformSystem.SetLocalPositionNoLerp(uid, xform.LocalPosition + comp.Direction * frameTime, xform); + _xformSystem.SetLocalPosition(uid, xform.LocalPosition + comp.Direction * frameTime, xform); } } diff --git a/Content.Shared/Cuffs/SharedCuffableSystem.cs b/Content.Shared/Cuffs/SharedCuffableSystem.cs index d64e15799dc..4951bb7f1cb 100644 --- a/Content.Shared/Cuffs/SharedCuffableSystem.cs +++ b/Content.Shared/Cuffs/SharedCuffableSystem.cs @@ -3,6 +3,7 @@ using Content.Shared.Administration.Components; using Content.Shared.Administration.Logs; using Content.Shared.Alert; +using Content.Shared.Atmos.Piping.Unary.Components; using Content.Shared.Buckle.Components; using Content.Shared.Cuffs.Components; using Content.Shared.Damage; @@ -85,6 +86,7 @@ public override void Initialize() SubscribeLocalEvent(OnCuffAfterInteract); SubscribeLocalEvent(OnCuffMeleeHit); SubscribeLocalEvent(OnAddCuffDoAfter); + SubscribeLocalEvent(OnCuffVirtualItemDeleted); } private void OnUncuffAttempt(ref UncuffAttemptEvent args) @@ -163,7 +165,7 @@ public void UpdateCuffState(EntityUid uid, CuffableComponent component) return; component.CanStillInteract = canInteract; - Dirty(component); + Dirty(uid, component); _actionBlocker.UpdateCanMove(uid); if (component.CanStillInteract) @@ -350,7 +352,11 @@ private void OnAddCuffDoAfter(EntityUid uid, HandcuffComponent component, AddCuf ("otherName", Identity.Name(user, EntityManager, target))), target, target); } } + } + private void OnCuffVirtualItemDeleted(EntityUid uid, HandcuffComponent component, VirtualItemDeletedEvent args) + { + Uncuff(args.User, null, uid, cuff: component); } /// @@ -543,7 +549,7 @@ public void TryUncuff(EntityUid target, EntityUid user, EntityUid? cuffsToRemove { if (!cuffable.Container.ContainedEntities.Contains(cuffsToRemove.Value)) { - Logger.Warning("A user is trying to remove handcuffs that aren't in the owner's container. This should never happen!"); + Log.Warning("A user is trying to remove handcuffs that aren't in the owner's container. This should never happen!"); } } @@ -608,21 +614,23 @@ public void TryUncuff(EntityUid target, EntityUid user, EntityUid? cuffsToRemove _audio.PlayPredicted(isOwner ? cuff.StartBreakoutSound : cuff.StartUncuffSound, target, user); } - public void Uncuff(EntityUid target, EntityUid user, EntityUid cuffsToRemove, CuffableComponent? cuffable = null, HandcuffComponent? cuff = null) + public void Uncuff(EntityUid target, EntityUid? user, EntityUid cuffsToRemove, CuffableComponent? cuffable = null, HandcuffComponent? cuff = null) { if (!Resolve(target, ref cuffable) || !Resolve(cuffsToRemove, ref cuff)) return; - var attempt = new UncuffAttemptEvent(user, target); - RaiseLocalEvent(user, ref attempt); - if (attempt.Cancelled) - return; + if (user != null) + { + var attempt = new UncuffAttemptEvent(user.Value, target); + RaiseLocalEvent(user.Value, ref attempt); + if (attempt.Cancelled) + return; + } _audio.PlayPredicted(cuff.EndUncuffSound, target, user); cuffable.Container.Remove(cuffsToRemove); - if (_net.IsServer) { // Handles spawning broken cuffs on server to avoid client misprediction @@ -640,12 +648,13 @@ public void Uncuff(EntityUid target, EntityUid user, EntityUid cuffsToRemove, Cu // Only play popups on server because popups suck if (cuffable.CuffedHandCount == 0) { - _popup.PopupEntity(Loc.GetString("cuffable-component-remove-cuffs-success-message"), user, user); + if (user != null) + _popup.PopupEntity(Loc.GetString("cuffable-component-remove-cuffs-success-message"), user.Value, user.Value); - if (target != user) + if (target != user && user != null) { _popup.PopupEntity(Loc.GetString("cuffable-component-remove-cuffs-by-other-success-message", - ("otherName", Identity.Name(user, EntityManager, user))), target, target); + ("otherName", Identity.Name(user.Value, EntityManager, user))), target, target); _adminLog.Add(LogType.Action, LogImpact.Medium, $"{ToPrettyString(user):player} has successfully uncuffed {ToPrettyString(target):player}"); } @@ -655,22 +664,22 @@ public void Uncuff(EntityUid target, EntityUid user, EntityUid cuffsToRemove, Cu $"{ToPrettyString(user):player} has successfully uncuffed themselves"); } } - else + else if (user != null) { if (user != target) { _popup.PopupEntity(Loc.GetString("cuffable-component-remove-cuffs-partial-success-message", ("cuffedHandCount", cuffable.CuffedHandCount), - ("otherName", Identity.Name(user, EntityManager, user))), user, user); + ("otherName", Identity.Name(user.Value, EntityManager, user.Value))), user.Value, user.Value); _popup.PopupEntity(Loc.GetString( "cuffable-component-remove-cuffs-by-other-partial-success-message", - ("otherName", Identity.Name(user, EntityManager, user)), + ("otherName", Identity.Name(user.Value, EntityManager, user.Value)), ("cuffedHandCount", cuffable.CuffedHandCount)), target, target); } else { _popup.PopupEntity(Loc.GetString("cuffable-component-remove-cuffs-partial-success-message", - ("cuffedHandCount", cuffable.CuffedHandCount)), user, user); + ("cuffedHandCount", cuffable.CuffedHandCount)), user.Value, user.Value); } } } diff --git a/Content.Shared/EntityList/EntityLootTablePrototype.cs b/Content.Shared/EntityList/EntityLootTablePrototype.cs index 06b33eb7f61..da535d570c4 100644 --- a/Content.Shared/EntityList/EntityLootTablePrototype.cs +++ b/Content.Shared/EntityList/EntityLootTablePrototype.cs @@ -15,7 +15,7 @@ public sealed class EntityLootTablePrototype : IPrototype public ImmutableList Entries = ImmutableList.Empty; /// - public List GetSpawns(IRobustRandom? random = null) + public List GetSpawns(IRobustRandom random) { return EntitySpawnCollection.GetSpawns(Entries, random); } diff --git a/Content.Shared/Kitchen/Components/KitchenSpikeComponent.cs b/Content.Shared/Kitchen/Components/KitchenSpikeComponent.cs index 8b43ab1a850..3057a75a4cc 100644 --- a/Content.Shared/Kitchen/Components/KitchenSpikeComponent.cs +++ b/Content.Shared/Kitchen/Components/KitchenSpikeComponent.cs @@ -15,7 +15,7 @@ public sealed partial class KitchenSpikeComponent : Component [DataField("sound")] public SoundSpecifier SpikeSound = new SoundPathSpecifier("/Audio/Effects/Fluids/splat.ogg"); - public List? PrototypesToSpawn; + public List? PrototypesToSpawn; // TODO: Spiking alive mobs? (Replace with uid) (deal damage to their limbs on spiking, kill on first butcher attempt?) public string MeatSource1p = "?"; diff --git a/Content.Shared/Materials/SharedMaterialReclaimerSystem.cs b/Content.Shared/Materials/SharedMaterialReclaimerSystem.cs index 3f5832f69a9..c3c712b617b 100644 --- a/Content.Shared/Materials/SharedMaterialReclaimerSystem.cs +++ b/Content.Shared/Materials/SharedMaterialReclaimerSystem.cs @@ -35,11 +35,17 @@ public override void Initialize() SubscribeLocalEvent(OnUnpaused); SubscribeLocalEvent(OnExamined); SubscribeLocalEvent(OnEmagged); + SubscribeLocalEvent(OnMapInit); SubscribeLocalEvent(OnCollide); SubscribeLocalEvent(OnActiveStartup); SubscribeLocalEvent(OnActiveUnpaused); } + private void OnMapInit(EntityUid uid, MaterialReclaimerComponent component, MapInitEvent args) + { + component.NextSound = Timing.CurTime; + } + private void OnShutdown(EntityUid uid, MaterialReclaimerComponent component, ComponentShutdown args) { component.Stream?.Stop(); @@ -109,8 +115,11 @@ public bool TryStartProcessItem(EntityUid uid, EntityUid item, MaterialReclaimer } if (Timing.CurTime > component.NextSound) - component.Stream = _audio.PlayPvs(component.Sound, uid); - component.NextSound = Timing.CurTime + component.SoundCooldown; + { + component.Stream = _audio.PlayPredicted(component.Sound, uid, user); + + component.NextSound = Timing.CurTime + component.SoundCooldown; + } var duration = GetReclaimingDuration(uid, item, component); // if it's instant, don't bother with all the active comp stuff. diff --git a/Content.Shared/Mind/SharedMindSystem.cs b/Content.Shared/Mind/SharedMindSystem.cs index be11d8a2ad4..cc4ac4af236 100644 --- a/Content.Shared/Mind/SharedMindSystem.cs +++ b/Content.Shared/Mind/SharedMindSystem.cs @@ -292,7 +292,7 @@ public bool TryRemoveObjective(EntityUid mindId, MindComponent mind, int index) return true; } - public bool TryGetObjectiveComp(EntityUid uid, [NotNullWhen(true)] out T? objective) where T : Component + public bool TryGetObjectiveComp(EntityUid uid, [NotNullWhen(true)] out T? objective) where T : IComponent { if (TryGetMind(uid, out var mindId, out var mind) && TryGetObjectiveComp(mindId, out objective, mind)) { @@ -302,7 +302,7 @@ public bool TryGetObjectiveComp(EntityUid uid, [NotNullWhen(true)] out T? obj return false; } - public bool TryGetObjectiveComp(EntityUid mindId, [NotNullWhen(true)] out T? objective, MindComponent? mind = null) where T : Component + public bool TryGetObjectiveComp(EntityUid mindId, [NotNullWhen(true)] out T? objective, MindComponent? mind = null) where T : IComponent { if (Resolve(mindId, ref mind)) { @@ -382,9 +382,9 @@ public bool TryGetMind( /// Gets a role component from a player's mind. /// /// Whether a role was found - public bool TryGetRole(EntityUid user, [NotNullWhen(true)] out T? role) where T : Component + public bool TryGetRole(EntityUid user, [NotNullWhen(true)] out T? role) where T : IComponent { - role = null; + role = default; if (!TryComp(user, out var mindContainer) || mindContainer.Mind == null) return false; diff --git a/Content.Shared/Popups/SharedPopupExtensions.cs b/Content.Shared/Popups/SharedPopupExtensions.cs deleted file mode 100644 index 94305330ef1..00000000000 --- a/Content.Shared/Popups/SharedPopupExtensions.cs +++ /dev/null @@ -1,48 +0,0 @@ -using Robust.Shared.Map; -using Robust.Shared.Player; - -namespace Content.Shared.Popups -{ - public static class SharedPopupExtensions - { - /// - /// Pops up a message at the location of for - /// alone to see. - /// - /// The entity above which the message will appear. - /// The entity that will see the message. - /// The message to show. - [Obsolete("Use PopupSystem.PopupEntity instead.")] - public static void PopupMessage(this EntityUid source, EntityUid viewer, string message) - { - var popupSystem = EntitySystem.Get(); - - popupSystem.PopupEntity(message, source, viewer); - } - - /// - /// Pops up a message at the given entity's location for it alone to see. - /// - /// The entity that will see the message. - /// The message to be seen. - [Obsolete("Use PopupSystem.PopupEntity instead.")] - public static void PopupMessage(this EntityUid viewer, string message) - { - viewer.PopupMessage(viewer, message); - } - - /// - /// Makes a string of text float up from a client's cursor. - /// - /// - /// The client attached entity that the message is being sent to. - /// - /// Text contents of the message. - [Obsolete("Use PopupSystem.PopupCursor instead.")] - public static void PopupMessageCursor(this EntityUid viewer, string message) - { - var popupSystem = EntitySystem.Get(); - popupSystem.PopupCursor(message, viewer); - } - } -} diff --git a/Content.Shared/Projectiles/SharedProjectileSystem.cs b/Content.Shared/Projectiles/SharedProjectileSystem.cs index 1df743bc0b1..63b4cb13aa6 100644 --- a/Content.Shared/Projectiles/SharedProjectileSystem.cs +++ b/Content.Shared/Projectiles/SharedProjectileSystem.cs @@ -3,11 +3,7 @@ using Content.Shared.DoAfter; using Content.Shared.Hands.EntitySystems; using Content.Shared.Interaction; -using Content.Shared.Projectiles; -using Content.Shared.Sound.Components; using Content.Shared.Throwing; -using Content.Shared.Weapons.Ranged.Components; -using Robust.Shared.Audio; using Robust.Shared.Map; using Robust.Shared.Network; using Robust.Shared.Physics; @@ -139,13 +135,13 @@ private void PreventCollision(EntityUid uid, ProjectileComponent component, ref } } - public void SetShooter(ProjectileComponent component, EntityUid uid) + public void SetShooter(EntityUid id, ProjectileComponent component, EntityUid shooterId) { - if (component.Shooter == uid) + if (component.Shooter == shooterId) return; - component.Shooter = uid; - Dirty(uid, component); + component.Shooter = shooterId; + Dirty(id, component); } [Serializable, NetSerializable] diff --git a/Content.Shared/Prying/Systems/PryingSystem.cs b/Content.Shared/Prying/Systems/PryingSystem.cs index 3bb3a9bc9b0..40b77efe228 100644 --- a/Content.Shared/Prying/Systems/PryingSystem.cs +++ b/Content.Shared/Prying/Systems/PryingSystem.cs @@ -92,7 +92,7 @@ public bool TryPry(EntityUid target, EntityUid user, out DoAfterId? id) // to be marked as handled as a popup would be generated on failure. return true; - return StartPry(target, user, null, 1.0f, out id); + return StartPry(target, user, null, 0.1f, out id); // hand-prying is much slower } private bool CanPry(EntityUid target, EntityUid user, PryingComponent? comp = null) diff --git a/Content.Shared/Pulling/Components/PullableComponent.cs b/Content.Shared/Pulling/Components/PullableComponent.cs index 51ab2c91e49..30222c481be 100644 --- a/Content.Shared/Pulling/Components/PullableComponent.cs +++ b/Content.Shared/Pulling/Components/PullableComponent.cs @@ -1,6 +1,5 @@ using Robust.Shared.GameStates; using Robust.Shared.Map; -using Robust.Shared.Physics.Dynamics.Joints; using Robust.Shared.Serialization; namespace Content.Shared.Pulling.Components @@ -39,16 +38,6 @@ public sealed partial class SharedPullableComponent : Component [Access(typeof(SharedPullingSystem), Other = AccessPermissions.ReadExecute)] [ViewVariables] public bool PrevFixedRotation; - - protected override void OnRemove() - { - if (Puller != null) - { - // This is absolute paranoia but it's also absolutely necessary. Too many puller state bugs. - 20kdc - Logger.ErrorS("c.go.c.pulling", "PULLING STATE CORRUPTION IMMINENT IN PULLABLE {0} - OnRemove called when Puller is set!", Owner); - } - base.OnRemove(); - } } [Serializable, NetSerializable] diff --git a/Content.Shared/Pulling/Components/SharedPullerComponent.cs b/Content.Shared/Pulling/Components/SharedPullerComponent.cs index 4ee8b3d129b..c21e8a76de2 100644 --- a/Content.Shared/Pulling/Components/SharedPullerComponent.cs +++ b/Content.Shared/Pulling/Components/SharedPullerComponent.cs @@ -17,15 +17,5 @@ public sealed partial class SharedPullerComponent : Component /// [DataField("needsHands")] public bool NeedsHands = true; - - protected override void OnRemove() - { - if (Pulling != default) - { - // This is absolute paranoia but it's also absolutely necessary. Too many puller state bugs. - 20kdc - Logger.ErrorS("c.go.c.pulling", "PULLING STATE CORRUPTION IMMINENT IN PULLER {0} - OnRemove called when Pulling is set!", Owner); - } - base.OnRemove(); - } } } diff --git a/Content.Shared/Pulling/Systems/SharedPullingStateManagementSystem.cs b/Content.Shared/Pulling/Systems/SharedPullingStateManagementSystem.cs index 63f6d648678..974859a6209 100644 --- a/Content.Shared/Pulling/Systems/SharedPullingStateManagementSystem.cs +++ b/Content.Shared/Pulling/Systems/SharedPullingStateManagementSystem.cs @@ -1,4 +1,3 @@ -using System.Linq; using Content.Shared.Physics.Pull; using Content.Shared.Pulling.Components; using JetBrains.Annotations; diff --git a/Content.Shared/Random/Helpers/SharedEntityExtensions.cs b/Content.Shared/Random/Helpers/SharedEntityExtensions.cs deleted file mode 100644 index 5b12ffb94d0..00000000000 --- a/Content.Shared/Random/Helpers/SharedEntityExtensions.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System.Numerics; -using Robust.Shared.Random; -using Robust.Shared.Utility; - -namespace Content.Shared.Random.Helpers -{ - public static class SharedEntityExtensions - { - public static void RandomOffset(this EntityUid entity, float minX, float maxX, float minY, float maxY) - { - DebugTools.AssertNotNull(entity); - DebugTools.Assert(minX <= maxX, $"Minimum X value ({minX}) must be smaller than or equal to the maximum X value ({maxX})"); - DebugTools.Assert(minY <= maxY, $"Minimum Y value ({minY}) must be smaller than or equal to the maximum Y value ({maxY})"); - - var random = IoCManager.Resolve(); - var randomX = random.NextFloat() * (maxX - minX) + minX; - var randomY = random.NextFloat() * (maxY - minY) + minY; - var offset = new Vector2(randomX, randomY); - - IoCManager.Resolve().GetComponent(entity).LocalPosition += offset; - } - - public static void RandomOffset(this EntityUid entity, float min, float max) - { - DebugTools.AssertNotNull(entity); - DebugTools.Assert(min <= max, $"Minimum value ({min}) must be smaller than or equal to the maximum value ({max})"); - - entity.RandomOffset(min, max, min, max); - } - - public static void RandomOffset(this EntityUid entity, float value) - { - value = Math.Abs(value); - entity.RandomOffset(-value, value); - } - } -} diff --git a/Content.Shared/Random/RandomHelperSystem.cs b/Content.Shared/Random/RandomHelperSystem.cs new file mode 100644 index 00000000000..66ebcc3f78b --- /dev/null +++ b/Content.Shared/Random/RandomHelperSystem.cs @@ -0,0 +1,35 @@ +using System.Numerics; +using Content.Shared.Random.Helpers; +using Robust.Shared.Random; +using Robust.Shared.Utility; + +namespace Content.Shared.Random; + +/// +/// System containing various content-related random helpers. +/// +public sealed class RandomHelperSystem : EntitySystem +{ + [Dependency] private readonly SharedTransformSystem _transform = default!; + [Dependency] private readonly IRobustRandom _random = default!; + + public void RandomOffset(EntityUid entity, float minX, float maxX, float minY, float maxY) + { + var randomX = _random.NextFloat() * (maxX - minX) + minX; + var randomY = _random.NextFloat() * (maxY - minY) + minY; + var offset = new Vector2(randomX, randomY); + + var xform = Transform(entity); + _transform.SetLocalPosition(xform, xform.LocalPosition + offset); + } + + public void RandomOffset(EntityUid entity, float min, float max) + { + RandomOffset(entity, min, max, min, max); + } + + public void RandomOffset(EntityUid entity, float value) + { + RandomOffset(entity, -value, value); + } +} diff --git a/Content.Shared/Research/Prototypes/TechnologyPrototype.cs b/Content.Shared/Research/Prototypes/TechnologyPrototype.cs index ec1ca029c71..38000677a13 100644 --- a/Content.Shared/Research/Prototypes/TechnologyPrototype.cs +++ b/Content.Shared/Research/Prototypes/TechnologyPrototype.cs @@ -1,6 +1,4 @@ using Robust.Shared.Prototypes; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List; using Robust.Shared.Utility; namespace Content.Shared.Research.Prototypes; @@ -19,57 +17,57 @@ public sealed class TechnologyPrototype : IPrototype /// The name of the technology. /// Supports locale strings /// - [DataField("name", required: true)] - public string Name = string.Empty; + [DataField(required: true)] + public LocId Name = string.Empty; /// /// An icon used to visually represent the technology in UI. /// - [DataField("icon", required: true)] + [DataField(required: true)] public SpriteSpecifier Icon = default!; /// /// What research discipline this technology belongs to. /// - [DataField("discipline", required: true, customTypeSerializer: typeof(PrototypeIdSerializer))] - public string Discipline = default!; + [DataField(required: true)] + public ProtoId Discipline; /// /// What tier research is this? /// The tier governs how much lower-tier technology /// needs to be unlocked before this one. /// - [DataField("tier", required: true)] + [DataField(required: true)] public int Tier; /// /// Hidden tech is not ever available at the research console. /// - [DataField("hidden")] + [DataField] public bool Hidden; /// /// How much research is needed to unlock. /// - [DataField("cost")] + [DataField] public int Cost = 10000; /// /// A list of s that need to be unlocked in order to unlock this technology. /// - [DataField("technologyPrerequisites", customTypeSerializer: typeof(PrototypeIdListSerializer))] - public IReadOnlyList TechnologyPrerequisites = new List(); + [DataField] + public List> TechnologyPrerequisites = new(); /// /// A list of s that are unlocked by this technology /// - [DataField("recipeUnlocks", customTypeSerializer: typeof(PrototypeIdListSerializer))] - public IReadOnlyList RecipeUnlocks = new List(); + [DataField] + public List> RecipeUnlocks = new(); /// /// A list of non-standard effects that are done when this technology is unlocked. /// - [DataField("genericUnlocks")] + [DataField] public IReadOnlyList GenericUnlocks = new List(); } @@ -80,13 +78,13 @@ public partial record struct GenericUnlock() /// What event is raised when this is unlocked? /// Used for doing non-standard logic. /// - [DataField("purchaseEvent")] + [DataField] public object? PurchaseEvent = null; /// /// A player facing tooltip for what the unlock does. /// Supports locale strings. /// - [DataField("unlockDescription")] + [DataField] public string UnlockDescription = string.Empty; } diff --git a/Content.Shared/Research/Systems/SharedResearchSystem.cs b/Content.Shared/Research/Systems/SharedResearchSystem.cs index e0cc937b004..12f27d0b9c9 100644 --- a/Content.Shared/Research/Systems/SharedResearchSystem.cs +++ b/Content.Shared/Research/Systems/SharedResearchSystem.cs @@ -3,6 +3,7 @@ using Content.Shared.Research.Prototypes; using Robust.Shared.Prototypes; using Robust.Shared.Random; +using Robust.Shared.Utility; namespace Content.Shared.Research.Systems; @@ -40,7 +41,7 @@ public void UpdateTechnologyCards(EntityUid uid, TechnologyDatabaseComponent? co component.CurrentTechnologyCards.Add(selected.ID); } - Dirty(component); + Dirty(uid, component); } public List GetAvailableTechnologies(EntityUid uid, TechnologyDatabaseComponent? component = null) @@ -142,6 +143,59 @@ public int GetHighestDisciplineTier(TechnologyDatabaseComponent component, TechD return tier - 1; } + public FormattedMessage GetTechnologyDescription( + TechnologyPrototype technology, + bool includeCost = true, + bool includeTier = true, + bool includePrereqs = false, + TechDisciplinePrototype? disciplinePrototype = null) + { + var description = new FormattedMessage(); + if (includeTier) + { + disciplinePrototype ??= PrototypeManager.Index(technology.Discipline); + description.AddMarkup(Loc.GetString("research-console-tier-discipline-info", + ("tier", technology.Tier), ("color", disciplinePrototype.Color), ("discipline", Loc.GetString(disciplinePrototype.Name)))); + description.PushNewline(); + } + + if (includeCost) + { + description.AddMarkup(Loc.GetString("research-console-cost", ("amount", technology.Cost))); + description.PushNewline(); + } + + if (includePrereqs && technology.TechnologyPrerequisites.Any()) + { + description.AddMarkup(Loc.GetString("research-console-prereqs-list-start")); + foreach (var recipe in technology.TechnologyPrerequisites) + { + var techProto = PrototypeManager.Index(recipe); + description.PushNewline(); + description.AddMarkup(Loc.GetString("research-console-prereqs-list-entry", + ("text", Loc.GetString(techProto.Name)))); + } + description.PushNewline(); + } + + description.AddMarkup(Loc.GetString("research-console-unlocks-list-start")); + foreach (var recipe in technology.RecipeUnlocks) + { + var recipeProto = PrototypeManager.Index(recipe); + description.PushNewline(); + description.AddMarkup(Loc.GetString("research-console-unlocks-list-entry", + ("name",recipeProto.Name))); + } + foreach (var generic in technology.GenericUnlocks) + { + description.PushNewline(); + description.AddMarkup(Loc.GetString("research-console-unlocks-list-entry-generic", + ("text", Loc.GetString(generic.UnlockDescription)))); + } + + return description; + } + /// /// Returns whether a technology is unlocked on this database or not. /// diff --git a/Content.Shared/Roles/SharedRoleSystem.cs b/Content.Shared/Roles/SharedRoleSystem.cs index 75296b96f4a..ebd6730bbe4 100644 --- a/Content.Shared/Roles/SharedRoleSystem.cs +++ b/Content.Shared/Roles/SharedRoleSystem.cs @@ -65,7 +65,7 @@ protected void SubscribeAntagEvents() where T : AntagonistRoleComponent /// /// Thrown if we already have a role with this type. /// - public void MindAddRole(EntityUid mindId, T component, MindComponent? mind = null, bool silent = false) where T : Component, new() + public void MindAddRole(EntityUid mindId, T component, MindComponent? mind = null, bool silent = false) where T : IComponent, new() { if (!Resolve(mindId, ref mind)) return; @@ -99,7 +99,7 @@ protected void SubscribeAntagEvents() where T : AntagonistRoleComponent /// /// Thrown if we do not have this role. /// - public void MindRemoveRole(EntityUid mindId) where T : Component + public void MindRemoveRole(EntityUid mindId) where T : IComponent { if (!RemComp(mindId)) { @@ -118,7 +118,7 @@ public void MindRemoveRole(EntityUid mindId) where T : Component $"'Role {typeof(T).Name}' removed from mind of {_minds.MindOwnerLoggingString(mind)}"); } - public bool MindTryRemoveRole(EntityUid mindId) where T : Component + public bool MindTryRemoveRole(EntityUid mindId) where T : IComponent { if (!MindHasRole(mindId)) return false; @@ -127,7 +127,7 @@ public bool MindTryRemoveRole(EntityUid mindId) where T : Component return true; } - public bool MindHasRole(EntityUid mindId) where T : Component + public bool MindHasRole(EntityUid mindId) where T : IComponent { return HasComp(mindId); } diff --git a/Content.Shared/Station/SharedStationSpawningSystem.cs b/Content.Shared/Station/SharedStationSpawningSystem.cs index d392cf7beda..8cdcff883b1 100644 --- a/Content.Shared/Station/SharedStationSpawningSystem.cs +++ b/Content.Shared/Station/SharedStationSpawningSystem.cs @@ -27,7 +27,7 @@ public void EquipStartingGear(EntityUid entity, StartingGearPrototype startingGe if (!string.IsNullOrEmpty(equipmentStr)) { var equipmentEntity = EntityManager.SpawnEntity(equipmentStr, EntityManager.GetComponent(entity).Coordinates); - InventorySystem.TryEquip(entity, equipmentEntity, slot.Name, true); + InventorySystem.TryEquip(entity, equipmentEntity, slot.Name, true, force:true); } } } diff --git a/Content.Shared/StatusEffect/StatusEffectsSystem.cs b/Content.Shared/StatusEffect/StatusEffectsSystem.cs index bedc5a824ce..17b88644930 100644 --- a/Content.Shared/StatusEffect/StatusEffectsSystem.cs +++ b/Content.Shared/StatusEffect/StatusEffectsSystem.cs @@ -1,8 +1,5 @@ using System.Diagnostics.CodeAnalysis; using Content.Shared.Alert; -using Content.Shared.Mobs; -using Content.Shared.Mobs.Components; -using Content.Shared.Mobs.Systems; using Content.Shared.Rejuvenate; using Robust.Shared.GameStates; using Robust.Shared.Prototypes; @@ -107,7 +104,7 @@ private void OnRejuvenate(EntityUid uid, StatusEffectsComponent component, Rejuv /// The component type to add and remove from the entity. public bool TryAddStatusEffect(EntityUid uid, string key, TimeSpan time, bool refresh, StatusEffectsComponent? status = null) - where T : Component, new() + where T : IComponent, new() { if (!Resolve(uid, ref status, false)) return false; diff --git a/Content.Shared/Storage/EntitySpawnEntry.cs b/Content.Shared/Storage/EntitySpawnEntry.cs index a39c2015a98..96fb9f9f405 100644 --- a/Content.Shared/Storage/EntitySpawnEntry.cs +++ b/Content.Shared/Storage/EntitySpawnEntry.cs @@ -78,12 +78,12 @@ public sealed class OrGroup /// The entity spawn entries. /// Resolve param. /// A list of entity prototypes that should be spawned. - public static List GetSpawns(IEnumerable entries, + public static List GetSpawns(IEnumerable entries, IRobustRandom? random = null) { IoCManager.Resolve(ref random); - var spawned = new List(); + var spawned = new List(); var ungrouped = CollectOrGroups(entries, out var orGroupedSpawns); foreach (var entry in ungrouped) @@ -93,6 +93,9 @@ public sealed class OrGroup if (entry.SpawnProbability != 1f && !random.Prob(entry.SpawnProbability)) continue; + if (entry.PrototypeId == null) + continue; + var amount = (int) entry.GetAmount(random); for (var i = 0; i < amount; i++) @@ -116,6 +119,9 @@ public sealed class OrGroup if (diceRoll > cumulative) continue; + if (entry.PrototypeId == null) + break; + // Dice roll succeeded, add item and break loop var amount = (int) entry.GetAmount(random); diff --git a/Content.Shared/Storage/EntitySystems/SharedEntityStorageSystem.cs b/Content.Shared/Storage/EntitySystems/SharedEntityStorageSystem.cs index 7553fb6c9cc..2d85f79e038 100644 --- a/Content.Shared/Storage/EntitySystems/SharedEntityStorageSystem.cs +++ b/Content.Shared/Storage/EntitySystems/SharedEntityStorageSystem.cs @@ -22,6 +22,7 @@ using Robust.Shared.Physics; using Robust.Shared.Physics.Components; using Robust.Shared.Physics.Systems; +using Robust.Shared.Prototypes; using Robust.Shared.Timing; using Robust.Shared.Utility; @@ -260,9 +261,12 @@ public bool Insert(EntityUid toInsert, EntityUid container, SharedEntityStorageC } _joints.RecursiveClearJoints(toInsert); + if (!component.Contents.Insert(toInsert, EntityManager)) + return false; + var inside = EnsureComp(toInsert); inside.Storage = container; - return component.Contents.Insert(toInsert, EntityManager); + return true; } public bool Remove(EntityUid toRemove, EntityUid container, SharedEntityStorageComponent? component = null, TransformComponent? xform = null) diff --git a/Content.Shared/Weapons/Melee/Events/MeleeLungeEvent.cs b/Content.Shared/Weapons/Melee/Events/MeleeLungeEvent.cs index 66acc213c1d..72851dc80ca 100644 --- a/Content.Shared/Weapons/Melee/Events/MeleeLungeEvent.cs +++ b/Content.Shared/Weapons/Melee/Events/MeleeLungeEvent.cs @@ -11,6 +11,11 @@ public sealed class MeleeLungeEvent : EntityEventArgs { public NetEntity Entity; + /// + /// The weapon used. + /// + public NetEntity Weapon; + /// /// Width of the attack angle. /// @@ -26,9 +31,10 @@ public sealed class MeleeLungeEvent : EntityEventArgs /// public string? Animation; - public MeleeLungeEvent(NetEntity entity, Angle angle, Vector2 localPos, string? animation) + public MeleeLungeEvent(NetEntity entity, NetEntity weapon, Angle angle, Vector2 localPos, string? animation) { Entity = entity; + Weapon = weapon; Angle = angle; LocalPos = localPos; Animation = animation; diff --git a/Content.Shared/Weapons/Melee/MeleeWeaponComponent.cs b/Content.Shared/Weapons/Melee/MeleeWeaponComponent.cs index ddc060e558b..54db0b8c67f 100644 --- a/Content.Shared/Weapons/Melee/MeleeWeaponComponent.cs +++ b/Content.Shared/Weapons/Melee/MeleeWeaponComponent.cs @@ -96,6 +96,17 @@ public sealed partial class MeleeWeaponComponent : Component [ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField] public EntProtoId WideAnimation = "WeaponArcSlash"; + /// + /// Rotation of the animation. + /// 0 degrees means the top faces the attacker. + /// + [ViewVariables(VVAccess.ReadWrite), DataField] + public Angle WideAnimationRotation = Angle.Zero; + + [ViewVariables(VVAccess.ReadWrite), DataField] + public bool SwingLeft; + + // Sounds /// diff --git a/Content.Shared/Weapons/Melee/SharedMeleeWeaponSystem.cs b/Content.Shared/Weapons/Melee/SharedMeleeWeaponSystem.cs index 4259706ba86..4b740b8d3c7 100644 --- a/Content.Shared/Weapons/Melee/SharedMeleeWeaponSystem.cs +++ b/Content.Shared/Weapons/Melee/SharedMeleeWeaponSystem.cs @@ -423,7 +423,7 @@ private bool AttemptAttack(EntityUid user, EntityUid weaponUid, MeleeWeaponCompo throw new NotImplementedException(); } - DoLungeAnimation(user, weapon.Angle, GetCoordinates(attack.Coordinates).ToMap(EntityManager, TransformSystem), weapon.Range, animation); + DoLungeAnimation(user, weaponUid, weapon.Angle, GetCoordinates(attack.Coordinates).ToMap(EntityManager, TransformSystem), weapon.Range, animation); } var attackEv = new MeleeAttackEvent(weaponUid); @@ -823,7 +823,7 @@ protected virtual bool DoDisarm(EntityUid user, DisarmAttackEvent ev, EntityUid return true; } - private void DoLungeAnimation(EntityUid user, Angle angle, MapCoordinates coordinates, float length, string? animation) + private void DoLungeAnimation(EntityUid user, EntityUid weapon, Angle angle, MapCoordinates coordinates, float length, string? animation) { // TODO: Assert that offset eyes are still okay. if (!TryComp(user, out var userXform)) @@ -844,8 +844,8 @@ private void DoLungeAnimation(EntityUid user, Angle angle, MapCoordinates coordi if (localPos.Length() > visualLength) localPos = localPos.Normalized() * visualLength; - DoLunge(user, angle, localPos, animation); + DoLunge(user, weapon, angle, localPos, animation); } - public abstract void DoLunge(EntityUid user, Angle angle, Vector2 localPos, string? animation, bool predicted = true); + public abstract void DoLunge(EntityUid user, EntityUid weapon, Angle angle, Vector2 localPos, string? animation, bool predicted = true); } diff --git a/Resources/Changelog/Admin.yml b/Resources/Changelog/Admin.yml index 5a24f0d9794..74156b9d132 100644 --- a/Resources/Changelog/Admin.yml +++ b/Resources/Changelog/Admin.yml @@ -41,3 +41,8 @@ Entries: - {message: 'Fixed not being able to sort the F7 players tab by playtime.', type: Fix} id: 6 time: '2023-10-14T23:52:00.0000000+00:00' +- author: DrSmugleaf + changes: + - {message: 'Fixed playtime being sorted incorrectly in the F7 players tab.', type: Fix} + id: 7 + time: '2023-10-16T04:23:00.0000000+00:00' diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 5142dad175f..cd0c690f584 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,84 +1,4 @@ Entries: -- author: Equivocateur - changes: - - {message: 'Added an electrical disruption kit to syndicate operatives, containing - 3 EMP grenades and an EMP implanter. Costs 6 telecrystals.', type: Add} - - {message: Changed EMP grenade pricing to 2 telecrystals., type: Tweak} - - {message: Changed EMP implant pricing to 3 telecrystals., type: Tweak} - id: 4508 - time: '2023-08-10T08:40:17.0000000+00:00' -- author: kxvvv - changes: - - {message: Added a homemade stun weapon., type: Add} - id: 4509 - time: '2023-08-10T09:33:34.0000000+00:00' -- author: mirrorcult - changes: - - {message: 'You can now construct chain link fencing. Bullets pass through it, - it''s very slowly vaultable, and you can construct gates. Expect to see it mapped - eventually.', type: Add} - id: 4510 - time: '2023-08-10T14:16:26.0000000+00:00' -- author: mirrorcult - changes: - - {message: 'Liquid plasma rivers now spawn on snow planets (you may have noticed - foreshadowing from the planet background sprites). They''re just as dangerous - as lava, so be careful.', type: Add} - id: 4511 - time: '2023-08-10T14:16:51.0000000+00:00' -- author: AlexMorgan3817 - changes: - - {message: Added supermatter grenade analog from SS13 and brand new whitehole grenade - for special operations., type: Add} - id: 4512 - time: '2023-08-10T14:29:47.0000000+00:00' -- author: Flareguy - changes: - - {message: 'Updated asteroid tiles to match their sprites from /tg/. They are much - more vibrant, and should fit in a lot better with their surroundings.', type: Tweak} - - {message: Updated pried tiles to match the appearance of the new tiles better., - type: Tweak} - id: 4513 - time: '2023-08-10T17:46:44.0000000+00:00' -- author: Flareguy - changes: - - {message: 'Updated asteroid tiles to match their sprites from /tg/. They are much - more vibrant, and should fit in a lot better with their surroundings.', type: Tweak} - - {message: Updated pried tiles to match the appearance of the new tiles better., - type: Tweak} - id: 4514 - time: '2023-08-10T18:33:15.435911+00:00' -- author: juliangiebel & mirrorcult - changes: - - {message: 'You may notice that chat text in general has become much prettier and - dynamic. Whispered text is smaller, announcements are larger, and names should - pop out more.', type: Tweak} - id: 4515 - time: '2023-08-10T18:33:15.436963+00:00' -- author: EmoGarbage404 - changes: - - {message: All crates have a brand new look., type: Tweak} - id: 4516 - time: '2023-08-11T00:12:38.0000000+00:00' -- author: EmoGarbage404 - changes: - - {message: Job icons now ignore lighting., type: Fix} - id: 4517 - time: '2023-08-11T00:36:26.0000000+00:00' -- author: Lank - changes: - - {message: 'As disease has been eradicated, Spaceacillin can no longer be created - or found.', type: Remove} - - {message: Creating medicated suture now required Cryptobiolin in place of Spaceacillin., - type: Tweak} - id: 4518 - time: '2023-08-11T03:04:49.0000000+00:00' -- author: crazybrain - changes: - - {message: Added missing emergency security orders to the hardsuit version of HoS's - locker., type: Fix} - id: 4519 - time: '2023-08-11T03:31:13.0000000+00:00' - author: Flareguy changes: - {message: The Microwave and wall-mounted Nanomed now use sprites similar to the @@ -2946,3 +2866,70 @@ Entries: - {message: 'chem dispensers to barratry, you can stop crying now', type: Add} id: 5007 time: '2023-10-14T21:51:33.0000000+00:00' +- author: ike709 + changes: + - {message: 'All non-high-security airlocks can now be pried open by hand when unpowered, + albeit much slower than using a crowbar', type: Tweak} + id: 5008 + time: '2023-10-15T22:17:45.0000000+00:00' +- author: iacore + changes: + - {message: Secure crates are now weldable!, type: Fix} + id: 5009 + time: '2023-10-16T05:27:23.0000000+00:00' +- author: brainfood1183 + changes: + - {message: Behonkers are fixed (in combat use right click to fire laser), type: Fix} + id: 5010 + time: '2023-10-16T05:29:14.0000000+00:00' +- author: ShadowCommander + changes: + - {message: Fixed material reclaimer sound error when processing something., type: Fix} + - {message: Fixed duplicate gib sound when the material reclaimer processes a mob., + type: Fix} + id: 5011 + time: '2023-10-16T05:30:35.0000000+00:00' +- author: EmoGarbage404 + changes: + - {message: Fixed being permanently cuffed if you transformed into a zombie with + cuffs on., type: Fix} + id: 5012 + time: '2023-10-16T05:31:04.0000000+00:00' +- author: Lomcastar + changes: + - {message: Uranium crabs are more radioactive!, type: Tweak} + id: 5013 + time: '2023-10-16T05:34:18.0000000+00:00' +- author: JoeHammad + changes: + - {message: Stun batons now take three hits to stun and have had their battery use + dropped by half, type: Tweak} + id: 5014 + time: '2023-10-16T11:39:06.0000000+00:00' +- author: metalgearsloth + changes: + - {message: Fix item drops mispredicting., type: Fix} + id: 5015 + time: '2023-10-16T11:49:41.0000000+00:00' +- author: Vasilis + changes: + - {message: Pneumatic Cannons can no longer shoot arrows., type: Tweak} + id: 5016 + time: '2023-10-17T22:58:05.0000000+00:00' +- author: Vasilis + changes: + - {message: Spears and arrows can now only hold up to 2u of liquids instead of 5u., + type: Tweak} + id: 5017 + time: '2023-10-17T23:01:25.0000000+00:00' +- author: notquitehadouken + changes: + - {message: The grey stick that shows up when you wide swing a weapon now looks + like the weapon used., type: Tweak} + id: 5018 + time: '2023-10-18T01:12:00.0000000+00:00' +- author: metalgearsloth + changes: + - {message: Fix vaulting mispredict., type: Fix} + id: 5019 + time: '2023-10-18T05:11:33.0000000+00:00' diff --git a/Resources/Locale/en-US/guidebook/guides.ftl b/Resources/Locale/en-US/guidebook/guides.ftl index 9fc69839c08..8893db9b230 100644 --- a/Resources/Locale/en-US/guidebook/guides.ftl +++ b/Resources/Locale/en-US/guidebook/guides.ftl @@ -34,6 +34,7 @@ guide-entry-botanicals = Botanicals guide-entry-cloning = Cloning guide-entry-cryogenics = Cryogenics guide-entry-science = Science +guide-entry-technologies = Technologies guide-entry-anomalous-research = Anomalous Research guide-entry-scanners-and-vessels = Scanners and Vessels guide-entry-ape = A.P.E. diff --git a/Resources/Locale/en-US/research/components/research-console-component.ftl b/Resources/Locale/en-US/research/components/research-console-component.ftl index 1063e6ebcb2..196983efcd4 100644 --- a/Resources/Locale/en-US/research/components/research-console-component.ftl +++ b/Resources/Locale/en-US/research/components/research-console-component.ftl @@ -14,5 +14,7 @@ research-console-cost = Cost: [color=orchid]{$amount}[/color] research-console-unlocks-list-start = Unlocks: research-console-unlocks-list-entry = - [color=yellow]{$name}[/color] research-console-unlocks-list-entry-generic = - [color=green]{$text}[/color] +research-console-prereqs-list-start = Requires: +research-console-prereqs-list-entry = - [color=orchid]{$text}[/color] research-console-no-access-popup = No access! diff --git a/Resources/Locale/en-US/ss14-ru/prototypes/entities/mobs/npcs/carp.ftl b/Resources/Locale/en-US/ss14-ru/prototypes/entities/mobs/npcs/carp.ftl index e8f65987418..a424af22b6e 100644 --- a/Resources/Locale/en-US/ss14-ru/prototypes/entities/mobs/npcs/carp.ftl +++ b/Resources/Locale/en-US/ss14-ru/prototypes/entities/mobs/npcs/carp.ftl @@ -6,6 +6,8 @@ ent-MobCarpMagic = magicarp .desc = Looks like some kind of fish. Might be magical. ent-MobCarpHolo = holocarp .desc = Carp made out of holographic energies. Sadly for you, it is very much real. +ent-MobCarpRainbow = rainbow carp + .desc = Wow such a shiny fishie! ent-MobCarpSalvage = { ent-MobCarp } .suffix = Salvage Ruleset .desc = { ent-MobCarp.desc } diff --git a/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/weapons/security.ftl b/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/weapons/security.ftl index f53c523d6ac..ef259b190cd 100644 --- a/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/weapons/security.ftl +++ b/Resources/Locale/en-US/ss14-ru/prototypes/entities/objects/weapons/security.ftl @@ -4,5 +4,7 @@ ent-Truncheon = truncheon .desc = A rigid, steel-studded baton, meant to harm. ent-Flash = flash .desc = An ultrabright flashbulb with a trigger, which causes the victim to be dazed and lose their eyesight for a moment. Useless when burnt out. +ent-SciFlash = flash + .desc = { ent-Flash.desc } ent-PortableFlasher = portable flasher .desc = An ultrabright flashbulb with a proximity trigger, useful for making an area security-only. diff --git a/Resources/Locale/ru-RU/guidebook/guides.ftl b/Resources/Locale/ru-RU/guidebook/guides.ftl index e5494b2a413..7a2a015d8fe 100644 --- a/Resources/Locale/ru-RU/guidebook/guides.ftl +++ b/Resources/Locale/ru-RU/guidebook/guides.ftl @@ -34,6 +34,7 @@ guide-entry-botanicals = Ботаника guide-entry-cloning = Клонирование guide-entry-cryogenics = Криогеника guide-entry-survival = Выживание +guide-entry-technologies = Технологии guide-entry-anomalous-research = Исследование аномалий guide-entry-scanners-and-vessels = Сканеры и сосуды guide-entry-ape = М.А.К.А.К. diff --git a/Resources/Locale/ru-RU/research/components/research-console-component.ftl b/Resources/Locale/ru-RU/research/components/research-console-component.ftl index f663ee878c7..9f11efc3388 100644 --- a/Resources/Locale/ru-RU/research/components/research-console-component.ftl +++ b/Resources/Locale/ru-RU/research/components/research-console-component.ftl @@ -14,4 +14,6 @@ research-console-unlocks-list-entry-generic = - [color=green]{ $text }[/color] research-console-menu-research-points-text = Очки исследований: { $points } research-console-menu-server-selection-button = Список серверов research-console-menu-server-sync-button = Синхронизировать +research-console-prereqs-list-start = Требует: +research-console-prereqs-list-entry = - [color=orchid]{ $text }[/color] research-console-no-access-popup = Нет доступа! diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/mobs/npcs/carp.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/mobs/npcs/carp.ftl index 03dc31d1314..176277564ab 100644 --- a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/mobs/npcs/carp.ftl +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/mobs/npcs/carp.ftl @@ -6,6 +6,8 @@ ent-MobCarpMagic = мэджикарп .desc = Похож на какую-то рыбу. Может быть волшебным. ent-MobCarpHolo = голокарп .desc = Карп из голографической энергии. К сожалению для вас, он вполне реален. +ent-MobCarpRainbow = радужный карп + .desc = Ух ты, какая блестящая рыбка! ent-MobCarpSalvage = { ent-MobCarp } .suffix = Salvage Ruleset .desc = { ent-MobCarp.desc } diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/weapons/security.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/weapons/security.ftl index 361d307c979..0e3286e6e2c 100644 --- a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/weapons/security.ftl +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/weapons/security.ftl @@ -4,5 +4,7 @@ ent-Truncheon = дубинка .desc = Жёсткая дубинка со стальным сердечником, предназначенная причинять боль. ent-Flash = вспышка .desc = Сверхъяркая лампочка с кнопкой включения, вызывает оцепенение и кратковременную потерю зрения. Бесполезна, когда перегорает. +ent-SciFlash = вспышка + .desc = { ent-Flash.desc } ent-PortableFlasher = переносная вспышка .desc = Сверхъяркая лампочка с дистанционным триггером, полезная для создания зоны, только для СБ. diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/structures/shuttles/thrusters.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/structures/shuttles/thrusters.ftl index 93de50b5f89..a21a989965f 100644 --- a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/structures/shuttles/thrusters.ftl +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/structures/shuttles/thrusters.ftl @@ -2,11 +2,17 @@ ent-BaseThruster = ракетный двигатель .desc = Он делает ньооооооом. ent-Thruster = ракетный двигатель .desc = Он делает ньооооооом. +ent-ThrusterUnanchored = { ent-Thruster } + .suffix = Unanchored + .desc = { ent-Thruster.desc } ent-DebugThruster = ракетный двигатель .desc = Он делает ньооооооом. Не требует ни питания, ни свободного места. .suffix = DEBUG ent-Gyroscope = гироскоп .desc = Увеличивает потенциальное угловое вращение шаттла. +ent-GyroscopeUnanchored = { ent-Gyroscope } + .suffix = Unanchored + .desc = { ent-Gyroscope.desc } ent-DebugGyroscope = гироскоп .desc = Увеличивает потенциальное угловое вращение шаттла. .suffix = DEBUG diff --git a/Resources/Maps/Test/dev_map.yml b/Resources/Maps/Test/dev_map.yml index fd0884b2b89..a573ee26459 100644 --- a/Resources/Maps/Test/dev_map.yml +++ b/Resources/Maps/Test/dev_map.yml @@ -407,6 +407,11 @@ entities: - pos: -9.5,0.5 parent: 179 type: Transform + - uid: 1182 + components: + - pos: 6.5,28.5 + parent: 179 + type: Transform - proto: AirlockCargo entities: - uid: 87 @@ -981,29 +986,21 @@ entities: - pos: -2.5,11.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - uid: 764 components: - pos: -1.5,11.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - uid: 765 components: - pos: -7.5,0.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - uid: 766 components: - pos: -0.5,11.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - uid: 767 components: - pos: -3.5,10.5 @@ -1174,36 +1171,26 @@ entities: - pos: -8.5,0.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - uid: 803 components: - pos: 2.5,-2.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - uid: 804 components: - pos: 2.5,-3.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - uid: 805 components: - pos: -9.5,0.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - uid: 806 components: - pos: -10.5,0.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - uid: 807 components: - pos: -14.5,0.5 @@ -1259,22 +1246,16 @@ entities: - pos: 7.5,5.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - uid: 818 components: - pos: 7.5,7.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - uid: 819 components: - pos: 7.5,8.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - uid: 820 components: - pos: 7.5,9.5 @@ -1385,8 +1366,6 @@ entities: - pos: 0.5,11.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - uid: 842 components: - pos: 2.5,12.5 @@ -1462,8 +1441,11 @@ entities: - pos: 7.5,6.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound + - uid: 873 + components: + - pos: 8.5,21.5 + parent: 179 + type: Transform - uid: 877 components: - pos: -6.5,3.5 @@ -1474,36 +1456,26 @@ entities: - pos: -2.5,-4.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - uid: 879 components: - pos: -1.5,-4.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - uid: 880 components: - pos: -0.5,-4.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - uid: 881 components: - pos: 0.5,-4.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - uid: 882 components: - pos: 1.5,-4.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - uid: 883 components: - pos: 2.5,-4.5 @@ -1519,106 +1491,76 @@ entities: - pos: 4.5,-4.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - uid: 886 components: - pos: 5.5,-4.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - uid: 887 components: - pos: 6.5,-4.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - uid: 888 components: - pos: 7.5,-4.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - uid: 889 components: - pos: 8.5,-4.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - uid: 890 components: - pos: 8.5,-3.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - uid: 891 components: - pos: 8.5,-2.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - uid: 892 components: - pos: 8.5,-1.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - uid: 893 components: - pos: 8.5,-0.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - uid: 894 components: - pos: 8.5,0.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - uid: 895 components: - pos: 8.5,1.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - uid: 896 components: - pos: 8.5,2.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - uid: 897 components: - pos: 8.5,3.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - uid: 898 components: - pos: 8.5,4.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - uid: 899 components: - pos: 8.5,5.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - uid: 900 components: - pos: -14.5,5.5 @@ -1639,6 +1581,11 @@ entities: - pos: -15.5,4.5 parent: 179 type: Transform + - uid: 909 + components: + - pos: 8.5,20.5 + parent: 179 + type: Transform - uid: 970 components: - pos: 9.5,12.5 @@ -1669,22 +1616,16 @@ entities: - pos: -5.5,-14.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - uid: 1027 components: - pos: -5.5,-13.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - uid: 1028 components: - pos: -5.5,-12.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - uid: 1029 components: - pos: -4.5,-12.5 @@ -1700,8 +1641,6 @@ entities: - pos: -2.5,-12.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - uid: 1032 components: - pos: -1.5,-12.5 @@ -1722,8 +1661,6 @@ entities: - pos: 1.5,-12.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - uid: 1036 components: - pos: 2.5,-12.5 @@ -1744,15 +1681,11 @@ entities: - pos: 0.5,-14.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - uid: 1040 components: - pos: 0.5,-15.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - uid: 1041 components: - pos: -1.5,-13.5 @@ -1763,29 +1696,21 @@ entities: - pos: -1.5,-14.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - uid: 1043 components: - pos: -1.5,-15.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - uid: 1044 components: - pos: 4.5,-12.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - uid: 1045 components: - pos: 4.5,-13.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - uid: 1051 components: - pos: 9.5,15.5 @@ -1901,8 +1826,6 @@ entities: - pos: 13.5,24.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - uid: 1082 components: - pos: 12.5,24.5 @@ -2283,6 +2206,26 @@ entities: - pos: 16.5,14.5 parent: 179 type: Transform + - uid: 1177 + components: + - pos: 8.5,22.5 + parent: 179 + type: Transform + - uid: 1178 + components: + - pos: 8.5,23.5 + parent: 179 + type: Transform + - uid: 1179 + components: + - pos: 8.5,24.5 + parent: 179 + type: Transform + - uid: 1180 + components: + - pos: 8.5,25.5 + parent: 179 + type: Transform - proto: CableApcStack entities: - uid: 70 @@ -2317,22 +2260,16 @@ entities: - pos: -6.5,-13.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - uid: 1020 components: - pos: -6.5,-12.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - uid: 1021 components: - pos: -6.5,-11.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - proto: CableHVStack entities: - uid: 184 @@ -2347,22 +2284,16 @@ entities: - pos: -6.5,-13.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - uid: 1024 components: - pos: -5.5,-13.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - uid: 1025 components: - pos: -5.5,-14.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - proto: CableMVStack entities: - uid: 325 @@ -3031,6 +2962,14 @@ entities: - pos: -0.5,-11.5 parent: 179 type: Transform +- proto: ComputerSurveillanceCameraMonitor + entities: + - uid: 1185 + components: + - rot: 3.141592653589793 rad + pos: -8.5,1.5 + parent: 179 + type: Transform - proto: ComputerTechnologyDiskTerminal entities: - uid: 1088 @@ -3280,6 +3219,13 @@ entities: - 0 - 0 type: EntityStorage +- proto: CrewMonitoringServer + entities: + - uid: 1183 + components: + - pos: 9.5,25.5 + parent: 179 + type: Transform - proto: Crowbar entities: - uid: 147 @@ -3543,8 +3489,6 @@ entities: pos: 5.5,-0.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - proto: GasPipeFourway entities: - uid: 728 @@ -3552,8 +3496,6 @@ entities: - pos: 5.5,-1.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - proto: GasPipeStraight entities: - uid: 749 @@ -3562,8 +3504,6 @@ entities: pos: 5.5,-3.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - proto: GasPipeTJunction entities: - uid: 748 @@ -3571,8 +3511,6 @@ entities: - pos: 5.5,-2.5 parent: 179 type: Transform - - enabled: True - type: AmbientSound - proto: GasPort entities: - uid: 457 @@ -3605,8 +3543,6 @@ entities: pos: 6.5,-3.5 parent: 179 type: Transform - - enabled: False - type: AmbientSound - proto: GasVentScrubber entities: - uid: 452 @@ -3615,8 +3551,6 @@ entities: pos: 6.5,-2.5 parent: 179 type: Transform - - enabled: False - type: AmbientSound - proto: GasVolumePump entities: - uid: 160 @@ -3719,6 +3653,13 @@ entities: - pos: -3.5805476,0.74100244 parent: 179 type: Transform +- proto: HandheldCrewMonitor + entities: + - uid: 1184 + components: + - pos: 1.6819578,7.502847 + parent: 179 + type: Transform - proto: HandheldHealthAnalyzer entities: - uid: 513 @@ -4115,56 +4056,6 @@ entities: - 0 - 0 type: EntityStorage -- proto: LockerSyndicatePersonalFilled - entities: - - uid: 909 - components: - - pos: -7.5,1.5 - parent: 179 - type: Transform - - air: - volume: 200 - immutable: False - temperature: 293.14957 - moles: - - 2.9923203 - - 11.2568245 - - 0 - - 0 - - 0 - - 0 - - 0 - - 0 - - 0 - - 0 - - 0 - - 0 - type: EntityStorage -- proto: LockerWardenFilled - entities: - - uid: 873 - components: - - pos: -8.5,1.5 - parent: 179 - type: Transform - - air: - volume: 200 - immutable: False - temperature: 293.14957 - moles: - - 2.9923203 - - 11.2568245 - - 0 - - 0 - - 0 - - 0 - - 0 - - 0 - - 0 - - 0 - - 0 - - 0 - type: EntityStorage - proto: LockerWeldingSuppliesFilled entities: - uid: 871 @@ -4197,8 +4088,6 @@ entities: - pos: 16.5,25.5 parent: 179 type: Transform - - enabled: False - type: AmbientSound - proto: MachineAnomalyVessel entities: - uid: 1087 @@ -4628,16 +4517,12 @@ entities: - pos: 16.5,27.5 parent: 179 type: Transform - - enabled: False - type: AmbientSound - uid: 1076 components: - rot: 1.5707963267948966 rad pos: 15.5,22.5 parent: 179 type: Transform - - enabled: False - type: AmbientSound - proto: PoweredSmallLight entities: - uid: 163 @@ -5152,6 +5037,13 @@ entities: - pos: -3.5,4.5 parent: 179 type: Transform +- proto: SpawnVehicleATV + entities: + - uid: 1176 + components: + - pos: -7.5,1.5 + parent: 179 + type: Transform - proto: SpawnVehicleJanicart entities: - uid: 904 @@ -5214,6 +5106,33 @@ entities: - pos: -4.3012447,8.817795 parent: 179 type: Transform +- proto: SurveillanceCameraGeneral + entities: + - uid: 1186 + components: + - rot: 3.141592653589793 rad + pos: -2.5,10.5 + parent: 179 + type: Transform + - uid: 1188 + components: + - rot: -1.5707963267948966 rad + pos: 15.5,21.5 + parent: 179 + type: Transform + - uid: 1190 + components: + - rot: 3.141592653589793 rad + pos: 27.5,10.5 + parent: 179 + type: Transform +- proto: SurveillanceCameraRouterGeneral + entities: + - uid: 1189 + components: + - pos: 9.5,24.5 + parent: 179 + type: Transform - proto: Syringe entities: - uid: 460 @@ -5770,6 +5689,13 @@ entities: - pos: -7.5,4.5 parent: 179 type: Transform +- proto: VehicleKeyATV + entities: + - uid: 1187 + components: + - pos: -6.8905525,1.5128828 + parent: 179 + type: Transform - proto: VehicleKeyJanicart entities: - uid: 14 @@ -7575,6 +7501,39 @@ entities: - pos: 17.5,28.5 parent: 179 type: Transform + - uid: 1181 + components: + - pos: 5.5,28.5 + parent: 179 + type: Transform +- proto: WarpPointBeaconCargo + entities: + - uid: 1175 + components: + - pos: -14.5,3.5 + parent: 179 + type: Transform +- proto: WarpPointBeaconEngineering + entities: + - uid: 1173 + components: + - pos: 5.5,0.5 + parent: 179 + type: Transform +- proto: WarpPointBeaconMedical + entities: + - uid: 1172 + components: + - pos: 17.5,7.5 + parent: 179 + type: Transform +- proto: WarpPointBeaconService + entities: + - uid: 1174 + components: + - pos: 6.5,14.5 + parent: 179 + type: Transform - proto: WaterTankFull entities: - uid: 115 diff --git a/Resources/Prototypes/Body/Prototypes/behonker.yml b/Resources/Prototypes/Body/Prototypes/behonker.yml deleted file mode 100644 index 26289d580d5..00000000000 --- a/Resources/Prototypes/Body/Prototypes/behonker.yml +++ /dev/null @@ -1,11 +0,0 @@ -- type: body - id: Behonker - name: "behonker" - root: hand 1 - slots: - hand 1: - part: LeftArmBorg - connections: - - hand 2 - hand 2: - part: LeftArmBorg diff --git a/Resources/Prototypes/Catalog/Fills/Crates/salvage.yml b/Resources/Prototypes/Catalog/Fills/Crates/salvage.yml index cd5daf6f722..feae7a8942f 100644 --- a/Resources/Prototypes/Catalog/Fills/Crates/salvage.yml +++ b/Resources/Prototypes/Catalog/Fills/Crates/salvage.yml @@ -92,30 +92,33 @@ id: CratePartsT3 name: tier 3 parts crate description: Contains 5 random tier 3 parts for upgrading machines. - components: - - type: StorageFill - contents: - - id: SalvagePartsT3Spawner - amount: 5 + # TODO add contents. + #components: + #- type: StorageFill + # contents: + # - id: SalvagePartsT3Spawner + # amount: 5 - type: entity parent: CrateGenericSteel id: CratePartsT3T4 name: tier 3/4 parts crate description: Contains 5 random tier 3 or 4 parts for upgrading machines. - components: - - type: StorageFill - contents: - - id: SalvagePartsT3T4Spawner - amount: 5 + # TODO add contents. + #components: + # type: StorageFill + # contents: + # - id: SalvagePartsT3T4Spawner + # amount: 5 - type: entity parent: CrateGenericSteel id: CratePartsT4 name: tier 4 parts crate description: Contains 5 random tier 4 parts for upgrading machines. - components: - - type: StorageFill - contents: - - id: SalvagePartsT4Spawner - amount: 5 + # TODO add contents. + #components: + #- type: StorageFill + # contents: + # - id: SalvagePartsT4Spawner + # amount: 5 diff --git a/Resources/Prototypes/Catalog/Fills/Lockers/suit_storage.yml b/Resources/Prototypes/Catalog/Fills/Lockers/suit_storage.yml index 09afc383495..7ee7351fbe2 100644 --- a/Resources/Prototypes/Catalog/Fills/Lockers/suit_storage.yml +++ b/Resources/Prototypes/Catalog/Fills/Lockers/suit_storage.yml @@ -39,7 +39,7 @@ - id: OxygenTankFilled - id: ClothingOuterSuitEmergency - id: ClothingMaskBreath - + #Prisoner EVA - type: entity id: SuitStorageEVAPrisoner @@ -80,7 +80,7 @@ - id: OxygenTankFilled - id: ClothingOuterHardsuitPirateEVA - id: ClothingMaskGas - + #NTSRA Voidsuit - type: entity id: SuitStorageNTSRA @@ -93,7 +93,7 @@ - id: ClothingOuterHardsuitAncientEVA - id: ClothingHeadHelmetAncient - id: ClothingMaskBreath - + #HARDSUITS #Basic hardsuit - type: entity @@ -121,6 +121,8 @@ - id: ClothingShoesBootsMag - id: ClothingOuterHardsuitEngineering - id: ClothingMaskBreath + - type: AccessReader + access: [["Engineering"]] #Atmospherics hardsuit - type: entity @@ -134,6 +136,8 @@ - id: OxygenTankFilled - id: ClothingOuterHardsuitAtmos - id: ClothingMaskBreath + - type: AccessReader + access: [["Atmospherics"]] #Security hardsuit - type: entity @@ -147,6 +151,8 @@ - id: OxygenTankFilled - id: ClothingOuterHardsuitSecurity - id: ClothingMaskBreath + - type: AccessReader + access: [["Security"]] #CE's hardsuit - type: entity @@ -162,6 +168,8 @@ - id: ClothingShoesBootsMagAdv - id: ClothingOuterHardsuitEngineeringWhite - id: ClothingMaskBreath + - type: AccessReader + access: [["ChiefEngineer"]] #CMO's hardsuit - type: entity @@ -175,6 +183,8 @@ - id: OxygenTankFilled - id: ClothingOuterHardsuitMedical - id: ClothingMaskBreathMedical + - type: AccessReader + access: [ [ "ChiefMedicalOfficer" ] ] #RD's hardsuit - type: entity @@ -188,6 +198,8 @@ - id: OxygenTankFilled - id: ClothingOuterHardsuitRd - id: ClothingMaskBreath + - type: AccessReader + access: [ [ "ResearchDirector" ] ] #HOS's hardsuit - type: entity @@ -202,6 +214,8 @@ - id: JetpackSecurityFilled - id: ClothingOuterHardsuitSecurityRed - id: ClothingMaskGasSwat + - type: AccessReader + access: [["HeadOfSecurity"]] #Warden's hardsuit - type: entity @@ -215,6 +229,8 @@ - id: OxygenTankFilled - id: ClothingOuterHardsuitWarden - id: ClothingMaskBreath + - type: AccessReader + access: [["Armory"]] #Captain's hardsuit - type: entity @@ -228,6 +244,8 @@ - id: OxygenTankFilled - id: ClothingOuterHardsuitCap - id: ClothingMaskGasCaptain + - type: AccessReader + access: [["Captain"]] #Salvage hardsuit - type: entity @@ -242,6 +260,8 @@ - id: ClothingShoesBootsMag - id: ClothingOuterHardsuitSpatio - id: ClothingMaskGasExplorer + - type: AccessReader + access: [["Salvage"]] #Blood-red hardsuit - type: entity @@ -282,4 +302,3 @@ - id: OxygenTankFilled - id: ClothingOuterHardsuitWizard - id: ClothingMaskBreath - \ No newline at end of file diff --git a/Resources/Prototypes/Catalog/VendingMachines/Inventories/robotics.yml b/Resources/Prototypes/Catalog/VendingMachines/Inventories/robotics.yml index 06a7398a23c..e64acaa9f26 100644 --- a/Resources/Prototypes/Catalog/VendingMachines/Inventories/robotics.yml +++ b/Resources/Prototypes/Catalog/VendingMachines/Inventories/robotics.yml @@ -2,7 +2,7 @@ id: RoboticsInventory startingInventory: CableApcStack: 4 - Flash: 4 + SciFlash: 4 ProximitySensor: 3 RemoteSignaller: 3 Igniter: 3 # its more ordnance but yeah diff --git a/Resources/Prototypes/Entities/Markers/warp_point.yml b/Resources/Prototypes/Entities/Markers/warp_point.yml index d7651e1245e..8e15994dc5f 100644 --- a/Resources/Prototypes/Entities/Markers/warp_point.yml +++ b/Resources/Prototypes/Entities/Markers/warp_point.yml @@ -13,6 +13,8 @@ name: warp point (beacon) components: - type: NavMapBeacon + - type: WarpPoint + location: beacon - type: entity parent: WarpPoint @@ -21,6 +23,8 @@ suffix: ninja bombing target components: - type: BombingTarget + - type: WarpPoint + location: bombing target - type: Sprite layers: - state: pink @@ -36,6 +40,8 @@ - type: NavMapBeacon text: bar color: "#791500" + - type: WarpPoint + location: bar - type: entity id: WarpPointBeaconCargo @@ -45,6 +51,8 @@ - type: NavMapBeacon text: cargo color: "#A46106" + - type: WarpPoint + location: cargo - type: entity id: WarpPointBeaconCommand @@ -54,6 +62,8 @@ - type: NavMapBeacon text: command color: "#334E6D" + - type: WarpPoint + location: command - type: entity id: WarpPointBeaconEngineering @@ -63,6 +73,8 @@ - type: NavMapBeacon text: engineering color: "#EFB341" + - type: WarpPoint + location: engineering - type: entity id: WarpPointBeaconMedical @@ -72,6 +84,8 @@ - type: NavMapBeacon text: medical color: "#52B4E9" + - type: WarpPoint + location: medical - type: entity id: WarpPointBeaconNeutral @@ -81,6 +95,8 @@ - type: NavMapBeacon text: neutral color: "#D4D4D4" + - type: WarpPoint + location: neutral - type: entity id: WarpPointBeaconScience @@ -90,6 +106,8 @@ - type: NavMapBeacon text: science color: "#D381C9" + - type: WarpPoint + location: science - type: entity id: WarpPointBeaconService @@ -99,3 +117,5 @@ - type: NavMapBeacon text: service color: "#9FED58" + - type: WarpPoint + location: service diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml b/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml index 0077fddcfc4..adba78141cc 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml @@ -1,6 +1,6 @@ - type: entity name: bat - parent: [ SimpleMobBase, FlyingMobBase ] + parent: [ SimpleMobBase, FlyingMobBase, MobCombat ] id: MobBat description: Some cultures find them terrifying, others crunchy on the teeth. components: @@ -51,7 +51,6 @@ - type: ReplacementAccent accent: mouse - type: MeleeWeapon - hidden: true soundHit: path: /Audio/Effects/bite.ogg angle: 0 @@ -126,13 +125,12 @@ - type: entity name: bee suffix: Angry - parent: MobBee + parent: [ MobBee, MobCombat ] id: MobAngryBee description: How nice a bee. Oh no, it looks angry and wants my pizza. components: - type: CombatMode - type: MeleeWeapon - hidden: true angle: 0 animation: WeaponArcBite damage: @@ -668,7 +666,7 @@ - type: entity name: gorilla - parent: SimpleMobBase + parent: [ SimpleMobBase, MobCombat ] id: MobGorilla description: Smashes, roars, looks cool. Don't stand near one. components: @@ -722,7 +720,7 @@ - type: entity name: kangaroo - parent: SimpleMobBase + parent: [ SimpleMobBase, MobCombat ] id: MobKangaroo description: A large marsupial herbivore. It has powerful hind legs, with nails that resemble long claws. components: @@ -1376,7 +1374,7 @@ - type: entity name: grenade penguin - parent: SimpleMobBase + parent: [ SimpleMobBase, MobCombat ] id: MobGrenadePenguin description: A small penguin with a grenade strapped around its neck. Harvested by the Syndicate from icy shit-hole planets. components: @@ -1420,7 +1418,6 @@ - id: FoodMeatPenguin amount: 3 - type: MeleeWeapon - hidden: true angle: 0 animation: WeaponArcBite damage: @@ -1603,7 +1600,7 @@ # random sprite state when you spawn it. - type: entity name: tarantula - parent: SimpleMobBase + parent: [ SimpleMobBase, MobCombat ] id: MobGiantSpider description: Widely recognized to be the literal worst thing in existence. components: @@ -1641,7 +1638,6 @@ 0: Alive 90: Dead - type: MeleeWeapon - hidden: true angle: 0 animation: WeaponArcBite soundHit: @@ -1731,7 +1727,6 @@ - DoorBumpOpener - FootstepSound - type: MeleeWeapon - hidden: true angle: 0 animation: WeaponArcBite soundHit: @@ -1984,7 +1979,7 @@ - type: entity name: corrupted corgi - parent: MobCorgi + parent: [ MobCorgi, MobCombat ] id: MobCorgiNarsi description: Ian! No! components: @@ -2001,7 +1996,6 @@ Dead: Base: narsian_dead - type: MeleeWeapon - hidden: true soundHit: path: /Audio/Effects/bite.ogg angle: 0 @@ -2314,7 +2308,7 @@ - type: entity name: hamster - parent: SimpleMobBase + parent: [ SimpleMobBase, MobCombat ] id: MobHamster description: A cute, fluffy, robust hamster. components: @@ -2421,7 +2415,6 @@ Blunt: 0.1 - type: CombatMode - type: MeleeWeapon - hidden: true soundHit: path: /Audio/Effects/bite.ogg angle: 0 diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/argocyte.yml b/Resources/Prototypes/Entities/Mobs/NPCs/argocyte.yml index cde11bf222b..4c36efa1773 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/argocyte.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/argocyte.yml @@ -1,6 +1,6 @@ - type: entity save: false - parent: BaseSimpleMob + parent: [ BaseSimpleMob, MobCombat ] id: BaseMobArgocyte suffix: AI description: A dangerous alien found on the wrong side of planets, known for their propensity for munching on ruins. @@ -31,7 +31,6 @@ - type: Insulated - type: CombatMode - type: MeleeWeapon - hidden: true angle: 0 animation: WeaponArcBite damage: diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/behonker.yml b/Resources/Prototypes/Entities/Mobs/NPCs/behonker.yml index cb7b9f4c015..3b3b9b44120 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/behonker.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/behonker.yml @@ -1,6 +1,6 @@ - type: entity name: behonker - parent: [ SimpleSpaceMobBase, FlyingMobBase ] + parent: [ SimpleSpaceMobBase, FlyingMobBase, MobCombat ] id: BaseMobBehonker abstract: true description: A floating demon aspect of the honkmother. @@ -13,7 +13,26 @@ - type: GhostTakeoverAvailable - type: HTN rootTask: - task: SimpleHostileCompound + task: SimpleRangedHostileCompound + - type: HitscanBatteryAmmoProvider + proto: RedLaser + fireCost: 62.5 + - type: Battery + maxCharge: 1000 + startingCharge: 1000 + - type: BatterySelfRecharger + autoRecharge: true + autoRechargeRate: 40 + - type: Gun + fireRate: 0.75 + useKey: false + selectedMode: SemiAuto + availableModes: + - SemiAuto + soundGunshot: /Audio/Weapons/Guns/Gunshots/laser_clown.ogg + - type: SpamEmitSound + sound: + collection: BikeHorn - type: NpcFactionMember factions: - SimpleHostile @@ -74,8 +93,9 @@ spawned: - id: MaterialBananium1 amount: 2 + - id: WeaponBehonkerLaser + amount: 1 - type: MeleeWeapon - hidden: true soundHit: path: /Audio/Weapons/Xeno/alien_claw_flesh3.ogg damage: @@ -92,10 +112,6 @@ Radiation: 10 - type: Input context: "human" - - type: Hands - showInHands: false - - type: Body - prototype: Behonker - type: entity name: behonker diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/carp.yml b/Resources/Prototypes/Entities/Mobs/NPCs/carp.yml index 5b32601033d..1f598dc10bc 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/carp.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/carp.yml @@ -1,7 +1,7 @@ - type: entity name: space carp id: BaseMobCarp - parent: [ SimpleSpaceMobBase, FlyingMobBase ] + parent: [ SimpleSpaceMobBase, FlyingMobBase, MobCombat ] description: It's a space carp. abstract: true components: @@ -56,7 +56,6 @@ amount: 2 - type: MeleeWeapon altDisarm: false - hidden: true angle: 0 animation: WeaponArcBite soundHit: @@ -128,6 +127,18 @@ - type: TypingIndicator proto: robot +- type: entity + parent: MobCarp + id: MobCarpRainbow + name: rainbow carp + description: Wow such a shiny fishie! + components: + - type: PointLight + radius: 1.5 + energy: 0.5 + - type: RgbLightController + layers: [ 0 ] + - type: entity id: MobCarpSalvage parent: MobCarp diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/elemental.yml b/Resources/Prototypes/Entities/Mobs/NPCs/elemental.yml index beed7db43ce..8ab65c340ea 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/elemental.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/elemental.yml @@ -76,7 +76,7 @@ - type: ZombieImmune - type: entity - parent: MobElementalBase + parent: [ MobElementalBase, MobCombat ] id: MobQuartzCrab name: quartz crab description: An ore crab made from quartz. @@ -88,7 +88,6 @@ rootTask: task: SimpleHostileCompound - type: MeleeWeapon - hidden: true soundHit: path: /Audio/Weapons/Xeno/alien_claw_flesh3.ogg damage: @@ -116,7 +115,7 @@ acts: [ "Destruction" ] - type: entity - parent: MobElementalBase + parent: [ MobElementalBase, MobCombat ] id: MobIronCrab name: ore crab description: An ore crab made from iron. @@ -128,7 +127,6 @@ rootTask: task: SimpleHostileCompound - type: MeleeWeapon - hidden: true soundHit: path: /Audio/Weapons/Xeno/alien_claw_flesh3.ogg damage: @@ -159,7 +157,7 @@ acts: [ "Destruction" ] - type: entity - parent: MobElementalBase + parent: [ MobElementalBase, MobCombat ] id: MobUraniumCrab name: ore crab description: An ore crab made from uranium. @@ -171,7 +169,6 @@ rootTask: task: IdleCompound - type: MeleeWeapon - hidden: true soundHit: path: /Audio/Weapons/Xeno/alien_claw_flesh3.ogg damage: @@ -185,7 +182,8 @@ factions: - SimpleHostile - type: RadiationSource - intensity: 0.3 + intensity: 2 + slope: 0.3 - type: Destructible thresholds: - trigger: @@ -198,8 +196,8 @@ - !type:SpawnEntitiesBehavior spawn: UraniumOre1: - min: 4 - max: 6 + min: 8 + max: 10 - !type:DoActsBehavior acts: [ "Destruction" ] - type: PointLight @@ -211,12 +209,12 @@ name: Reagent slime id: ReagentSlime suffix: Water - parent: MobAdultSlimes + parent: [ MobAdultSlimes, MobCombat ] description: It consists of a liquid, and it wants to dissolve you in itself. components: - type: NpcFactionMember factions: - - SimpleHostile + - SimpleHostile - type: Sprite drawdepth: Mobs sprite: Mobs/Aliens/elemental.rsi @@ -240,7 +238,7 @@ speedModifierThresholds: 50: 0.4 - type: Bloodstream - bloodReagent: Water + bloodReagent: Water chemicalMaxVolume: 100 - type: StatusEffects allowed: @@ -350,7 +348,7 @@ - map: [ "enum.DamageStateVisualLayers.Base" ] state: alive color: "#128e80" - + - type: entity id: ReagentSlimeTHC parent: ReagentSlime @@ -367,7 +365,7 @@ - map: [ "enum.DamageStateVisualLayers.Base" ] state: alive color: "#808080" - + - type: entity id: ReagentSlimeBicaridine parent: ReagentSlime @@ -418,7 +416,7 @@ - map: [ "enum.DamageStateVisualLayers.Base" ] state: alive color: "#FA00AF" - + - type: entity id: ReagentSlimeOmnizine parent: ReagentSlime @@ -434,4 +432,4 @@ layers: - map: [ "enum.DamageStateVisualLayers.Base" ] state: alive - color: "#fcf7f9" \ No newline at end of file + color: "#fcf7f9" diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/flesh.yml b/Resources/Prototypes/Entities/Mobs/NPCs/flesh.yml index 43c78c639eb..a09927619ce 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/flesh.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/flesh.yml @@ -1,5 +1,5 @@ - type: entity - parent: SimpleMobBase + parent: [ SimpleMobBase, MobCombat ] id: BaseMobFlesh name: aberrant flesh description: A shambling mass of flesh, animated through anomalous energy. @@ -45,7 +45,6 @@ bloodMaxVolume: 100 - type: CombatMode - type: MeleeWeapon - hidden: true soundHit: path: /Audio/Weapons/Xeno/alien_claw_flesh3.ogg angle: 0 @@ -73,7 +72,6 @@ Dead: Base: dead - type: MeleeWeapon - hidden: true soundHit: path: /Audio/Weapons/Xeno/alien_claw_flesh3.ogg angle: 0 @@ -103,7 +101,6 @@ 0: Alive 50: Dead - type: MeleeWeapon - hidden: true soundHit: path: /Audio/Weapons/Xeno/alien_claw_flesh3.ogg angle: 0 @@ -190,7 +187,6 @@ baseWalkSpeed: 1.5 baseSprintSpeed: 2.5 - type: MeleeWeapon - hidden: true soundHit: path: /Audio/Weapons/Xeno/alien_claw_flesh3.ogg angle: 0 diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/mimic.yml b/Resources/Prototypes/Entities/Mobs/NPCs/mimic.yml index 9675321da07..657ac466f84 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/mimic.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/mimic.yml @@ -1,7 +1,7 @@ - type: entity name: Mimic id: MobMimic - parent: SimpleMobBase + parent: [ SimpleMobBase, MobCombat ] description: Surprise. # When this gets a proper write this should use the object's actual description >:) components: - type: Tag @@ -33,7 +33,6 @@ - MachineLayer - type: AnimationPlayer - type: MeleeWeapon - hidden: true angle: 0 animation: WeaponArcFist damage: diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml b/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml index a167bb51c37..be94050ca2b 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml @@ -570,7 +570,6 @@ 0: Alive 150: Dead - type: MeleeWeapon - hidden: true angle: 0 animation: WeaponArcBite soundHit: diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/regalrat.yml b/Resources/Prototypes/Entities/Mobs/NPCs/regalrat.yml index 557d602bff1..b3f09b999d9 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/regalrat.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/regalrat.yml @@ -1,7 +1,7 @@ - type: entity name: Rat King id: MobRatKing - parent: SimpleMobBase + parent: [ SimpleMobBase, MobCombat ] description: He's da rat. He make da roolz. components: - type: CombatMode @@ -45,7 +45,6 @@ 0: Alive 200: Dead - type: MeleeWeapon - hidden: true soundHit: path: /Audio/Weapons/Xeno/alien_claw_flesh1.ogg angle: 0 @@ -133,7 +132,6 @@ 0: Alive 350: Dead - type: MeleeWeapon - hidden: true soundHit: path: /Audio/Weapons/Xeno/alien_claw_flesh2.ogg angle: 0 @@ -153,7 +151,7 @@ - type: entity name: Rat Servant id: MobRatServant - parent: SimpleMobBase + parent: [ SimpleMobBase, MobCombat ] description: He's da mini rat. He don't make da roolz. noSpawn: true #Must be configured to a King or the AI breaks. components: @@ -208,7 +206,6 @@ - type: Stamina critThreshold: 60 - type: MeleeWeapon - hidden: true soundHit: path: /Audio/Weapons/bladeslice.ogg angle: 0 diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/slimes.yml b/Resources/Prototypes/Entities/Mobs/NPCs/slimes.yml index 47cac320462..905b102f2cd 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/slimes.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/slimes.yml @@ -1,7 +1,7 @@ - type: entity name: basic slime id: MobAdultSlimes - parent: SimpleMobBase + parent: [ SimpleMobBase, MobCombat ] abstract: true description: It looks so much like jelly. I wonder what it tastes like? components: @@ -97,9 +97,7 @@ - type: Body prototype: Slimes requiredLegs: 1 - - type: CombatMode - type: MeleeWeapon - hidden: true soundHit: path: /Audio/Weapons/punch3.ogg angle: 0 diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/space.yml b/Resources/Prototypes/Entities/Mobs/NPCs/space.yml index 62366e0b142..d784f5c162f 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/space.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/space.yml @@ -46,7 +46,6 @@ heatDamageThreshold: 500 coldDamageThreshold: 0 - type: MeleeWeapon - hidden: true soundHit: path: /Audio/Weapons/Xeno/alien_claw_flesh3.ogg angle: 0 @@ -143,7 +142,6 @@ state: glow shader: unshaded - type: MeleeWeapon - hidden: true soundHit: path: /Audio/Weapons/Xeno/alien_claw_flesh3.ogg angle: 0 @@ -249,7 +247,6 @@ layer: - MobLayer - type: MeleeWeapon - hidden: true soundHit: path: /Audio/Effects/bite.ogg angle: 0 diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/spacetick.yml b/Resources/Prototypes/Entities/Mobs/NPCs/spacetick.yml index 08db5857447..c1ac66705a3 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/spacetick.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/spacetick.yml @@ -59,7 +59,6 @@ bloodMaxVolume: 50 - type: CombatMode - type: MeleeWeapon - hidden: true soundHit: path: /Audio/Effects/bite.ogg angle: 0 diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/xeno.yml b/Resources/Prototypes/Entities/Mobs/NPCs/xeno.yml index 9831d20e27a..1626a1bc81a 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/xeno.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/xeno.yml @@ -74,7 +74,6 @@ bloodReagent: FluorosulfuricAcid - type: MeleeWeapon altDisarm: false - hidden: true angle: 0 soundHit: collection: AlienClaw @@ -213,7 +212,6 @@ 150: 0.7 - type: MovementSpeedModifier - type: MeleeWeapon - hidden: true damage: groups: Brute: 12 @@ -251,7 +249,6 @@ - type: MovementSpeedModifier baseSprintSpeed: 4 - type: MeleeWeapon - hidden: true damage: groups: Brute: 10 @@ -285,7 +282,6 @@ - type: MovementSpeedModifier baseSprintSpeed: 6.0 - type: MeleeWeapon - hidden: true damage: groups: Brute: 5 @@ -396,7 +392,6 @@ factions: - Xeno - type: MeleeWeapon - hidden: true angle: 0 animation: WeaponArcBite damage: diff --git a/Resources/Prototypes/Entities/Mobs/Player/dragon.yml b/Resources/Prototypes/Entities/Mobs/Player/dragon.yml index 368d1846925..d188070b269 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/dragon.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/dragon.yml @@ -103,7 +103,6 @@ soundPerceivedByOthers: false # A 75% chance for a loud roar would get old fast. - type: MeleeWeapon altDisarm: false - hidden: true soundHit: path: /Audio/Weapons/Xeno/alien_claw_flesh3.ogg damage: diff --git a/Resources/Prototypes/Entities/Mobs/Player/familiars.yml b/Resources/Prototypes/Entities/Mobs/Player/familiars.yml index 65a47987e90..8a5c319d773 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/familiars.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/familiars.yml @@ -46,7 +46,6 @@ rules: ghost-role-information-cerberus-rules - type: GhostTakeoverAvailable - type: MeleeWeapon - hidden: true angle: 0 animation: WeaponArcBite damage: diff --git a/Resources/Prototypes/Entities/Mobs/Player/guardian.yml b/Resources/Prototypes/Entities/Mobs/Player/guardian.yml index 49c3175fc6b..1e863aa80f8 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/guardian.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/guardian.yml @@ -130,7 +130,7 @@ color: "#40a7d7" shader: unshaded - type: NpcFactionMember - factions: + factions: - Syndicate - type: HTN rootTask: @@ -225,7 +225,6 @@ Burn: 3 - type: InventorySlots - type: MeleeWeapon - hidden: true angle: 30 animation: WeaponArcFist attackRate: 1.8 @@ -238,7 +237,7 @@ nameSegments: - names_clown - type: NpcFactionMember - factions: + factions: - Syndicate - type: HTN rootTask: diff --git a/Resources/Prototypes/Entities/Mobs/Species/base.yml b/Resources/Prototypes/Entities/Mobs/Species/base.yml index 74c676eb688..55473daf157 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/base.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/base.yml @@ -161,7 +161,6 @@ - type: CombatMode canDisarm: true - type: MeleeWeapon - hidden: true soundHit: collection: Punch angle: 30 diff --git a/Resources/Prototypes/Entities/Mobs/Species/reptilian.yml b/Resources/Prototypes/Entities/Mobs/Species/reptilian.yml index 9c6976b78f1..00412e2f8ba 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/reptilian.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/reptilian.yml @@ -42,7 +42,6 @@ damageContainer: Biological damageModifierSet: Scale - type: MeleeWeapon - hidden: true soundHit: path: /Audio/Weapons/pierce.ogg angle: 30 diff --git a/Resources/Prototypes/Entities/Objects/Fun/Instruments/instruments_string.yml b/Resources/Prototypes/Entities/Objects/Fun/Instruments/instruments_string.yml index c29c482dfd0..c71fecd91ba 100644 --- a/Resources/Prototypes/Entities/Objects/Fun/Instruments/instruments_string.yml +++ b/Resources/Prototypes/Entities/Objects/Fun/Instruments/instruments_string.yml @@ -83,6 +83,7 @@ tags: - StringInstrument - type: MeleeWeapon + wideAnimationRotation: 45 damage: types: Blunt: 6 @@ -121,7 +122,7 @@ - back sprite: Objects/Fun/Instruments/guitar.rsi - type: Wieldable - - type: Damageable # Smash it! Does 20 damage a hit, but breaks after 1 hit. + - type: Damageable # Smash it! Does 20 damage a hit, but breaks after 1 hit. damageContainer: Inorganic - type: Destructible thresholds: @@ -144,6 +145,7 @@ types: Blunt: 20 - type: MeleeWeapon + wideAnimationRotation: 45 damage: types: Blunt: 5 diff --git a/Resources/Prototypes/Entities/Objects/Fun/bike_horn.yml b/Resources/Prototypes/Entities/Objects/Fun/bike_horn.yml index 1a95cdd9962..fc20f1a58dd 100644 --- a/Resources/Prototypes/Entities/Objects/Fun/bike_horn.yml +++ b/Resources/Prototypes/Entities/Objects/Fun/bike_horn.yml @@ -32,6 +32,7 @@ - Payload # yes, you can make re-usable prank grenades - BikeHorn - type: MeleeWeapon + wideAnimationRotation: 135 soundHit: collection: BikeHorn params: @@ -77,6 +78,7 @@ params: variation: 0.246 - type: MeleeWeapon + wideAnimationRotation: 135 soundHit: collection: CluwneHorn params: diff --git a/Resources/Prototypes/Entities/Objects/Fun/puppet.yml b/Resources/Prototypes/Entities/Objects/Fun/puppet.yml index 666422ea5cd..bff9fb2e219 100644 --- a/Resources/Prototypes/Entities/Objects/Fun/puppet.yml +++ b/Resources/Prototypes/Entities/Objects/Fun/puppet.yml @@ -1,5 +1,5 @@ - type: entity - parent: BaseItem + parent: [ BaseItem, MobCombat ] id: MrChips name: mr chips suffix: Dummy @@ -25,7 +25,6 @@ allowedStates: - Alive - type: MeleeWeapon - hidden: true soundHit: path: /Audio/Weapons/boxingpunch1.ogg angle: 30 diff --git a/Resources/Prototypes/Entities/Objects/Fun/toys.yml b/Resources/Prototypes/Entities/Objects/Fun/toys.yml index dfa4dbcc7b1..491ae0037a3 100644 --- a/Resources/Prototypes/Entities/Objects/Fun/toys.yml +++ b/Resources/Prototypes/Entities/Objects/Fun/toys.yml @@ -122,6 +122,7 @@ sound: path: /Audio/Items/Toys/mousesqueek.ogg - type: MeleeWeapon + wideAnimationRotation: 180 soundHit: path: /Audio/Items/Toys/mousesqueek.ogg @@ -185,6 +186,7 @@ sound: path: /Audio/Items/Toys/weh.ogg - type: MeleeWeapon + wideAnimationRotation: 180 soundHit: path: /Audio/Items/Toys/weh.ogg @@ -206,6 +208,7 @@ sound: path: /Audio/Items/Toys/muffled_weh.ogg - type: MeleeWeapon + wideAnimationRotation: 180 soundHit: path: /Audio/Items/Toys/muffled_weh.ogg @@ -231,6 +234,7 @@ sound: path: /Audio/Items/Toys/toy_rustle.ogg - type: MeleeWeapon + wideAnimationRotation: 180 soundHit: path: /Audio/Items/Toys/toy_rustle.ogg - type: SolutionContainerManager @@ -353,6 +357,7 @@ sound: path: /Audio/Effects/bite.ogg - type: MeleeWeapon + wideAnimationRotation: -90 soundHit: path: /Audio/Effects/bite.ogg angle: 0 @@ -379,6 +384,7 @@ sound: path: /Audio/Items/Toys/rattle.ogg - type: MeleeWeapon + wideAnimationRotation: 180 soundHit: path: /Audio/Items/Toys/rattle.ogg @@ -394,6 +400,7 @@ sound: path: /Audio/Items/Toys/mousesqueek.ogg - type: MeleeWeapon + wideAnimationRotation: -90 soundHit: path: /Audio/Items/Toys/mousesqueek.ogg - type: Clothing @@ -436,6 +443,7 @@ sound: path: /Audio/Voice/Vox/shriek1.ogg - type: MeleeWeapon + wideAnimationRotation: 180 soundHit: path: /Audio/Voice/Vox/shriek1.ogg @@ -466,6 +474,7 @@ sound: path: /Audio/Weapons/Xeno/alien_spitacid.ogg - type: MeleeWeapon + wideAnimationRotation: 180 soundHit: path: /Audio/Weapons/Xeno/alien_spitacid.ogg diff --git a/Resources/Prototypes/Entities/Objects/Misc/books.yml b/Resources/Prototypes/Entities/Objects/Misc/books.yml index 5bfcaef42d0..8bf992cb2fb 100644 --- a/Resources/Prototypes/Entities/Objects/Misc/books.yml +++ b/Resources/Prototypes/Entities/Objects/Misc/books.yml @@ -84,7 +84,7 @@ id: BookChefGaming parent: BaseItem name: chef gaming - description: A book about cooking written by a gamer chef. + description: A book about cooking written by a gamer chef. components: - type: Sprite sprite: Objects/Misc/books.rsi @@ -156,7 +156,7 @@ id: BookSecurity parent: BaseItem name: security 101 - description: A book about security written by Nanotrasen. The book is stained with blood. It seems to have been used more as a weapon than reading material. + description: A book about security written by Nanotrasen. The book is stained with blood. It seems to have been used more as a weapon than reading material. components: - type: Sprite sprite: Objects/Misc/books.rsi @@ -166,6 +166,7 @@ tags: - Book - type: MeleeWeapon + wideAnimationRotation: 180 damage: types: Blunt: 6 diff --git a/Resources/Prototypes/Entities/Objects/Misc/desk_bell.yml b/Resources/Prototypes/Entities/Objects/Misc/desk_bell.yml index 2c57cc105a8..12406f2890d 100644 --- a/Resources/Prototypes/Entities/Objects/Misc/desk_bell.yml +++ b/Resources/Prototypes/Entities/Objects/Misc/desk_bell.yml @@ -36,6 +36,7 @@ - type: UseDelay delay: 0.5 - type: MeleeWeapon + wideAnimationRotation: 180 soundHit: collection: DeskBell params: diff --git a/Resources/Prototypes/Entities/Objects/Misc/fire_extinguisher.yml b/Resources/Prototypes/Entities/Objects/Misc/fire_extinguisher.yml index 66ab0ab7fb8..a90f598a5dd 100644 --- a/Resources/Prototypes/Entities/Objects/Misc/fire_extinguisher.yml +++ b/Resources/Prototypes/Entities/Objects/Misc/fire_extinguisher.yml @@ -37,6 +37,7 @@ - type: FireExtinguisher hasSafety: true - type: MeleeWeapon + wideAnimationRotation: 180 damage: types: Blunt: 10 diff --git a/Resources/Prototypes/Entities/Objects/Misc/paper.yml b/Resources/Prototypes/Entities/Objects/Misc/paper.yml index 4493ec6190e..5b4e5e24bac 100644 --- a/Resources/Prototypes/Entities/Objects/Misc/paper.yml +++ b/Resources/Prototypes/Entities/Objects/Misc/paper.yml @@ -265,6 +265,7 @@ state: overpriced_pen - type: ItemCooldown - type: MeleeWeapon + wideAnimationRotation: -45 damage: types: Piercing: 15 @@ -464,7 +465,7 @@ whitelist: tags: - Write - insertOnInteract: false + insertOnInteract: false - type: Item sprite: Objects/Misc/clipboard.rsi size: 10 @@ -488,6 +489,7 @@ tags: - Write - type: MeleeWeapon + wideAnimationRotation: 180 damage: types: Blunt: 6 diff --git a/Resources/Prototypes/Entities/Objects/Misc/utensils.yml b/Resources/Prototypes/Entities/Objects/Misc/utensils.yml index b180e7d6316..5f2ce47ba13 100644 --- a/Resources/Prototypes/Entities/Objects/Misc/utensils.yml +++ b/Resources/Prototypes/Entities/Objects/Misc/utensils.yml @@ -11,7 +11,7 @@ tags: - Metal - type: SpaceGarbage - + - type: entity parent: UtensilBase id: UtensilBasePlastic @@ -42,6 +42,7 @@ types: - Fork - type: MeleeWeapon + wideAnimationRotation: 180 attackRate: 1.5 damage: types: @@ -73,6 +74,7 @@ types: - Spoon - type: MeleeWeapon + wideAnimationRotation: 180 attackRate: 1.5 damage: types: diff --git a/Resources/Prototypes/Entities/Objects/Tools/tools.yml b/Resources/Prototypes/Entities/Objects/Tools/tools.yml index c8cca769c79..12a6ede2318 100644 --- a/Resources/Prototypes/Entities/Objects/Tools/tools.yml +++ b/Resources/Prototypes/Entities/Objects/Tools/tools.yml @@ -19,6 +19,7 @@ - state: cutters-cutty-thingy - type: ItemCooldown - type: MeleeWeapon + wideAnimationRotation: -90 damage: types: Piercing: 2 @@ -65,6 +66,7 @@ sprite: Objects/Tools/screwdriver.rsi - type: ItemCooldown - type: MeleeWeapon + wideAnimationRotation: -90 attackRate: 1 damage: types: @@ -105,6 +107,7 @@ sprite: Objects/Tools/wrench.rsi - type: ItemCooldown - type: MeleeWeapon + wideAnimationRotation: 135 attackRate: 1.5 damage: types: @@ -140,6 +143,7 @@ size: 10 - type: ItemCooldown - type: MeleeWeapon + wideAnimationRotation: -135 damage: types: Blunt: 8 @@ -318,6 +322,7 @@ - type: StaticPrice price: 100 - type: MeleeWeapon + wideAnimationRotation: -90 attackRate: 1.5 damage: types: @@ -487,6 +492,7 @@ state: icon - type: ItemCooldown - type: MeleeWeapon + wideAnimationRotation: -135 damage: types: Blunt: 14 @@ -512,8 +518,14 @@ - type: Item sprite: Objects/Tools/rolling_pin.rsi size: 10 + - type: Clothing + sprite: Objects/Tools/rolling_pin.rsi + quickEquip: false + slots: + - Belt - type: ItemCooldown - type: MeleeWeapon + wideAnimationRotation: -135 damage: types: Blunt: 7 diff --git a/Resources/Prototypes/Entities/Objects/Tools/welders.yml b/Resources/Prototypes/Entities/Objects/Tools/welders.yml index 3a105a29947..7c3de82d0ad 100644 --- a/Resources/Prototypes/Entities/Objects/Tools/welders.yml +++ b/Resources/Prototypes/Entities/Objects/Tools/welders.yml @@ -30,6 +30,7 @@ shader: unshaded - type: ItemCooldown - type: MeleeWeapon + wideAnimationRotation: -90 damage: types: Blunt: 5 #i mean... i GUESS you could use it like that diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/arrows.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/arrows.yml index 201e328c75b..7dd6360a405 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/arrows.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/arrows.yml @@ -44,16 +44,16 @@ - type: SolutionContainerManager solutions: ammo: - maxVol: 5 + maxVol: 2 - type: RefillableSolution solution: ammo - type: InjectableSolution solution: ammo - type: SolutionInjectOnCollide - transferAmount: 5 + transferAmount: 2 blockSlots: NONE - type: SolutionTransfer - maxTransferAmount: 5 + maxTransferAmount: 2 - type: Appearance - type: SolutionContainerVisuals maxFillLevels: 1 diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/pneumatic_cannon.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/pneumatic_cannon.yml index b79ec2c6739..f9413d6c673 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/pneumatic_cannon.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/pneumatic_cannon.yml @@ -33,6 +33,9 @@ - type: PneumaticCannon - type: Storage capacity: 30 + blacklist: + tags: + - Arrow - type: Appearance - type: ItemMapper containerWhitelist: [gas_tank] diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/armblade.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/armblade.yml index 764683183d9..9e9288c8d4a 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/armblade.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/armblade.yml @@ -9,6 +9,7 @@ sprite: Objects/Weapons/Melee/armblade.rsi state: icon - type: MeleeWeapon + wideAnimationRotation: 90 attackRate: 0.75 damage: types: diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/baseball_bat.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/baseball_bat.yml index 4cd71e72393..e244647a130 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/baseball_bat.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/baseball_bat.yml @@ -8,6 +8,7 @@ sprite: Objects/Weapons/Melee/baseball_bat.rsi state: icon - type: MeleeWeapon + wideAnimationRotation: -135 damage: types: Blunt: 10 diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/chainsaw.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/chainsaw.yml index 387913715cf..b0874bfaef1 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/chainsaw.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/chainsaw.yml @@ -15,6 +15,7 @@ sprite: Objects/Weapons/Melee/chainsaw.rsi state: icon - type: MeleeWeapon + wideAnimationRotation: -135 damage: types: Slash: 5 diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/cult.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/cult.yml index 3061e29e112..833614105d9 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/cult.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/cult.yml @@ -9,6 +9,7 @@ sprite: Objects/Weapons/Melee/cult_dagger.rsi state: icon - type: MeleeWeapon + wideAnimationRotation: -135 attackRate: 1.5 damage: types: @@ -32,6 +33,7 @@ sprite: Objects/Weapons/Melee/cult_blade.rsi state: icon - type: MeleeWeapon + wideAnimationRotation: -135 attackRate: 0.75 damage: types: @@ -58,6 +60,7 @@ sprite: Objects/Weapons/Melee/cult_halberd.rsi state: icon - type: MeleeWeapon + wideAnimationRotation: -135 attackRate: 0.75 damage: types: diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/e_sword.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/e_sword.yml index 5c5972d839b..7cf02ad05cb 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/e_sword.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/e_sword.yml @@ -22,6 +22,7 @@ shader: unshaded map: [ "blade" ] - type: MeleeWeapon + wideAnimationRotation: -135 attackRate: 1 soundHit: path: /Audio/Weapons/eblade1.ogg @@ -87,6 +88,7 @@ shader: unshaded map: [ "blade" ] - type: MeleeWeapon + wideAnimationRotation: -135 attackRate: 1 hidden: true damage: @@ -179,6 +181,7 @@ Blunt: -4.5 litDisarmMalus: 0.7 - type: MeleeWeapon + wideAnimationRotation: -135 attackRate: 1.5 angle: 100 soundHit: diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/fireaxe.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/fireaxe.yml index fcc2129a51f..62a983cd4da 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/fireaxe.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/fireaxe.yml @@ -12,6 +12,8 @@ sprite: Objects/Weapons/Melee/fireaxe.rsi state: icon - type: MeleeWeapon + wideAnimationRotation: -90 + swingLeft: true attackRate: 0.75 damage: types: diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/gohei.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/gohei.yml index 1fdb237f4a0..9e673da49d0 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/gohei.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/gohei.yml @@ -8,6 +8,7 @@ sprite: Objects/Weapons/Melee/gohei.rsi state: gohei - type: MeleeWeapon + wideAnimationRotation: -150 damage: types: Blunt: 3 #You'd be better off punching people diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/knife.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/knife.yml index 34fa0a53b81..bbd18927e1f 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/knife.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/knife.yml @@ -12,6 +12,7 @@ - Knife - type: ItemCooldown - type: MeleeWeapon + wideAnimationRotation: -135 damage: types: Slash: 12 @@ -59,6 +60,7 @@ size: 4 state: butch - type: MeleeWeapon + wideAnimationRotation: -135 attackRate: 1.5 damage: types: @@ -85,6 +87,7 @@ size: 2 state: icon - type: MeleeWeapon + wideAnimationRotation: -135 attackRate: 1.5 damage: types: diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/mining.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/mining.yml index af073435bae..f3bb0ceec91 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/mining.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/mining.yml @@ -44,6 +44,7 @@ capacity: 1 count: 1 - type: MeleeWeapon + wideAnimationRotation: -135 damage: types: Blunt: 8 @@ -73,6 +74,7 @@ sprite: Objects/Weapons/Melee/crusher_dagger.rsi state: icon - type: MeleeWeapon + wideAnimationRotation: -135 attackRate: 1.5 damage: types: @@ -107,6 +109,7 @@ - type: Sprite sprite: Objects/Weapons/Melee/crusher_glaive.rsi - type: MeleeWeapon + wideAnimationRotation: -135 attackRate: 1.25 - type: Item size: 150 diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/needle.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/needle.yml index cfe6c7b2737..48b2d6ad2b8 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/needle.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/needle.yml @@ -8,6 +8,7 @@ sprite: Objects/Weapons/Melee/needle.rsi state: icon - type: MeleeWeapon + wideAnimationRotation: -135 damage: types: Piercing: 1 diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/pickaxe.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/pickaxe.yml index 513e691395f..8d04fd316b4 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/pickaxe.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/pickaxe.yml @@ -12,6 +12,7 @@ state: pickaxe - type: ItemCooldown - type: MeleeWeapon + wideAnimationRotation: -135 damage: groups: Brute: 5 diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/spear.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/spear.yml index bbd4d2389d3..f19b76b3e81 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/spear.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/spear.yml @@ -34,6 +34,7 @@ map: ["enum.SolutionContainerLayers.Fill"] visible: false - type: MeleeWeapon + wideAnimationRotation: -135 damage: types: Piercing: 12 @@ -58,7 +59,7 @@ - type: SolutionContainerManager solutions: melee: - maxVol: 5 + maxVol: 2 - type: MeleeChemicalInjector solution: melee - type: RefillableSolution @@ -66,10 +67,10 @@ - type: InjectableSolution solution: melee - type: SolutionInjectOnCollide - transferAmount: 5 + transferAmount: 2 blockSlots: NONE - type: SolutionTransfer - maxTransferAmount: 5 + maxTransferAmount: 2 - type: Wieldable - type: IncreaseDamageOnWield damage: @@ -117,6 +118,7 @@ - type: Sprite sprite: Objects/Weapons/Melee/reinforced_spear.rsi - type: MeleeWeapon + wideAnimationRotation: -135 damage: types: Piercing: 15 @@ -136,6 +138,7 @@ - type: Sprite sprite: Objects/Weapons/Melee/plasma_spear.rsi - type: MeleeWeapon + wideAnimationRotation: -135 damage: types: Piercing: 18 @@ -155,6 +158,7 @@ - type: Sprite sprite: Objects/Weapons/Melee/uranium_spear.rsi - type: MeleeWeapon + wideAnimationRotation: -135 damage: types: Piercing: 10 diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/stunprod.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/stunprod.yml index 8ecd97827c7..25c9cf61257 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/stunprod.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/stunprod.yml @@ -12,6 +12,7 @@ - type: Stunbaton energyPerUse: 70 - type: MeleeWeapon + wideAnimationRotation: -135 damage: types: Blunt: 9 @@ -44,4 +45,4 @@ price: 100 - type: Construction graph: makeshiftstunprod - node: msstunprod \ No newline at end of file + node: msstunprod diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/sword.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/sword.yml index 2e733cf658a..23160f13ea7 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/sword.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/sword.yml @@ -9,6 +9,7 @@ sprite: Objects/Weapons/Melee/captain_sabre.rsi state: icon - type: MeleeWeapon + wideAnimationRotation: -135 attackRate: 1.5 damage: types: @@ -41,6 +42,7 @@ sprite: Objects/Weapons/Melee/katana.rsi state: icon - type: MeleeWeapon + wideAnimationRotation: -135 damage: types: Slash: 25 @@ -61,6 +63,7 @@ sprite: Objects/Weapons/Melee/energykatana.rsi state: icon - type: MeleeWeapon + wideAnimationRotation: -60 damage: types: Slash: 30 @@ -95,6 +98,7 @@ sprite: Objects/Weapons/Melee/machete.rsi state: icon - type: MeleeWeapon + wideAnimationRotation: -135 damage: types: Slash: 20 @@ -116,6 +120,7 @@ sprite: Objects/Weapons/Melee/claymore.rsi state: icon - type: MeleeWeapon + wideAnimationRotation: -135 attackRate: 0.75 damage: types: @@ -144,6 +149,7 @@ sprite: Objects/Weapons/Melee/cutlass.rsi state: icon - type: MeleeWeapon + wideAnimationRotation: -135 damage: types: Slash: 16 diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/weapon_toolbox.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/weapon_toolbox.yml index 9eaf14cf9ab..b5f85903044 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/weapon_toolbox.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/weapon_toolbox.yml @@ -12,6 +12,7 @@ size: 150 sprite: Objects/Tools/Toolboxes/toolbox_red.rsi - type: MeleeWeapon + wideAnimationRotation: -135 attackRate: 1.5 damage: types: diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/white_cane.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/white_cane.yml index f38c714c650..36ea58c1116 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/white_cane.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/white_cane.yml @@ -11,6 +11,7 @@ size: 15 sprite: Objects/Weapons/Melee/white_cane.rsi - type: MeleeWeapon + wideAnimationRotation: 45 damage: types: Blunt: 5 @@ -21,4 +22,3 @@ damage: types: Blunt: 3 - \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Objects/Weapons/security.yml b/Resources/Prototypes/Entities/Objects/Weapons/security.yml index dc5c052639b..eafcc46815d 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/security.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/security.yml @@ -10,8 +10,9 @@ - state: stunbaton_off map: [ "enum.ToggleVisuals.Layer" ] - type: Stunbaton - energyPerUse: 100 + energyPerUse: 50 - type: MeleeWeapon + wideAnimationRotation: -135 damage: types: Blunt: 7 @@ -19,10 +20,10 @@ angle: 60 animation: WeaponArcSlash - type: StaminaDamageOnHit - damage: 55 + damage: 35 sound: /Audio/Weapons/egloves.ogg - type: StaminaDamageOnCollide - damage: 55 + damage: 35 sound: /Audio/Weapons/egloves.ogg - type: Battery maxCharge: 1000 @@ -74,6 +75,7 @@ sprite: Objects/Weapons/Melee/truncheon.rsi state: icon - type: MeleeWeapon + wideAnimationRotation: -135 damage: types: Blunt: 20 @@ -114,6 +116,7 @@ maxCharges: 5 charges: 5 - type: MeleeWeapon + wideAnimationRotation: 180 damage: types: Blunt: 0 # melee weapon to allow flashing individual targets @@ -138,6 +141,15 @@ guides: - Security +- type: entity + name: flash + parent: Flash + id: SciFlash + components: + - type: LimitedCharges + maxCharges: 2 + charges: 2 + - type: entity name: portable flasher parent: BaseStructure diff --git a/Resources/Prototypes/Entities/Structures/Doors/Airlocks/base_structureairlocks.yml b/Resources/Prototypes/Entities/Structures/Doors/Airlocks/base_structureairlocks.yml index 8d9c3b46524..0f72bf6fd29 100644 --- a/Resources/Prototypes/Entities/Structures/Doors/Airlocks/base_structureairlocks.yml +++ b/Resources/Prototypes/Entities/Structures/Doors/Airlocks/base_structureairlocks.yml @@ -137,6 +137,7 @@ tags: - Airlock # This tag is used to nagivate the Airlock construction graph. It's needed because the construction graph is shared between Airlock, AirlockGlass, and HighSecDoor + - type: PryUnpowered placement: mode: SnapgridCenter diff --git a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml index 9510e62dd55..b2877c6925c 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml @@ -398,7 +398,7 @@ staticRecipes: - MMI - PositronicBrain - - Flash + - SciFlash - BorgModuleCable - BorgModuleFireExtinguisher - BorgModuleGPS diff --git a/Resources/Prototypes/Entities/Structures/Storage/Closets/base_structureclosets.yml b/Resources/Prototypes/Entities/Structures/Storage/Closets/base_structureclosets.yml index f39938fd955..5edad73e337 100644 --- a/Resources/Prototypes/Entities/Structures/Storage/Closets/base_structureclosets.yml +++ b/Resources/Prototypes/Entities/Structures/Storage/Closets/base_structureclosets.yml @@ -184,6 +184,8 @@ name: suit storage unit description: A fancy hi-tech storage unit made for storing space suits. components: + - type: AccessReader + - type: Lock - type: Anchorable delay: 2 - type: StaticPrice @@ -196,11 +198,14 @@ sprite: Structures/Storage/suit_storage.rsi layers: - state: base - - state: closed + - state: door map: ["enum.StorageVisualLayers.Door"] - state: welded visible: false map: ["enum.WeldableLayers.BaseWelded"] + - state: locked + map: ["enum.StorageVisualLayers.Lock"] + shader: unshaded - type: MovedByPressure - type: DamageOnHighSpeedImpact damage: @@ -257,5 +262,7 @@ - type: Appearance - type: EntityStorageVisuals stateBase: base + stateLocked: locked + stateUnlocked: unlocked stateDoorOpen: base - stateDoorClosed: closed + stateDoorClosed: door diff --git a/Resources/Prototypes/Guidebook/science.yml b/Resources/Prototypes/Guidebook/science.yml index d9a3d442b44..03840ec15ee 100644 --- a/Resources/Prototypes/Guidebook/science.yml +++ b/Resources/Prototypes/Guidebook/science.yml @@ -3,11 +3,18 @@ name: guide-entry-science text: "/ServerInfo/Guidebook/Science/Science.xml" children: + - Technologies - AnomalousResearch - Xenoarchaeology - Robotics - MachineUpgrading +- type: guideEntry + id: Technologies + name: guide-entry-technologies + text: "/ServerInfo/Guidebook/Science/Technologies.xml" + filterEnabled: True + - type: guideEntry id: AnomalousResearch name: guide-entry-anomalous-research diff --git a/Resources/Prototypes/Procedural/salvage_factions.yml b/Resources/Prototypes/Procedural/salvage_factions.yml index 1097ed90497..847a40ac025 100644 --- a/Resources/Prototypes/Procedural/salvage_factions.yml +++ b/Resources/Prototypes/Procedural/salvage_factions.yml @@ -33,6 +33,9 @@ #- proto: MobCarpMagic # cost: 5 # prob: 0.1 + - proto: MobCarpRainbow # carp version of rouny... + cost: 3 + prob: 0.05 - proto: MobDragonDungeon cost: 10 prob: 0.02 diff --git a/Resources/Prototypes/Recipes/Crafting/Graphs/storage/cratesecure.yml b/Resources/Prototypes/Recipes/Crafting/Graphs/storage/cratesecure.yml index f9875e4e2d2..2a9047077d5 100644 --- a/Resources/Prototypes/Recipes/Crafting/Graphs/storage/cratesecure.yml +++ b/Resources/Prototypes/Recipes/Crafting/Graphs/storage/cratesecure.yml @@ -21,6 +21,8 @@ - tool: Screwing doAfter: 5 conditions: + - !type:StorageWelded + welded: false - !type:Locked locked: false completed: diff --git a/Resources/Prototypes/Recipes/Lathes/robotics.yml b/Resources/Prototypes/Recipes/Lathes/robotics.yml index 4825adbe493..f9f00daf43b 100644 --- a/Resources/Prototypes/Recipes/Lathes/robotics.yml +++ b/Resources/Prototypes/Recipes/Lathes/robotics.yml @@ -6,6 +6,15 @@ Steel: 200 Glass: 300 +- type: latheRecipe + id: SciFlash + result: SciFlash + completetime: 2 + materials: + Glass: 100 + Plastic: 200 + Steel: 100 + - type: latheRecipe id: CyborgEndoskeleton result: CyborgEndoskeleton diff --git a/Resources/ServerInfo/Guidebook/Science/Science.xml b/Resources/ServerInfo/Guidebook/Science/Science.xml index 21959d419a5..59c9ccaad45 100644 --- a/Resources/ServerInfo/Guidebook/Science/Science.xml +++ b/Resources/ServerInfo/Guidebook/Science/Science.xml @@ -12,6 +12,8 @@ Каждая технология стоит определённое число [color=#a4885c]Очков исследований[/color], и их изучение открывает новые рецепты для печати на производственных станках. Некоторые технологии нельзя разблокировать, не изучив технологии им предшествующие. +Информацию о различных технологиях можно посмотреть [textlink="на странице справочника технологий" link="Technologies"]. + ## Дисциплины Технологии распределены по 5 различным дисциплинам: diff --git a/Resources/ServerInfo/Guidebook/Science/Technologies.xml b/Resources/ServerInfo/Guidebook/Science/Technologies.xml new file mode 100644 index 00000000000..5db8cd28bd1 --- /dev/null +++ b/Resources/ServerInfo/Guidebook/Science/Technologies.xml @@ -0,0 +1,23 @@ + +# Технологии + +Все технологии имеют определенную стоимость и требования к уровню для их изучения. Их открытие расширяет ассортимент рецептов, доступных для печати на фабрикаторах и станках. + +Ниже перечислены различные технологии и соответствующие им дисциплины. + +## Промышленность + + +## Биохимия + + +## Арсенал + + +## Экспериментальное + + +## Обслуживание персонала + + + diff --git a/Resources/Textures/Clothing/Belt/belt_overlay.rsi/meta.json b/Resources/Textures/Clothing/Belt/belt_overlay.rsi/meta.json index f46241eab5b..b8464e42430 100644 --- a/Resources/Textures/Clothing/Belt/belt_overlay.rsi/meta.json +++ b/Resources/Textures/Clothing/Belt/belt_overlay.rsi/meta.json @@ -142,10 +142,6 @@ "name": "plasmatank-equipped-BELT", "directions": 4 }, - { - "name": "rolling_pin-equipped-BELT", - "directions": 4 - }, { "name": "rpd-equipped-BELT", "directions": 4 diff --git a/Resources/Textures/Clothing/Belt/belt_overlay.rsi/rolling_pin-equipped-BELT.png b/Resources/Textures/Objects/Tools/rolling_pin.rsi/equipped-BELT.png similarity index 100% rename from Resources/Textures/Clothing/Belt/belt_overlay.rsi/rolling_pin-equipped-BELT.png rename to Resources/Textures/Objects/Tools/rolling_pin.rsi/equipped-BELT.png diff --git a/Resources/Textures/Objects/Tools/rolling_pin.rsi/meta.json b/Resources/Textures/Objects/Tools/rolling_pin.rsi/meta.json index 407ebc30c0e..bc2ff1de9dc 100644 --- a/Resources/Textures/Objects/Tools/rolling_pin.rsi/meta.json +++ b/Resources/Textures/Objects/Tools/rolling_pin.rsi/meta.json @@ -1,7 +1,7 @@ { "version": 1, "license": "CC-BY-SA-3.0", - "copyright": "icon.png taken from https://github.com/DesertRose2/desertrose/blob/0348c98f8343b5cb82d87df12411ba647b2b1b4f/icons/obj/kitchen.dmi. Inhand sprites created by deltanedas (github) for SS14.", + "copyright": "icon.png taken from https://github.com/DesertRose2/desertrose/blob/0348c98f8343b5cb82d87df12411ba647b2b1b4f/icons/obj/kitchen.dmi. Inhand sprites created by deltanedas (github) for SS14. Belt sprite taken from unknown file in tgstation at commit https://github.com/tgstation/tgstation/commit/dc89ef0239830774bd3d9d7d6c8da2856da2b869", "size": { "x": 32, "y": 32 @@ -17,6 +17,10 @@ { "name": "inhand-right", "directions": 4 + }, + { + "name": "equipped-BELT", + "directions": 4 } ] } diff --git a/Resources/Textures/Structures/Storage/suit_storage.rsi/base.png b/Resources/Textures/Structures/Storage/suit_storage.rsi/base.png index 3a686cd6ecb..5171b03f461 100644 Binary files a/Resources/Textures/Structures/Storage/suit_storage.rsi/base.png and b/Resources/Textures/Structures/Storage/suit_storage.rsi/base.png differ diff --git a/Resources/Textures/Structures/Storage/suit_storage.rsi/closed.png b/Resources/Textures/Structures/Storage/suit_storage.rsi/closed.png deleted file mode 100644 index 79d0dba8c57..00000000000 Binary files a/Resources/Textures/Structures/Storage/suit_storage.rsi/closed.png and /dev/null differ diff --git a/Resources/Textures/Structures/Storage/suit_storage.rsi/door.png b/Resources/Textures/Structures/Storage/suit_storage.rsi/door.png new file mode 100644 index 00000000000..e2d18e4eb46 Binary files /dev/null and b/Resources/Textures/Structures/Storage/suit_storage.rsi/door.png differ diff --git a/Resources/Textures/Structures/Storage/suit_storage.rsi/locked.png b/Resources/Textures/Structures/Storage/suit_storage.rsi/locked.png new file mode 100644 index 00000000000..40b036a2e5f Binary files /dev/null and b/Resources/Textures/Structures/Storage/suit_storage.rsi/locked.png differ diff --git a/Resources/Textures/Structures/Storage/suit_storage.rsi/meta.json b/Resources/Textures/Structures/Storage/suit_storage.rsi/meta.json index aa1c1f09ec7..c4d4dc3468d 100644 --- a/Resources/Textures/Structures/Storage/suit_storage.rsi/meta.json +++ b/Resources/Textures/Structures/Storage/suit_storage.rsi/meta.json @@ -11,7 +11,16 @@ "name": "base" }, { - "name": "closed" + "name": "door" + }, + { + "name": "unlocked" + }, + { + "name": "locked" + }, + { + "name": "panel" }, { "name": "welded" diff --git a/Resources/Textures/Structures/Storage/suit_storage.rsi/panel.png b/Resources/Textures/Structures/Storage/suit_storage.rsi/panel.png new file mode 100644 index 00000000000..7c4ef0d075e Binary files /dev/null and b/Resources/Textures/Structures/Storage/suit_storage.rsi/panel.png differ diff --git a/Resources/Textures/Structures/Storage/suit_storage.rsi/unlocked.png b/Resources/Textures/Structures/Storage/suit_storage.rsi/unlocked.png new file mode 100644 index 00000000000..cb906e3cb20 Binary files /dev/null and b/Resources/Textures/Structures/Storage/suit_storage.rsi/unlocked.png differ diff --git a/Resources/Textures/Structures/Storage/suit_storage.rsi/welded.png b/Resources/Textures/Structures/Storage/suit_storage.rsi/welded.png index 6e9fbacb2ea..d8e0281ebb1 100644 Binary files a/Resources/Textures/Structures/Storage/suit_storage.rsi/welded.png and b/Resources/Textures/Structures/Storage/suit_storage.rsi/welded.png differ diff --git a/RobustToolbox b/RobustToolbox index 7095a58685f..904ddea2749 160000 --- a/RobustToolbox +++ b/RobustToolbox @@ -1 +1 @@ -Subproject commit 7095a58685f60707b38edfc4689b658a5bd21a92 +Subproject commit 904ddea27497caa6e652eec1b9d3ff2743a79e5c diff --git a/Secrets b/Secrets index 04ae3deb142..f217e467a9f 160000 --- a/Secrets +++ b/Secrets @@ -1 +1 @@ -Subproject commit 04ae3deb142ff28e20d3f473ac6c03dc2eac75d5 +Subproject commit f217e467a9f33ba01ac04cb21fa3f8e4327f7f83 diff --git a/SpaceStation14.sln.DotSettings b/SpaceStation14.sln.DotSettings index 57f0e3c4db6..72e550ac6e3 100644 --- a/SpaceStation14.sln.DotSettings +++ b/SpaceStation14.sln.DotSettings @@ -587,6 +587,7 @@ public sealed partial class $CLASS$ : Shared$CLASS$ { True True True + True True True True