From 895c546a99b19b6780f3aac70bc4b10900731016 Mon Sep 17 00:00:00 2001 From: Remuchi Date: Fri, 26 Jan 2024 16:08:08 +0700 Subject: [PATCH 1/5] =?UTF-8?q?feat:=20=D0=BF=D1=80=D0=BE=D1=81=D1=82?= =?UTF-8?q?=D0=B0=D1=8F=20=D1=85=D0=B8=D1=80=D1=83=D1=80=D0=B3=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit автор Грабля --- .../White/CheapSurgery/CheapSurgerySystem.cs | 49 +++++++ .../Controls/RadialContainer.xaml.cs | 112 +++++++++------- .../White/CheapSurgery/CheapSurgerySystem.cs | 122 ++++++++++++++++++ .../White/Construction/Completions/Surgery.cs | 28 ++++ .../CheapSurgery/ActiveSurgeryComponent.cs | 7 + .../White/CheapSurgery/OnSurgeryStarted.cs | 44 +++++++ .../CheapSurgery/SharedCheapSurgerySystem.cs | 9 ++ .../Objects/Specific/Medical/surgery.yml | 2 +- .../Construction/Surgery/body_surgery.yml | 21 +++ 9 files changed, 347 insertions(+), 47 deletions(-) create mode 100644 Content.Client/White/CheapSurgery/CheapSurgerySystem.cs create mode 100644 Content.Server/White/CheapSurgery/CheapSurgerySystem.cs create mode 100644 Content.Server/White/Construction/Completions/Surgery.cs create mode 100644 Content.Shared/White/CheapSurgery/ActiveSurgeryComponent.cs create mode 100644 Content.Shared/White/CheapSurgery/OnSurgeryStarted.cs create mode 100644 Content.Shared/White/CheapSurgery/SharedCheapSurgerySystem.cs create mode 100644 Resources/Prototypes/White/Construction/Surgery/body_surgery.yml diff --git a/Content.Client/White/CheapSurgery/CheapSurgerySystem.cs b/Content.Client/White/CheapSurgery/CheapSurgerySystem.cs new file mode 100644 index 0000000000..7891242fa7 --- /dev/null +++ b/Content.Client/White/CheapSurgery/CheapSurgerySystem.cs @@ -0,0 +1,49 @@ +using Content.Client.White.UserInterface.Controls; +using Content.Shared.White.CheapSurgery; +using Robust.Client.GameObjects; + +namespace Content.Client.White.CheapSurgery; + +public sealed class CheapSurgerySystem : SharedCheapSurgerySystem +{ + [Dependency] private readonly SpriteSystem _sprite = default!; + + public override void Initialize() + { + base.Initialize(); + SubscribeNetworkEvent(OnStarted); + } + + private void OnStarted(OnSurgeryStarted ev) + { + OpenRadialMenu(ev.OrganItems); + } + + public void OpenRadialMenu(List items) + { + if (items.Count == 0) + return; + + var radialContainer = new RadialContainer(); + foreach (var organ in items) + { + var radialButton = radialContainer.AddButton(organ.Name, _sprite.Frame0(organ.Icon)); + radialButton.Controller.OnPressed += _ => + { + radialContainer.Close(); + if (organ.Children.Count > 0) + OpenRadialMenu(organ.Children); + else + SelectOrgan(GetEntity(organ.Uid)); + }; + } + + radialContainer.OpenCentered(); + } + + public void SelectOrgan(EntityUid uid) + { + var ev = new OnOrganSelected(GetNetEntity(uid)); + RaiseNetworkEvent(ev); + } +} diff --git a/Content.Client/White/UserInterface/Controls/RadialContainer.xaml.cs b/Content.Client/White/UserInterface/Controls/RadialContainer.xaml.cs index d9678af38d..2cf2cafe5d 100644 --- a/Content.Client/White/UserInterface/Controls/RadialContainer.xaml.cs +++ b/Content.Client/White/UserInterface/Controls/RadialContainer.xaml.cs @@ -6,6 +6,7 @@ using Content.Client.Viewport; using JetBrains.Annotations; using Robust.Client.Animations; using Robust.Client.AutoGenerated; +using Robust.Client.GameObjects; using Robust.Client.Graphics; using Robust.Client.Player; using Robust.Client.ResourceManagement; @@ -31,10 +32,10 @@ public sealed class RadialContainerCommandTest : LocalizedCommands for (int i = 0; i < 24; i++) { var testButton = radial.AddButton("Action " + i, "/Textures/Interface/emotions.svg.192dpi.png"); - testButton.Controller.OnPressed += (_) => { Logger.Debug("Press gay"); }; + testButton.Controller.OnPressed += _ => { Logger.Debug("Press gay"); }; } - radial.CloseButton.Controller.OnPressed += (_) => + radial.CloseButton.Controller.OnPressed += _ => { Logger.Debug("Close event for your own logic"); }; @@ -46,17 +47,16 @@ public sealed class RadialContainerCommandTest : LocalizedCommands [GenerateTypedNameReferences, Virtual] public partial class RadialContainer : Control { - private bool _isOpened = false; + private bool _isOpened; - private Vector2 _focusSize = new Vector2(64, 64); - private Vector2 _normalSize = new Vector2(50, 50); + private Vector2 _focusSize = new(64, 64); + private Vector2 _normalSize = new(50, 50); - private float _moveAniTime = 0.3f; - private float _focusAniTime = 0.25f; + private IResourceCache _resourceCache; - private int _maxButtons = 8; + private const int MaxButtons = 8; - private string _backgroundTexture = "/Textures/Interface/Default/SlotBackground.png"; + private const string BackgroundTexture = "/Textures/Interface/Default/SlotBackground.png"; public const string MoveAnimationKey = "move"; public const string InSizeAnimationKey = "insize"; @@ -67,29 +67,24 @@ public partial class RadialContainer : Control get => _focusSize.Y; set => _focusSize = new Vector2(value, value); } + public float NormalSize { get => _normalSize.Y; set => _normalSize = new Vector2(value, value); } - public float MoveAnimationTime - { - get => _moveAniTime; - set => _moveAniTime = value; - } - public float FocusAnimationTime - { - get => _focusAniTime; - set => _focusAniTime = value; - } + public float MoveAnimationTime { get; set; } = 0.3f; + + public float FocusAnimationTime { get; set; } = 0.25f; public bool IsAction = true; - public RadialContainer() : base() + public RadialContainer() { RobustXamlLoader.Load(this); IoCManager.InjectDependencies(this); + _resourceCache = IoCManager.Resolve(); } public void Open(Vector2 position) @@ -103,9 +98,10 @@ public partial class RadialContainer : Control { AddToRoot(); if (Parent != null) - LayoutContainer.SetPosition(this, (Parent.Size/2) - (this.Size/2)); + LayoutContainer.SetPosition(this, Parent.Size / 2 - Size / 2); else - LayoutContainer.SetPosition(this, (UserInterfaceManager.MainViewport.Size/2) - (this.Size/2)); + LayoutContainer.SetPosition(this, UserInterfaceManager.MainViewport.Size / 2 - Size / 2); + UpdateButtons(); } @@ -114,7 +110,7 @@ public partial class RadialContainer : Control if (UserInterfaceManager.ActiveScreen == null) return; - var ent = IoCManager.Resolve().LocalPlayer?.ControlledEntity; + var ent = IoCManager.Resolve().LocalSession?.AttachedEntity; if (ent == null) return; @@ -122,7 +118,11 @@ public partial class RadialContainer : Control return; AddToRoot(); - LayoutContainer.SetPosition(this, (IoCManager.Resolve().MapToScreen(xform.MapPosition).Position * 1.5f)); + var position = IoCManager.Resolve().GetMapCoordinates(xform); + + LayoutContainer.SetPosition(this, + IoCManager.Resolve().MapToScreen(position).Position * 1.5f); + UpdateButtons(); } @@ -139,9 +139,21 @@ public partial class RadialContainer : Control { var button = new RadialButton(); button.Content = action; - button.Controller.TextureNormal = IoCManager.Resolve().GetTexture(_backgroundTexture); + button.Controller.TextureNormal = _resourceCache.GetTexture(BackgroundTexture); if (texture != null) - button.BackgroundTexture.Texture = IoCManager.Resolve().GetTexture(texture); + button.BackgroundTexture.Texture = _resourceCache.GetTexture(texture); + + Layout.AddChild(button); + + return button; + } + + public RadialButton AddButton(string action, Texture texture) + { + var button = new RadialButton(); + button.Content = action; + button.Controller.TextureNormal = _resourceCache.GetTexture(BackgroundTexture); + button.BackgroundTexture.Texture = texture; Layout.AddChild(button); return button; @@ -151,6 +163,7 @@ public partial class RadialContainer : Control { if (_isOpened) return; + UserInterfaceManager.WindowRoot.AddChild(this); _isOpened = !_isOpened; } @@ -159,31 +172,33 @@ public partial class RadialContainer : Control { Visible = true; - var angleDegrees = 360/Layout.ChildCount; + var angleDegrees = 360 / Layout.ChildCount; var stepAngle = -angleDegrees + -90; var distance = FocusSize * 1.2; - if (Layout.Children.Count() > _maxButtons) + if (Layout.Children.Count() > MaxButtons) { - for (int i = 0; i < (Layout.Children.Count() - _maxButtons); i++) + for (int i = 0; i < (Layout.Children.Count() - MaxButtons); i++) { - distance += (NormalSize/3); + distance += (NormalSize / 3); } } + foreach (var child in Layout.Children) { - var button = (RadialButton)child; + var button = (RadialButton) child; button.ButtonSize = _normalSize; stepAngle += angleDegrees; var pos = GetPointFromPolar(stepAngle, distance); PlayRadialAnimation(button, pos, MoveAnimationKey); - button.Controller.OnMouseEntered += (_) => + button.Controller.OnMouseEntered += _ => { PlaySizeAnimation(button, _focusSize, OutSizeAnimationKey, InSizeAnimationKey); ActionLabel.Text = button.Content ?? string.Empty; ActionLabel.Visible = IsAction; }; - button.Controller.OnMouseExited += (_) => + + button.Controller.OnMouseExited += _ => { PlaySizeAnimation(button, _normalSize, InSizeAnimationKey, OutSizeAnimationKey); ActionLabel.Visible = false; @@ -191,18 +206,20 @@ public partial class RadialContainer : Control } CloseButton.ButtonSize = _normalSize; - CloseButton.Controller.OnMouseEntered += (_) => + CloseButton.Controller.OnMouseEntered += _ => { PlaySizeAnimation(CloseButton, _focusSize, OutSizeAnimationKey, InSizeAnimationKey); ActionLabel.Text = CloseButton.Content ?? string.Empty; ActionLabel.Visible = true; }; - CloseButton.Controller.OnMouseExited += (_) => + + CloseButton.Controller.OnMouseExited += _ => { PlaySizeAnimation(CloseButton, _normalSize, InSizeAnimationKey, OutSizeAnimationKey); ActionLabel.Visible = false; }; - CloseButton.Controller.OnPressed += (_) => + + CloseButton.Controller.OnPressed += _ => { Close(); }; @@ -212,7 +229,7 @@ public partial class RadialContainer : Control { var anim = new Animation { - Length = TimeSpan.FromMilliseconds(_moveAniTime * 1000), + Length = TimeSpan.FromMilliseconds(MoveAnimationTime * 1000), AnimationTracks = { new AnimationTrackControlProperty @@ -221,12 +238,13 @@ public partial class RadialContainer : Control InterpolationMode = AnimationInterpolationMode.Linear, KeyFrames = { - new AnimationTrackProperty.KeyFrame(new Vector2(0,0), 0f), - new AnimationTrackProperty.KeyFrame(pos, _moveAniTime) + new AnimationTrackProperty.KeyFrame(new Vector2(0, 0), 0f), + new AnimationTrackProperty.KeyFrame(pos, MoveAnimationTime) } } } }; + if (!button.HasRunningAnimation(playKey)) button.PlayAnimation(anim, playKey); } @@ -235,7 +253,7 @@ public partial class RadialContainer : Control { var anim = new Animation { - Length = TimeSpan.FromMilliseconds(_focusAniTime * 1000), + Length = TimeSpan.FromMilliseconds(FocusAnimationTime * 1000), AnimationTracks = { new AnimationTrackControlProperty @@ -245,7 +263,7 @@ public partial class RadialContainer : Control KeyFrames = { new AnimationTrackProperty.KeyFrame(button.Size, 0f), - new AnimationTrackProperty.KeyFrame(size, _focusAniTime) + new AnimationTrackProperty.KeyFrame(size, FocusAnimationTime) } } } @@ -253,6 +271,7 @@ public partial class RadialContainer : Control if (stopKey != null && button.HasRunningAnimation(stopKey)) button.StopAnimation(stopKey); + if (!button.HasRunningAnimation(playKey)) button.PlayAnimation(anim, playKey); } @@ -263,11 +282,12 @@ public partial class RadialContainer : Control foreach (var child in Layout.Children) { - var button = (RadialButton)child; - LayoutContainer.SetPosition(child, button.Offset - (button.Size/2)); + var button = (RadialButton) child; + LayoutContainer.SetPosition(child, button.Offset - (button.Size / 2)); } - LayoutContainer.SetPosition(CloseButton, CloseButton.Offset - (CloseButton.Size/2)); - LayoutContainer.SetPosition(ActionBox, new Vector2(0 - (ActionLabel.Size.X), FocusSize*1.5f)); + + LayoutContainer.SetPosition(CloseButton, CloseButton.Offset - (CloseButton.Size / 2)); + LayoutContainer.SetPosition(ActionBox, new Vector2(0 - (ActionLabel.Size.X), FocusSize * 1.5f)); } private static Vector2 GetPointFromPolar(double angleDegrees, double distance) @@ -277,6 +297,6 @@ public partial class RadialContainer : Control var x = distance * Math.Cos(angleRadians); var y = distance * Math.Sin(angleRadians); - return new Vector2((int)Math.Round(x), (int)Math.Round(y)); + return new Vector2((int) Math.Round(x), (int) Math.Round(y)); } } diff --git a/Content.Server/White/CheapSurgery/CheapSurgerySystem.cs b/Content.Server/White/CheapSurgery/CheapSurgerySystem.cs new file mode 100644 index 0000000000..62f3529ccb --- /dev/null +++ b/Content.Server/White/CheapSurgery/CheapSurgerySystem.cs @@ -0,0 +1,122 @@ +using Content.Server.Body.Systems; +using Content.Server.Construction; +using Content.Server.Construction.Components; +using Content.Server.Kitchen.Components; +using Content.Shared.Body.Components; +using Content.Shared.Body.Organ; +using Content.Shared.Body.Part; +using Content.Shared.Humanoid; +using Content.Shared.Interaction; +using Content.Shared.Mobs.Systems; +using Content.Shared.White.CheapSurgery; +using Robust.Shared.Utility; + +namespace Content.Server.White.CheapSurgery; + +public sealed class CheapSurgerySystem : SharedCheapSurgerySystem +{ + [Dependency] private readonly BodySystem _body = default!; + [Dependency] private readonly MobStateSystem _mobState = default!; + [Dependency] private readonly ConstructionSystem _construction = default!; + + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnUsing); + SubscribeNetworkEvent(OnSelected); + } + + private void OnSelected(OnOrganSelected ev) + { + var entity = GetEntity(ev.Uid); + + if (TryComp(entity, out var partComponent) && partComponent.Body != null) + { + StartDrop(partComponent.Body.Value, entity); + } + else if (TryComp(entity, out var organComponent) && organComponent.Body != null) + { + StartDrop(organComponent.Body.Value, entity); + } + } + + private void OnUsing(EntityUid uid, BodyComponent component, InteractUsingEvent args) + { + if (args.Handled || !TryComp(args.Used, out _) || _mobState.IsAlive(uid) + || TryComp(uid, out _)) + return; + + if (!TryComp(uid, out _)) + return; + + var organs = GenList(uid); + + var ev = new OnSurgeryStarted(GetNetEntity(uid), organs); + RaiseNetworkEvent(ev, args.User); + } + + private OrganItem GetOrganItem(EntityUid part, List? child = null) + { + var metadata = MetaData(part); + + var organ = new OrganItem(metadata.EntityName, GetNetEntity(part), + new SpriteSpecifier.EntityPrototype(metadata.EntityPrototype!.ID)); + + if (child != null) + organ.Children = child; + + return organ; + } + + public List GenList(EntityUid uid) + { + var organs = new List(); + + if (TryComp(uid, out var bodyComponent)) + { + foreach (var (part, _) in _body.GetBodyChildren(uid, bodyComponent)) + { + if (part == uid) + { + continue; + } + + var child = GenList(part); + if (child.Count > 0) + organs.Add(GetOrganItem(part, child)); + } + } + else if (TryComp(uid, out var partComponent)) + { + foreach (var (part, _) in _body.GetBodyPartChildren(uid, partComponent)) + { + if (part == uid) + { + continue; + } + + var child = GenList(part); + if (child.Count > 0) + organs.Add(GetOrganItem(part, child)); + } + + foreach (var (part, _) in _body.GetPartOrgans(uid, partComponent)) + { + organs.Add(GetOrganItem(part, GenList(part))); + } + } + + return organs; + } + + public bool StartDrop(EntityUid uid, EntityUid organUid, EntityUid? user = null, BodyComponent? component = null) + { + if (!Resolve(uid, ref component)) + return false; + + EnsureComp(uid).OrganUid = organUid; + + var construct = EnsureComp(uid); + return _construction.ChangeGraph(uid, user, "BodySurgery", "head", true, construct); + } +} diff --git a/Content.Server/White/Construction/Completions/Surgery.cs b/Content.Server/White/Construction/Completions/Surgery.cs new file mode 100644 index 0000000000..6744954c27 --- /dev/null +++ b/Content.Server/White/Construction/Completions/Surgery.cs @@ -0,0 +1,28 @@ +using Content.Server.Body.Systems; +using Content.Shared.Body.Organ; +using Content.Shared.Construction; +using Content.Shared.White.CheapSurgery; + +namespace Content.Server.White.Construction.Completions; + +public sealed partial class Surgery : IGraphAction +{ + private ISawmill _sawmill = default!; + + public void PerformAction(EntityUid uid, EntityUid? userUid, IEntityManager entityManager) + { + _sawmill = Logger.GetSawmill("Surgery"); + var bodySystem = entityManager.EntitySysManager.GetEntitySystem(); + + if (!entityManager.TryGetComponent(uid, out var surgeryComponent)) + { + _sawmill.Warning($"Entity {uid} does not have a ActiveSurgery Component"); + return; + } + + if (entityManager.TryGetComponent(surgeryComponent.OrganUid, out var organComponent)) + bodySystem.RemoveOrgan(surgeryComponent.OrganUid, organComponent); + + entityManager.RemoveComponent(uid); + } +} diff --git a/Content.Shared/White/CheapSurgery/ActiveSurgeryComponent.cs b/Content.Shared/White/CheapSurgery/ActiveSurgeryComponent.cs new file mode 100644 index 0000000000..c1c5c1fa94 --- /dev/null +++ b/Content.Shared/White/CheapSurgery/ActiveSurgeryComponent.cs @@ -0,0 +1,7 @@ +namespace Content.Shared.White.CheapSurgery; + +[RegisterComponent] +public sealed partial class ActiveSurgeryComponent : Component +{ + [ViewVariables] public EntityUid OrganUid = EntityUid.Invalid; +} diff --git a/Content.Shared/White/CheapSurgery/OnSurgeryStarted.cs b/Content.Shared/White/CheapSurgery/OnSurgeryStarted.cs new file mode 100644 index 0000000000..28b843246c --- /dev/null +++ b/Content.Shared/White/CheapSurgery/OnSurgeryStarted.cs @@ -0,0 +1,44 @@ +using Robust.Shared.Serialization; +using Robust.Shared.Utility; + +namespace Content.Shared.White.CheapSurgery; + +[Serializable, NetSerializable] +public sealed class OnSurgeryStarted : EntityEventArgs +{ + public NetEntity Target; + public List OrganItems; + + public OnSurgeryStarted(NetEntity target, List organItems) + { + Target = target; + OrganItems = organItems; + } +} + +[Serializable, NetSerializable] +public sealed class OrganItem +{ + public string Name; + public NetEntity Uid; + public SpriteSpecifier Icon; + public List Children = new(); + + public OrganItem(string name, NetEntity uid, SpriteSpecifier icon) + { + Name = name; + Uid = uid; + Icon = icon; + } +} + +[Serializable, NetSerializable] +public sealed class OnOrganSelected : EntityEventArgs +{ + public NetEntity Uid; + + public OnOrganSelected(NetEntity uid) + { + Uid = uid; + } +} diff --git a/Content.Shared/White/CheapSurgery/SharedCheapSurgerySystem.cs b/Content.Shared/White/CheapSurgery/SharedCheapSurgerySystem.cs new file mode 100644 index 0000000000..1a7e1dcd21 --- /dev/null +++ b/Content.Shared/White/CheapSurgery/SharedCheapSurgerySystem.cs @@ -0,0 +1,9 @@ +namespace Content.Shared.White.CheapSurgery; + +public abstract class SharedCheapSurgerySystem : EntitySystem +{ + public override void Initialize() + { + + } +} diff --git a/Resources/Prototypes/Entities/Objects/Specific/Medical/surgery.yml b/Resources/Prototypes/Entities/Objects/Specific/Medical/surgery.yml index e157817ec4..5fc3a22941 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/Medical/surgery.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/Medical/surgery.yml @@ -54,7 +54,7 @@ - type: entity name: scalpel id: Scalpel - parent: BaseToolSurgery + parent: [BaseToolSurgery, BaseKnife] description: A surgical tool used to make incisions into flesh. components: - type: Sharp diff --git a/Resources/Prototypes/White/Construction/Surgery/body_surgery.yml b/Resources/Prototypes/White/Construction/Surgery/body_surgery.yml new file mode 100644 index 0000000000..a04d1dd542 --- /dev/null +++ b/Resources/Prototypes/White/Construction/Surgery/body_surgery.yml @@ -0,0 +1,21 @@ +- type: constructionGraph + id: BodySurgery + start: head + graph: + - node: head + edges: + - to: drop + steps: + - tool: Sawing + doAfter: 1 + + - tool: Slicing + doAfter: 1 + + - tool: Sawing + doAfter: 1 + + + - node: drop + actions: + - !type:Surgery From a009a8fae3b7d5f084781d3695d7ee45bf724227 Mon Sep 17 00:00:00 2001 From: Remuchi Date: Fri, 26 Jan 2024 16:35:45 +0700 Subject: [PATCH 2/5] =?UTF-8?q?fix:=20=D1=87=D0=B0=D1=81=D1=82=D0=B8=D1=87?= =?UTF-8?q?=D0=BD=D1=8B=D0=B9=20=D1=84=D0=B8=D0=BA=D1=81=20=D1=8D=D0=BC?= =?UTF-8?q?=D0=BE=D1=83=D1=82=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../White/Animations/EmoteAnimationSystem.cs | 55 ++++++++++--------- .../White/Animations/DancingComponent.cs | 2 +- .../White/Animations/DancingSystem.cs | 7 +-- .../White/Animations/EmoteAnimationSystem.cs | 46 +--------------- .../AspectsSystem/Aspects/DancingAspect.cs | 10 +++- .../Animations/EmoteAnimationComponent.cs | 12 ++-- .../Locale/ru-RU/white/actions/emotes.ftl | 6 -- Resources/Prototypes/White/Actions/emotes.yml | 37 ------------- 8 files changed, 45 insertions(+), 130 deletions(-) delete mode 100644 Resources/Locale/ru-RU/white/actions/emotes.ftl diff --git a/Content.Client/White/Animations/EmoteAnimationSystem.cs b/Content.Client/White/Animations/EmoteAnimationSystem.cs index 6828789c07..1083c2ef29 100644 --- a/Content.Client/White/Animations/EmoteAnimationSystem.cs +++ b/Content.Client/White/Animations/EmoteAnimationSystem.cs @@ -1,16 +1,22 @@ +using Content.Shared.White.Animations; using System.Numerics; -using Content.Shared.Animations; using Robust.Client.Animations; +using Robust.Client.GameObjects; using Robust.Shared.Animations; using Robust.Shared.GameStates; -using Robust.Client.GameObjects; -using static Content.Shared.Animations.EmoteAnimationComponent; -namespace Content.Client.Animations; +using static Content.Shared.White.Animations.EmoteAnimationComponent; -public class EmoteAnimationSystem : EntitySystem +namespace Content.Client.White.Animations; + +public sealed class EmoteAnimationSystem : EntitySystem { [Dependency] private readonly AnimationPlayerSystem _animationSystem = default!; + private readonly Dictionary> _emoteList = new(); + + private const string AnimationKey = "emoteAnimationKeyId"; + private const string AnimationKeyTurn = "emoteAnimationKeyId_rotate"; + //OnVerbsResponse?.Invoke(msg); public override void Initialize() { @@ -19,16 +25,13 @@ public class EmoteAnimationSystem : EntitySystem // EmoteFlip animation _emoteList.Add("EmoteFlip", uid => { - var animationKey = "emoteAnimationKeyId"; - - if (_animationSystem.HasRunningAnimation(uid, animationKey)) + if (_animationSystem.HasRunningAnimation(uid, AnimationKey)) return; var baseAngle = Angle.Zero; if (EntityManager.TryGetComponent(uid, out SpriteComponent? sprite)) { - if (sprite != null) - baseAngle = sprite.Rotation; + baseAngle = sprite.Rotation; } var animation = new Animation @@ -43,7 +46,7 @@ public class EmoteAnimationSystem : EntitySystem InterpolationMode = AnimationInterpolationMode.Linear, KeyFrames = { - new AnimationTrackProperty.KeyFrame(Angle.FromDegrees(baseAngle.Degrees), 0f), + new AnimationTrackProperty.KeyFrame(Angle.FromDegrees(baseAngle.Degrees - 10), 0f), new AnimationTrackProperty.KeyFrame(Angle.FromDegrees(baseAngle.Degrees + 180), 0.25f), new AnimationTrackProperty.KeyFrame(Angle.FromDegrees(baseAngle.Degrees + 360), 0.25f), new AnimationTrackProperty.KeyFrame(Angle.FromDegrees(baseAngle.Degrees), 0f), @@ -52,14 +55,13 @@ public class EmoteAnimationSystem : EntitySystem } }; - _animationSystem.Play(uid, animation, animationKey); + _animationSystem.Play(uid, animation, AnimationKey); }); - // EmoteJump animation - _emoteList.Add("EmoteJump", (EntityUid uid) => - { - var animationKey = "emoteAnimationKeyId"; - if (_animationSystem.HasRunningAnimation(uid, animationKey)) + // EmoteJump animation + _emoteList.Add("EmoteJump", uid => + { + if (_animationSystem.HasRunningAnimation(uid, AnimationKey)) return; var animation = new Animation @@ -82,19 +84,18 @@ public class EmoteAnimationSystem : EntitySystem } }; - _animationSystem.Play(uid, animation, animationKey); + _animationSystem.Play(uid, animation, AnimationKey); }); - // EmoteTurn animation - _emoteList.Add("EmoteTurn", (EntityUid uid) => - { - var animationKey = "emoteAnimationKeyId_rotate"; // it needs for only rotate anim - if (_animationSystem.HasRunningAnimation(uid, animationKey)) + // EmoteTurn animation + _emoteList.Add("EmoteTurn", uid => + { + if (_animationSystem.HasRunningAnimation(uid, AnimationKeyTurn)) return; var animation = new Animation { - Length = TimeSpan.FromMilliseconds(600), // Пока пусть на 0.6 секунд. В идеале бы до 0.9 на 3 поворота + Length = TimeSpan.FromMilliseconds(900), AnimationTracks = { new AnimationTrackComponentProperty @@ -118,7 +119,7 @@ public class EmoteAnimationSystem : EntitySystem } }; - _animationSystem.Play(uid, animation, animationKey); + _animationSystem.Play(uid, animation, AnimationKeyTurn); }); } @@ -128,9 +129,9 @@ public class EmoteAnimationSystem : EntitySystem return; component.AnimationId = state.AnimationId; - if (_emoteList.ContainsKey(component.AnimationId)) + if (_emoteList.TryGetValue(component.AnimationId, out var value)) { - _emoteList[component.AnimationId].Invoke(uid); + value.Invoke(uid); } } } diff --git a/Content.Server/White/Animations/DancingComponent.cs b/Content.Server/White/Animations/DancingComponent.cs index 7e278319f0..8183500bc3 100644 --- a/Content.Server/White/Animations/DancingComponent.cs +++ b/Content.Server/White/Animations/DancingComponent.cs @@ -1,4 +1,4 @@ -namespace Content.Server.Animations; +namespace Content.Server.White.Animations; [RegisterComponent] public sealed partial class DancingComponent : Component diff --git a/Content.Server/White/Animations/DancingSystem.cs b/Content.Server/White/Animations/DancingSystem.cs index 0d9a4e0c5f..8f0e82a03a 100644 --- a/Content.Server/White/Animations/DancingSystem.cs +++ b/Content.Server/White/Animations/DancingSystem.cs @@ -1,11 +1,10 @@ -using Content.Server.White.Animations; -using Content.Shared.Animations; using Content.Shared.Bed.Sleep; using Content.Shared.Mobs.Components; using Content.Shared.Mobs.Systems; +using Content.Shared.White.Animations; using Robust.Shared.Random; -namespace Content.Server.Animations; +namespace Content.Server.White.Animations; public sealed class DancingSystem : EntitySystem { @@ -13,7 +12,7 @@ public sealed class DancingSystem : EntitySystem [Dependency] private readonly EmoteAnimationSystem _emoteAnimation = default!; [Dependency] private readonly MobStateSystem _mobState = default!; - private readonly string[] _emoteList = {"EmoteFlip", "EmoteTurn"}; + private readonly string[] _emoteList = { "EmoteFlip", "EmoteTurn" }; public override void Initialize() { diff --git a/Content.Server/White/Animations/EmoteAnimationSystem.cs b/Content.Server/White/Animations/EmoteAnimationSystem.cs index 0eadeb1e44..1ccd2b12d5 100644 --- a/Content.Server/White/Animations/EmoteAnimationSystem.cs +++ b/Content.Server/White/Animations/EmoteAnimationSystem.cs @@ -1,31 +1,17 @@ -using Content.Server.Actions; using Content.Server.Chat.Systems; -using Content.Shared.Animations; using Content.Shared.Chat.Prototypes; +using Content.Shared.White.Animations; using Robust.Shared.GameStates; -using Robust.Shared.Prototypes; -using static Content.Shared.Animations.EmoteAnimationComponent; +using static Content.Shared.White.Animations.EmoteAnimationComponent; namespace Content.Server.White.Animations; public sealed class EmoteAnimationSystem : EntitySystem { - [Dependency] private readonly ActionsSystem _action = default!; - [Dependency] private readonly IPrototypeManager _proto = default!; - - /// - /// We write 'EmoteAction' word before id name for instant action. - /// Example: EmoteActionJump, EmoteActionFlip and etc. - /// - private const string InstantIdentifier = "EmoteAction"; - public override void Initialize() { SubscribeLocalEvent(OnGetState); - SubscribeLocalEvent(OnMapInint); - SubscribeLocalEvent(OnShutdown); SubscribeLocalEvent(OnEmote); - SubscribeLocalEvent(OnEmoteAction); } private void OnGetState(EntityUid uid, EmoteAnimationComponent component, ref ComponentGetState args) @@ -33,28 +19,6 @@ public sealed class EmoteAnimationSystem : EntitySystem args.State = new EmoteAnimationComponentState(component.AnimationId); } - private void OnMapInint(EntityUid uid, EmoteAnimationComponent component, MapInitEvent args) - { - foreach (var item in _proto.EnumeratePrototypes()) - { - if (item.ID.Length <= InstantIdentifier.Length || - item.ID[..InstantIdentifier.Length] != InstantIdentifier) - continue; - - EntityUid? action = null; - component.Actions.Add(action); - _action.AddAction(uid, ref action, item.ID); - } - } - - private void OnShutdown(EntityUid uid, EmoteAnimationComponent component, ComponentShutdown args) - { - foreach (var item in component.Actions) - { - _action.RemoveAction(uid, item); - } - } - private void OnEmote(EntityUid uid, EmoteAnimationComponent component, ref EmoteEvent args) { if (args.Handled || !args.Emote.Category.HasFlag(EmoteCategory.Gesture)) @@ -63,12 +27,6 @@ public sealed class EmoteAnimationSystem : EntitySystem PlayEmoteAnimation(uid, component, args.Emote.ID); } - private void OnEmoteAction(EntityUid uid, EmoteAnimationComponent component, EmoteActionEvent args) - { - PlayEmoteAnimation(uid, component, args.Emote); - args.Handled = true; - } - public void PlayEmoteAnimation(EntityUid uid, EmoteAnimationComponent component, string emoteId) { component.AnimationId = emoteId; diff --git a/Content.Server/White/AspectsSystem/Aspects/DancingAspect.cs b/Content.Server/White/AspectsSystem/Aspects/DancingAspect.cs index 0e6c890462..5822520fe4 100644 --- a/Content.Server/White/AspectsSystem/Aspects/DancingAspect.cs +++ b/Content.Server/White/AspectsSystem/Aspects/DancingAspect.cs @@ -1,10 +1,10 @@ -using Content.Server.Animations; using Content.Server.GameTicking; using Content.Server.GameTicking.Rules.Components; +using Content.Server.White.Animations; using Content.Server.White.AspectsSystem.Aspects.Components; using Content.Server.White.AspectsSystem.Base; -using Content.Shared.Animations; using Content.Shared.Mobs.Components; +using Content.Shared.White.Animations; namespace Content.Server.White.AspectsSystem.Aspects; @@ -16,7 +16,11 @@ public sealed class DancingAspect : AspectSystem SubscribeLocalEvent(HandleLateJoin); } - protected override void Started(EntityUid uid, DancingAspectComponent component, GameRuleComponent gameRule, GameRuleStartedEvent args) + protected override void Started( + EntityUid uid, + DancingAspectComponent component, + GameRuleComponent gameRule, + GameRuleStartedEvent args) { base.Started(uid, component, gameRule, args); var query = EntityQueryEnumerator(); diff --git a/Content.Shared/White/Animations/EmoteAnimationComponent.cs b/Content.Shared/White/Animations/EmoteAnimationComponent.cs index 4e6e18de49..76ff6a8c34 100644 --- a/Content.Shared/White/Animations/EmoteAnimationComponent.cs +++ b/Content.Shared/White/Animations/EmoteAnimationComponent.cs @@ -2,29 +2,25 @@ using Content.Shared.Actions; using Robust.Shared.GameStates; using Robust.Shared.Serialization; -namespace Content.Shared.Animations; +namespace Content.Shared.White.Animations; /// /// Event for playing animations /// public sealed partial class EmoteActionEvent : InstantActionEvent { - [ViewVariables] - [DataField("emote", readOnly: true, required: true)] + [ViewVariables, DataField("emote", readOnly: true, required: true)] public string Emote = default!; }; -[RegisterComponent] -[NetworkedComponent] +[RegisterComponent, NetworkedComponent] public sealed partial class EmoteAnimationComponent : Component { [ViewVariables(VVAccess.ReadWrite)] public string AnimationId = "none"; - public readonly List Actions = new(); - [Serializable, NetSerializable] - public class EmoteAnimationComponentState : ComponentState + public partial class EmoteAnimationComponentState : ComponentState { public string AnimationId { get; init; } diff --git a/Resources/Locale/ru-RU/white/actions/emotes.ftl b/Resources/Locale/ru-RU/white/actions/emotes.ftl deleted file mode 100644 index f6cdedb653..0000000000 --- a/Resources/Locale/ru-RU/white/actions/emotes.ftl +++ /dev/null @@ -1,6 +0,0 @@ -emote-flip-action-name = Сальто -emote-flip-action-description = Сделать крутой акработический трюк! -emote-jump-action-name = Подпрыгнуть -emote-jump-action-description = Подпрыгни из-за радости или испуга от мыши. -emote-turn-action-name = Танцевать -emote-turn-action-description = You spin me right round baby... diff --git a/Resources/Prototypes/White/Actions/emotes.yml b/Resources/Prototypes/White/Actions/emotes.yml index 9ab52fc333..2141500500 100644 --- a/Resources/Prototypes/White/Actions/emotes.yml +++ b/Resources/Prototypes/White/Actions/emotes.yml @@ -1,40 +1,3 @@ -# flip animation -- type: entity - id: EmoteActionFlip - name: emote-flip-action-name - description: emote-flip-action-description - noSpawn: true - components: - - type: InstantAction - icon: White/Actions/EmoteFlip.png - event: !type:EmoteActionEvent - emote: EmoteFlip - -# jump animation -- type: entity - id: EmoteActionJump - name: emote-jump-action-name - description: emote-jump-action-description - noSpawn: true - components: - - type: InstantAction - icon: White/Actions/EmoteJump.png - event: !type:EmoteActionEvent - emote: EmoteJump - - # turn around in 4 directions animation -- type: entity - id: EmoteActionTurn - name: emote-turn-action-name - description: emote-turn-action-description - noSpawn: true - components: - - type: InstantAction - icon: White/Actions/EmoteTurn.png - event: !type:EmoteActionEvent - emote: EmoteTurn - - # Using EmoteAnimation from IC action chat - type: emote id: EmoteFlip From 64903d14036d75097ab06311fec48f6605d23fd4 Mon Sep 17 00:00:00 2001 From: Remuchi <72476615+Remuchi@users.noreply.github.com> Date: Sun, 12 Nov 2023 21:21:53 +0700 Subject: [PATCH 3/5] =?UTF-8?q?[FEAT]=20=D0=92=D1=81=D1=8F=D0=BA=D0=B8?= =?UTF-8?q?=D0=B5=20=D0=BF=D1=80=D0=B8=D0=BA=D0=BE=D0=BB=D1=8C=D0=BD=D1=8B?= =?UTF-8?q?=D0=B5=20=D1=80=D0=B0=D0=B7=D0=BD=D0=BE=D1=81=D1=82=D0=B8=20?= =?UTF-8?q?=D0=B8=20=D0=B2=D0=BA=D1=83=D1=81=D0=BD=D0=BE=D1=81=D1=82=D0=B8?= =?UTF-8?q?=20(#554)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: трикодер * feat: принтер документов * fix: текст фелинидов * feat: возможность менять голос эмоутов * feat: мяукаем при аспекте мяуканья * feat: ПНВ * fix: забирай свои метадаты * fix: oopsies * fix: линтер снова * fix: пожалуйста линтер отстань # Conflicts: # Content.Server/Speech/Components/VocalComponent.cs # Content.Server/White/AspectsSystem/Aspects/CatEarsAspect.cs # Resources/Prototypes/Catalog/Fills/Items/belt.yml # Resources/Prototypes/Reagents/Materials/materials.yml # Resources/Prototypes/White/Catalog/seniors_fills.yml # Resources/Prototypes/White/Catalog/uplink.yml # Resources/Prototypes/White/Recipes/lathe_recipes.yml # Resources/Prototypes/White/Research/experimental.yml --- .../White/Items/Tricorder/TricorderSystem.cs | 73 ++ .../Speech/Components/VocalComponent.cs | 5 +- .../AspectsSystem/Aspects/CatEarsAspect.cs | 38 +- .../White/Items/Tricorder/TricorderSystem.cs | 161 +++ .../Item/Tricorder/SharedTricorderSystem.cs | 30 + .../Item/Tricorder/TricorderComponent.cs | 38 + .../Locale/ru-RU/materials/materials.ftl | 1 + .../Locale/ru-RU/white/items/tricorder.ftl | 1 + .../ru-RU/white/species/felinid/felinid.ftl | 2 +- .../structures/doc-printer/paper-text.ftl | 610 +++++++++++ .../Prototypes/Catalog/Fills/Items/belt.yml | 8 +- Resources/Prototypes/White/Catalog/uplink.yml | 12 + .../Clothing/Head/night_vision_goggle.yml | 27 + .../Entities/Objects/Tools/tricorder.yml | 53 + .../Structures/Machines/doc_printer.yml | 985 ++++++++++++++++++ .../White/Recipes/lathe_recipes.yml | 10 + .../White/Research/experimental.yml | 43 + .../Head/nightvision.rsi/equipped-EYES.png | Bin 0 -> 387 bytes .../Clothing/Head/nightvision.rsi/icon.png | Bin 0 -> 218 bytes .../Head/nightvision.rsi/inhand-left.png | Bin 0 -> 385 bytes .../Head/nightvision.rsi/inhand-right.png | Bin 0 -> 410 bytes .../Clothing/Head/nightvision.rsi/meta.json | 26 + .../White/Items/Tools/tricorder.rsi/icon.png | Bin 0 -> 312 bytes .../White/Items/Tools/tricorder.rsi/meta.json | 20 + .../White/Items/Tools/tricorder.rsi/off.png | Bin 0 -> 151 bytes .../White/Items/Tools/tricorder.rsi/on.png | Bin 0 -> 151 bytes .../Machines/doc_printer.rsi/folder-CC.png | Bin 0 -> 246 bytes .../Machines/doc_printer.rsi/folder-base.png | Bin 0 -> 98 bytes .../Machines/doc_printer.rsi/folder-car.png | Bin 0 -> 256 bytes .../Machines/doc_printer.rsi/folder-com.png | Bin 0 -> 264 bytes .../Machines/doc_printer.rsi/folder-eng.png | Bin 0 -> 261 bytes .../Machines/doc_printer.rsi/folder-med.png | Bin 0 -> 263 bytes .../doc_printer.rsi/folder-overlay-paper.png | Bin 0 -> 113 bytes .../Machines/doc_printer.rsi/folder-sci.png | Bin 0 -> 261 bytes .../Machines/doc_printer.rsi/folder-sec.png | Bin 0 -> 260 bytes .../Machines/doc_printer.rsi/folder-ser.png | Bin 0 -> 255 bytes .../Machines/doc_printer.rsi/folder-syn.png | Bin 0 -> 249 bytes .../Machines/doc_printer.rsi/icon.png | Bin 0 -> 393 bytes .../Machines/doc_printer.rsi/idle.png | Bin 0 -> 735 bytes .../Machines/doc_printer.rsi/inserting.png | Bin 0 -> 1471 bytes .../Machines/doc_printer.rsi/meta.json | 96 ++ .../Machines/doc_printer.rsi/printing.png | Bin 0 -> 1426 bytes .../Machines/doc_printer.rsi/unlit.png | Bin 0 -> 232 bytes 43 files changed, 2228 insertions(+), 11 deletions(-) create mode 100644 Content.Client/White/Items/Tricorder/TricorderSystem.cs create mode 100644 Content.Server/White/Items/Tricorder/TricorderSystem.cs create mode 100644 Content.Shared/White/Item/Tricorder/SharedTricorderSystem.cs create mode 100644 Content.Shared/White/Item/Tricorder/TricorderComponent.cs create mode 100644 Resources/Locale/ru-RU/white/items/tricorder.ftl create mode 100644 Resources/Locale/ru-RU/white/structures/doc-printer/paper-text.ftl create mode 100644 Resources/Prototypes/White/Entities/Clothing/Head/night_vision_goggle.yml create mode 100644 Resources/Prototypes/White/Entities/Objects/Tools/tricorder.yml create mode 100644 Resources/Prototypes/White/Entities/Structures/Machines/doc_printer.yml create mode 100644 Resources/Prototypes/White/Research/experimental.yml create mode 100644 Resources/Textures/White/Clothing/Head/nightvision.rsi/equipped-EYES.png create mode 100644 Resources/Textures/White/Clothing/Head/nightvision.rsi/icon.png create mode 100644 Resources/Textures/White/Clothing/Head/nightvision.rsi/inhand-left.png create mode 100644 Resources/Textures/White/Clothing/Head/nightvision.rsi/inhand-right.png create mode 100644 Resources/Textures/White/Clothing/Head/nightvision.rsi/meta.json create mode 100644 Resources/Textures/White/Items/Tools/tricorder.rsi/icon.png create mode 100644 Resources/Textures/White/Items/Tools/tricorder.rsi/meta.json create mode 100644 Resources/Textures/White/Items/Tools/tricorder.rsi/off.png create mode 100644 Resources/Textures/White/Items/Tools/tricorder.rsi/on.png create mode 100644 Resources/Textures/White/Structures/Machines/doc_printer.rsi/folder-CC.png create mode 100644 Resources/Textures/White/Structures/Machines/doc_printer.rsi/folder-base.png create mode 100644 Resources/Textures/White/Structures/Machines/doc_printer.rsi/folder-car.png create mode 100644 Resources/Textures/White/Structures/Machines/doc_printer.rsi/folder-com.png create mode 100644 Resources/Textures/White/Structures/Machines/doc_printer.rsi/folder-eng.png create mode 100644 Resources/Textures/White/Structures/Machines/doc_printer.rsi/folder-med.png create mode 100644 Resources/Textures/White/Structures/Machines/doc_printer.rsi/folder-overlay-paper.png create mode 100644 Resources/Textures/White/Structures/Machines/doc_printer.rsi/folder-sci.png create mode 100644 Resources/Textures/White/Structures/Machines/doc_printer.rsi/folder-sec.png create mode 100644 Resources/Textures/White/Structures/Machines/doc_printer.rsi/folder-ser.png create mode 100644 Resources/Textures/White/Structures/Machines/doc_printer.rsi/folder-syn.png create mode 100644 Resources/Textures/White/Structures/Machines/doc_printer.rsi/icon.png create mode 100644 Resources/Textures/White/Structures/Machines/doc_printer.rsi/idle.png create mode 100644 Resources/Textures/White/Structures/Machines/doc_printer.rsi/inserting.png create mode 100644 Resources/Textures/White/Structures/Machines/doc_printer.rsi/meta.json create mode 100644 Resources/Textures/White/Structures/Machines/doc_printer.rsi/printing.png create mode 100644 Resources/Textures/White/Structures/Machines/doc_printer.rsi/unlit.png diff --git a/Content.Client/White/Items/Tricorder/TricorderSystem.cs b/Content.Client/White/Items/Tricorder/TricorderSystem.cs new file mode 100644 index 0000000000..3fe0137fbf --- /dev/null +++ b/Content.Client/White/Items/Tricorder/TricorderSystem.cs @@ -0,0 +1,73 @@ +using Content.Client.Items; +using Content.Client.Message; +using Content.Client.Stylesheets; +using Content.Shared.White.Item.Tricorder; +using Robust.Client.UserInterface; +using Robust.Client.UserInterface.Controls; +using Robust.Shared.GameStates; +using Robust.Shared.Timing; + +namespace Content.Client.White.Items.Tricorder; + +/// +public sealed class TricorderSystem : SharedTricorderSystem +{ + /// + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnCollectItemStatus); + SubscribeLocalEvent(HandleTricorderState); + } + + private static void OnCollectItemStatus(EntityUid uid, TricorderComponent component, ItemStatusCollectMessage args) + { + if (component.CurrentMode != TricorderMode.Multitool) + { + args.Controls.Clear(); + } + + args.Controls.Add(new StatusControl(component)); + } + + private static void HandleTricorderState(EntityUid uid, TricorderComponent component, ref ComponentHandleState args) + { + if (args.Current is not TricorderComponentState state) + { + return; + } + + component.CurrentMode = state.CurrentMode; + } + + private sealed class StatusControl : Control + { + private readonly RichTextLabel _label; + private readonly TricorderComponent _tricorder; + + private TricorderMode? _linkModeActive; + + public StatusControl(TricorderComponent tricorder) + { + _tricorder = tricorder; + _label = new RichTextLabel { StyleClasses = { StyleNano.StyleClassItemStatus } }; + AddChild(_label); + } + + protected override void FrameUpdate(FrameEventArgs args) + { + base.FrameUpdate(args); + + if (_linkModeActive != null && _linkModeActive == _tricorder.CurrentMode) + return; + + _linkModeActive = _tricorder.CurrentMode; + + var modeLocString = GetNameByMode(_tricorder.CurrentMode); + + _label.SetMarkup(Robust.Shared.Localization.Loc.GetString("tricorder-item-status-label", + ("mode", Robust.Shared.Localization.Loc.GetString(modeLocString)))); + } + } +} \ No newline at end of file diff --git a/Content.Server/Speech/Components/VocalComponent.cs b/Content.Server/Speech/Components/VocalComponent.cs index 029d638a66..e06dd60ee1 100644 --- a/Content.Server/Speech/Components/VocalComponent.cs +++ b/Content.Server/Speech/Components/VocalComponent.cs @@ -1,4 +1,5 @@ using Content.Server.Speech.EntitySystems; +using Content.Server.White.AspectsSystem.Aspects; using Content.Shared.Chat.Prototypes; using Content.Shared.Humanoid; using Robust.Shared.Audio; @@ -12,7 +13,7 @@ namespace Content.Server.Speech.Components; /// Component required for entities to be able to do vocal emotions. /// [RegisterComponent] -[Access(typeof(VocalSystem))] +[Access(typeof(VocalSystem), typeof(CatEarsAspect))] public sealed partial class VocalComponent : Component { /// @@ -41,6 +42,6 @@ public sealed partial class VocalComponent : Component /// Currently loaded emote sounds prototype, based on entity sex. /// Null if no valid prototype for entity sex was found. /// - [ViewVariables] + [ViewVariables(VVAccess.ReadWrite)] public EmoteSoundsPrototype? EmoteSounds = null; } diff --git a/Content.Server/White/AspectsSystem/Aspects/CatEarsAspect.cs b/Content.Server/White/AspectsSystem/Aspects/CatEarsAspect.cs index 2d70763cf2..665a055e18 100644 --- a/Content.Server/White/AspectsSystem/Aspects/CatEarsAspect.cs +++ b/Content.Server/White/AspectsSystem/Aspects/CatEarsAspect.cs @@ -1,12 +1,14 @@ using Content.Server.Chat.Systems; using Content.Server.GameTicking; using Content.Server.GameTicking.Rules.Components; +using Content.Server.Speech.Components; using Content.Server.White.AspectsSystem.Aspects.Components; using Content.Server.White.AspectsSystem.Base; using Content.Shared.GameTicking; using Content.Shared.Humanoid; using Content.Shared.Humanoid.Markings; using Content.Shared.Speech; +using Robust.Shared.Enums; using Robust.Shared.Prototypes; using Robust.Shared.Random; @@ -21,6 +23,9 @@ public sealed class CatEarsAspect : AspectSystem private MarkingPrototype _ears = default!; private MarkingPrototype _tail = default!; + private const string FemaleFelinidVoices = "FemaleFelinid"; + private const string MaleFelinidVoices = "MaleFelinid"; + public override void Initialize() { base.Initialize(); @@ -42,13 +47,16 @@ public sealed class CatEarsAspect : AspectSystem var entQuery = EntityQueryEnumerator(); while (entQuery.MoveNext(out var ent, out _, out _)) { - _chat.TrySendInGameICMessage(ent, _random.Pick(new[] {"Мяу", "Мур", "Ня"}), InGameICChatType.Speak, + _chat.TrySendInGameICMessage(ent, _random.Pick(new[] { "Мяу", "Мур", "Ня" }), InGameICChatType.Speak, ChatTransmitRange.Normal); } } } - protected override void Started(EntityUid uid, CatEarsAspectComponent component, GameRuleComponent gameRule, + protected override void Started( + EntityUid uid, + CatEarsAspectComponent component, + GameRuleComponent gameRule, GameRuleStartedEvent args) { base.Started(uid, component, gameRule, args); @@ -93,12 +101,14 @@ public sealed class CatEarsAspect : AspectSystem AddTail(appearance); Dirty(uid, appearance); + ChangeEmotesVoice(uid, appearance); return; } default: AddEars(appearance); AddTail(appearance); Dirty(uid, appearance); + ChangeEmotesVoice(uid, appearance); break; } } @@ -114,7 +124,7 @@ public sealed class CatEarsAspect : AspectSystem if (!appearance.MarkingSet.TryGetMarking(MarkingCategories.Tail, _tail.ID, out _)) { appearance.MarkingSet.AddFront(MarkingCategories.Tail, - new Marking(_tail.ID, GetColors(appearance, _tail)) {Forced = true}); + new Marking(_tail.ID, GetColors(appearance, _tail)) { Forced = true }); } } @@ -123,7 +133,25 @@ public sealed class CatEarsAspect : AspectSystem if (!appearance.MarkingSet.TryGetMarking(MarkingCategories.HeadTop, _tail.ID, out _)) { appearance.MarkingSet.AddFront(MarkingCategories.HeadTop, - new Marking(_ears.ID, GetColors(appearance, _ears)) {Forced = true}); + new Marking(_ears.ID, GetColors(appearance, _ears)) { Forced = true }); } } -} + + private void ChangeEmotesVoice(EntityUid user, HumanoidAppearanceComponent appearanceComponent) + { + if (!TryComp(user, out VocalComponent? vocals)) + { + return; + } + + switch (appearanceComponent.Gender) + { + case Gender.Female: + _protoMan.TryIndex(FemaleFelinidVoices, out vocals.EmoteSounds); + break; + case Gender.Male: + _protoMan.TryIndex(MaleFelinidVoices, out vocals.EmoteSounds); + break; + } + } +} \ No newline at end of file diff --git a/Content.Server/White/Items/Tricorder/TricorderSystem.cs b/Content.Server/White/Items/Tricorder/TricorderSystem.cs new file mode 100644 index 0000000000..62d0f13689 --- /dev/null +++ b/Content.Server/White/Items/Tricorder/TricorderSystem.cs @@ -0,0 +1,161 @@ +using Content.Server.Medical.Components; +using Content.Server.UserInterface; +using Content.Shared.Atmos.Components; +using Content.Shared.Database; +using Content.Shared.DeviceNetwork; +using Content.Shared.DeviceNetwork.Components; +using Content.Shared.Examine; +using Content.Shared.MedicalScanner; +using Content.Shared.Verbs; +using Content.Shared.White.Item.Tricorder; +using Robust.Server.GameObjects; +using Robust.Shared.Audio; +using Robust.Shared.GameStates; +using Robust.Shared.Utility; + +namespace Content.Server.White.Items.Tricorder; + +public sealed class TricorderSystem : SharedTricorderSystem +{ + [Dependency] private readonly IComponentFactory _componentFactory = default!; + [Dependency] private readonly AudioSystem _audioSystem = default!; + [Dependency] private readonly IEntityManager _entityManager = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnExamined); + + SubscribeLocalEvent>(OnAddSwitchModeVerbs); + } + + private void OnExamined(EntityUid uid, TricorderComponent component, ExaminedEvent args) + { + var mode = GetNameByMode(component.CurrentMode); + args.PushMarkup(Loc.GetString("network-configurator-examine-current-mode", ("mode", Loc.GetString(mode)))); + } + + private void OnAddSwitchModeVerbs(EntityUid uid, TricorderComponent component, GetVerbsEvent args) + { + if (!args.CanAccess || !args.CanInteract || !args.Using.HasValue || + !HasComp(args.Target)) + { + return; + } + + var icon = new SpriteSpecifier.Texture(new ResPath("/Textures/Interface/VerbIcons/settings.svg.192dpi.png")); + + AlternativeVerb switchToMultitoolVerb = new() + { + Text = "Переключить на мультитул", + Icon = icon, + Act = () => SwitchToMode(args.User, uid, component, TricorderMode.Multitool), + Impact = LogImpact.Low + }; + + AlternativeVerb switchToGasAnalyzerlVerb = new() + { + Text = "Переключить на газоанализатор", + Icon = icon, + Act = () => SwitchToMode(args.User, uid, component, TricorderMode.GasAnalyzer), + Impact = LogImpact.Low + }; + + AlternativeVerb switchToHealthAnalyzerVerb = new() + { + Text = "Переключить на анализатор здоровья", + Icon = icon, + Act = () => SwitchToMode(args.User, uid, component, TricorderMode.HealthAnalyzer), + Impact = LogImpact.Low + }; + + args.Verbs.Add(switchToHealthAnalyzerVerb); + args.Verbs.Add(switchToGasAnalyzerlVerb); + args.Verbs.Add(switchToMultitoolVerb); + } + + public void SwitchToMode(EntityUid? user, EntityUid tricoderUid, TricorderComponent tricorder, TricorderMode mode) + { + if (tricorder.CurrentMode == mode) + { + return; + } + + tricorder.CurrentMode = mode; + + switch (mode) + { + case TricorderMode.Multitool: + SetToMultitool(tricoderUid); + break; + case TricorderMode.GasAnalyzer: + SetToGasAnalyzer(tricoderUid); + break; + case TricorderMode.HealthAnalyzer: + SetToHealthAnalyzer(tricoderUid); + break; + } + + if (!user.HasValue) + return; + + UpdateModeAppearance(user.Value, tricorder); + } + + private void UpdateModeAppearance( + EntityUid userUid, + TricorderComponent tricorder) + { + Dirty(tricorder); + _audioSystem.PlayPvs(tricorder.SoundSwitchMode, userUid, AudioParams.Default.WithVolume(1.5f)); + } + + private void SetToMultitool(EntityUid uid) + { + var comp = AddComp(uid); + RemComp(uid); + RemComp(uid); + Dirty(comp); + + if (!TryComp(uid, out ActivatableUIComponent? ui)) + { + return; + } + + ui.Key = NetworkConfiguratorUiKey.Configure; + } + + private void SetToGasAnalyzer(EntityUid uid) + { + RemComp(uid); + AddComp(uid); + RemComp(uid); + + if (!TryComp(uid, out ActivatableUIComponent? ui)) + { + return; + } + + ui.Key = GasAnalyzerComponent.GasAnalyzerUiKey.Key; + } + + private void SetToHealthAnalyzer(EntityUid uid) + { + RemComp(uid); + RemComp(uid); + + var healthAnalyzerComponent = _componentFactory.GetComponent(); + healthAnalyzerComponent.ScanningEndSound = new SoundPathSpecifier("/Audio/Items/Medical/healthscanner.ogg"); + + healthAnalyzerComponent.Owner = uid; + _entityManager.AddComponent(uid, healthAnalyzerComponent); + + if (!TryComp(uid, out ActivatableUIComponent? ui)) + { + return; + } + + ui.Key = HealthAnalyzerUiKey.Key; + } +} \ No newline at end of file diff --git a/Content.Shared/White/Item/Tricorder/SharedTricorderSystem.cs b/Content.Shared/White/Item/Tricorder/SharedTricorderSystem.cs new file mode 100644 index 0000000000..c0f356ea6d --- /dev/null +++ b/Content.Shared/White/Item/Tricorder/SharedTricorderSystem.cs @@ -0,0 +1,30 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared.White.Item.Tricorder; + +public abstract class SharedTricorderSystem : EntitySystem +{ + /// + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(GetTricorderState); + } + + private static void GetTricorderState(EntityUid uid, TricorderComponent component, ref ComponentGetState args) + { + args.State = new TricorderComponentState(component.CurrentMode); + } + + public static string GetNameByMode(TricorderMode mode) + { + return mode switch + { + TricorderMode.Multitool => "[color=yellow]мультитул[/color]", + TricorderMode.GasAnalyzer => "[color=cyan]газоанализатор[/color]", + TricorderMode.HealthAnalyzer => "[color=green]анализатор здоровья[/color]", + _ => "[color=yellow]мультитул[/color]" + }; + } +} \ No newline at end of file diff --git a/Content.Shared/White/Item/Tricorder/TricorderComponent.cs b/Content.Shared/White/Item/Tricorder/TricorderComponent.cs new file mode 100644 index 0000000000..7f391c8b2a --- /dev/null +++ b/Content.Shared/White/Item/Tricorder/TricorderComponent.cs @@ -0,0 +1,38 @@ +using Robust.Shared.Audio; +using Robust.Shared.GameStates; +using Robust.Shared.Serialization; + +namespace Content.Shared.White.Item.Tricorder; + +[RegisterComponent] +[NetworkedComponent] +[Access(typeof(SharedTricorderSystem))] +public sealed class TricorderComponent : Component +{ + [DataField("currentState"), ViewVariables(VVAccess.ReadWrite)] + public TricorderMode CurrentMode = TricorderMode.Multitool; + + [DataField("soundSwitchMode")] + public SoundSpecifier SoundSwitchMode = new SoundPathSpecifier("/Audio/Machines/quickbeep.ogg"); +} + +/// +/// Contains network state for TricorderComponent. +/// +[Serializable, NetSerializable] +public sealed class TricorderComponentState : ComponentState +{ + public TricorderMode CurrentMode; + + public TricorderComponentState(TricorderMode currentMode) + { + CurrentMode = currentMode; + } +} + +public enum TricorderMode +{ + Multitool, + GasAnalyzer, + HealthAnalyzer +} \ No newline at end of file diff --git a/Resources/Locale/ru-RU/materials/materials.ftl b/Resources/Locale/ru-RU/materials/materials.ftl index 8404304f04..a149ddd7a7 100644 --- a/Resources/Locale/ru-RU/materials/materials.ftl +++ b/Resources/Locale/ru-RU/materials/materials.ftl @@ -8,6 +8,7 @@ materials-steel = сталь materials-gold = золото materials-silver = серебро materials-plasteel = пласталь +materials-paper = бумага # Other materials-biomass = биомасса materials-cloth = ткань diff --git a/Resources/Locale/ru-RU/white/items/tricorder.ftl b/Resources/Locale/ru-RU/white/items/tricorder.ftl new file mode 100644 index 0000000000..3b73829b81 --- /dev/null +++ b/Resources/Locale/ru-RU/white/items/tricorder.ftl @@ -0,0 +1 @@ +tricorder-item-status-label = Текущий режим: { $mode } \ No newline at end of file diff --git a/Resources/Locale/ru-RU/white/species/felinid/felinid.ftl b/Resources/Locale/ru-RU/white/species/felinid/felinid.ftl index 33be7d6643..99d8c0a523 100644 --- a/Resources/Locale/ru-RU/white/species/felinid/felinid.ftl +++ b/Resources/Locale/ru-RU/white/species/felinid/felinid.ftl @@ -1,7 +1,7 @@ hairball-action = Откашлять комок шерсти. hairball-action-desc = Люди это не любят. hairball-mask = Сначала сними { $mask }. -hairball-cough = { CAPITALIZE(THE($name)) } пытается выкашлять комок шесрти! +hairball-cough = { CAPITALIZE(THE($name)) } пытается выкашлять комок шерсти! action-name-eat-mouse = Съесть мышь. action-description-eat-mouse = Съешьте мышь в своей руке, получая питательные вещества и заряд комка шерсти. diff --git a/Resources/Locale/ru-RU/white/structures/doc-printer/paper-text.ftl b/Resources/Locale/ru-RU/white/structures/doc-printer/paper-text.ftl new file mode 100644 index 0000000000..65684621c1 --- /dev/null +++ b/Resources/Locale/ru-RU/white/structures/doc-printer/paper-text.ftl @@ -0,0 +1,610 @@ +paper-text-request = Запрос Центральному Командованию + --------------------------------------------------------------------- + Я, "имя капитана", в должности Капитана, запрашиваю цель для станции "номер станции" + --------------------------------------------------------------------- + Для выполнения задачи Центрального Командования будут задействованы все доступные ресурсы станции с минимальным ущербом самой станции, если не было приказано иначе. + --------------------------------------------------------------------- + Подпись: "подпись заявителя" + Дата: "день"."месяц".2562 + Печать: + +paper-text-report = Заявление в штаб Центрального Командования + --------------------------------------------------------------------- + Я, "имя заявителя" "должность" станции "номер станции", отправляю рапорт о ходе выполнения цели станции и ее продвижении. + Цель: "цель смены". + Ситуация: "как проходит цель". + --------------------------------------------------------------------- + Рапорт был составлен мною в пребывании адекватного состояния. Все расписанное, готов подтвердить повторно, при необходимости. + --------------------------------------------------------------------- + Подпись: "подпись заявителя" + Дата: "день"."месяц".2562 + Печать: + +paper-text-completed = Заявление в штаб Центрального Командования + --------------------------------------------------------------------- + Я, Капитан "имя заявителя" станции "номер станции", с гордостью сообщаю об успешном выполнении экипажем назначенной цели текущей смены. + + Цель: "цель смены". + + Оценка личного состава и состояния станции: "кратко опишите ситуацию на станции". + --------------------------------------------------------------------- + Запрашиваю начало процедуры смены экипажа и ожидаю дальнейших указаний. + --------------------------------------------------------------------- + Подпись: "подпись заявителя" + Дата: "день"."месяц".2562 + Печать: + +paper-text-failed = Заявление в штаб Центрального Командования + --------------------------------------------------------------------- + Я, Капитан "имя заявителя" станции "номер станции", с прискорбием сообщаю о невозможности выполнения экипажем назначенной цели текущей смены. + + Цель: "цель смены". + + Причина: "почему ее нельзя выполнить". + --------------------------------------------------------------------- + Вследствие провала задания, запрашиваю начало "процедуры смены экипажа / эвакуации" и ожидаю дальнейших указаний. + --------------------------------------------------------------------- + Подпись: "подпись заявителя" + Дата: "день"."месяц".2562 + Печать: + +paper-text-request-CentComm = Рапорт Офицерскому составу Центрального Командования + --------------------------------------------------------------------- + Номер станции: "укажите номер станции из ПДА" + Я, "имя заявителя", в должности "должность заявителя", представляю доклад о "происшествии/несоответствии" Офицерскому составу Центрального Командования. + + Причина:"описание происшествия/несоответствия". + + Данная ситуация требует вмешательства "сотрудника ЦК", так как не может быть решена силами экипажа и командования станции. + --------------------------------------------------------------------- + Рапорт был составлен мною в пребывании адекватного состояния. Все расписанное, готов подтвердить повторно, при необходимости. + + Отправляя этот запрос, возлагаю на себя полную ответственность и, в случае сокрытия информации для собственной выгоды, готов понести высшую меру наказания. + --------------------------------------------------------------------- + Подпись: "подпись заявителя" + Дата: "день"."месяц".2562 + Печать: + +paper-text-request-ERT = Запрос в отдел Аварийно-Восстановительных Формирований NanoTrasen + --------------------------------------------------------------------- + Я, "имя заявителя", в должности "должность заявителя", отправляю запрос в отдел Аварийно-Восстановительного Формирования для вызова на станцию "номер станции из ПДА" Отряда Быстрого Реагирования. + + Причина: "описание происшествия". + + Данная ситуация требует вмешательства "название типа ОБР" ОБР, так как не может быть решена силами экипажа и командования станции и ставит под угрозу существование самой станции. + --------------------------------------------------------------------- + Запрос был составлен мною в пребывании адекватного состояния. Все расписанное, готов подтвердить повторно, при необходимости. + + Отправляя этот запрос, возлагаю на себя полную ответственность и, в случае сокрытия информации для собственной выгоды, готов понести высшую меру наказания. + --------------------------------------------------------------------- + Подпись: "подпись заявителя" + Дата: "день"."месяц".2562 + Печать: + +paper-text-request-RXBZZ = Запрос в отдел Аварийно-Восстановительных Формирований NanoTrasen + --------------------------------------------------------------------- + Я, "имя заявителя", в должности "должность заявителя", отправляю запрос в отдел Аварийно-Восстановительного Формирования для вызова на станцию "номер станции из ПДА" Отряда Быстрого Реагирования. + + Причина: "описание происшествия". + + Данная ситуация требует вмешательства "название типа ОБР" ОБР, так как не может быть решена силами экипажа и командования станции и ставит под угрозу существование самой станции. + --------------------------------------------------------------------- + Запрос был составлен мною в пребывании адекватного состояния. Все расписанное, готов подтвердить повторно, при необходимости. + + Отправляя этот запрос, возлагаю на себя полную ответственность и, в случае сокрытия информации для собственной выгоды, готов понести высшую меру наказания. + --------------------------------------------------------------------- + Подпись: "подпись заявителя" + Дата: "день"."месяц".2562 + Печать: + +paper-text-request-high-order-compaint = Заявление в бюро доносов NanoTrasen + --------------------------------------------------------------------- + Номер станции: "укажите номер станции из ПДА" + Заявитель: "имя заявителя" + Должность: "должность заявителя" + + Субъект правонарушения: "имя нарушителя" + Должность: "должность нарушителя" + + Нарушенные пункты КЗ: "нарушенные статьи/отсутствует" + Нарушенные пункты СОП: "нарушенные пункты/отсутствует" + Нарушенные пункты ОПЧК: "нарушенные пункты/отсутствует" + + Свидетели нарушений: "имена свидетелей/отсутствуют" + --------------------------------------------------------------------- + Описание: "подробное, но лаконичное описание правонарушения". + + Жалоба была составлена мною в пребывании адекватного состояния. Все, расписанное в данной жалобе, готов подтвердить повторно, при необходимости. + + Запрос: "ожидаемый заявителем исход/принять соответствующие меры по пресечению будущих нарушений". + --------------------------------------------------------------------- + Подпись: "подпись заявителя" + Дата: "день"."месяц".2562 + Печать: + +paper-text-request-magistrat = Запрос в Верховный суд Nanotrasen + --------------------------------------------------------------------- + Я, "имя заявителя", в должности "должность заявителя", отправляю запрос в Верховный суд для вызова на станцию "номер станции из ПДА" Магистрата. + + Заявление об инициации судебного процесса: прилагается. + + Данная ситуация требует вмешательства сотрудника Верховного суда, так как не может быть решена компетенцией экипажа и командования станции и ставит под угрозу справедливость вынесенного приговора. + --------------------------------------------------------------------- + Запрос был составлен мною в пребывании адекватного состояния. Все расписанное, готов подтвердить повторно, при необходимости. + + Отправляя этот запрос, возлагаю на себя полную ответственность и, в случае сокрытия информации для собственной выгоды, готов понести высшую меру наказания. + --------------------------------------------------------------------- + Подпись: "подпись заявителя" + Дата: "день"."месяц".2562 + Печать: + +paper-comm-text-crew-mem-domotion = Постановление в архив командования станции + --------------------------------------------------------------------- + Главе персонала станции "номер станции из ПДА". + + Я, "имя заявителя", в должности главы отдела "ваш отдел" приказываю понизить сотрудника "должность сотрудника" "имя сотрудника" до должности "должность после понижения". + + Причина: "кратко опишите причину понижения". + --------------------------------------------------------------------- + Обязуюсь восполнить отсутствие персонала и поддерживать эффективность отдела на высшем уровне. + + Приказ ввести в исполнение немедленно во избежание необратимого ущерба. + --------------------------------------------------------------------- + Подпись: "подпись заявителя" + Дата: "день"."месяц".2562 + Печать: + +paper-comm-text-crew-mem-dismissal = Постановление в архив командования станции + --------------------------------------------------------------------- + Главе персонала станции "номер станции из ПДА". + + Я, "имя заявителя", в должности главы отдела "ваш отдел" приказываю немедленно уволить сотрудника "имя сотрудника" с должности "должность сотрудника". + + Причина: "кратко опишите причину увольнения". + + Сотрудник обязан(-а) немедленно покинуть рабочее место и сдать все выданное снаряжение и имущество отдела. В случае нарушения данного приказа, будут приняты дополнительные меры в соответствии с настоящим законодательством. + --------------------------------------------------------------------- + Обязуюсь восполнить отсутствие персонала и поддерживать эффективность отдела на высшем уровне. + + Приказ ввести в исполнение немедленно во избежание необратимого ущерба. + --------------------------------------------------------------------- + Подпись: "подпись заявителя" + Дата: "день"."месяц".2562 + Печать: + +paper-comm-text-request-council = Запрос командному составу станции + --------------------------------------------------------------------- + Я, "имя заявителя", в должности "ваша должность" запрашиваю провести голосование среди командного состава станции "номер станции". + + Причина: "причина голосования". + + Цель: "ожидаемый итог голосования". + --------------------------------------------------------------------- + Подпись: "подпись заявителя" + Дата: "день"."месяц".2562 + Печать: + +paper-comm-text-council-end = Отчет по голосованию + --------------------------------------------------------------------- + Голосованием глав станции "номер станции", по вопросу "причина голосования", было принято решение "Поддержать / Отклонить" инициативу. + + Количество голосов "За": "кол-во" + + Количество голосов "Против": "кол-во" + --------------------------------------------------------------------- + Подпись: "подпись" + Дата: "день"."месяц".2562 + Печать: + +paper-sec-text-order = Ордер на обыск + --------------------------------------------------------------------- + Выдан: "имя заявителя" "Юрист/Капитан". + Подозреваемый: "имя подозреваемого" "должность". + Характер обыска: "обыск отдела/обыск сотрудника". + + Причина обыска: "причина подозрения" + --------------------------------------------------------------------- + Подпись: "подпись заявителя" + Дата: "день"."месяц".2562 + Печать: + +paper-sec-text-complaint = Жалоба + --------------------------------------------------------------------- + Заявитель: "имя заявителя" + Должность: "должность заявителя" + + Субъект правонарушения: "имя нарушителя" + Должность: "должность нарушителя" + + Свидетели нарушений: "имена свидетелей/отсутствуют" + --------------------------------------------------------------------- + Описание: "нарушение". + --------------------------------------------------------------------- + Жалоба была составлена мною в пребывании адекватного состояния. Все, расписанное в данной жалобе, готов подтвердить повторно, при необходимости. + --------------------------------------------------------------------- + Подпись: "подпись заявителя" + Дата: "день"."месяц".2562 + Печать: + +paper-sec-text-lic = Разрешение на ношение оружия + --------------------------------------------------------------------- + Заявитель: "имя заявителя" + Должность: "должность заявителя" + Разрешение на ношение: "название оружия" + --------------------------------------------------------------------- + Причина: "причина на запрос оружия". + --------------------------------------------------------------------- + Обязуюсь, что орудоваемое мною оружие будет использовано в целях описаных выше или в целях вынужденной самообороны. + --------------------------------------------------------------------- + Подпись: "подпись заявителя" + Дата: "день"."месяц".2562 + Печать: + +paper-sec-text-request-weapon = Временный запрос оружия + --------------------------------------------------------------------- + Заявитель: "имя заявителя" + Должность: "должность заявителя" + Запрос оружия: "название оружия" + --------------------------------------------------------------------- + Причина: "причина на запрос оружия". + На период: "через сколько обязан вернуть оружие" + --------------------------------------------------------------------- + Обязуюсь использовать исключительно в целях указанных выше или при вынужденной самообороне и сдать оружие в арсенал в указанное время или по первому требованию службы безопасности. + --------------------------------------------------------------------- + Подпись: "подпись заявителя" + Дата: "день"."месяц".2562 + Печать: + +paper-sec-text-request-execution = Запрос на казнь сотрудника + --------------------------------------------------------------------- + Заявитель: "имя заявителя" + Должность: "должность заявителя" + + Нарушитель: "имя и фамилия" + --------------------------------------------------------------------- + Причина: "что нарушил". + --------------------------------------------------------------------- + Отправляя этот запрос, возлагаю на себя полную ответственность и, в случае сокрытия информации для собственной выгоды, готов понести высшую меру наказания. + + Данный документ приобретает юридическую силу, если имеет печать Капитана или Центрального Командования. + --------------------------------------------------------------------- + Подпись: "подпись заявителя" + Дата: "день"."месяц".2562 + Печать: + +paper-sec-text-request-cargo-weapon = Разрешение на заказ оружие отделом Снабжения + --------------------------------------------------------------------- + Заявитель: "имя заявителя" + Должность: "должность заявителя" + + Причина: "по какой причине нужно оружие". + --------------------------------------------------------------------- + Отправляя этот запрос, возлагаю на себя полную ответственность за заказанное оружие. + --------------------------------------------------------------------- + Подпись: "подпись заявителя" + Дата: "день"."месяц".2562 + Печать: + +paper-sec-text-request-guard = Заявление под программу защиты свидетелей + --------------------------------------------------------------------- + Заявитель: "имя заявителя" + Должность: "должность заявителя" + --------------------------------------------------------------------- + Причина: "что угрожает вашей жизни". + Запрос: "убежища в бриге / предоставить вам защиту" + --------------------------------------------------------------------- + Служба безопасности берет ответственность за жизнь данного сотрудника и обязана предоставить ему защиту. + --------------------------------------------------------------------- + Подпись: "подпись заявителя" + Дата: "день"."месяц".2562 + Печать: + +paper-eng-text-request-build = Заявление о проведении строительных работ + --------------------------------------------------------------------- + Заявитель: "имя заявителя" + Должность: "должность заявителя" + --------------------------------------------------------------------- + Строительные работы будут проведены в отделе "название отдела". + + Объект: "что будет сделано". + --------------------------------------------------------------------- + Исполнитель несёт полную ответственность за качество выполненных работ. + + Во время строительства обязаны быть соблюдены все нормы безопасности. + --------------------------------------------------------------------- + Подпись: "подпись заявителя" + Дата: "день"."месяц".2562 + Печать: + +paper-eng-text-request-material = Запрос материалов + --------------------------------------------------------------------- + Заявитель: "имя заявителя" + Должность: "должность заявителя" + --------------------------------------------------------------------- + Список: "что вам нужно". + + Причина: "зачем вам материалы". + --------------------------------------------------------------------- + Подпись: "подпись заявителя" + Дата: "день"."месяц".2562 + Печать: + +paper-eng-text-report-elect = Отчет об электроснабжении + --------------------------------------------------------------------- + Заявитель: "имя заявителя" + Должность: "должность заявителя" + --------------------------------------------------------------------- + Производитель электроэнергии: "ДАМ / Сингулярность / альтернативный источник" + Коэффициент потраченной / производимой электроэнергии: "указать коэффициент, к примеру: 2/9" + Стабильность электропитания: "указать уровень стабильности" + --------------------------------------------------------------------- + Я - подотчетное лицо, несу полную ответственность своих действий и не пытаюсь скрыть какую-либо информацию. + В случае сокрытия информации подотчетное лицо будет подвержено наказанию высшей степени. + --------------------------------------------------------------------- + Подпись: "подпись заявителя" + Дата: "день"."месяц".2562 + Печать: + +paper-eng-text-report-atmos = Отчет об атмосфере + --------------------------------------------------------------------- + Заявитель: "имя заявителя" + Должность: "должность заявителя" + --------------------------------------------------------------------- + Производимые газы:"указать производимые газы" + Коэффициент газов в атмосфере станции:"указать коэффициент газов, к примеру кислород - 22%, азот - 77%, углерод - 1%" + Дополнительно производимые газы:"указать дополнительно производимые газы, к примеру - тритий, фрезон и т.п." + --------------------------------------------------------------------- + Я - подотчетное лицо, несу полную ответственность своих действий и не пытаюсь скрыть какую-либо информацию. + В случае сокрытия информации подотчетное лицо будет подвержено наказанию высшей степени. + --------------------------------------------------------------------- + Подпись: "подпись заявителя" + Дата: "день"."месяц".2562 + Печать: + +paper-med-text-request-perm-narc = Лекарственный рецепт + --------------------------------------------------------------------- + Я, "имя и фамилия", в должности "психолога/СМО", выписываю для лечения пациента "имя пациента" следующие препараты: "названия препаратов". + + Причина: "заболевание". + --------------------------------------------------------------------- + Этот документ подтверждает право пациента на хранение и употребление вышеперечисленных препаратов. + --------------------------------------------------------------------- + Подпись: "подпись заявителя" + Дата: "день"."месяц".2562 + Печать: + +paper-med-text-request-execution = Запрос на проведение эвтаназии + --------------------------------------------------------------------- + Я, "имя и фамилия", в должности "должность" в связи "указать причину", прошу провести для себя процедуру эвтаназии. + --------------------------------------------------------------------- + Претензий к медицинскому отделу, при соблюдении ими протоколов, не имею. + + Данный документ приобретает юридическую силу, если имеет печать Юриста. + --------------------------------------------------------------------- + Подпись: "подпись заявителя" + Дата: "день"."месяц".2562 + Печать: + +paper-med-text-waiver-claims = Отказ от претензий + --------------------------------------------------------------------- + Я, "имя и фамилия", в должности "должность" даю разрешение провести на мне ряд научных исследований во благо науки. + + Эксперимент: "что на вас будут проверять". + --------------------------------------------------------------------- + Претензий к "медицинскому/научному" отделу, при соблюдении ими протоколов, не имею. + + Я полностью осведомлен(а) и информирован(а) об эксперименте и возможных угрозах. + + Настоящая расписка составлена и подписана добровольно, без какого-либо давления, обещаний или угроз. + + Данный документ приобретает юридическую силу, если имеет печать Юриста. + --------------------------------------------------------------------- + Подпись: "подпись заявителя" + Дата: "день"."месяц".2562 + Печать: + +paper-med-text-durka = Заключение о невменяемости + --------------------------------------------------------------------- + Я, "имя и фамилия", в должности "СМО/Психолога" признаю сотрудника "имя пациента" невменяемым. В связи с тем, что психические расстройства несут опасность как для самого пациента, так и для остального экипажа, пациент должен быть помещен в перманентную тюрьму. + --------------------------------------------------------------------- + Служба безопасности обязана соблюдать все права в отношении пациента, защищать и проводить его для эвакуации до Центрального Командования. + + Подписывая данный документ, возлагаю на себя полную ответственность и, в случае неправильного диагноза, понесу высшую меру наказания. + + Данный документ приобретает юридическую силу, если имеет печать ГСБ или Капитана. + --------------------------------------------------------------------- + Подпись: "подпись заявителя" + Дата: "день"."месяц".2562 + Печать: + +paper-sci-text-reasonable = Признание разумности существа + --------------------------------------------------------------------- + Я, "имя и фамилия", в должности "Ученого/Научного руководителя", подтверждаю разумность существа. + + Существо: "название" + --------------------------------------------------------------------- + В процессе проведения экспериментов было подтверждено, что данное существо обладает характеристиками, необходимыми для признания его разумным, такими как: способность к мышлению, обучаемость, понимание моральных норм и способность осознавать последствия своих действий. + + Существо имеет потенциал для работы на корпорацию NanoTrasen, в связи с чем должно пройти процедуру найма. + --------------------------------------------------------------------- + После того, как глава персонала сделает ПДА данному существу, оно официально войдёт под юрисдикцию ОПЧК на равных основах с остальными членами корпорации. + + Заявитель несет ответственность за правильное признание существа разумным. + --------------------------------------------------------------------- + Подпись: "подпись заявителя" + Дата: "день"."месяц".2562 + Печать: + +paper-sci-text-request-law = Постановление о изменении законов боргов + --------------------------------------------------------------------- + Данный документ информирует о изменении законов "всех/название борга" борга/ов. + + Вносимые изменения: "перечень внесённых изменений". + --------------------------------------------------------------------- + Данный документ приобретает юридическую силу, если имеет печати и подписи двух или более глав. + + Подписи глав: "подписи через запятую" + + Новые законы не нарушают ОПЧК и Космический Закон, направлены на принесение пользы корпорации NanoTrasen. + --------------------------------------------------------------------- + Подпись: "подпись заявителя" + Дата: "день"."месяц".2562 + Печать: + +paper-sci-text-brain = Постановление о пересадке мозга + --------------------------------------------------------------------- + Данный документ информирует о пересадке мозга человека в борга по причине невозможности реанимировать прошлого владельца. + + Я, "имя и фамилия", в должности "должность" проведу операцию по пересадки мозга "должность" "имя и фамилия пациента" в тело борга. + --------------------------------------------------------------------- + Данный документ приобретает юридическую силу, если имеет печать СМО. + --------------------------------------------------------------------- + Подпись: "подпись заявителя" + Дата: "день"."месяц".2562 + Печать: + +paper-car-text-order = Заказ товара + --------------------------------------------------------------------- + Заявитель: "имя заявителя" + Должность: "должность заявителя" + --------------------------------------------------------------------- + Товар: "кол-во - название товара" + + Причина: "зачем вам это". + --------------------------------------------------------------------- + Подпись: "подпись заявителя" + Дата: "день"."месяц".2562 + Печать: + +paper-ser-text-up-IDcard = Повышение доступа + --------------------------------------------------------------------- + Я, "имя заявителя" "должность", прошу предоставить мне дополнительно следующие доступы: "название мест". + + Причина: "причина повышения доступов" + --------------------------------------------------------------------- + Доступ будет использован исключительно в интересах станции и экипажа. Я обязуюсь не заимствовать вещи из других отделов без разрешения главы отдела, а также покину отдел в случае приказа главы. + --------------------------------------------------------------------- + Подпись: "подпись заявителя" + Дата: "день"."месяц".2562 + Печать: + +paper-ser-text-work = Ускоренный найм + --------------------------------------------------------------------- + Главе персонала станции "номер станции из ПДА". + + Я, "имя заявителя", желаю пройти процедуру ускоренного найма на космической станции NanoTrasen. Ознакомившись с условиями и положениями ускоренного трудоустройства. + + Желаемая должность: "название должности" + Отдел: "название отдела" + + "По желанию - опыт в профессии, причина трудоустройства" + --------------------------------------------------------------------- + Со стандартными рабочими процедурами, правилами и политикой NanoTrasen ознакомлен. Ответственность, возлагаемую на себя, осознаю. + --------------------------------------------------------------------- + Подпись: "подпись заявителя" + Дата: "день"."месяц".2562 + Печать: + +paper-ser-text-trash = Свидетельство о заключении брака + --------------------------------------------------------------------- + Я, "имя и фамилия", в должности священника, заключаю брак между "имя и фамилия" и "имя и фамилия" с согласия обоих сторон. + --------------------------------------------------------------------- + После заключения брака присвоены фамилии: Мужу "фамилия" Жене "фамилия" + Подпись жениха: "имя и фамилия" + Подпись невесты: "имя и фамилия" + --------------------------------------------------------------------- + Подпись: "подпись заявителя" + Дата: "день"."месяц".2562 + Печать: + +paper-ser-text-trash-end = Свидетельство о расторжении брака + --------------------------------------------------------------------- + Я, "имя и фамилия", в должности священника, расторгаю брак между "имя и фамилия" и "имя и фамилия" с согласия обоих сторон. + --------------------------------------------------------------------- + После расторжения брака присвоены фамилии: Мужу "фамилия" Жене "фамилия" + Подпись мужа: "имя и фамилия" + Подпись жены: "имя и фамилия" + --------------------------------------------------------------------- + Подпись: "подпись заявителя" + Дата: "день"."месяц".2562 + Печать: + +paper-ser-text-court = Инициация судебного процесса + --------------------------------------------------------------------- + Я, "имя и фамилия", в должности "должность", настаиваю на немедленной инициации судебного процесса в отношении "имя обвиняемого" в должности "должность обвиняемого". + + Безотлагательный судебный процесс необходим, поскольку: "почему приговор несправедливый со стороны охранной службы". + + Дополнительная документация: "прилагается / отсутствует". + + Свидетели: "список свидетелей / отсутствуют". + + Исходя из данных, представленных выше, должен пройти публичный судейский процесс, подающий пример остальным сотрудникам станции. + --------------------------------------------------------------------- + Запрос был составлен мною в пребывании адекватного состояния. Все расписанное, готов подтвердить повторно, при необходимости. + + Данный документ приобретает юридическую силу, если имеет печать Юриста. + --------------------------------------------------------------------- + Подпись: "подпись заявителя" + Дата: "день"."месяц".2562 + Печать: + +paper-ser-text-dismissal = Увольнение + --------------------------------------------------------------------- + Я, "имя заявителя", прошу уволить меня с должности "ваша должность" по собственному желанию. + + Причина: "кратко опишите причину увольнения". + --------------------------------------------------------------------- + Документ составлен в адекватном состоянии, со всеми последствиями ознакомлен. + --------------------------------------------------------------------- + Подпись: "подпись заявителя" + Дата: "день"."месяц".2562 + Печать: + +paper-ser-text-promotion = Повышение + --------------------------------------------------------------------- + Я, "имя заявителя", в должности "ваша должность" прошу повысить меня до "желаемая должность" в отделе "название отдела". + + Причина: "кратко опишите свои заслуги". + --------------------------------------------------------------------- + Я убежден, что повышение позволит мне сделать значительный вклад в работу отдела и обязуюсь с особой старательностью выполнять свои обязанности. Со стандартными рабочими процедурами, правилами и политикой NanoTrasen ознакомлен. Ответственность, возлагаемую на себя, осознаю. + --------------------------------------------------------------------- + Подпись: "подпись заявителя" + Дата: "день"."месяц".2562 + Печать: + +paper-ser-text-request-botan = Запрос растений + --------------------------------------------------------------------- + Я, "имя заявителя", в должности "должность" запрашиваю растения в ботанике. + + Растения: "название растения" + + Причина: "причина". + --------------------------------------------------------------------- + Данное растения будет использовано исключительно в выше описанных целях. + --------------------------------------------------------------------- + Подпись: "подпись заявителя" + Дата: "день"."месяц".2562 + Печать: + +paper-syn-text-ha-ha = . + ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ + ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ + ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣤⣤⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ + ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⣾⣿⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ + ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⣿⣷⣦⣀⡄⠀⠀⣠⣤⣾⡿⢿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ + ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢻⣿⣷⣜⣋⣸⣿⣿⣷⣤⣾⣿⣷⣤⣴⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ + ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⠏⠉⠻⣿⣿⣿⣿⣿⠋⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ + ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢻⣿⣿⡿⠟⠉⠀⠀⠀⠨⠛⠿⠿⠿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ + ⠀⠀⠀⠀⠀⠀⢰⣦⡀⠀⠀⠀⠀⠀⠉⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⡆⠀⠀⠀⠀⠀⠀ + ⠀⠀⠀⢰⣶⣤⠀⠙⣿⣦⡀⠀⠀⠀⠀⠀⠀⠀⣠⡄⠀⣄⡀⠀⠀⠀⠀⠀⠀⠀⣠⣼⡟⠁⠀⢠⠄⠀⠀⠀ + ⠀⠀⠀⠈⢿⣯⡀⠀⠈⠛⢿⣷⣦⣤⣤⣤⣶⣿⣿⠃⠀⢻⣿⣶⣤⣤⣤⣤⣴⣿⠟⠉⠀⠀⢰⠃⠀⠀⠀⠀ + ⠀⠀⠀⠀⠘⠿⡀⠀⢀⠀⠀⠈⠙⠛⠛⠛⠋⠉⠀⠀⠀⠀⠈⠛⠛⠛⠛⠋⠁⠀⢀⣤⣴⣶⠃⠀⠀⠀⠀⠀ + ⠀⠀⠀⠀⠀⠀⠳⢶⣏⡀⣠⣤⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣀⣀⣠⣴⣾⡿⠿⠛⠁⠀⠀⠀⠀⠀⠀ + ⠀⠀⠀⠀⠀⠀⠀⠈⠻⠿⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟⠛⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ + ⣷⣦⣀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠉⠙⠛⠛⠿⠿⠿⠿⠿⠿⠿⠟⠛⠛⠋⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣴ + ⣿⣿⣿⣿⣶⣤⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣤⣶⣿⣿⣿ + ⣿⣿⣿⣿⣿⣿⣿⣿⣶⣤⣀⠀⠀⢠⣶⣶⣶⣶⣶⣶⣶⣶⣶⣶⣶⣶⣶⡄⠀⠀⣀⣤⣶⣿⣿⣿⣿⣿⣿⣿ + ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣦⡘⢿⡿⣿⠛⠉⠉⠉⠉⠙⠻⡿⢿⡿⢁⣴⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ + ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣦⣴⣿⣦⠀⠀⠀⠀⢀⣼⣿⣦⣴⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ + ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣟⠓⠀⠀⠀⠛⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ diff --git a/Resources/Prototypes/Catalog/Fills/Items/belt.yml b/Resources/Prototypes/Catalog/Fills/Items/belt.yml index 8a27e36f08..74ea42f5ae 100644 --- a/Resources/Prototypes/Catalog/Fills/Items/belt.yml +++ b/Resources/Prototypes/Catalog/Fills/Items/belt.yml @@ -26,6 +26,7 @@ - id: Welder - id: Multitool +# WD EDIT START - type: entity id: ClothingBeltChiefEngineerFilled parent: ClothingBeltChiefEngineer @@ -36,10 +37,11 @@ - id: PowerDrill - id: JawsOfLife - id: WelderExperimental - - id: Multitool + - id: Tricorder - id: HolofanProjector - - id: GasAnalyzer - - id: trayScanner + amount: 2 + - id: CableApcStack +# WD EDIT END - type: entity id: ClothingBeltSecurityFilled diff --git a/Resources/Prototypes/White/Catalog/uplink.yml b/Resources/Prototypes/White/Catalog/uplink.yml index 9e1dc62a02..b3ce4624c5 100644 --- a/Resources/Prototypes/White/Catalog/uplink.yml +++ b/Resources/Prototypes/White/Catalog/uplink.yml @@ -84,3 +84,15 @@ Telecrystal: 15 categories: - UplinkImplants + +# Night Vision +- type: listing + id: UplinkNightGoggles + name: ПНВ [Хамелеон] + description: Теперь ты видишь во тьме! + productEntity: ClothingEyesNightVisionGogglesSyndie + icon: { sprite: White/Clothing/Head/nightvision.rsi, state: icon } + cost: + Telecrystal: 3 + categories: + - UplinkArmor diff --git a/Resources/Prototypes/White/Entities/Clothing/Head/night_vision_goggle.yml b/Resources/Prototypes/White/Entities/Clothing/Head/night_vision_goggle.yml new file mode 100644 index 0000000000..a484c97e96 --- /dev/null +++ b/Resources/Prototypes/White/Entities/Clothing/Head/night_vision_goggle.yml @@ -0,0 +1,27 @@ +# Night Vision Goggles +- type: entity + parent: ClothingEyesBase + id: ClothingEyesNightVisionGoggles + name: ПНВ + description: Теперь ты видишь во тьме! + components: + - type: Sprite + sprite: White/Clothing/Head/nightvision.rsi + - type: Clothing + sprite: White/Clothing/Head/nightvision.rsi + - type: ClothingGrantComponent + component: + - type: NightVision + +# Night Vision Goggles (Chameleon) +- type: entity + parent: ClothingEyesNightVisionGoggles + id: ClothingEyesNightVisionGogglesSyndie + components: + - type: ChameleonClothing + slot: [ eyes ] + default: ClothingEyesGlassesSunglasses + - type: UserInterface + interfaces: + - key: enum.ChameleonUiKey.Key + type: ChameleonBoundUserInterface diff --git a/Resources/Prototypes/White/Entities/Objects/Tools/tricorder.yml b/Resources/Prototypes/White/Entities/Objects/Tools/tricorder.yml new file mode 100644 index 0000000000..9a6db54c9f --- /dev/null +++ b/Resources/Prototypes/White/Entities/Objects/Tools/tricorder.yml @@ -0,0 +1,53 @@ +- type: entity + parent: BaseItem + id: Tricorder + name: трикодер + description: Многофункциональное устройство, которое может выполнять огромный спектр задач. + components: + - type: Sprite + sprite: White/Items/Tools/tricorder.rsi + layers: + - state: icon + - state: on + map: [ "tricorder_power" ] + - type: Tricorder + - type: StaticPrice + price: 300 + - type: Tool + qualities: + - Pulsing + - type: ActivatableUI + key: enum.NetworkConfiguratorUiKey.List + inHandsOnly: true + - type: UserInterface + interfaces: + - key: enum.NetworkConfiguratorUiKey.List + type: NetworkConfiguratorBoundUserInterface + - key: enum.NetworkConfiguratorUiKey.Configure + type: NetworkConfiguratorBoundUserInterface + - key: enum.NetworkConfiguratorUiKey.Link + type: NetworkConfiguratorBoundUserInterface + - key: enum.GasAnalyzerUiKey.Key + type: GasAnalyzerBoundUserInterface + - key: enum.HealthAnalyzerUiKey.Key + type: HealthAnalyzerBoundUserInterface + - type: NetworkConfigurator + - type: Tag + tags: + - DroneUsable + - Multitool + - DiscreteHealthAnalyzer + - type: Clothing + sprite: Objects/Tools/multitool.rsi + quickEquip: false + slots: + - Belt + - type: EmitSoundOnPickup + sound: + path: /Audio/White/Items/handling/multitool_pickup.ogg + - type: EmitSoundOnDrop + sound: + path: /Audio/Items/multitool_drop.ogg + - type: EmitSoundOnLand + sound: + path: /Audio/Items/multitool_drop.ogg diff --git a/Resources/Prototypes/White/Entities/Structures/Machines/doc_printer.yml b/Resources/Prototypes/White/Entities/Structures/Machines/doc_printer.yml new file mode 100644 index 0000000000..8d813d12e0 --- /dev/null +++ b/Resources/Prototypes/White/Entities/Structures/Machines/doc_printer.yml @@ -0,0 +1,985 @@ +# Base Document Printer +- type: entity + id: BaseDocPrinter + parent: BaseMachinePowered + abstract: true + name: принтер + components: + - type: Appearance + - type: Physics + bodyType: Static + - type: Fixtures + fixtures: + fix1: + shape: + !type:PhysShapeAabb + bounds: "-0.25,-0.25,0.25,0.25" + density: 25 + mask: + - TabletopMachineMask + layer: + - TabletopMachineLayer + - type: Lathe + - type: MaterialStorage + - type: ActivatableUI + key: enum.LatheUiKey.Key + - type: ActivatableUIRequiresPower + - type: UserInterface + interfaces: + - key: enum.LatheUiKey.Key + type: LatheBoundUserInterface + - key: enum.ResearchClientUiKey.Key + type: ResearchClientBoundUserInterface + - type: Transform + anchored: true + - type: Pullable + - type: StaticPrice + price: 800 + - type: ResearchClient + - type: TechnologyDatabase + +# Document Printer +- type: entity + parent: BaseDocPrinter + id: DocPrinter + name: принтер форм документов + description: Принтер для распечатки разных форм документов. Блюспейс-технологии на службе бюрократии! + components: + - type: Physics + bodyType: Static + - type: Sprite + sprite: White/Structures/Machines/doc_printer.rsi + drawdepth: SmallObjects + layers: + - state: icon + map: ["enum.LatheVisualLayers.IsRunning"] + - state: unlit + shader: unshaded + map: ["enum.PowerDeviceVisualLayers.Powered"] + - state: inserting + map: ["enum.MaterialStorageVisualLayers.Inserting"] + - type: Lathe + producingSound: /Audio/Machines/scanning.ogg + idleState: icon + runningState: printing + staticRecipes: + - BoxFolderGreenBAN + - PaperRequestTargetStation + - PaperReportCC + - PaperCompletedStation + - PaperFailedStation + - PaperRequestCentComm + - PaperRequestERT + - PaperRequestRXBZZ + - PaperRequestExecution + - PaperRequestMagistrat + - BoxFolderBlueBAN + - PaperDomotionComm + - PaperDismissalReq + - PaperRequestHeadCouncil + - PaperHeadCouncilEnd + - BoxFolderRedBAN + - PaperOrderSec + - PaperDonos + - PaperLic + - PaperTimeRequestWeapon + - PaperRequestExecutionSec + - PaperOrderWeapon + - PaperRequestGuard + - BoxFolderRYellowBAN + - PaperRequestBuild + - PaperRequestMaterial + - PaperReportElect + - PaperReportAtmos + - BoxFolderWhiteBAN + - PaperRequestNarco + - PaperRequestExecutionMed + - PaperWaiverOfClaims + - PaperDurka + - BoxFolderPurpleBAN + - PaperRequestReasonable + - PaperRequestLaw + - PaperBrain + - BoxFolderYellowBAN + - PaperCargoOrder + - BoxFolderGreyBAN + - PaperRequestUpID + - PaperRequestWork + - PaperRequestTrash + - PaperEndTrash + - PaperRequestCourt + - PaperDismissalSer + - PaperPromotion + - PaperRequestBotan + - type: EmagLatheRecipes + emagStaticRecipes: + - BoxFolderBlackBAN + - PaperSyndicat + - type: MaterialStorage + +# Recipe Paper +# Station->CentComm +- type: latheRecipe + id: PaperRequestTargetStation # Tide + result: PaperRequestTargetStation + completetime: 1 + materials: + Paper: 0 + +- type: latheRecipe + id: PaperReportCC # Tide + result: PaperReportCC + completetime: 1 + materials: + Paper: 0 + +- type: latheRecipe + id: PaperCompletedStation # Tide + result: PaperCompletedStation + completetime: 1 + materials: + Paper: 0 + +- type: latheRecipe + id: PaperFailedStation # Tide + result: PaperFailedStation + completetime: 1 + materials: + Paper: 0 + +- type: latheRecipe + id: PaperRequestCentComm # Tide + result: PaperRequestCentComm + completetime: 1 + materials: + Paper: 0 + +- type: latheRecipe + id: PaperRequestERT # Tide + result: PaperRequestERT + completetime: 1 + materials: + Paper: 0 + +- type: latheRecipe + id: PaperRequestRXBZZ # Tide + result: PaperRequestRXBZZ + completetime: 1 + materials: + Paper: 0 + +- type: latheRecipe + id: PaperRequestExecution # Tide + result: PaperRequestExecution + completetime: 1 + materials: + Paper: 0 + +- type: latheRecipe + id: PaperRequestMagistrat # Tide + result: PaperRequestMagistrat + completetime: 1 + materials: + Paper: 0 + +# PaperCommand +- type: latheRecipe + id: PaperDomotionComm # Tide + result: PaperDomotionComm + completetime: 1 + materials: + Paper: 0 + +- type: latheRecipe + id: PaperDismissalReq # Tide + result: PaperDismissalReq + completetime: 1 + materials: + Paper: 0 + +- type: latheRecipe + id: PaperRequestHeadCouncil # Tide + result: PaperRequestHeadCouncil + completetime: 1 + materials: + Paper: 0 + +- type: latheRecipe + id: PaperHeadCouncilEnd # Tide + result: PaperHeadCouncilEnd + completetime: 1 + materials: + Paper: 0 + +# PaperSecurity +- type: latheRecipe + id: PaperOrderSec # Tide + result: PaperOrderSec + completetime: 1 + materials: + Paper: 0 + +- type: latheRecipe + id: PaperRequestExecutionSec # Tide + result: PaperRequestExecutionSec + completetime: 1 + materials: + Paper: 0 + +- type: latheRecipe + id: PaperDonos # Tide + result: PaperDonos + completetime: 1 + materials: + Paper: 0 + +- type: latheRecipe + id: PaperLic # Tide + result: PaperLic + completetime: 1 + materials: + Paper: 0 + +- type: latheRecipe + id: PaperTimeRequestWeapon # Tide + result: PaperTimeRequestWeapon + completetime: 1 + materials: + Paper: 0 + +- type: latheRecipe + id: PaperOrderWeapon # Tide + result: PaperOrderWeapon + completetime: 1 + materials: + Paper: 0 + +- type: latheRecipe + id: PaperRequestGuard # Tide + result: PaperRequestGuard + completetime: 1 + materials: + Paper: 0 + +# PaperEng +- type: latheRecipe + id: PaperRequestBuild # Tide + result: PaperRequestBuild + completetime: 1 + materials: + Paper: 0 + +- type: latheRecipe + id: PaperRequestMaterial # Tide + result: PaperRequestMaterial + completetime: 1 + materials: + Paper: 0 + +- type: latheRecipe + id: PaperReportElect # Tide + result: PaperReportElect + completetime: 1 + materials: + Paper: 0 + +- type: latheRecipe + id: PaperReportAtmos # Tide + result: PaperReportAtmos + completetime: 1 + materials: + Paper: 0 + +# PaperMed +- type: latheRecipe + id: PaperRequestNarco # Tide + result: PaperRequestNarco + completetime: 1 + materials: + Paper: 0 + +- type: latheRecipe + id: PaperRequestExecutionMed # Tide + result: PaperRequestExecutionMed + completetime: 1 + materials: + Paper: 0 + +- type: latheRecipe + id: PaperWaiverOfClaims # Tide + result: PaperWaiverOfClaims + completetime: 1 + materials: + Paper: 0 + +- type: latheRecipe + id: PaperDurka # Tide + result: PaperDurka + completetime: 1 + materials: + Paper: 0 + +# PaperSci +- type: latheRecipe + id: PaperRequestReasonable # Tide + result: PaperRequestReasonable + completetime: 1 + materials: + Paper: 0 + +- type: latheRecipe + id: PaperRequestLaw # Tide + result: PaperRequestLaw + completetime: 1 + materials: + Paper: 0 + +- type: latheRecipe + id: PaperBrain # Tide + result: PaperBrain + completetime: 1 + materials: + Paper: 0 + +# PaperCargo +- type: latheRecipe + id: PaperCargoOrder # Tide + result: PaperCargoOrder + completetime: 1 + materials: + Paper: 0 + +# PaperService +- type: latheRecipe + id: PaperRequestUpID # Tide + result: PaperRequestUpID + completetime: 1 + materials: + Paper: 0 + +- type: latheRecipe + id: PaperRequestWork # Tide + result: PaperRequestWork + completetime: 1 + materials: + Paper: 0 + +- type: latheRecipe + id: PaperRequestTrash # Tide + result: PaperRequestTrash + completetime: 1 + materials: + Paper: 0 + +- type: latheRecipe + id: PaperEndTrash # Tide + result: PaperEndTrash + completetime: 1 + materials: + Paper: 0 + +- type: latheRecipe + id: PaperRequestCourt # Tide + result: PaperRequestCourt + completetime: 1 + materials: + Paper: 0 + +- type: latheRecipe + id: PaperDismissalSer # Tide + result: PaperDismissalSer + completetime: 1 + materials: + Paper: 0 + +- type: latheRecipe + id: PaperPromotion # Tide + result: PaperPromotion + completetime: 1 + materials: + Paper: 0 + +- type: latheRecipe + id: PaperRequestBotan # Tide + result: PaperRequestBotan + completetime: 1 + materials: + Paper: 0 + +# PaperSyndicat +- type: latheRecipe + id: PaperSyndicat # Tide + result: PaperSyndicat + completetime: 1 + materials: + Paper: 0 + +# PapersAll +# Station->CentComm +- type: entity + parent: Paper + id: PaperRequestTargetStation + noSpawn: true + name: запрос цели + components: + - type: Paper + content: paper-text-request + +- type: entity + parent: Paper + id: PaperReportCC + noSpawn: true + name: отчет о цели + components: + - type: Paper + content: paper-text-report + +- type: entity + parent: Paper + id: PaperCompletedStation + noSpawn: true + name: цель выполнена + components: + - type: Paper + content: paper-text-completed + +- type: entity + parent: Paper + id: PaperFailedStation + noSpawn: true + name: цель провалена + components: + - type: Paper + content: paper-text-failed + +- type: entity + parent: Paper + id: PaperRequestCentComm + noSpawn: true + name: запрос ПЦК + components: + - type: Paper + content: paper-text-request-CentComm + +- type: entity + parent: Paper + id: PaperRequestERT + noSpawn: true + name: запрос ОБР + components: + - type: Paper + content: paper-text-request-ERT + +- type: entity + parent: Paper + id: PaperRequestRXBZZ + noSpawn: true + name: запрос РХБЗЗ + components: + - type: Paper + content: paper-text-request-RXBZZ + +- type: entity + parent: Paper + id: PaperRequestExecution + noSpawn: true + name: жалоба высшей степени + components: + - type: Paper + content: paper-text-request-high-order-compaint + +- type: entity + parent: Paper + id: PaperRequestMagistrat + noSpawn: true + name: запрос в магистрат + components: + - type: Paper + content: paper-text-request-magistrat + +# PaperCommand +- type: entity + parent: Paper + id: PaperDomotionComm + noSpawn: true + name: запрос на понижение + components: + - type: Paper + content: paper-comm-text-crew-mem-domotion + +- type: entity + parent: Paper + id: PaperDismissalReq + noSpawn: true + name: запрос на увольнение + components: + - type: Paper + content: paper-comm-text-crew-mem-dismissal + +- type: entity + parent: Paper + id: PaperRequestHeadCouncil + noSpawn: true + name: запрос на голосование глав + components: + - type: Paper + content: paper-comm-text-request-council + +- type: entity + parent: Paper + id: PaperHeadCouncilEnd + noSpawn: true + name: отчет по голосованию глав + components: + - type: Paper + content: paper-comm-text-council-end + +# PaperSecurity +- type: entity + parent: Paper + id: PaperOrderSec + noSpawn: true + name: ордер на арест + components: + - type: Paper + content: paper-sec-text-order + +- type: entity + parent: Paper + id: PaperDonos + noSpawn: true + name: жалоба + components: + - type: Paper + content: paper-sec-text-complaint + +- type: entity + parent: Paper + id: PaperLic + noSpawn: true + name: разрешение на ношение оружия + components: + - type: Paper + content: paper-sec-text-lic + +- type: entity + parent: Paper + id: PaperTimeRequestWeapon + noSpawn: true + name: временный запрос на оружие + components: + - type: Paper + content: paper-sec-text-request-weapon + +- type: entity + parent: Paper + id: PaperRequestExecutionSec + noSpawn: true + name: запрос на казнь + components: + - type: Paper + content: paper-sec-text-request-execution + +- type: entity + parent: Paper + id: PaperOrderWeapon + noSpawn: true + name: разрешение на заказ оружия + components: + - type: Paper + content: paper-sec-text-request-cargo-weapon + +- type: entity + parent: Paper + id: PaperRequestGuard + noSpawn: true + name: программа защиты свидетелей + components: + - type: Paper + content: paper-sec-text-request-guard + +# PaperEng +- type: entity + parent: Paper + id: PaperRequestBuild + noSpawn: true + name: разрешение о проведении строительных работ + components: + - type: Paper + content: paper-eng-text-request-build + +- type: entity + parent: Paper + id: PaperRequestMaterial + noSpawn: true + name: запрос материалов + components: + - type: Paper + content: paper-eng-text-request-material + +- type: entity + parent: Paper + id: PaperReportElect + noSpawn: true + name: отчет об электроснабжении + components: + - type: Paper + content: paper-eng-text-report-elect + +- type: entity + parent: Paper + id: PaperReportAtmos + noSpawn: true + name: отчет об атмосфере + components: + - type: Paper + content: paper-eng-text-report-atmos + +# PaperMed +- type: entity + parent: Paper + id: PaperRequestNarco + noSpawn: true + name: лекарственный рецепт + components: + - type: Paper + content: paper-med-text-request-perm-narc + +- type: entity + parent: Paper + id: PaperRequestExecutionMed + noSpawn: true + name: запрос на проведение эвтаназии + components: + - type: Paper + content: paper-med-text-request-execution + +- type: entity + parent: Paper + id: PaperWaiverOfClaims + noSpawn: true + name: отказ от претензий + components: + - type: Paper + content: paper-med-text-waiver-claims + +- type: entity + parent: Paper + id: PaperDurka + noSpawn: true + name: заключение о невменяемости + components: + - type: Paper + content: paper-med-text-durka + +# PaperSci +- type: entity + parent: Paper + id: PaperRequestReasonable + noSpawn: true + name: признание разумности существа + components: + - type: Paper + content: paper-sci-text-reasonable + +- type: entity + parent: Paper + id: PaperRequestLaw + noSpawn: true + name: постановление о изменении законов боргов + components: + - type: Paper + content: paper-sci-text-request-law + +- type: entity + parent: Paper + id: PaperBrain + noSpawn: true + name: постановление о пересадке мозга + components: + - type: Paper + content: paper-sci-text-brain + +# PaperCargo +- type: entity + parent: Paper + id: PaperCargoOrder + noSpawn: true + name: заказ товара + components: + - type: Paper + content: paper-car-text-order + +# PaperService +- type: entity + parent: Paper + id: PaperRequestUpID + noSpawn: true + name: повышение доступа + components: + - type: Paper + content: paper-ser-text-up-IDcard + +- type: entity + parent: Paper + id: PaperRequestWork + noSpawn: true + name: ускоренный найм + components: + - type: Paper + content: paper-ser-text-work + +- type: entity + parent: Paper + id: PaperRequestTrash + noSpawn: true + name: свидетельство о заключении брака + components: + - type: Paper + content: paper-ser-text-trash + +- type: entity + parent: Paper + id: PaperEndTrash + noSpawn: true + name: свидетельство о расторжении брака + components: + - type: Paper + content: paper-ser-text-trash-end + +- type: entity + parent: Paper + id: PaperRequestCourt + noSpawn: true + name: инициация судебного процесса + components: + - type: Paper + content: paper-ser-text-court + +- type: entity + parent: Paper + id: PaperDismissalSer + noSpawn: true + name: увольнение + components: + - type: Paper + content: paper-ser-text-dismissal + +- type: entity + parent: Paper + id: PaperPromotion + noSpawn: true + name: повышение + components: + - type: Paper + content: paper-ser-text-promotion + +- type: entity + parent: Paper + id: PaperRequestBotan + noSpawn: true + name: запрос растений + components: + - type: Paper + content: paper-ser-text-request-botan + +# PaperSyndicat +- type: entity + parent: Paper + id: PaperSyndicat + noSpawn: true + name: секретные документы + components: + - type: Paper + content: paper-syn-text-ha-ha + +# BoxFolder +- type: entity + id: BoxFolderRedBAN + parent: BoxFolderBase + noSpawn: true + name: формы службы безопасноти + suffix: Red + components: + - type: Sprite + sprite: White/Structures/Machines/doc_printer.rsi + layers: + - state: folder-sec + - type: TimedDespawn + lifetime: 0,1 + +- type: entity + id: BoxFolderBlueBAN + parent: BoxFolderBase + noSpawn: true + name: формы командования + suffix: Blue + components: + - type: Sprite + sprite: White/Structures/Machines/doc_printer.rsi + layers: + - state: folder-com + - type: TimedDespawn + lifetime: 0,1 + +- type: entity + id: BoxFolderYellowBAN + parent: BoxFolderBase + noSpawn: true + name: формы карго + suffix: Yellow + components: + - type: Sprite + sprite: White/Structures/Machines/doc_printer.rsi + layers: + - state: folder-car + - type: TimedDespawn + lifetime: 0,1 + +- type: entity + id: BoxFolderWhiteBAN + parent: BoxFolderBase + noSpawn: true + name: формы медиков + suffix: White + components: + - type: Sprite + sprite: White/Structures/Machines/doc_printer.rsi + layers: + - state: folder-med + - type: TimedDespawn + lifetime: 0,1 + +- type: entity + id: BoxFolderGreyBAN + parent: BoxFolderBase + noSpawn: true + name: формы сервиса + suffix: Grey + components: + - type: Sprite + sprite: White/Structures/Machines/doc_printer.rsi + layers: + - state: folder-ser + - type: TimedDespawn + lifetime: 0,1 + +- type: entity + id: BoxFolderGreenBAN + parent: BoxFolderBase + noSpawn: true + name: формы для ЦентКома + suffix: Green + components: + - type: Sprite + sprite: White/Structures/Machines/doc_printer.rsi + layers: + - state: folder-CC + - type: TimedDespawn + lifetime: 0,1 + +- type: entity + id: BoxFolderRYellowBAN + parent: BoxFolderBase + noSpawn: true + name: формы инженеров + suffix: RYellow + components: + - type: Sprite + sprite: White/Structures/Machines/doc_printer.rsi + layers: + - state: folder-eng + - type: TimedDespawn + lifetime: 0,1 + +- type: entity + id: BoxFolderPurpleBAN + parent: BoxFolderBase + noSpawn: true + name: формы учёных + suffix: Purple + components: + - type: Sprite + sprite: White/Structures/Machines/doc_printer.rsi + layers: + - state: folder-sci + - type: TimedDespawn + lifetime: 0,1 + +- type: entity + id: BoxFolderBlackBAN + parent: BoxFolderBase + noSpawn: true + name: формы J@4D*S + suffix: Black + components: + - type: Sprite + sprite: White/Structures/Machines/doc_printer.rsi + layers: + - state: folder-syn + - type: TimedDespawn + lifetime: 0,1 + +# RecipeBoxFolder +- type: latheRecipe + id: BoxFolderGreenBAN # Tide + result: BoxFolderGreenBAN + completetime: 1 + materials: + Paper: 1 + +- type: latheRecipe + id: BoxFolderGreyBAN # Tide + result: BoxFolderGreyBAN + completetime: 1 + materials: + Paper: 1 + +- type: latheRecipe + id: BoxFolderWhiteBAN # Tide + result: BoxFolderWhiteBAN + completetime: 1 + materials: + Paper: 1 + +- type: latheRecipe + id: BoxFolderYellowBAN # Tide + result: BoxFolderYellowBAN + completetime: 1 + materials: + Paper: 1 + +- type: latheRecipe + id: BoxFolderBlueBAN # Tide + result: BoxFolderBlueBAN + completetime: 1 + materials: + Paper: 1 + +- type: latheRecipe + id: BoxFolderRedBAN # Tide + result: BoxFolderRedBAN + completetime: 1 + materials: + Paper: 1 + +- type: latheRecipe + id: BoxFolderRYellowBAN # Tide + result: BoxFolderRYellowBAN + completetime: 1 + materials: + Paper: 1 + +- type: latheRecipe + id: BoxFolderPurpleBAN # Tide + result: BoxFolderPurpleBAN + completetime: 1 + materials: + Paper: 1 + +- type: latheRecipe + id: BoxFolderBlackBAN # Tide + result: BoxFolderBlackBAN + completetime: 1 + materials: + Paper: 1 diff --git a/Resources/Prototypes/White/Recipes/lathe_recipes.yml b/Resources/Prototypes/White/Recipes/lathe_recipes.yml index 85f5284bf7..1680f0e9fe 100644 --- a/Resources/Prototypes/White/Recipes/lathe_recipes.yml +++ b/Resources/Prototypes/White/Recipes/lathe_recipes.yml @@ -11,3 +11,13 @@ completetime: 5 materials: Steel: 1500 +- type: latheRecipe + id: ClothingEyesNightVisionGoggles + result: ClothingEyesNightVisionGoggles + completetime: 2 + materials: + Steel: 200 + Glass: 100 + Silver: 100 + Gold: 100 + diff --git a/Resources/Prototypes/White/Research/experimental.yml b/Resources/Prototypes/White/Research/experimental.yml new file mode 100644 index 0000000000..5df1e504e2 --- /dev/null +++ b/Resources/Prototypes/White/Research/experimental.yml @@ -0,0 +1,43 @@ +- type: technology + id: AdvancedRobotics + name: research-technology-advanced-robotics + icon: + sprite: White/Mobs/Player/Borgs/cyborg.rsi + state: icon + discipline: Experimental + tier: 1 + cost: 5000 + recipeUnlocks: + - CyborgMonitoringComputerCircuitboard + - BorgChargerMachineCircuitboard + - CyborgMonitoringServerMachineCircuitboard + - PositronicBrain + +- type: technology + id: UpgradeBorgModule + name: research-technology-upgrade-borg + icon: + sprite: White/Objects/Devices/cyborgradiomodule.rsi + state: icon + discipline: Experimental + tier: 2 + cost: 15000 + recipeUnlocks: + - CyborgHUDModuleSec + - CyborgHUDModuleMed + - CyborgSpeedModule + - CyborgInstrumentModuleFilled + - CyborgJetpackModule + +# Night Vision Tech +- type: technology + id: NightVisionTech + name: night vision technology + icon: + sprite: White/Clothing/Head/nightvision.rsi + state: icon + discipline: Experimental + tier: 2 + cost: 10000 + recipeUnlocks: + - ClothingEyesNightVisionGoggles diff --git a/Resources/Textures/White/Clothing/Head/nightvision.rsi/equipped-EYES.png b/Resources/Textures/White/Clothing/Head/nightvision.rsi/equipped-EYES.png new file mode 100644 index 0000000000000000000000000000000000000000..7d15515f7ad7d92ea8ecc536d8f5c06b83633aa0 GIT binary patch literal 387 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7T#lEVD$2IaSW+oe0$5@+bK}u_{VsK zmc{=Mln57fwy8aQMS4BMO|5y)xJM&sW{DT+Ur+HP`sGE$7e0hfaN4p#5d)g4}&Km{s$+pREi3_*Uj-+Sk0%FD o-l-)SUA^y^Fg~k(_&$&}IPYm+xyRrwFmM?>UHx3vIVCg!09<{XZ2$lO literal 0 HcmV?d00001 diff --git a/Resources/Textures/White/Clothing/Head/nightvision.rsi/icon.png b/Resources/Textures/White/Clothing/Head/nightvision.rsi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..bf770f70f8969ba008b8e4d2b2687cd602520849 GIT binary patch literal 218 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfv=>VS)*8>L**f|I28rn!mD1}BQ zi!9KSsclyt1T!`qZMy~(> literal 0 HcmV?d00001 diff --git a/Resources/Textures/White/Clothing/Head/nightvision.rsi/inhand-left.png b/Resources/Textures/White/Clothing/Head/nightvision.rsi/inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..995b37471b38d3dbcef1e91888c4ed58239b2d29 GIT binary patch literal 385 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7T#lEVD#{GaSW+oe0ytS)}a8AV;?79 zTDrUS+Q#IAP0lZsthSWoxw9WU{v!DYhg1B5>~=oQcTG*fg=?A>V|Tglb68?=^-eYO z#s71CKGf`de*CKH@t#%&CJu!LG~z%Yr^~+Gxjp%tUSD5r^X>EFvzGg-|4-4(F^q^Z znq&F=?YHVp)rX(%y813!_Xwq1POdh~sI^pF2$AHG+EHSOm8{6o=W#kb{d*H*u; zS^a$a*}YN)E5Bwqi(qjds&fl0m=50K3wI1TBe%n+zhXZBibaLCi>F;y-d9lL*MH>| rOUn$om3QkIfC6>yPr#m?k;`yJy1Mbjqo4nPLCfIj>gTe~DWM4fU$Cme literal 0 HcmV?d00001 diff --git a/Resources/Textures/White/Clothing/Head/nightvision.rsi/inhand-right.png b/Resources/Textures/White/Clothing/Head/nightvision.rsi/inhand-right.png new file mode 100644 index 0000000000000000000000000000000000000000..c3efa67f837fbc9cc5851d2ec09ce705d1bc7652 GIT binary patch literal 410 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7T#lEU`+IMaSW+oe0ytS)}a82qaV*- zI(paX^^L%Q0*zQNYmK?LH#R>={vl!4^nkmhv>;%Yc+?A(J}Zr~mvWYk+>A$OyLd19 z_g={GyV~0qbm+$>=7ys&Nlh=Q< zJ!dO^ygOUHQG3Fv|Ldli?To*f`uzN=uk8ZK*JtUR*PLIZwZ3S#ynd*fZk_a9R-vmW zsw=~TEKR3G|E%SZ_IKFwA|qhSyU$x~P2=DG{(Shi#ZG}pxv9aGQ=@<0?f6!7|K*OY zQ`GdIZ7#TX)%Rz{DfjNVPVE`;cFGM5OdJaMh-%K9T5Fl-U7qDhM|P%(6`OryKf<{% z{5<>ZPQmAGm2;F^RICj@-Ef>4WXl*eqeQ*!+LOX1|M&}1Z*)FXu}}gTEi?as)UL{^ V#;mG;OXk;vd$@?2>@%NsSE%B literal 0 HcmV?d00001 diff --git a/Resources/Textures/White/Clothing/Head/nightvision.rsi/meta.json b/Resources/Textures/White/Clothing/Head/nightvision.rsi/meta.json new file mode 100644 index 0000000000..541bdfbedc --- /dev/null +++ b/Resources/Textures/White/Clothing/Head/nightvision.rsi/meta.json @@ -0,0 +1,26 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/5a73e8f825ff279e82949b9329783a9e3070e2da", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + }, + { + "name": "equipped-EYES", + "directions": 4 + }, + { + "name": "inhand-left", + "directions": 4 + }, + { + "name": "inhand-right", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/White/Items/Tools/tricorder.rsi/icon.png b/Resources/Textures/White/Items/Tools/tricorder.rsi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3517223cba7f4a55286641c0b60375a35679a381 GIT binary patch literal 312 zcmV-80muG{P)!k7~%I>Htum+08&l@Z{n{2;LUp*M@D-DVS)*8>L*c>Op2|7EY2SIjvn z>1uhk6)QrcR)qflZ#-+2hCNUjV@Z%-FoVOh8)-m}mZytjh{nX^1c`4B9S2n;d{5jI w@paw6Ig2Yeebw&fURmFU=83P$0%RE&Y9yE}bBw(bfVvnwUHx3vIVCg!05PU7%K!iX literal 0 HcmV?d00001 diff --git a/Resources/Textures/White/Items/Tools/tricorder.rsi/on.png b/Resources/Textures/White/Items/Tools/tricorder.rsi/on.png new file mode 100644 index 0000000000000000000000000000000000000000..0c86a50d2eb58229daff08e53ac7b45485e9f63d GIT binary patch literal 151 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfv=>VS)*8>L*c>Op2|7EY2SB&hN zL)=H(SF8w)S`qsHzj3t_X9-XlV@Z%-FoVOh8)-m}mZytjh{nX^1c`4B9S2n;d{5jI w@paw6Ig2Yeebw&fURmFU=83P$0%RE&Y9yE}bBw(bfVvnwUHx3vIVCg!0FE0lxc~qF literal 0 HcmV?d00001 diff --git a/Resources/Textures/White/Structures/Machines/doc_printer.rsi/folder-CC.png b/Resources/Textures/White/Structures/Machines/doc_printer.rsi/folder-CC.png new file mode 100644 index 0000000000000000000000000000000000000000..f740aa3c9be4c986e3fe6a7efa60e0d519bc7eac GIT binary patch literal 246 zcmV8^M z-V5jmzw$5oCV*cAj|6!Dw_4x(CoaR;y7B<76bd?=Z8@0kUjYHSI{**iaq^?7_aAn& wbsC2N>H%|F9t2nXFbX;_Ob6%y9r&LEAJkMate?r+4gdfE07*qoM6N<$f<`J}^8f$< literal 0 HcmV?d00001 diff --git a/Resources/Textures/White/Structures/Machines/doc_printer.rsi/folder-base.png b/Resources/Textures/White/Structures/Machines/doc_printer.rsi/folder-base.png new file mode 100644 index 0000000000000000000000000000000000000000..5fbb47268fc20367d8ba35969dae8e1dda8bf9cf GIT binary patch literal 98 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdzO-~ockch)?FDNoG81OJ{{Pf>F w*f!dD@(*VNW`_Asg|@ymo^)g?14B4>?>rVJ{`tncfSMRQUHx3vIVCg!0F{&*i2wiq literal 0 HcmV?d00001 diff --git a/Resources/Textures/White/Structures/Machines/doc_printer.rsi/folder-car.png b/Resources/Textures/White/Structures/Machines/doc_printer.rsi/folder-car.png new file mode 100644 index 0000000000000000000000000000000000000000..068d11192efbe0051d86587cae338d0b3fa020e4 GIT binary patch literal 256 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJ#ArYL(2@@XI7(om88@IQC|K2$PgY7nU z_Drx^B*UO}-;?pkHRdHVELWA8u(&xVn6PAsF)@7cSC6}};Pefkml!-<{an^LB{Ts5 Dclllk literal 0 HcmV?d00001 diff --git a/Resources/Textures/White/Structures/Machines/doc_printer.rsi/folder-com.png b/Resources/Textures/White/Structures/Machines/doc_printer.rsi/folder-com.png new file mode 100644 index 0000000000000000000000000000000000000000..3c679a983c3d6c0adab2eac7e4e0cad1e268208a GIT binary patch literal 264 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJ^PVn_ArYL(2@<3#}pUdCCi3=CI~Yii5$Z#V<=8iS{+ KpUXO@geCxtI9##- literal 0 HcmV?d00001 diff --git a/Resources/Textures/White/Structures/Machines/doc_printer.rsi/folder-eng.png b/Resources/Textures/White/Structures/Machines/doc_printer.rsi/folder-eng.png new file mode 100644 index 0000000000000000000000000000000000000000..d99478b036d3b80a168c0bea92a31746de1bb3d6 GIT binary patch literal 261 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJGoCJvArYL(2@E+?(|Oa#y_IQx3I9 zJxk|mEpldf){<>re|Uz*mT6Yn%pQI&Gp0U#IC;KC(GLq1Ylf5=(KnPujLX+fa(+1Z zkm6~^DG?p-EGEe^aJ>r859n1iYh3iI>4QfZgNL*pcj8Ni*{(Z|u-SFVdQ I&MBb@0LECYe9EEr z$Y<$Xtw+ubuiDOU=SwW*T|Y~f*`v=tYVO0&x6>o8CJ3wCWK?kG+giPNMr!y@(N=%1 zb{+PBB*k5iJ<1p~R!HvO=VJKWe!B(Nd=b8rd<>F(r=2D|wtMKIyhFzH!Ony$jLdRO zN7N5ZpI)$3x$8)05yOfmMOJ}m{s~FXR@}NMAi>*sQD8wN2LrgTe~DWM4f0K8(B literal 0 HcmV?d00001 diff --git a/Resources/Textures/White/Structures/Machines/doc_printer.rsi/folder-overlay-paper.png b/Resources/Textures/White/Structures/Machines/doc_printer.rsi/folder-overlay-paper.png new file mode 100644 index 0000000000000000000000000000000000000000..82f57cdd65389bfe37dd9288cd8c9dc8f56aa2ac GIT binary patch literal 113 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz3r`ovkch)?FK*;zFyLTzob$K* zV@FzRN#KL^%PMASG0ZqomY0A2^^HnK&rQ{gOe&q?0uBreHA@+FMA+3gm@cgbn!(`d L>gTe~DWM4f>yaXG literal 0 HcmV?d00001 diff --git a/Resources/Textures/White/Structures/Machines/doc_printer.rsi/folder-sci.png b/Resources/Textures/White/Structures/Machines/doc_printer.rsi/folder-sci.png new file mode 100644 index 0000000000000000000000000000000000000000..e97c6682f6939f0b8024c448821d3e91eaf3520a GIT binary patch literal 261 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJGoCJvArYL(2@wsm#zG0u?AW2)`oT~S0A7E?RT zI3=RvoysIx2Ci4%?duoKaL!?Jy~y%(!W)JOb}?dyE-{*Q7j*Jg=t-0wXlQ4+*ePK9 z^s!gSk}lz=3<0dpTngLd6po$=+zNHH!)5^n1|>~($=SCLl>xoQ;OXk;vd$@?2>{M1 BTZsSw literal 0 HcmV?d00001 diff --git a/Resources/Textures/White/Structures/Machines/doc_printer.rsi/folder-ser.png b/Resources/Textures/White/Structures/Machines/doc_printer.rsi/folder-ser.png new file mode 100644 index 0000000000000000000000000000000000000000..554cb609fe7a08f7886f804aef3b0dc4f318cf85 GIT binary patch literal 255 zcmV_>k_s7 z-6YN#O^FiyK$3IPxhZ;=8Pp#h672Xr;l$a$N*}lTeUJCs_Gpe5rv{_y1q;UWXY5Pw z&b{bZ{Q2J8=QBUG*7dUoPftupd1v5zfpJFDjlgx%T`yR;oV`}+tS;}_SW~<8|5`)l z0|w7yezpm$x_9Xh%ZKv^ROd)Oh`n-sU;M92dnFmp&1XycU&@`)@NByS!&%`4{0|Fd wRyMcRH!js+Sp8D?fLo&Cv@nqM8_JmY``cww<;zXlfPP`{boFyt=akR{02Xy<8vp^*^%Ab1W7&tu^^1i{J^*jrg@X=&;5Wb+wjC$97VF0wEI$v7r? zkIc(RbhEwL;^%q3pXD@7V^#CxteE}{;Bg#N6h-={<9!@Q_}zxYWdaO73OgsTQ6J>%CsS6{`Pccf}yWo)6 zh2|_F6BGNt`>@YWY@&*%hrIp|27^OZoyla9yUncj?BB}Pf3gL#t|8v(bg12Kv$rjm zOOzjcLGYpP48Vvl77N;Lw=96oW-FPTGgF`*#%`@v6Jv*|YjVVrQ2JsINIMV1j6)_j#$L+J{nE@K)eogF0)XMu>6H5Y z{;%8^J)h6bS2pi2!2-n3VLA5AqUITG!aY>O=EN8^j=pU}nZ| zQJ)Y9F$AOql-)jpU?}~}9$+HBZD6SD5c(_t%;%Vf%1l}72U{nke&tt!3c&7uRl8Nt4KndJD0r6>2vi#ChV&11dNk=L# zTc3R;mL;y|1N3}=o)3^l$X%9K{-vlG1i5JIV}D-iHlg&{X)xseJO?18zSsjo?ay-n zP!>vG1Q2R}UIGwGUjzWdoc8D6lk)+|d4OX|?a{mL&!1|tnT!5xHv4fd!Pw!dp9#Qe ze?EN>;mSRF*88N;MZece4kp;=66|Y9ASoAvV5t3h&Ne+CaH68;1Gw&SWtnt7q4Fz1 z1#o4L`Zv|sSpeQ~Yw;pp=Y3Q3*ZM_#)w)VR2`B+2pahhF5>Nt4KndJFfiIHcGZ)la R2&Mo4002ovPDHLkV1h!*SF!*A literal 0 HcmV?d00001 diff --git a/Resources/Textures/White/Structures/Machines/doc_printer.rsi/inserting.png b/Resources/Textures/White/Structures/Machines/doc_printer.rsi/inserting.png new file mode 100644 index 0000000000000000000000000000000000000000..f966089daea1d06e546ce4665de4e907060c71cb GIT binary patch literal 1471 zcmah}|2xwO9RF-467jShHBl~+qfK&H?%6&I7hywnJ-*D$og@yO8OJawl~DPTiZw~+ z%N6teZad^Sg)x!Z2(`rw54fJ^^?tuzujlpt?e#qG>pp}NdOAoQ008tn z++F>)n6Wh>+S|7FNK%pq0BB}+k50nVHJ2A<&^-2mZG0szT6dQ zUua-rEr+s=eD4!TiBR+Jf=hMXb-ip5Gnub6kGxE-sfo$KJiiVfb2KO4acZOGt~--= zN%(T6pK0H~z`!YAd24HHRhivtD+V_4$ze*l><~CLx6$^AU0>#IUgtUpgG5J1AJe}i z7KEm_Vy4NBcPmRvPU~}P^pf1d^Bh2HJvHkf^rwy4+3ML9war9dpJ(q% zJvji#Q%s<3bd4Lh++R1|j$0jr`v?aOywq;c?1*-E#sR*obW@?IPomRLOL8@GV4?$; zhM>FSpIo#iFzSr`&7a*}z5$y_HcVZDUfa&)wUN1i8N)6(I`$q1iqH%Rj*H(!qfk`8 zpgB8Q%H)xB5=(bB)834*{oHhm9FO-)}74GkrBVUUz+ZU@M3;^i(Fd~`3I zC6P!~QfWk?1QW@h*f(DxMn8afN%AuqU6w{^_Zy$~8Et=Fqp#l7$A&(_%r^CVj=r8c zxKRdFih6pkj|v2db+5Y#L}Gj%srKnpJ!J&hPeYKE;Uyq;k`VwVvm`AxwzRpqxjS-< zqFM=BGEAm52aw5Ww(JmL%G-C_OWR#1)ngAKx!zhWV>9Ly5OX)4BUW|+@ z5;sPiZOLdNe*I-*M_=k?hs3ek!EH33Z!>I>Jn5X4tYzT12A%_3)rC@UdTEk9;LWu; zr*;BKun#*{o55zItQlitfo?77W<_eXdWf5`PFL&I4eBCtL0;B49ob&RBca zCqQ1EQu`;3Ph3qjBvzNCHSVKGejWIs9-j(6J}CKwnLfScc%X z$93qNuuwvgqDRHXb*LcP8$#i|-5>Ci3RQPST<)}@QAxqsq}3h;ya`}F!o82j%l>%k z7Cq}oNpUe8hpylYtGu2(&RK4SfgvtLpLgOXDwT?I@l6ok(a{mhou~W9Kn&_E__y#f zr3%LEEh3E`0_7+W`QzpbWjNIK{mZ@heGT}^-3_Y~CIwBkmQ|lQXYhq zZ)pZ{8qSKLmA42yu{cHqYp9bQ?>rpGy|8H+y4j~32uoAd36y>(F`7PBSf&juYos=6 zav|(58A@QJm41y+gtPb&N2k_w2aW9VLeW*)9A!&_nE zTmv%2#b~W|Y^ehjMUJh(<{i^Hoznpcrg9ZUtn}`#q1tRb)&z4Rzo-APgR>rJ ztiDP7GYXv$WelCU+bLVfDgvS#z2WHJEXbvc!llqRE3MA#x#3g_?whn_2iq_@$1wZ% z%yp^~el47FS}y%X+;2Z$agPNe!0J`%u=E^qd6-Asufr(uwZf(%DuNxb<5Ui_<_8wd z?tG`KO#lAh0n?VTI;A`0^5z+y4E2$`7Z#cd@bpXlx+;oKlrS^bSCw#f5u-pZZ61y= zULNizGAz?epw0za5b6tI&{;De_vBTDfD6pxR&3gK78xu;L)wo)$QvVvA6jTLfd2)U buf3*WSm`MN@<+0_9y8$KMsTe;9&+g)2gSew literal 0 HcmV?d00001 diff --git a/Resources/Textures/White/Structures/Machines/doc_printer.rsi/meta.json b/Resources/Textures/White/Structures/Machines/doc_printer.rsi/meta.json new file mode 100644 index 0000000000..75d284d44e --- /dev/null +++ b/Resources/Textures/White/Structures/Machines/doc_printer.rsi/meta.json @@ -0,0 +1,96 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Made by Valentyi", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + }, + { + "name": "unlit", + "delays": [ + [ + 0.6, + 0.7, + 0.6, + 0.7 + ] + ] + }, + { + "name": "folder-base" + }, + { + "name": "idle" + }, + { + "name": "folder-CC" + }, + { + "name": "folder-overlay-paper" + }, + { + "name": "folder-med" + }, + { + "name": "folder-sec" + }, + { + "name": "folder-eng" + }, + { + "name": "folder-sci" + }, + { + "name": "folder-car" + }, + { + "name": "folder-syn" + }, + { + "name": "folder-com" + }, + { + "name": "folder-ser" + }, + { + "name": "inserting", + "delays": [ + [ + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2 + ] + ] + }, + { + "name": "printing", + "delays": [ + [ + 0.4, + 0.4, + 0.4, + 0.4, + 0.4, + 0.4, + 0.4, + 0.4, + 0.4 + ] + ] + } + ] +} \ No newline at end of file diff --git a/Resources/Textures/White/Structures/Machines/doc_printer.rsi/printing.png b/Resources/Textures/White/Structures/Machines/doc_printer.rsi/printing.png new file mode 100644 index 0000000000000000000000000000000000000000..802903c41057ee0b215e17e9e8ae2ac4a79a4bfb GIT binary patch literal 1426 zcmZ{kdpOez7{`BOOgER(Xso%MD8h4GhLzb6M!BVAayXPrF1dGM3w4wfPA;Q5MlQp& z9qP=j$T{wpk)h+V35A2rqA_C}J?G!k^L)SW_wzjOfA9Bs-c%PSy90Y+djSAAfU~!8 z+fCnZmXY3_(|I?{06@wUXM=UW3F7`%?EuFrrf91_mfnBqjFhX2-hSw;)JYrpgvS$! zd4?bN1tET%EpwPTB!h%DVNQb8$1Vj8xjTf~$oE>LMdw$|_44wUm?k&2^`6(iGFl~X zFnLU~0s-u9aWS|ccvuMvj%tUs-Xp$evq(?lDz{!3@P>u?A?;yh35~cv1J)-W(V%E7V>Er&&VJ zMB>HtKCSUjtg)xJPMKV73Jb59I~GtSIqyk~j`nYFZy(bwxPLg^4CFPOl$3Nb#KU1I zy?||DVKF`N^Z1zYF+!wl#MB|>eM4o?i>}ue9d)%U2s)w{k}?x(Ym9s{`A#-IsIjpT z*;8g@WaMcsD2>H@TR%{3@$vC7O-oDT8ap>^lm^?{+O4z&gopE7^BILzXu-2ubq0}> zQX~2aG62W$+1Z74b~A*(^6mt3<3^c{4I{D_$@n4PyAGBE(vb(tx`xor<2DjT#tJM= zdy$m>q~5tdE9T>ufyR|C$%g`SDZ&WoHO0DTKqrGrr4F)7OEMc$YEM?U)O&dv++XYor8I*`thr1g@Eu{)K#`{I3-ln8TjS!1f9yZA%lfx* zgQhp%AY8bc3Z-z2$I%w&4RK;u7cM$JK4fiuy)?vKOtcAxWcpENR)hIqEXwLdR%uho zikze4(g~I4o9r1?T2VJhvEbZ&MTGMllgT_@!7Ybj9uzgx>3u?BojD3+Xb>Mi?j1CB z-a1FJ9IF6S7Vp6piN=Z@0DM@b^X{!ybai!SJ#>YSc;G&DT5`#-bX!L>fW97jr2ztg zR5iuLeq!Ab%S(`zG=OE;OBdX1Ii5@-qMV$Zdinf_+&jY`C?kRJOt%E0t^T^^tgy|_ zMd!Q6?A|hpi1~|vPvwSonI|j z;&(FR;^Ib@mX@xNCvS2%zlxMdXL&~bVP}^iF(~v7kLLuIUlaqR)V}*~$nQ{U0SRwR zIOom}Dj~4d(=*=uaP(oqd(bzW{|~{|aPo3%7wK`vjiR~LYlLxZPkQ=7?NaCV%jQ2i zvTnoWHPIaZai2*q7oix`lrGWVrrd0{XGWZ8Hc9^YR?@GvV^g20_|+5A`Y2;gHS-Dj zMRC2Zn%@ysc?G1l6ePl3Be$BWHb`1awhCkM`YAL-_Yp1z0ROKF^ph+Lw-?smf;T_! P{#pQc#>s|e<(vF3EX}KS literal 0 HcmV?d00001 diff --git a/Resources/Textures/White/Structures/Machines/doc_printer.rsi/unlit.png b/Resources/Textures/White/Structures/Machines/doc_printer.rsi/unlit.png new file mode 100644 index 0000000000000000000000000000000000000000..c7b0bff3ea017516fd2ac5e2931560674cf1c702 GIT binary patch literal 232 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=>pfi@Ln;{G-g4w>HV|OF@X~i# zdk%jf|IMA9y{xKwyE+40;+zyFKJl-K?!CYvpy1HJz{teHAs`_%Be~CAdTshMv$joa zd}~ejo4#z}pwyy7!;|?x_ktve|a#qk^*ezl-<%5&qD1qWayo okgN5t-mi*6*n}{mpsbO9v4^b8j;DH0flg=eboFyt=akR{0JlX;I{*Lx literal 0 HcmV?d00001 From a085815fc5b3a87151a0ddd0264d2ebcb6a9dd00 Mon Sep 17 00:00:00 2001 From: Remuchi <72476615+Remuchi@users.noreply.github.com> Date: Mon, 13 Nov 2023 17:09:10 +0700 Subject: [PATCH 4/5] =?UTF-8?q?[Tweak]=20=D0=91=D1=83=D0=BC=D0=B0=D0=B6?= =?UTF-8?q?=D0=BD=D0=B0=D1=8F=20=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=B0=20?= =?UTF-8?q?=D0=B8=20=D1=84=D0=B8=D0=BA=D1=81=20=D0=BA=D1=80=D0=B0=D1=84?= =?UTF-8?q?=D1=82=D0=B0=20=D0=BF=D0=BD=D0=B2.=20(#560)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: персонал станции вспомнил как делать пнв * feat: заказ бумаги в карго * feat: бумажная дверь # Conflicts: # Resources/Prototypes/Entities/Structures/Machines/lathe.yml # Resources/Prototypes/White/Recipes/lathe_recipes.yml --- .../Entities/Structures/Machines/lathe.yml | 1 + .../Prototypes/White/Catalog/Fills/misc.yml | 9 + Resources/Prototypes/White/Catalog/cargo.yml | 9 + .../White/Construction/Paperworks/graphs.yml | 27 +++ .../Construction/Paperworks/structures.yml | 15 ++ .../Structures/Machines/doc_printer.yml | 224 +++++++++--------- .../White/Research/experimental.yml | 2 +- .../White/Structures/Windows/paper.yml | 62 +++++ .../Windows/paperwindow.rsi/full.png | Bin 0 -> 413 bytes .../Windows/paperwindow.rsi/meta.json | 46 ++++ .../Windows/paperwindow.rsi/window0.png | Bin 0 -> 811 bytes .../Windows/paperwindow.rsi/window1.png | Bin 0 -> 753 bytes .../Windows/paperwindow.rsi/window2.png | Bin 0 -> 811 bytes .../Windows/paperwindow.rsi/window3.png | Bin 0 -> 753 bytes .../Windows/paperwindow.rsi/window4.png | Bin 0 -> 747 bytes .../Windows/paperwindow.rsi/window5.png | Bin 0 -> 715 bytes .../Windows/paperwindow.rsi/window6.png | Bin 0 -> 747 bytes .../Windows/paperwindow.rsi/window7.png | Bin 0 -> 673 bytes 18 files changed, 282 insertions(+), 113 deletions(-) create mode 100644 Resources/Prototypes/White/Catalog/Fills/misc.yml create mode 100644 Resources/Prototypes/White/Catalog/cargo.yml create mode 100644 Resources/Prototypes/White/Construction/Paperworks/graphs.yml create mode 100644 Resources/Prototypes/White/Construction/Paperworks/structures.yml create mode 100644 Resources/Prototypes/White/Structures/Windows/paper.yml create mode 100644 Resources/Textures/White/Structures/Windows/paperwindow.rsi/full.png create mode 100644 Resources/Textures/White/Structures/Windows/paperwindow.rsi/meta.json create mode 100644 Resources/Textures/White/Structures/Windows/paperwindow.rsi/window0.png create mode 100644 Resources/Textures/White/Structures/Windows/paperwindow.rsi/window1.png create mode 100644 Resources/Textures/White/Structures/Windows/paperwindow.rsi/window2.png create mode 100644 Resources/Textures/White/Structures/Windows/paperwindow.rsi/window3.png create mode 100644 Resources/Textures/White/Structures/Windows/paperwindow.rsi/window4.png create mode 100644 Resources/Textures/White/Structures/Windows/paperwindow.rsi/window5.png create mode 100644 Resources/Textures/White/Structures/Windows/paperwindow.rsi/window6.png create mode 100644 Resources/Textures/White/Structures/Windows/paperwindow.rsi/window7.png diff --git a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml index 9f4faf469c..3e597191a3 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml @@ -308,6 +308,7 @@ - FauxTileAstroGrass - FauxTileAstroIce - OreBagOfHolding + - ClothingEyesNightVisionGoggles # WD EDIT - type: EmagLatheRecipes emagDynamicRecipes: - ExplosivePayload diff --git a/Resources/Prototypes/White/Catalog/Fills/misc.yml b/Resources/Prototypes/White/Catalog/Fills/misc.yml new file mode 100644 index 0000000000..3e018c180d --- /dev/null +++ b/Resources/Prototypes/White/Catalog/Fills/misc.yml @@ -0,0 +1,9 @@ +- type: entity + id: CratePaper + name: ящик бумаги + parent: CrateGenericSteel + components: + - type: StorageFill + contents: + - id: SheetPaper + amount: 3 diff --git a/Resources/Prototypes/White/Catalog/cargo.yml b/Resources/Prototypes/White/Catalog/cargo.yml new file mode 100644 index 0000000000..34ea2aeba9 --- /dev/null +++ b/Resources/Prototypes/White/Catalog/cargo.yml @@ -0,0 +1,9 @@ +- type: cargoProduct + id: CratePaper + icon: + sprite: Objects/Materials/Sheets/other.rsi + state: paper + product: CratePaper + cost: 1000 + category: Materials + group: market \ No newline at end of file diff --git a/Resources/Prototypes/White/Construction/Paperworks/graphs.yml b/Resources/Prototypes/White/Construction/Paperworks/graphs.yml new file mode 100644 index 0000000000..de1e1e6cbd --- /dev/null +++ b/Resources/Prototypes/White/Construction/Paperworks/graphs.yml @@ -0,0 +1,27 @@ +# Paper window constructiom +- type: constructionGraph + id: WindowPaperGraph + start: start + graph: + - node: start + actions: + - !type:DestroyEntity { } + edges: + - to: paperDoor + completed: + - !type:SnapToGrid { } + steps: + - material: Paper + amount: 10 + doAfter: 10 + - node: paperDoor + entity: WindowPaper + edges: + - to: start + completed: + - !type:SpawnPrototype + prototype: SheetPaper1 + amount: 10 + steps: + - tool: Anchoring + doAfter: 15 \ No newline at end of file diff --git a/Resources/Prototypes/White/Construction/Paperworks/structures.yml b/Resources/Prototypes/White/Construction/Paperworks/structures.yml new file mode 100644 index 0000000000..7f83e9f054 --- /dev/null +++ b/Resources/Prototypes/White/Construction/Paperworks/structures.yml @@ -0,0 +1,15 @@ +# Paper window construction +- type: construction + name: сёдзи + id: WindowPaper + graph: WindowPaperGraph + startNode: start + targetNode: paperDoor + category: construction-category-structures + description: Окно, но только из бумаги + objectType: Structure + placementMode: SnapgridCenter + canBuildInImpassable: false + icon: + sprite: White/Structures/Windows/paperwindow.rsi + state: full diff --git a/Resources/Prototypes/White/Entities/Structures/Machines/doc_printer.yml b/Resources/Prototypes/White/Entities/Structures/Machines/doc_printer.yml index 8d813d12e0..16c2174118 100644 --- a/Resources/Prototypes/White/Entities/Structures/Machines/doc_printer.yml +++ b/Resources/Prototypes/White/Entities/Structures/Machines/doc_printer.yml @@ -52,69 +52,69 @@ drawdepth: SmallObjects layers: - state: icon - map: ["enum.LatheVisualLayers.IsRunning"] + map: [ "enum.LatheVisualLayers.IsRunning" ] - state: unlit shader: unshaded - map: ["enum.PowerDeviceVisualLayers.Powered"] + map: [ "enum.PowerDeviceVisualLayers.Powered" ] - state: inserting - map: ["enum.MaterialStorageVisualLayers.Inserting"] + map: [ "enum.MaterialStorageVisualLayers.Inserting" ] - type: Lathe producingSound: /Audio/Machines/scanning.ogg idleState: icon runningState: printing staticRecipes: - - BoxFolderGreenBAN - - PaperRequestTargetStation - - PaperReportCC - - PaperCompletedStation - - PaperFailedStation - - PaperRequestCentComm - - PaperRequestERT - - PaperRequestRXBZZ - - PaperRequestExecution - - PaperRequestMagistrat - - BoxFolderBlueBAN - - PaperDomotionComm - - PaperDismissalReq - - PaperRequestHeadCouncil - - PaperHeadCouncilEnd - - BoxFolderRedBAN - - PaperOrderSec - - PaperDonos - - PaperLic - - PaperTimeRequestWeapon - - PaperRequestExecutionSec - - PaperOrderWeapon - - PaperRequestGuard - - BoxFolderRYellowBAN - - PaperRequestBuild - - PaperRequestMaterial - - PaperReportElect - - PaperReportAtmos - - BoxFolderWhiteBAN - - PaperRequestNarco - - PaperRequestExecutionMed - - PaperWaiverOfClaims - - PaperDurka - - BoxFolderPurpleBAN - - PaperRequestReasonable - - PaperRequestLaw - - PaperBrain - - BoxFolderYellowBAN - - PaperCargoOrder - - BoxFolderGreyBAN - - PaperRequestUpID - - PaperRequestWork - - PaperRequestTrash - - PaperEndTrash - - PaperRequestCourt - - PaperDismissalSer - - PaperPromotion - - PaperRequestBotan + - BoxFolderGreenBAN + - PaperRequestTargetStation + - PaperReportCC + - PaperCompletedStation + - PaperFailedStation + - PaperRequestCentComm + - PaperRequestERT + - PaperRequestRXBZZ + - PaperRequestExecution + - PaperRequestMagistrat + - BoxFolderBlueBAN + - PaperDomotionComm + - PaperDismissalReq + - PaperRequestHeadCouncil + - PaperHeadCouncilEnd + - BoxFolderRedBAN + - PaperOrderSec + - PaperDonos + - PaperLic + - PaperTimeRequestWeapon + - PaperRequestExecutionSec + - PaperOrderWeapon + - PaperRequestGuard + - BoxFolderRYellowBAN + - PaperRequestBuild + - PaperRequestMaterial + - PaperReportElect + - PaperReportAtmos + - BoxFolderWhiteBAN + - PaperRequestNarco + - PaperRequestExecutionMed + - PaperWaiverOfClaims + - PaperDurka + - BoxFolderPurpleBAN + - PaperRequestReasonable + - PaperRequestLaw + - PaperBrain + - BoxFolderYellowBAN + - PaperCargoOrder + - BoxFolderGreyBAN + - PaperRequestUpID + - PaperRequestWork + - PaperRequestTrash + - PaperEndTrash + - PaperRequestCourt + - PaperDismissalSer + - PaperPromotion + - PaperRequestBotan - type: EmagLatheRecipes emagStaticRecipes: - - BoxFolderBlackBAN - - PaperSyndicat + - BoxFolderBlackBAN + - PaperSyndicat - type: MaterialStorage # Recipe Paper @@ -122,63 +122,63 @@ - type: latheRecipe id: PaperRequestTargetStation # Tide result: PaperRequestTargetStation - completetime: 1 + completetime: 5 materials: Paper: 0 - type: latheRecipe id: PaperReportCC # Tide result: PaperReportCC - completetime: 1 + completetime: 5 materials: Paper: 0 - type: latheRecipe id: PaperCompletedStation # Tide result: PaperCompletedStation - completetime: 1 + completetime: 5 materials: Paper: 0 - type: latheRecipe id: PaperFailedStation # Tide result: PaperFailedStation - completetime: 1 + completetime: 5 materials: Paper: 0 - type: latheRecipe id: PaperRequestCentComm # Tide result: PaperRequestCentComm - completetime: 1 + completetime: 5 materials: Paper: 0 - type: latheRecipe id: PaperRequestERT # Tide result: PaperRequestERT - completetime: 1 + completetime: 5 materials: Paper: 0 - type: latheRecipe id: PaperRequestRXBZZ # Tide result: PaperRequestRXBZZ - completetime: 1 + completetime: 5 materials: Paper: 0 - type: latheRecipe id: PaperRequestExecution # Tide result: PaperRequestExecution - completetime: 1 + completetime: 5 materials: Paper: 0 - type: latheRecipe id: PaperRequestMagistrat # Tide result: PaperRequestMagistrat - completetime: 1 + completetime: 5 materials: Paper: 0 @@ -186,28 +186,28 @@ - type: latheRecipe id: PaperDomotionComm # Tide result: PaperDomotionComm - completetime: 1 + completetime: 5 materials: Paper: 0 - type: latheRecipe id: PaperDismissalReq # Tide result: PaperDismissalReq - completetime: 1 + completetime: 5 materials: Paper: 0 - type: latheRecipe id: PaperRequestHeadCouncil # Tide result: PaperRequestHeadCouncil - completetime: 1 + completetime: 5 materials: Paper: 0 - type: latheRecipe id: PaperHeadCouncilEnd # Tide result: PaperHeadCouncilEnd - completetime: 1 + completetime: 5 materials: Paper: 0 @@ -215,49 +215,49 @@ - type: latheRecipe id: PaperOrderSec # Tide result: PaperOrderSec - completetime: 1 + completetime: 5 materials: Paper: 0 - type: latheRecipe id: PaperRequestExecutionSec # Tide result: PaperRequestExecutionSec - completetime: 1 + completetime: 5 materials: Paper: 0 - type: latheRecipe id: PaperDonos # Tide result: PaperDonos - completetime: 1 + completetime: 5 materials: Paper: 0 - type: latheRecipe id: PaperLic # Tide result: PaperLic - completetime: 1 + completetime: 5 materials: Paper: 0 - type: latheRecipe id: PaperTimeRequestWeapon # Tide result: PaperTimeRequestWeapon - completetime: 1 + completetime: 5 materials: Paper: 0 - type: latheRecipe id: PaperOrderWeapon # Tide result: PaperOrderWeapon - completetime: 1 + completetime: 5 materials: Paper: 0 - type: latheRecipe id: PaperRequestGuard # Tide result: PaperRequestGuard - completetime: 1 + completetime: 5 materials: Paper: 0 @@ -265,28 +265,28 @@ - type: latheRecipe id: PaperRequestBuild # Tide result: PaperRequestBuild - completetime: 1 + completetime: 5 materials: Paper: 0 - type: latheRecipe id: PaperRequestMaterial # Tide result: PaperRequestMaterial - completetime: 1 + completetime: 5 materials: Paper: 0 - type: latheRecipe id: PaperReportElect # Tide result: PaperReportElect - completetime: 1 + completetime: 5 materials: Paper: 0 - type: latheRecipe id: PaperReportAtmos # Tide result: PaperReportAtmos - completetime: 1 + completetime: 5 materials: Paper: 0 @@ -294,28 +294,28 @@ - type: latheRecipe id: PaperRequestNarco # Tide result: PaperRequestNarco - completetime: 1 + completetime: 5 materials: Paper: 0 - type: latheRecipe id: PaperRequestExecutionMed # Tide result: PaperRequestExecutionMed - completetime: 1 + completetime: 5 materials: Paper: 0 - type: latheRecipe id: PaperWaiverOfClaims # Tide result: PaperWaiverOfClaims - completetime: 1 + completetime: 5 materials: Paper: 0 - type: latheRecipe id: PaperDurka # Tide result: PaperDurka - completetime: 1 + completetime: 5 materials: Paper: 0 @@ -323,21 +323,21 @@ - type: latheRecipe id: PaperRequestReasonable # Tide result: PaperRequestReasonable - completetime: 1 + completetime: 5 materials: Paper: 0 - type: latheRecipe id: PaperRequestLaw # Tide result: PaperRequestLaw - completetime: 1 + completetime: 5 materials: Paper: 0 - type: latheRecipe id: PaperBrain # Tide result: PaperBrain - completetime: 1 + completetime: 5 materials: Paper: 0 @@ -345,7 +345,7 @@ - type: latheRecipe id: PaperCargoOrder # Tide result: PaperCargoOrder - completetime: 1 + completetime: 5 materials: Paper: 0 @@ -353,56 +353,56 @@ - type: latheRecipe id: PaperRequestUpID # Tide result: PaperRequestUpID - completetime: 1 + completetime: 5 materials: Paper: 0 - type: latheRecipe id: PaperRequestWork # Tide result: PaperRequestWork - completetime: 1 + completetime: 5 materials: Paper: 0 - type: latheRecipe id: PaperRequestTrash # Tide result: PaperRequestTrash - completetime: 1 + completetime: 5 materials: Paper: 0 - type: latheRecipe id: PaperEndTrash # Tide result: PaperEndTrash - completetime: 1 + completetime: 5 materials: Paper: 0 - type: latheRecipe id: PaperRequestCourt # Tide result: PaperRequestCourt - completetime: 1 + completetime: 5 materials: Paper: 0 - type: latheRecipe id: PaperDismissalSer # Tide result: PaperDismissalSer - completetime: 1 + completetime: 5 materials: Paper: 0 - type: latheRecipe id: PaperPromotion # Tide result: PaperPromotion - completetime: 1 + completetime: 5 materials: Paper: 0 - type: latheRecipe id: PaperRequestBotan # Tide result: PaperRequestBotan - completetime: 1 + completetime: 5 materials: Paper: 0 @@ -410,7 +410,7 @@ - type: latheRecipe id: PaperSyndicat # Tide result: PaperSyndicat - completetime: 1 + completetime: 5 materials: Paper: 0 @@ -924,62 +924,62 @@ - type: latheRecipe id: BoxFolderGreenBAN # Tide result: BoxFolderGreenBAN - completetime: 1 + completetime: 5 materials: - Paper: 1 + Paper: 999 - type: latheRecipe id: BoxFolderGreyBAN # Tide result: BoxFolderGreyBAN - completetime: 1 + completetime: 5 materials: - Paper: 1 + Paper: 999 - type: latheRecipe id: BoxFolderWhiteBAN # Tide result: BoxFolderWhiteBAN - completetime: 1 + completetime: 5 materials: - Paper: 1 + Paper: 999 - type: latheRecipe id: BoxFolderYellowBAN # Tide result: BoxFolderYellowBAN - completetime: 1 + completetime: 5 materials: - Paper: 1 + Paper: 999 - type: latheRecipe id: BoxFolderBlueBAN # Tide result: BoxFolderBlueBAN - completetime: 1 + completetime: 5 materials: - Paper: 1 + Paper: 999 - type: latheRecipe id: BoxFolderRedBAN # Tide result: BoxFolderRedBAN - completetime: 1 + completetime: 5 materials: - Paper: 1 + Paper: 999 - type: latheRecipe id: BoxFolderRYellowBAN # Tide result: BoxFolderRYellowBAN - completetime: 1 + completetime: 5 materials: - Paper: 1 + Paper: 999 - type: latheRecipe id: BoxFolderPurpleBAN # Tide result: BoxFolderPurpleBAN - completetime: 1 + completetime: 5 materials: - Paper: 1 + Paper: 999 - type: latheRecipe id: BoxFolderBlackBAN # Tide result: BoxFolderBlackBAN - completetime: 1 + completetime: 5 materials: - Paper: 1 + Paper: 999 diff --git a/Resources/Prototypes/White/Research/experimental.yml b/Resources/Prototypes/White/Research/experimental.yml index 5df1e504e2..6ea76940a5 100644 --- a/Resources/Prototypes/White/Research/experimental.yml +++ b/Resources/Prototypes/White/Research/experimental.yml @@ -32,7 +32,7 @@ # Night Vision Tech - type: technology id: NightVisionTech - name: night vision technology + name: Технологии ночного видиния icon: sprite: White/Clothing/Head/nightvision.rsi state: icon diff --git a/Resources/Prototypes/White/Structures/Windows/paper.yml b/Resources/Prototypes/White/Structures/Windows/paper.yml new file mode 100644 index 0000000000..12da8ec076 --- /dev/null +++ b/Resources/Prototypes/White/Structures/Windows/paper.yml @@ -0,0 +1,62 @@ +# Window Paper +- type: entity + id: WindowPaper + parent: BaseStructure + name: сёдзи + description: Окно, но только из бумаги + placement: + mode: SnapgridCenter + snap: + - Window + components: + - type: WallMount + arc: 360 # interact despite grilles + - type: Tag + tags: + - RCDDeconstructWhitelist + - ForceFixRotations + - Window + - type: Sprite + drawdepth: WallTops + sprite: White/Structures/Windows/paperwindow.rsi + - type: Icon + sprite: White/Structures/Windows/paperwindow.rsi + state: full + - type: Physics + bodyType: Static + - type: Fixtures + fixtures: + fix1: + shape: + !type:PhysShapeAabb { } + mask: + - FullTileMask + layer: + - GlassLayer + - type: Damageable + damageContainer: Inorganic + damageModifierSet: Glass + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 50 #excess damage (nuke?). avoid computational cost of spawning entities. + behaviors: + - !type:DoActsBehavior + acts: [ "Destruction" ] + - trigger: + !type:DamageTrigger + damage: 25 + behaviors: + - !type:DoActsBehavior + acts: [ "Destruction" ] + - type: Airtight + - type: IconSmooth + key: windows + base: window + - type: Construction + graph: WindowPaperGraph + node: paperDoor + - type: Appearance + - type: StaticPrice + price: 100 diff --git a/Resources/Textures/White/Structures/Windows/paperwindow.rsi/full.png b/Resources/Textures/White/Structures/Windows/paperwindow.rsi/full.png new file mode 100644 index 0000000000000000000000000000000000000000..d602799c0c7e9149bf417e42f1e0af3d576a2a4d GIT binary patch literal 413 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=hEVFs69AIEF-Uz74m|V=@$wRqAta zo#jy?)3D{X64xZ{3js{5rz8bf11>$`YGf*GD`2ovky^3Cc~kzy%_(bj`j;7qSf5=N z{@Jd_RxDU};{LxiGwd(9m+zWpb>!nG+jpv^1`+RAZk4WZl94|qKUYO<+U(}v2U{6e zIMsao{F*1m-#v5Nt&3lueBOH?^E3A$nZp$ix#uf51=ws;^PBB&_sENFjf={)N6kPg zD)AFLZ$ziZnxmH+tXqCGFsE{A^F_^T{Fm|UOaAoDCUN%{y?*=3yW#S)W&w$|bcNGK zj+&8fDo3x~p2|_s6JfW#>u0EVh-gIx>mI!g-!_Z3`+eXE`Oe^V$h$+_Er*xKX}149 zYp*3G9BVOc1X;Z0(39ni>v`Ay%{h9oC4Ipz_5h)G6U+P?9Wy?ktarCPX#3zC!!cFQ wFUz->%u3Yrv7A#RcC;Ys^!G;#AOEy}{r_by*EZ`+V6ZcIy85}Sb4q9e0CLW;c>n+a literal 0 HcmV?d00001 diff --git a/Resources/Textures/White/Structures/Windows/paperwindow.rsi/meta.json b/Resources/Textures/White/Structures/Windows/paperwindow.rsi/meta.json new file mode 100644 index 0000000000..677f0a1ff7 --- /dev/null +++ b/Resources/Textures/White/Structures/Windows/paperwindow.rsi/meta.json @@ -0,0 +1,46 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from tgstation", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "full" + }, + { + "name": "window0", + "directions": 4 + }, + { + "name": "window1", + "directions": 4 + }, + { + "name": "window2", + "directions": 4 + }, + { + "name": "window3", + "directions": 4 + }, + { + "name": "window4", + "directions": 4 + }, + { + "name": "window5", + "directions": 4 + }, + { + "name": "window6", + "directions": 4 + }, + { + "name": "window7", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/White/Structures/Windows/paperwindow.rsi/window0.png b/Resources/Textures/White/Structures/Windows/paperwindow.rsi/window0.png new file mode 100644 index 0000000000000000000000000000000000000000..21a611833887a3614cd72cdf2f7f619014dfc38b GIT binary patch literal 811 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7T#lEVEW|g;uuoF_;&V2zdH^BZM=^J zofwxmc)2@ruGJKDofPijEU6)IzCpvnODc|0BVeAQrm||NQec56ayqm_sqNd^_N)JpOwGLcFlit^xegyPMZpIcPug7wxRV$luKddhV;PL z=T@7T8;%S7Pc4a-sk!w^=fPR&E4B+(F@|jYv1;zI`ns*%SJ!M3JFsXQQ}*xr`g;FW zF@HB0o=i^7{r!%?qgB}FJww0@5tsKM_7t&(?!X2mKKuO7&sRTP$58X9>Jmr2%ze@K z*RCyodhx4YvF|DVaE4QxbS`ZDDd7;XW{%RXT;m?5Tq(Ia;~g8tkDQ8{-!8X6H6vGk z_v6dYx4u1J%O9|IsiS=Nj48V}?A#Z#X3gH?K@o4Ay?$>olw>ok^FE$yQd3-a=G*4y zY77Q-#t$V^S&nZEn0dYG#Mz_+B?VnmZ9Cfe(-EVKluN{&QpHd;h(t< zL9A|WSq%2?<*asJTCKqGH9h=(v%Z~$`T^4jZIh=w(Fq?Er<_S*IO-|xs+e9RW6Z1| z>K9;nr0tdovqNH#0IFC>KhugWuR|=Jc&tlSV`%%%n0oV$gALc)JUK0MaqAz3-whA& zFudPoB4M@Tr?B`LP@IGy$B#HeWV{;#Q{0LK&$*jcwbbt26q0E$ll_2Tw@Hn9#Ci1( z8e8QjM?`Yp%MrO?ogYpBvJIzC;-wh!vQ^mA=7;w{A+5V;7&t`v{vTs_@Xey-@P0#vn#7phh71=L$2|NnoylV#*Mx@2 z&ABW4UQ`G(eCs>cz5e2ch*#g{2&}s+|7ORGsJJJg3h$Zg%$yb;<^Q);=G)aJhO7Zs z6??M7Z?Af4%Fx2qUa#vKKADXnuix3?&+6QxG2Q#TFY|gjoaq(3EPtoF*df|5eQK>k z+;Kxa^>iNJ8k5s~FHM6DS3WN&l3+OSwy@qsMO?v`0pzUcs{c%47Q^6`=2hD)*DS`Jmkh7GrOx37@NcoNZ|&gSsS`8(tF>FI$N{waH~Iz&#>+y4Ff z^Q6++$NsnfUOI5JDU45L4qwOo)a<+AxB8?Q))h2NR9h#yo{izq4uvf&9=8LT4~X&w zTspG#(NzWq3GtR`44Kwis~uKvKXiq;Qa)f>p30?=111aj>o?Ec+}M5XI)f?0i_$zp zlM6pDi(FwSXk`w04ASTF7{s0;%Ha9m%wOQef7TaMf8N-BZ0URP6*(=vB)&9I$wRyeOgILppMfjZ9J^WNw4F|-sq{%CT_EoRtph*2wK148I+ Ze&1tWX^-uCGk{5%!PC{xWt~$(697KgOcwwE literal 0 HcmV?d00001 diff --git a/Resources/Textures/White/Structures/Windows/paperwindow.rsi/window2.png b/Resources/Textures/White/Structures/Windows/paperwindow.rsi/window2.png new file mode 100644 index 0000000000000000000000000000000000000000..21a611833887a3614cd72cdf2f7f619014dfc38b GIT binary patch literal 811 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7T#lEVEW|g;uuoF_;&V2zdH^BZM=^J zofwxmc)2@ruGJKDofPijEU6)IzCpvnODc|0BVeAQrm||NQec56ayqm_sqNd^_N)JpOwGLcFlit^xegyPMZpIcPug7wxRV$luKddhV;PL z=T@7T8;%S7Pc4a-sk!w^=fPR&E4B+(F@|jYv1;zI`ns*%SJ!M3JFsXQQ}*xr`g;FW zF@HB0o=i^7{r!%?qgB}FJww0@5tsKM_7t&(?!X2mKKuO7&sRTP$58X9>Jmr2%ze@K z*RCyodhx4YvF|DVaE4QxbS`ZDDd7;XW{%RXT;m?5Tq(Ia;~g8tkDQ8{-!8X6H6vGk z_v6dYx4u1J%O9|IsiS=Nj48V}?A#Z#X3gH?K@o4Ay?$>olw>ok^FE$yQd3-a=G*4y zY77Q-#t$V^S&nZEn0dYG#Mz_+B?VnmZ9Cfe(-EVKluN{&QpHd;h(t< zL9A|WSq%2?<*asJTCKqGH9h=(v%Z~$`T^4jZIh=w(Fq?Er<_S*IO-|xs+e9RW6Z1| z>K9;nr0tdovqNH#0IFC>KhugWuR|=Jc&tlSV`%%%n0oV$gALc)JUK0MaqAz3-whA& zFudPoB4M@Tr?B`LP@IGy$B#HeWV{;#Q{0LK&$*jcwbbt26q0E$ll_2Tw@Hn9#Ci1( z8e8QjM?`Yp%MrO?ogYpBvJIzC;-wh!vQ^mA=7;w{A+5V;7&t`v{vTs_@Xey-@P0#vn#7phh71=L$2|NnoylV#*Mx@2 z&ABW4UQ`G(eCs>cz5e2ch*#g{2&}s+|7ORGsJJJg3h$Zg%$yb;<^Q);=G)aJhO7Zs z6??M7Z?Af4%Fx2qUa#vKKADXnuix3?&+6QxG2Q#TFY|gjoaq(3EPtoF*df|5eQK>k z+;Kxa^>iNJ8k5s~FHM6DS3WN&l3+OSwy@qsMO?v`0pzUcs{c%47Q^6`=2hD)*DS`Jmkh7GrOx37@NcoNZ|&gSsS`8(tF>FI$N{waH~Iz&#>+y4Ff z^Q6++$NsnfUOI5JDU45L4qwOo)a<+AxB8?Q))h2NR9h#yo{izq4uvf&9=8LT4~X&w zTspG#(NzWq3GtR`44Kwis~uKvKXiq;Qa)f>p30?=111aj>o?Ec+}M5XI)f?0i_$zp zlM6pDi(FwSXk`w04ASTF7{s0;%Ha9m%wOQef7TaMf8N-BZ0URP6*(=vB)&9I$wRyeOgILppMfjZ9J^WNw4F|-sq{%CT_EoRtph*2wK148I+ Ze&1tWX^-uCGk{5%!PC{xWt~$(697KgOcwwE literal 0 HcmV?d00001 diff --git a/Resources/Textures/White/Structures/Windows/paperwindow.rsi/window4.png b/Resources/Textures/White/Structures/Windows/paperwindow.rsi/window4.png new file mode 100644 index 0000000000000000000000000000000000000000..a5c5add73e50c7e5b45fd4fa689955abe56a5644 GIT binary patch literal 747 zcmV%*E2{^ToEDa<(0=U3IOy>vy zFfI|DBY+DWM0Jh;0OJxNB_OL^;N)OiiYMAWD*|dAQ0sv3zVELQ(K+uK)H=W;#9Z`e zI3!C0t{EU@P}@E<a^w-?(>6JK!6#uYMsRL;L=H9=P za_&4uW2%!6TG%8_{ru5ryGIVq3)fPc+?f#RTP7wfLTq1G+PchUC(3**w0n9Tz z5T!-DbR3mkz~Vk$3LN$-1k^g9)&buI52Y2Z@z8dN6twQuwm~j%5MvD-{?!NoFfI`Y zz`9o>fD0T%Sp$cEH39&PO9TS2?#1`w^n70eqWJRwdby$GCN6|h-|Q%vv{vkNBt~ue zc>mSogDbZND^UOevB05UBIZ`iAb>mL01o}uU?mD5zz4>aOT^rY83bTPxxk^{8q7ct z?*bHaJr9U{E(KN`!l;Sz{VedwD8ui+d7;F<<7uB;J*=@=j&7C7`xgV%5l z0=P2{;Lz8I!E_7|-~;2zron4C2LYH-E^z2;#2^_%d>$ZiPPRm#WQ6y dpjYNC+Xu3n4j2`aDjNU*002ovPDHLkV1n^0L+tF`L&1}$Y|{XTE;E!Zmi0AI(^!sCc7Do%~r)(q0| zXkueT4_&7dum%7Dv>8u@u==OtAwWt@Ytso>1AqWt0TbQHRapj^-{-9rTtxui2cQAO zQQQ0gv1X8tM-$8?j`?%~)&L*?G74f^+v=Z=hX6UmW6;CxFu~FZSOb6n+Kh`(JK}Oz zcs>H;RDcMuBTpBg$};HtfXv_ZpC9joJQE-fM#wnnqofB!!t-l_IXyrcCgx8%`x1Of z1z^RHaW(=VqadfXXCpu^am=5M0NRX$IOekj@O?my4EXN>sOvbQv~g<8u8{!hdtezH zBYNmMHTW9NA%HgHsSq_{puPtLNQr4}YVb9jLjbRUiQX45KObPNBB>zDdsv?@sIn2V z5D={IBhWzNsBNBrSjDH~(L{5JV?LdLH2?^JjDncfw)&^zAwVv1%%>Bu1^@xH83%F9 zxB92!AwWt@Yg-94u?#ZrD>Na1?*s6Gj-$5p0kM7r=y-MyXhr~J^j}thR6)!HG#Ey$ x5cCXM1Hf(a(vO1Ge+&5GSpf)uGWe?s_y*()uo3{KT}c1{002ovPDHLkV1mF&H{<{S literal 0 HcmV?d00001 diff --git a/Resources/Textures/White/Structures/Windows/paperwindow.rsi/window6.png b/Resources/Textures/White/Structures/Windows/paperwindow.rsi/window6.png new file mode 100644 index 0000000000000000000000000000000000000000..a5c5add73e50c7e5b45fd4fa689955abe56a5644 GIT binary patch literal 747 zcmV%*E2{^ToEDa<(0=U3IOy>vy zFfI|DBY+DWM0Jh;0OJxNB_OL^;N)OiiYMAWD*|dAQ0sv3zVELQ(K+uK)H=W;#9Z`e zI3!C0t{EU@P}@E<a^w-?(>6JK!6#uYMsRL;L=H9=P za_&4uW2%!6TG%8_{ru5ryGIVq3)fPc+?f#RTP7wfLTq1G+PchUC(3**w0n9Tz z5T!-DbR3mkz~Vk$3LN$-1k^g9)&buI52Y2Z@z8dN6twQuwm~j%5MvD-{?!NoFfI`Y zz`9o>fD0T%Sp$cEH39&PO9TS2?#1`w^n70eqWJRwdby$GCN6|h-|Q%vv{vkNBt~ue zc>mSogDbZND^UOevB05UBIZ`iAb>mL01o}uU?mD5zz4>aOT^rY83bTPxxk^{8q7ct z?*bHaJr9U{E(KN`!l;Sz{VedwD8ui+d7;F<<7uB;J*=@=j&7C7`xgV%5l z0=P2{;Lz8I!E_7|-~;2zron4C2LYH-E^z2;#2^_%d>$ZiPPRm#WQ6y dpjYNC+Xu3n4j2`aDjNU*002ovPDHLkV1n^0L+tBeFN>i_%X<|s z1?7cY9V;1DuxK>*1g+yMGGdx^`UT^j7j`L;o4)-#c4>`j{G-}6_s^fPsotCM-TL$U zpAVn8Yd(DYVPE(keUayJ`@Z|H-~Ima^>?3M{jyKFQfGbV?{A*UjU^8Mtn2EYJUc(j zR^`Q>42}rqsNM6AOMQ}Jny{B`OIf|gh02Qp7r5s9tX!kGUU9)P1BdMI?JRS}c^R{T ztj`h8WAYyv{`gc;?e{je#?0}64f}=zmm{)EmreP;drPBnM>T&z(*M)EjHa#LN4;2O&xc*XT5kXy4_4Q(h@tydR^4uUmMu)_`(zuU7+73H*)2X_{Zm%Yq0#7?YYx=< zVj;*23oc9K*2YwEB=j2ol2e$>&ZuE!{oshp6pl#7a-g%9_s;=3!~3Z20~_`)0SWV% zU%WQirq?RR6p_4va~sg`tv}>WDmJJwL|l0n*lfxMwh%0)u*%}V%=?SkvU$KZW`ES& z`KPvlD?u@!b75Wlg{KNj7$Rz(TQ>13_Fi1t-0ijRZv7Wq7c~KbP0l+XkKv;!>r literal 0 HcmV?d00001 From 27e500a7a9a7c132ec004a8902c67f19825352d2 Mon Sep 17 00:00:00 2001 From: Remuchi Date: Fri, 26 Jan 2024 17:36:10 +0700 Subject: [PATCH 5/5] feat: night vision --- .../White/Overlays/NightVisionOverlay.cs | 50 ++++++++++++++ .../White/Overlays/NightVisionSystem.cs | 66 +++++++++++++++++++ .../White/Items/Tricorder/TricorderSystem.cs | 42 +++++------- Content.Shared/Content.Shared.csproj | 3 - .../Item/Tricorder/TricorderComponent.cs | 8 +-- .../White/Overlays/NightVisionComponent.cs | 19 ++++++ Resources/Prototypes/Shaders/shaders.yml | 5 ++ .../Clothing/Head/night_vision_goggle.yml | 1 + .../Textures/Shaders/White/nightvision.swsl | 38 +++++++++++ 9 files changed, 199 insertions(+), 33 deletions(-) create mode 100644 Content.Client/White/Overlays/NightVisionOverlay.cs create mode 100644 Content.Client/White/Overlays/NightVisionSystem.cs create mode 100644 Content.Shared/White/Overlays/NightVisionComponent.cs create mode 100644 Resources/Textures/Shaders/White/nightvision.swsl diff --git a/Content.Client/White/Overlays/NightVisionOverlay.cs b/Content.Client/White/Overlays/NightVisionOverlay.cs new file mode 100644 index 0000000000..adc646a2e2 --- /dev/null +++ b/Content.Client/White/Overlays/NightVisionOverlay.cs @@ -0,0 +1,50 @@ +using Content.Shared.White.Overlays; +using Robust.Client.Graphics; +using Robust.Client.Player; +using Robust.Shared.Enums; +using Robust.Shared.Prototypes; + +namespace Content.Client.White.Overlays +{ + public sealed class NightVisionOverlay : Overlay + { + [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + [Dependency] private readonly IPlayerManager _playerManager = default!; + [Dependency] private readonly IEntityManager _entityManager = default!; + + public override bool RequestScreenTexture => true; + + public override OverlaySpace Space => OverlaySpace.WorldSpace; + + private readonly ShaderInstance _shader; + + public NightVisionOverlay() + { + IoCManager.InjectDependencies(this); + _shader = _prototypeManager.Index("NightVision").InstanceUnique(); + } + + protected override void Draw(in OverlayDrawArgs args) + { + if (ScreenTexture == null) + return; + + var handle = args.WorldHandle; + + if (!_entityManager.TryGetComponent(_playerManager.LocalSession?.AttachedEntity, + out var component)) + { + return; + } + + _shader.SetParameter("SCREEN_TEXTURE", ScreenTexture); + _shader.SetParameter("tint", component.Tint); + _shader.SetParameter("luminance_threshold", component.Strength); + _shader.SetParameter("noise_amount", component.Noise); + + handle.UseShader(_shader); + handle.DrawRect(args.WorldBounds, component.Color); + handle.UseShader(null); + } + } +} diff --git a/Content.Client/White/Overlays/NightVisionSystem.cs b/Content.Client/White/Overlays/NightVisionSystem.cs new file mode 100644 index 0000000000..eea89161a5 --- /dev/null +++ b/Content.Client/White/Overlays/NightVisionSystem.cs @@ -0,0 +1,66 @@ +using Content.Shared.GameTicking; +using Content.Shared.White.Overlays; +using Robust.Client.Graphics; +using Robust.Client.Player; +using Robust.Shared.Player; + +namespace Content.Client.White.Overlays; + +public sealed class NightVisionSystem : EntitySystem +{ + [Dependency] private readonly IPlayerManager _player = default!; + [Dependency] private readonly IOverlayManager _overlayMan = default!; + [Dependency] private readonly ILightManager _lightManager = default!; + + private NightVisionOverlay _overlay = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnInit); + SubscribeLocalEvent(OnRemove); + + SubscribeLocalEvent(OnPlayerAttached); + SubscribeLocalEvent(OnPlayerDetached); + SubscribeLocalEvent(OnRestart); + + _overlay = new NightVisionOverlay(); + } + + private void OnPlayerAttached(EntityUid uid, NightVisionComponent component, PlayerAttachedEvent args) + { + _overlayMan.AddOverlay(_overlay); + _lightManager.DrawLighting = false; + } + + private void OnPlayerDetached(EntityUid uid, NightVisionComponent component, PlayerDetachedEvent args) + { + _overlayMan.RemoveOverlay(_overlay); + _lightManager.DrawLighting = true; + } + + private void OnInit(EntityUid uid, NightVisionComponent component, ComponentInit args) + { + if (_player.LocalSession?.AttachedEntity != uid) + return; + + _overlayMan.AddOverlay(_overlay); + _lightManager.DrawLighting = false; + } + + private void OnRemove(EntityUid uid, NightVisionComponent component, ComponentRemove args) + { + if (_player.LocalSession?.AttachedEntity != uid) + return; + + _overlayMan.RemoveOverlay(_overlay); + _lightManager.DrawLighting = true; + } + + private void OnRestart(RoundRestartCleanupEvent ev) + { + _overlayMan.RemoveOverlay(_overlay); + _lightManager.DrawLighting = true; + } +} diff --git a/Content.Server/White/Items/Tricorder/TricorderSystem.cs b/Content.Server/White/Items/Tricorder/TricorderSystem.cs index 62d0f13689..f08de51a57 100644 --- a/Content.Server/White/Items/Tricorder/TricorderSystem.cs +++ b/Content.Server/White/Items/Tricorder/TricorderSystem.cs @@ -8,9 +8,8 @@ using Content.Shared.Examine; using Content.Shared.MedicalScanner; using Content.Shared.Verbs; using Content.Shared.White.Item.Tricorder; -using Robust.Server.GameObjects; +using Robust.Server.Audio; using Robust.Shared.Audio; -using Robust.Shared.GameStates; using Robust.Shared.Utility; namespace Content.Server.White.Items.Tricorder; @@ -38,8 +37,7 @@ public sealed class TricorderSystem : SharedTricorderSystem private void OnAddSwitchModeVerbs(EntityUid uid, TricorderComponent component, GetVerbsEvent args) { - if (!args.CanAccess || !args.CanInteract || !args.Using.HasValue || - !HasComp(args.Target)) + if (!args.CanAccess || !args.CanInteract || !args.Using.HasValue || !HasComp(args.Target)) { return; } @@ -100,44 +98,41 @@ public sealed class TricorderSystem : SharedTricorderSystem if (!user.HasValue) return; - UpdateModeAppearance(user.Value, tricorder); + UpdateModeAppearance(user.Value, tricoderUid, tricorder); } - private void UpdateModeAppearance( - EntityUid userUid, - TricorderComponent tricorder) + private void UpdateModeAppearance(EntityUid userUid, EntityUid tricoderUid, TricorderComponent tricorder) { - Dirty(tricorder); _audioSystem.PlayPvs(tricorder.SoundSwitchMode, userUid, AudioParams.Default.WithVolume(1.5f)); + Dirty(tricoderUid, tricorder); } private void SetToMultitool(EntityUid uid) { - var comp = AddComp(uid); RemComp(uid); RemComp(uid); - Dirty(comp); - if (!TryComp(uid, out ActivatableUIComponent? ui)) + var comp = AddComp(uid); + if (TryComp(uid, out ActivatableUIComponent? ui)) { - return; + ui.Key = NetworkConfiguratorUiKey.Configure; } - ui.Key = NetworkConfiguratorUiKey.Configure; + Dirty(uid, comp); } private void SetToGasAnalyzer(EntityUid uid) { RemComp(uid); - AddComp(uid); RemComp(uid); - if (!TryComp(uid, out ActivatableUIComponent? ui)) + var comp = AddComp(uid); + if (TryComp(uid, out ActivatableUIComponent? ui)) { - return; + ui.Key = GasAnalyzerComponent.GasAnalyzerUiKey.Key; } - ui.Key = GasAnalyzerComponent.GasAnalyzerUiKey.Key; + Dirty(uid, comp); } private void SetToHealthAnalyzer(EntityUid uid) @@ -147,15 +142,12 @@ public sealed class TricorderSystem : SharedTricorderSystem var healthAnalyzerComponent = _componentFactory.GetComponent(); healthAnalyzerComponent.ScanningEndSound = new SoundPathSpecifier("/Audio/Items/Medical/healthscanner.ogg"); - healthAnalyzerComponent.Owner = uid; + _entityManager.AddComponent(uid, healthAnalyzerComponent); - - if (!TryComp(uid, out ActivatableUIComponent? ui)) + if (TryComp(uid, out ActivatableUIComponent? ui)) { - return; + ui.Key = HealthAnalyzerUiKey.Key; } - - ui.Key = HealthAnalyzerUiKey.Key; } -} \ No newline at end of file +} diff --git a/Content.Shared/Content.Shared.csproj b/Content.Shared/Content.Shared.csproj index b8fc551e75..e67223ae3c 100644 --- a/Content.Shared/Content.Shared.csproj +++ b/Content.Shared/Content.Shared.csproj @@ -23,9 +23,6 @@ false - - - diff --git a/Content.Shared/White/Item/Tricorder/TricorderComponent.cs b/Content.Shared/White/Item/Tricorder/TricorderComponent.cs index 7f391c8b2a..a8669ce97a 100644 --- a/Content.Shared/White/Item/Tricorder/TricorderComponent.cs +++ b/Content.Shared/White/Item/Tricorder/TricorderComponent.cs @@ -4,10 +4,8 @@ using Robust.Shared.Serialization; namespace Content.Shared.White.Item.Tricorder; -[RegisterComponent] -[NetworkedComponent] -[Access(typeof(SharedTricorderSystem))] -public sealed class TricorderComponent : Component +[RegisterComponent, NetworkedComponent, Access(typeof(SharedTricorderSystem))] +public sealed partial class TricorderComponent : Component { [DataField("currentState"), ViewVariables(VVAccess.ReadWrite)] public TricorderMode CurrentMode = TricorderMode.Multitool; @@ -35,4 +33,4 @@ public enum TricorderMode Multitool, GasAnalyzer, HealthAnalyzer -} \ No newline at end of file +} diff --git a/Content.Shared/White/Overlays/NightVisionComponent.cs b/Content.Shared/White/Overlays/NightVisionComponent.cs new file mode 100644 index 0000000000..a78ccbd8d5 --- /dev/null +++ b/Content.Shared/White/Overlays/NightVisionComponent.cs @@ -0,0 +1,19 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared.White.Overlays; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +public sealed partial class NightVisionComponent : Component +{ + [DataField("tint"), ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] + public Vector3 Tint = new(0.3f, 0.3f, 0.3f); + + [DataField("strength"), ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] + public float Strength = 2f; + + [DataField("noise"), ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] + public float Noise = 0.5f; + + [DataField("color"), ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] + public Color Color = Color.FromHex("#98FB98"); +} diff --git a/Resources/Prototypes/Shaders/shaders.yml b/Resources/Prototypes/Shaders/shaders.yml index f6f30fdd4e..b6b32d2be1 100644 --- a/Resources/Prototypes/Shaders/shaders.yml +++ b/Resources/Prototypes/Shaders/shaders.yml @@ -100,6 +100,11 @@ kind: source path: "/Textures/Shaders/cataracts.swsl" +- type: shader + id: NightVision + kind: source + path: "/Textures/Shaders/White/nightvision.swsl" + - type: shader id: SaturationScale kind: source diff --git a/Resources/Prototypes/White/Entities/Clothing/Head/night_vision_goggle.yml b/Resources/Prototypes/White/Entities/Clothing/Head/night_vision_goggle.yml index a484c97e96..e771deb421 100644 --- a/Resources/Prototypes/White/Entities/Clothing/Head/night_vision_goggle.yml +++ b/Resources/Prototypes/White/Entities/Clothing/Head/night_vision_goggle.yml @@ -17,6 +17,7 @@ - type: entity parent: ClothingEyesNightVisionGoggles id: ClothingEyesNightVisionGogglesSyndie + suffix: "Хамелеон" components: - type: ChameleonClothing slot: [ eyes ] diff --git a/Resources/Textures/Shaders/White/nightvision.swsl b/Resources/Textures/Shaders/White/nightvision.swsl new file mode 100644 index 0000000000..8a3e7706ad --- /dev/null +++ b/Resources/Textures/Shaders/White/nightvision.swsl @@ -0,0 +1,38 @@ +light_mode unshaded; + +uniform sampler2D SCREEN_TEXTURE; +uniform highp vec3 tint; // Colour of the tint +uniform highp float luminance_threshold; // number between 0 and 1 +uniform highp float noise_amount; // number between 0 and 1 + +lowp float rand (lowp vec2 n) { + return 0.5 + 0.5 * fract (sin (dot (n.xy, vec2 (12.9898, 78.233)))* 43758.5453); +} + +void fragment() { + + highp vec4 color = zTextureSpec(SCREEN_TEXTURE, FRAGCOORD.xy * SCREEN_PIXEL_SIZE); + + // convert color to grayscale using luminance + highp float grey = dot(color.rgb, vec3(0.298, 0.5882, 0.1137)); + + // calculate local threshold + highp float threshold = grey * luminance_threshold; + + // amplify low luminance parts + if (grey < threshold) { + grey += (threshold - grey) * 0.5; + if (grey > 1.0) { + grey = 1.0; + } + } + + // apply night vision color tint + color.rgb = mix(color.rgb, tint, grey); + + // add some noise for realism + lowp float noise = rand(FRAGCOORD.xy + TIME) * noise_amount / 10.0; + color.rgb += noise; + + COLOR = color; +}