diff --git a/.github/workflows/build-test-debug.yml b/.github/workflows/build-test-debug.yml index 47f9fd1a514..0189aa91a70 100644 --- a/.github/workflows/build-test-debug.yml +++ b/.github/workflows/build-test-debug.yml @@ -36,7 +36,7 @@ jobs: - name: Setup .NET Core uses: actions/setup-dotnet@v3.2.0 with: - dotnet-version: 8.0.x + dotnet-version: 8.0.203 - name: Install dependencies run: dotnet restore diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 58cc9ba4d20..9f9cc0bf554 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -77,7 +77,7 @@ jobs: with: host: ${{ secrets.BUILDS_HOST }} username: ${{ secrets.BUILDS_USERNAME }} - password: ${{ secrets.BUILD_PASSWORD }} + key: ${{ secrets.BUILDS_SSH_KEY }} port: ${{ secrets.BUILDS_PORT }} script: python3 ~/manifest.py --version ${{ github.sha }} diff --git a/.github/workflows/test-packaging.yml b/.github/workflows/test-packaging.yml index e3cd5159d5d..be0399b3b75 100644 --- a/.github/workflows/test-packaging.yml +++ b/.github/workflows/test-packaging.yml @@ -51,7 +51,7 @@ jobs: - name: Setup .NET Core uses: actions/setup-dotnet@v3.2.0 with: - dotnet-version: 8.0.x + dotnet-version: 8.0.203 - name: Install dependencies run: dotnet restore diff --git a/.github/workflows/yaml-linter.yml b/.github/workflows/yaml-linter.yml index dfe497b100c..32b933d6f72 100644 --- a/.github/workflows/yaml-linter.yml +++ b/.github/workflows/yaml-linter.yml @@ -26,7 +26,7 @@ jobs: - name: Setup .NET Core uses: actions/setup-dotnet@v3.2.0 with: - dotnet-version: 8.0.x + dotnet-version: 8.0.203 - name: Install dependencies run: dotnet restore - name: Build diff --git a/ADT_STATION b/ADT_STATION index ed73f1253d5..97bff099ae4 160000 --- a/ADT_STATION +++ b/ADT_STATION @@ -1 +1 @@ -Subproject commit ed73f1253d585bbab612647b94eb4341b4344a09 +Subproject commit 97bff099ae4400e9d077e34f73ee7ca7996ee14f diff --git a/Content.Client/ADT/Changeling/ChangelingPanelSystem.cs b/Content.Client/ADT/Changeling/ChangelingPanelSystem.cs new file mode 100644 index 00000000000..e0e8bd60e19 --- /dev/null +++ b/Content.Client/ADT/Changeling/ChangelingPanelSystem.cs @@ -0,0 +1,104 @@ +/// Made for Adventure Time Project by ModerN. https://github.com/modern-nm mailto:modern-nm@yandex.by +/// see also https://github.com/DocNITE/liebendorf-station/tree/feature/emote-radial-panel +using Content.Client.Humanoid; +using Content.Client.UserInterface.Systems.Radial; +using Content.Client.UserInterface.Systems.Radial.Controls; +using Content.Shared.Changeling; +using Content.Shared.Humanoid.Prototypes; +using Robust.Client.GameObjects; +using Robust.Client.Player; +using Robust.Client.UserInterface; +using Robust.Client.UserInterface.Controls; +using Robust.Shared.Map; +using Robust.Shared.Player; +using Robust.Shared.Prototypes; +using Robust.Shared.Random; +using Robust.Shared.Utility; +using System.Numerics; + +namespace Content.Client.ADT.Language; + +public sealed class ChangelingPanelSystem : EntitySystem +{ + [Dependency] private readonly IPrototypeManager _proto = default!; + [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly IUserInterfaceManager _userInterfaceManager = default!; + [Dependency] private readonly IPlayerManager _playerMan = default!; + [Dependency] private readonly SpriteSystem _spriteSystem = default!; + [Dependency] private readonly IEntityManager _entManager = default!; + [Dependency] private readonly HumanoidAppearanceSystem _appearanceSystem = default!; + + /// + /// We should enable radial for single target + /// + private RadialContainer? _openedMenu; + + private const string DefaultIcon = "/Textures/Interface/AdminActions/play.png"; + + private const string EmptyIcon = "/Textures/Interface/AdminActions/emptyIcon.png"; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnPlayerAttached); + SubscribeLocalEvent(OnPlayerDetached); + + SubscribeNetworkEvent(HandleChangelingFormsMenuEvent); + } + + private void HandleChangelingFormsMenuEvent(RequestChangelingFormsMenuEvent args) + { + if (_openedMenu != null) + return; + if (_playerMan.LocalEntity == null) + { + return; + } + + //if (!TryComp(_playerMan.LocalEntity.Value, out var changelingComponent)) // нет на клиенте + // return; + + _openedMenu = _userInterfaceManager.GetUIController() + .CreateRadialContainer(); + + foreach (var humanoid in args.HumanoidData) + { + var dummy = _entManager.SpawnEntity(_proto.Index(humanoid.Species).DollPrototype, MapCoordinates.Nullspace); + //var humanoidEntityUid = GetEntity(humanoid); // Entities on the client outside of the FOV are nonexistant. You can see that if you zoom out. //So it'll give you UID 0 which is EntityUid.Invalid. + _appearanceSystem.LoadProfile(dummy, humanoid.Profile); + var face = new SpriteView(); + face.SetEntity(dummy); + + var actionName = humanoid.Name; + var texturePath = _spriteSystem.Frame0(new SpriteSpecifier.Texture(new ResPath(EmptyIcon))); + + var emoteButton = _openedMenu.AddButton(actionName, texturePath, face); + emoteButton.Opacity = 210; + emoteButton.Tooltip = null; + emoteButton.Controller.OnPressed += (_) => + { + var ev = new SelectChangelingFormEvent(args.Target, entitySelected: humanoid.NetEntity); + RaiseNetworkEvent(ev); + _openedMenu.Dispose(); + }; + } + _openedMenu.OnClose += (_) => + { + _openedMenu = null; + }; + if (_playerMan.LocalEntity != null) + _openedMenu.OpenAttached(_playerMan.LocalEntity.Value); + + } + + private void OnPlayerAttached(PlayerAttachedEvent args) + { + _openedMenu?.Dispose(); + } + + private void OnPlayerDetached(PlayerDetachedEvent args) + { + _openedMenu?.Dispose(); + } +} diff --git a/Content.Client/ADT/Chaplain/ChaplainSystem.cs b/Content.Client/ADT/Chaplain/ChaplainSystem.cs new file mode 100644 index 00000000000..90a64f77fcd --- /dev/null +++ b/Content.Client/ADT/Chaplain/ChaplainSystem.cs @@ -0,0 +1,53 @@ +using Content.Shared.Bible.Components; +using Content.Shared.Phantom.Components; +using Robust.Client.GameObjects; +using Robust.Client.Player; +using Robust.Shared.Player; +using Robust.Shared.Prototypes; +using Content.Client.UserInterface.Systems.Radial; +using Content.Client.UserInterface.Systems.Radial.Controls; +using Robust.Shared.Random; +using Robust.Shared.Utility; +using Robust.Client.UserInterface; +using Content.Shared.StatusIcon.Components; +using Content.Shared.Ghost; +using Content.Shared.Antag; +using Content.Shared.Actions; +using Robust.Client.Graphics; +using Robust.Client.Utility; +using Content.Shared.Humanoid; +using Content.Shared.Humanoid.Prototypes; +using Content.Client.Humanoid; +using System.Numerics; +using Content.Shared.Preferences; + +namespace Content.Client.Chaplain; + +public sealed class ChaplainSystem : EntitySystem +{ + [Dependency] private readonly SharedAppearanceSystem _appearance = default!; + [Dependency] private readonly IPrototypeManager _proto = default!; + [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly IUserInterfaceManager _userInterfaceManager = default!; + [Dependency] private readonly IPlayerManager _playerMan = default!; + [Dependency] private readonly SpriteSystem _spriteSystem = default!; + [Dependency] private readonly HumanoidAppearanceSystem _appearanceSystem = default!; + [Dependency] private readonly IEntityManager _entManager = default!; + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnCanDisplayStatusIcons); + } + + private void OnCanDisplayStatusIcons(EntityUid uid, ChaplainComponent component, ref CanDisplayStatusIconsEvent args) + { + if (HasComp(args.User) || HasComp(args.User) || HasComp(args.User)) + return; + + if (component.IconVisibleToGhost && HasComp(args.User)) + return; + + args.Cancelled = true; + } +} diff --git a/Content.Client/ADT/Chaplain/EUI/AcceptReligionEui.cs b/Content.Client/ADT/Chaplain/EUI/AcceptReligionEui.cs new file mode 100644 index 00000000000..42d974fba95 --- /dev/null +++ b/Content.Client/ADT/Chaplain/EUI/AcceptReligionEui.cs @@ -0,0 +1,46 @@ +using Content.Client.Eui; +using Content.Shared.Cloning; +using JetBrains.Annotations; +using Robust.Client.Graphics; +using Content.Shared.Chaplain; +using Content.Shared.Bible.Components; + +namespace Content.Client.Chaplain; + +[UsedImplicitly] +public sealed class AcceptReligionEui : BaseEui +{ + private readonly AcceptReligionWindow _window; + + public AcceptReligionEui() + { + _window = new AcceptReligionWindow(); + + _window.DenyButton.OnPressed += _ => + { + SendMessage(new AcceptReligionChoiceMessage(AcceptReligionButton.Deny)); + _window.Close(); + }; + + _window.OnClose += () => SendMessage(new AcceptReligionChoiceMessage(AcceptReligionButton.Deny)); + + _window.AcceptButton.OnPressed += _ => + { + SendMessage(new AcceptReligionChoiceMessage(AcceptReligionButton.Accept)); + _window.Close(); + }; + } + + public override void Opened() + { + IoCManager.Resolve().RequestWindowAttention(); + _window.OpenCentered(); + } + + public override void Closed() + { + _window.Close(); + } + +} + diff --git a/Content.Client/ADT/Chaplain/EUI/AcceptReligionEuiWindow.cs b/Content.Client/ADT/Chaplain/EUI/AcceptReligionEuiWindow.cs new file mode 100644 index 00000000000..dba84289dbb --- /dev/null +++ b/Content.Client/ADT/Chaplain/EUI/AcceptReligionEuiWindow.cs @@ -0,0 +1,61 @@ +using System.Numerics; +using Robust.Client.UserInterface; +using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.CustomControls; +using Robust.Shared.Localization; +using static Robust.Client.UserInterface.Controls.BoxContainer; + +namespace Content.Client.Chaplain; + +public sealed class AcceptReligionWindow : DefaultWindow +{ + public readonly Button DenyButton; + public readonly Button AcceptButton; + + public AcceptReligionWindow() + { + + Title = Loc.GetString("accept-religion-window-title"); + + Contents.AddChild(new BoxContainer + { + Orientation = LayoutOrientation.Vertical, + Children = + { + new BoxContainer + { + Orientation = LayoutOrientation.Vertical, + Children = + { + (new Label() + { + Text = Loc.GetString("accept-religion-window-prompt-text-part") + }), + new BoxContainer + { + Orientation = LayoutOrientation.Horizontal, + Align = AlignMode.Center, + Children = + { + (AcceptButton = new Button + { + Text = Loc.GetString("accept-religion-window-accept-button"), + }), + + (new Control() + { + MinSize = new Vector2(20, 0) + }), + + (DenyButton = new Button + { + Text = Loc.GetString("accept-religion-window-deny-button"), + }) + } + }, + } + }, + } + }); + } +} diff --git a/Content.Client/ADT/Phantom/EUI/AcceptHelpingHandEui.cs b/Content.Client/ADT/Phantom/EUI/AcceptHelpingHandEui.cs new file mode 100644 index 00000000000..164d7fd301e --- /dev/null +++ b/Content.Client/ADT/Phantom/EUI/AcceptHelpingHandEui.cs @@ -0,0 +1,45 @@ +using Content.Client.Eui; +using Content.Shared.Cloning; +using JetBrains.Annotations; +using Robust.Client.Graphics; +using Content.Shared.Phantom; + +namespace Content.Client.Phantom; + +[UsedImplicitly] +public sealed class AcceptHelpingHandEui : BaseEui +{ + private readonly AcceptHelpingHandWindow _window; + + public AcceptHelpingHandEui() + { + _window = new AcceptHelpingHandWindow(); + + _window.DenyButton.OnPressed += _ => + { + SendMessage(new AcceptHelpingHandChoiceMessage(AcceptHelpingHandButton.Deny)); + _window.Close(); + }; + + _window.OnClose += () => SendMessage(new AcceptHelpingHandChoiceMessage(AcceptHelpingHandButton.Deny)); + + _window.AcceptButton.OnPressed += _ => + { + SendMessage(new AcceptHelpingHandChoiceMessage(AcceptHelpingHandButton.Accept)); + _window.Close(); + }; + } + + public override void Opened() + { + IoCManager.Resolve().RequestWindowAttention(); + _window.OpenCentered(); + } + + public override void Closed() + { + _window.Close(); + } + +} + diff --git a/Content.Client/ADT/Phantom/EUI/AcceptHelpingHandWindow.cs b/Content.Client/ADT/Phantom/EUI/AcceptHelpingHandWindow.cs new file mode 100644 index 00000000000..847cdac6188 --- /dev/null +++ b/Content.Client/ADT/Phantom/EUI/AcceptHelpingHandWindow.cs @@ -0,0 +1,61 @@ +using System.Numerics; +using Robust.Client.UserInterface; +using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.CustomControls; +using Robust.Shared.Localization; +using static Robust.Client.UserInterface.Controls.BoxContainer; + +namespace Content.Client.Phantom; + +public sealed class AcceptHelpingHandWindow : DefaultWindow +{ + public readonly Button DenyButton; + public readonly Button AcceptButton; + + public AcceptHelpingHandWindow() + { + + Title = Loc.GetString("accept-phantom-help-window-title"); + + Contents.AddChild(new BoxContainer + { + Orientation = LayoutOrientation.Vertical, + Children = + { + new BoxContainer + { + Orientation = LayoutOrientation.Vertical, + Children = + { + (new Label() + { + Text = Loc.GetString("accept-phantom-help-window-prompt-text-part") + }), + new BoxContainer + { + Orientation = LayoutOrientation.Horizontal, + Align = AlignMode.Center, + Children = + { + (AcceptButton = new Button + { + Text = Loc.GetString("accept-phantom-help-window-accept-button"), + }), + + (new Control() + { + MinSize = new Vector2(20, 0) + }), + + (DenyButton = new Button + { + Text = Loc.GetString("accept-phantom-help-window-deny-button"), + }) + } + }, + } + }, + } + }); + } +} diff --git a/Content.Client/ADT/Phantom/EUI/AcceptPhantomPowersEui.cs b/Content.Client/ADT/Phantom/EUI/AcceptPhantomPowersEui.cs new file mode 100644 index 00000000000..66dbb7884ca --- /dev/null +++ b/Content.Client/ADT/Phantom/EUI/AcceptPhantomPowersEui.cs @@ -0,0 +1,45 @@ +using Content.Client.Eui; +using Content.Shared.Cloning; +using JetBrains.Annotations; +using Robust.Client.Graphics; +using Content.Shared.Phantom; + +namespace Content.Client.Phantom; + +[UsedImplicitly] +public sealed class AcceptPhantomPowersEui : BaseEui +{ + private readonly AcceptPhantomPowersWindow _window; + + public AcceptPhantomPowersEui() + { + _window = new AcceptPhantomPowersWindow(); + + _window.DenyButton.OnPressed += _ => + { + SendMessage(new AcceptPhantomPowersChoiceMessage(AcceptPhantomPowersButton.Deny)); + _window.Close(); + }; + + _window.OnClose += () => SendMessage(new AcceptPhantomPowersChoiceMessage(AcceptPhantomPowersButton.Deny)); + + _window.AcceptButton.OnPressed += _ => + { + SendMessage(new AcceptPhantomPowersChoiceMessage(AcceptPhantomPowersButton.Accept)); + _window.Close(); + }; + } + + public override void Opened() + { + IoCManager.Resolve().RequestWindowAttention(); + _window.OpenCentered(); + } + + public override void Closed() + { + _window.Close(); + } + +} + diff --git a/Content.Client/ADT/Phantom/EUI/AcceptPhantomPowersWindow.cs b/Content.Client/ADT/Phantom/EUI/AcceptPhantomPowersWindow.cs new file mode 100644 index 00000000000..898493c5102 --- /dev/null +++ b/Content.Client/ADT/Phantom/EUI/AcceptPhantomPowersWindow.cs @@ -0,0 +1,61 @@ +using System.Numerics; +using Robust.Client.UserInterface; +using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.CustomControls; +using Robust.Shared.Localization; +using static Robust.Client.UserInterface.Controls.BoxContainer; + +namespace Content.Client.Phantom; + +public sealed class AcceptPhantomPowersWindow : DefaultWindow +{ + public readonly Button DenyButton; + public readonly Button AcceptButton; + + public AcceptPhantomPowersWindow() + { + + Title = Loc.GetString("accept-phantom-window-title"); + + Contents.AddChild(new BoxContainer + { + Orientation = LayoutOrientation.Vertical, + Children = + { + new BoxContainer + { + Orientation = LayoutOrientation.Vertical, + Children = + { + (new Label() + { + Text = Loc.GetString("accept-phantom-window-prompt-text-part") + }), + new BoxContainer + { + Orientation = LayoutOrientation.Horizontal, + Align = AlignMode.Center, + Children = + { + (AcceptButton = new Button + { + Text = Loc.GetString("accept-phantom-window-accept-button"), + }), + + (new Control() + { + MinSize = new Vector2(20, 0) + }), + + (DenyButton = new Button + { + Text = Loc.GetString("accept-phantom-window-deny-button"), + }) + } + }, + } + }, + } + }); + } +} diff --git a/Content.Client/ADT/Phantom/EUI/AmnesiaEui.cs b/Content.Client/ADT/Phantom/EUI/AmnesiaEui.cs new file mode 100644 index 00000000000..46ebec2c2fb --- /dev/null +++ b/Content.Client/ADT/Phantom/EUI/AmnesiaEui.cs @@ -0,0 +1,38 @@ +using Content.Client.Eui; +using Content.Shared.Cloning; +using JetBrains.Annotations; +using Robust.Client.Graphics; +using Content.Shared.Phantom; + +namespace Content.Client.Phantom; + +[UsedImplicitly] +public sealed class PhantomAmnesiaEui : BaseEui +{ + private readonly PhantomAmnesiaWindow _window; + + public PhantomAmnesiaEui() + { + _window = new PhantomAmnesiaWindow(); + + _window.OnClose += () => SendMessage(new PhantomAmnesiaChoiceMessage(PhantomAmnesiaButton.Accept)); + + _window.AcceptButton.OnPressed += _ => + { + SendMessage(new PhantomAmnesiaChoiceMessage(PhantomAmnesiaButton.Accept)); + _window.Close(); + }; + } + + public override void Opened() + { + IoCManager.Resolve().RequestWindowAttention(); + _window.OpenCentered(); + } + + public override void Closed() + { + _window.Close(); + } + +} diff --git a/Content.Client/ADT/Phantom/EUI/AmnesiaWindow.cs b/Content.Client/ADT/Phantom/EUI/AmnesiaWindow.cs new file mode 100644 index 00000000000..d038a8e80e5 --- /dev/null +++ b/Content.Client/ADT/Phantom/EUI/AmnesiaWindow.cs @@ -0,0 +1,50 @@ +using System.Numerics; +using Robust.Client.UserInterface; +using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.CustomControls; +using Robust.Shared.Localization; +using static Robust.Client.UserInterface.Controls.BoxContainer; + +namespace Content.Client.Phantom; + +public sealed class PhantomAmnesiaWindow : DefaultWindow +{ + public readonly Button AcceptButton; + + public PhantomAmnesiaWindow() + { + + Title = Loc.GetString("phantom-oblivion-window-title"); + + Contents.AddChild(new BoxContainer + { + Orientation = LayoutOrientation.Vertical, + Children = + { + new BoxContainer + { + Orientation = LayoutOrientation.Vertical, + Children = + { + (new Label() + { + Text = Loc.GetString("phantom-oblivion-window-prompt-text-part") + }), + new BoxContainer + { + Orientation = LayoutOrientation.Horizontal, + Align = AlignMode.Center, + Children = + { + (AcceptButton = new Button + { + Text = Loc.GetString("phantom-oblivion-window-accept-button"), + }) + } + }, + } + }, + } + }); + } +} diff --git a/Content.Client/ADT/Phantom/EUI/FinaleEui.cs b/Content.Client/ADT/Phantom/EUI/FinaleEui.cs new file mode 100644 index 00000000000..121fdc1a1fb --- /dev/null +++ b/Content.Client/ADT/Phantom/EUI/FinaleEui.cs @@ -0,0 +1,44 @@ +using Content.Client.Eui; +using Content.Shared.Cloning; +using JetBrains.Annotations; +using Robust.Client.Graphics; +using Content.Shared.Phantom; + +namespace Content.Client.Phantom; + +[UsedImplicitly] +public sealed class PhantomFinaleEui : BaseEui +{ + private readonly PhantomFinaleWindow _window; + + public PhantomFinaleEui() + { + _window = new PhantomFinaleWindow(); + + _window.DenyButton.OnPressed += _ => + { + SendMessage(new PhantomFinaleChoiceMessage(PhantomFinaleButton.Deny)); + _window.Close(); + }; + + _window.OnClose += () => SendMessage(new PhantomFinaleChoiceMessage(PhantomFinaleButton.Deny)); + + _window.AcceptButton.OnPressed += _ => + { + SendMessage(new PhantomFinaleChoiceMessage(PhantomFinaleButton.Accept)); + _window.Close(); + }; + } + + public override void Opened() + { + IoCManager.Resolve().RequestWindowAttention(); + _window.OpenCentered(); + } + + public override void Closed() + { + _window.Close(); + } + +} diff --git a/Content.Client/ADT/Phantom/EUI/FinaleWindow.cs b/Content.Client/ADT/Phantom/EUI/FinaleWindow.cs new file mode 100644 index 00000000000..45e47b1a5f1 --- /dev/null +++ b/Content.Client/ADT/Phantom/EUI/FinaleWindow.cs @@ -0,0 +1,61 @@ +using System.Numerics; +using Robust.Client.UserInterface; +using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.CustomControls; +using Robust.Shared.Localization; +using static Robust.Client.UserInterface.Controls.BoxContainer; + +namespace Content.Client.Phantom; + +public sealed class PhantomFinaleWindow : DefaultWindow +{ + public readonly Button DenyButton; + public readonly Button AcceptButton; + + public PhantomFinaleWindow() + { + + Title = Loc.GetString("phantom-finale-window-title"); + + Contents.AddChild(new BoxContainer + { + Orientation = LayoutOrientation.Vertical, + Children = + { + new BoxContainer + { + Orientation = LayoutOrientation.Vertical, + Children = + { + (new Label() + { + Text = Loc.GetString("phantom-finale-window-prompt-text-part") + }), + new BoxContainer + { + Orientation = LayoutOrientation.Horizontal, + Align = AlignMode.Center, + Children = + { + (AcceptButton = new Button + { + Text = Loc.GetString("phantom-finale-window-accept-button"), + }), + + (new Control() + { + MinSize = new Vector2(20, 0) + }), + + (DenyButton = new Button + { + Text = Loc.GetString("phantom-finale-window-deny-button"), + }) + } + }, + } + }, + } + }); + } +} diff --git a/Content.Client/ADT/Phantom/PhantomHudSystem.cs b/Content.Client/ADT/Phantom/PhantomHudSystem.cs new file mode 100644 index 00000000000..4c8e2ffcf61 --- /dev/null +++ b/Content.Client/ADT/Phantom/PhantomHudSystem.cs @@ -0,0 +1,44 @@ +using Content.Shared.Overlays; +using Content.Shared.StatusIcon.Components; +using Content.Shared.Phantom.Components; +using Content.Shared.StatusIcon; +using Robust.Shared.Prototypes; +using Content.Client.Overlays; + +namespace Content.Client.Phantom; +public sealed class ShowHauntedIconsSystem : EquipmentHudSystem +{ + [Dependency] private readonly IPrototypeManager _prototype = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnGetStatusIconsEvent); + } + + private void OnGetStatusIconsEvent(EntityUid uid, PhantomHolderIconComponent haunted, ref GetStatusIconsEvent args) + { + if (!IsActive || args.InContainer) + { + return; + } + + var syndicateIcons = SyndicateIcon(uid, haunted); + + args.StatusIcons.AddRange(syndicateIcons); + } + + private IReadOnlyList SyndicateIcon(EntityUid uid, PhantomHolderIconComponent haunted) + { + var result = new List(); + + if (_prototype.TryIndex(haunted.StatusIcon, out var icon)) + { + result.Add(icon); + } + + return result; + } +} + diff --git a/Content.Client/ADT/Phantom/PhantomSystem.cs b/Content.Client/ADT/Phantom/PhantomSystem.cs new file mode 100644 index 00000000000..71a7a04a3ee --- /dev/null +++ b/Content.Client/ADT/Phantom/PhantomSystem.cs @@ -0,0 +1,248 @@ +using Content.Shared.Phantom; +using Content.Shared.Phantom.Components; +using Robust.Client.GameObjects; +using Robust.Client.Player; +using Robust.Shared.Player; +using Robust.Shared.Prototypes; +using Content.Client.UserInterface.Systems.Radial; +using Content.Client.UserInterface.Systems.Radial.Controls; +using Robust.Shared.Random; +using Robust.Shared.Utility; +using Robust.Client.UserInterface; +using Content.Shared.StatusIcon.Components; +using Content.Shared.Ghost; +using Content.Shared.Antag; +using Content.Shared.Actions; +using Robust.Client.Graphics; +using Robust.Client.Utility; +using Content.Shared.Humanoid; +using Content.Shared.Humanoid.Prototypes; +using Content.Client.Humanoid; +using Content.Client.UserInterface.Systems.Radial; +using Content.Client.UserInterface.Systems.Radial.Controls; +using Content.Shared.Changeling; +using Content.Shared.Humanoid.Prototypes; +using Robust.Client.GameObjects; +using Robust.Client.Player; +using Robust.Client.UserInterface; +using Robust.Client.UserInterface.Controls; +using Robust.Shared.Map; +using Robust.Shared.Player; +using Robust.Shared.Prototypes; +using Robust.Shared.Random; +using Robust.Shared.Utility; +using System.Numerics; +using Content.Shared.Preferences; + +namespace Content.Client.Phantom; + +public sealed class PhantomSystem : EntitySystem +{ + [Dependency] private readonly SharedAppearanceSystem _appearance = default!; + [Dependency] private readonly IPrototypeManager _proto = default!; + [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly IUserInterfaceManager _userInterfaceManager = default!; + [Dependency] private readonly IPlayerManager _playerMan = default!; + [Dependency] private readonly SpriteSystem _spriteSystem = default!; + [Dependency] private readonly HumanoidAppearanceSystem _appearanceSystem = default!; + [Dependency] private readonly IEntityManager _entManager = default!; + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnAppearanceChange); + + SubscribeLocalEvent(OnPlayerAttached); + SubscribeLocalEvent(OnPlayerDetached); + + SubscribeNetworkEvent(HandleMenuEvent); + SubscribeNetworkEvent(HandleFreedomMenuEvent); + SubscribeNetworkEvent(HandleVesselMenuEvent); + + SubscribeLocalEvent(OnCanDisplayStatusIcons); + SubscribeLocalEvent(OnCanDisplayStatusIcons); + SubscribeLocalEvent(OnCanDisplayStatusIcons); + } + + #region Radial Menu + + private RadialContainer? _openedMenu; + + private const string DefaultIcon = "/Textures/Interface/AdminActions/play.png"; + + private const string EmptyIcon = "/Textures/Interface/AdminActions/empty.png"; + + private void OnPlayerAttached(PlayerAttachedEvent args) + { + _openedMenu?.Dispose(); + } + + private void OnPlayerDetached(PlayerDetachedEvent args) + { + _openedMenu?.Dispose(); + } + + /// + /// Draws RadialUI. + /// + /// + private void HandleMenuEvent(RequestPhantomStyleMenuEvent args) + { + if (_openedMenu != null) + return; + + _openedMenu = _userInterfaceManager.GetUIController() + .CreateRadialContainer(); + + foreach (var protoId in args.Prototypes) + { + if (_proto.TryIndex(protoId, out var prototype)) + { + var actionName = prototype.Name; + var texturePath = _spriteSystem.Frame0(new SpriteSpecifier.Texture(new ResPath(DefaultIcon))); + if (actionName == null) + actionName = "Unnamed"; + if (prototype.Icon != null) + texturePath = _spriteSystem.Frame0(prototype.Icon); + + var emoteButton = _openedMenu.AddButton(actionName, texturePath); + emoteButton.Opacity = 210; + emoteButton.Tooltip = null; + emoteButton.Controller.OnPressed += (_) => + { + var ev = new SelectPhantomStyleEvent(args.Target, protoId); + RaiseNetworkEvent(ev); + _openedMenu.Dispose(); + }; + } + } + + _openedMenu.OnClose += (_) => + { + _openedMenu = null; + }; + if (_playerMan.LocalEntity != null) + _openedMenu.OpenAttached(_playerMan.LocalEntity.Value); + + } + + private void HandleFreedomMenuEvent(RequestPhantomFreedomMenuEvent args) + { + if (_openedMenu != null) + return; + + _openedMenu = _userInterfaceManager.GetUIController() + .CreateRadialContainer(); + + foreach (var protoId in args.Prototypes) + { + if (_proto.TryIndex(protoId, out var prototype)) + { + if (!prototype.TryGetComponent(out var actionComp)) + continue; + + var actionName = prototype.Name; + var texturePath = actionComp.Icon; + if (actionName == null) + actionName = "Unnamed"; + if (texturePath == null) + continue; + + var emoteButton = _openedMenu.AddButton(actionName, _spriteSystem.Frame0(texturePath)); + emoteButton.Opacity = 210; + emoteButton.Tooltip = null; + emoteButton.Controller.OnPressed += (_) => + { + var ev = new SelectPhantomFreedomEvent(args.Target, protoId); + RaiseNetworkEvent(ev); + _openedMenu.Dispose(); + }; + } + } + + _openedMenu.OnClose += (_) => + { + _openedMenu = null; + }; + if (_playerMan.LocalEntity != null) + _openedMenu.OpenAttached(_playerMan.LocalEntity.Value); + + } + + private void HandleVesselMenuEvent(RequestPhantomVesselMenuEvent args) + { + if (_openedMenu != null) + return; + + _openedMenu = _userInterfaceManager.GetUIController() + .CreateRadialContainer(); + + foreach (var (vessel, humanoid, name) in args.Vessels) + { + var dummy = _entManager.SpawnEntity(_proto.Index(humanoid.Species).DollPrototype, MapCoordinates.Nullspace); + //var humanoidEntityUid = GetEntity(humanoid); // Entities on the client outside of the FOV are nonexistant. You can see that if you zoom out. //So it'll give you UID 0 which is EntityUid.Invalid. + _appearanceSystem.LoadProfile(dummy, humanoid); + var face = new SpriteView(); + face.SetEntity(dummy); + + var actionName = name; + var texturePath = _spriteSystem.Frame0(new SpriteSpecifier.Texture(new ResPath(EmptyIcon))); + + var button = _openedMenu.AddButton(actionName, texturePath, face); + button.Opacity = 210; + button.Tooltip = null; + button.Controller.OnPressed += (_) => + { + var ev = new SelectPhantomVesselEvent(args.Uid, vessel); + RaiseNetworkEvent(ev); + _openedMenu.Dispose(); + }; + } + + _openedMenu.OnClose += (_) => + { + _openedMenu = null; + }; + if (_playerMan.LocalEntity != null) + _openedMenu.OpenAttached(_playerMan.LocalEntity.Value); + + } + #endregion + + + private void OnCanDisplayStatusIcons(EntityUid uid, T component, ref CanDisplayStatusIconsEvent args) where T : IAntagStatusIconComponent + { + if (HasComp(args.User) || HasComp(args.User) || HasComp(args.User)) + return; + + if (component.IconVisibleToGhost && HasComp(args.User)) + return; + + args.Cancelled = true; + } + + private void OnAppearanceChange(EntityUid uid, PhantomComponent component, ref AppearanceChangeEvent args) + { + if (args.Sprite == null) + return; + + if (_appearance.TryGetData(uid, PhantomVisuals.Haunting, out var haunt, args.Component)) + { + if (haunt) + args.Sprite.LayerSetState(0, component.HauntingState); + else + args.Sprite.LayerSetState(0, component.State); + } + else if (_appearance.TryGetData(uid, PhantomVisuals.Stunned, out var stunned, args.Component) && stunned) + { + args.Sprite.LayerSetState(0, component.StunnedState); + } + else if (_appearance.TryGetData(uid, PhantomVisuals.Corporeal, out var corporeal, args.Component)) + { + if (corporeal) + args.Sprite.LayerSetState(0, component.CorporealState); + else + args.Sprite.LayerSetState(0, component.State); + } + } +} diff --git a/Content.Client/ADT/Poltergeist/RestInPeaceEui.cs b/Content.Client/ADT/Poltergeist/RestInPeaceEui.cs new file mode 100644 index 00000000000..f86c26b541c --- /dev/null +++ b/Content.Client/ADT/Poltergeist/RestInPeaceEui.cs @@ -0,0 +1,45 @@ +using Content.Client.Eui; +using Content.Shared.Cloning; +using JetBrains.Annotations; +using Robust.Client.Graphics; +using Content.Shared.Poltergeist; + +namespace Content.Client.Poltergeist; + +[UsedImplicitly] +public sealed class RestInPeaceEui : BaseEui +{ + private readonly RestInPeaceWindow _window; + + public RestInPeaceEui() + { + _window = new RestInPeaceWindow(); + + _window.DenyButton.OnPressed += _ => + { + SendMessage(new RestInPeaceChoiceMessage(RestInPeaceButton.Deny)); + _window.Close(); + }; + + _window.OnClose += () => SendMessage(new RestInPeaceChoiceMessage(RestInPeaceButton.Deny)); + + _window.AcceptButton.OnPressed += _ => + { + SendMessage(new RestInPeaceChoiceMessage(RestInPeaceButton.Accept)); + _window.Close(); + }; + } + + public override void Opened() + { + IoCManager.Resolve().RequestWindowAttention(); + _window.OpenCentered(); + } + + public override void Closed() + { + _window.Close(); + } + +} + diff --git a/Content.Client/ADT/Poltergeist/RestInPeaceWindow.cs b/Content.Client/ADT/Poltergeist/RestInPeaceWindow.cs new file mode 100644 index 00000000000..7b45032c02e --- /dev/null +++ b/Content.Client/ADT/Poltergeist/RestInPeaceWindow.cs @@ -0,0 +1,61 @@ +using System.Numerics; +using Robust.Client.UserInterface; +using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.CustomControls; +using Robust.Shared.Localization; +using static Robust.Client.UserInterface.Controls.BoxContainer; + +namespace Content.Client.Poltergeist; + +public sealed class RestInPeaceWindow : DefaultWindow +{ + public readonly Button DenyButton; + public readonly Button AcceptButton; + + public RestInPeaceWindow() + { + + Title = Loc.GetString("poltergeist-die-window-title"); + + Contents.AddChild(new BoxContainer + { + Orientation = LayoutOrientation.Vertical, + Children = + { + new BoxContainer + { + Orientation = LayoutOrientation.Vertical, + Children = + { + (new Label() + { + Text = Loc.GetString("poltergeist-die-window-prompt-text-part") + }), + new BoxContainer + { + Orientation = LayoutOrientation.Horizontal, + Align = AlignMode.Center, + Children = + { + (AcceptButton = new Button + { + Text = Loc.GetString("poltergeist-die-window-accept-button"), + }), + + (new Control() + { + MinSize = new Vector2(20, 0) + }), + + (DenyButton = new Button + { + Text = Loc.GetString("poltergeist-die-window-deny-button"), + }) + } + }, + } + }, + } + }); + } +} diff --git a/Content.Client/ADT/license.txt b/Content.Client/ADT/license.txt new file mode 100644 index 00000000000..79f9846ed4e --- /dev/null +++ b/Content.Client/ADT/license.txt @@ -0,0 +1,19 @@ +Copyright (c) 2024 Adventure Station + +1. The provided software code in this and nested directories (hereinafter referred to as the "Adventure Station" project code) is intended solely for use within the "Adventure Station" project. + +2. Any use, copying, distribution, or modification of the "Adventure Station" project code outside of "Adventure Station" project is prohibited. + +3. This license does not grant any rights to own, use, or distribute the "Adventure Station" project code outside of the "Adventure Station" project. + +4. This license is valid indefinitely, or until a decision is made by the copyright holder of the "Adventure Station" project to revoke/modify it. + +Copyright (c) 2024 Adventure Station + +1. Представленный программный код в данном и вложенных директориях (далее - код проекта "Adventure Station") предназначен исключительно для использования в рамках проекта "Adventure Station" + +2. Любое использование, копирование, распространение и изменение кода проекта "Adventure Station" за пределами данного проекта запрещены. + +3. Настоящая лицензия не предоставляет никаких прав на владение, использование или распространение кода проекта "Adventure Station" вне проекта "Adventure Station". + +4. Настоящая лицензия действительна бессрочно, или до решения об упразднении/изменении правообладателем проекта "Adventure Station". \ No newline at end of file diff --git a/Content.Client/Antag/AntagStatusIconSystem.cs b/Content.Client/Antag/AntagStatusIconSystem.cs index 5d87837893c..a70e16cb489 100644 --- a/Content.Client/Antag/AntagStatusIconSystem.cs +++ b/Content.Client/Antag/AntagStatusIconSystem.cs @@ -5,6 +5,8 @@ using Content.Shared.Zombies; using Robust.Client.Player; using Robust.Shared.Prototypes; +using Content.Shared.Phantom.Components; +using Content.Shared.Bible.Components; namespace Content.Client.Antag; @@ -22,6 +24,14 @@ public override void Initialize() SubscribeLocalEvent(GetRevIcon); SubscribeLocalEvent(GetIcon); SubscribeLocalEvent(GetIcon); + + // ADT Phantom update start + SubscribeLocalEvent(GetVesselIcon); + SubscribeLocalEvent(GetIcon); + SubscribeLocalEvent(GetIcon); + SubscribeLocalEvent(GetIcon); + SubscribeLocalEvent(GetIcon); + // ADT Phantom update end } /// @@ -51,4 +61,13 @@ private void GetRevIcon(EntityUid uid, RevolutionaryComponent comp, ref GetStatu GetIcon(uid, comp, ref ev); } + + private void GetVesselIcon(EntityUid uid, VesselComponent comp, ref GetStatusIconsEvent ev) + { + if (HasComp(uid)) + return; + + GetIcon(uid, comp, ref ev); + + } } diff --git a/Content.Client/BluespaceHarvester/BluespaceHarvesterBoundUserInterface.cs b/Content.Client/BluespaceHarvester/BluespaceHarvesterBoundUserInterface.cs new file mode 100644 index 00000000000..dc64dcf751c --- /dev/null +++ b/Content.Client/BluespaceHarvester/BluespaceHarvesterBoundUserInterface.cs @@ -0,0 +1,53 @@ +using Content.Shared.BluespaceHarvester; +using JetBrains.Annotations; + +namespace Content.Client.BluespaceHarvester; + +[UsedImplicitly] +public sealed class BluespaceHarvesterBoundUserInterface : BoundUserInterface +{ + private BluespaceHarvesterMenu? _window; + + public BluespaceHarvesterBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey) + { + } + + protected override void Open() + { + base.Open(); + + _window = new BluespaceHarvesterMenu(this); + _window.OnClose += Close; + _window?.OpenCentered(); + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) + return; + + _window?.Dispose(); + _window = null; + } + + protected override void UpdateState(BoundUserInterfaceState state) + { + base.UpdateState(state); + + if (state is not BluespaceHarvesterBoundUserInterfaceState current) + return; + + _window?.UpdateState(current); + } + + public void SendTargetLevel(int level) + { + SendMessage(new BluespaceHarvesterTargetLevelMessage(level)); + } + + public void SendBuy(Shared.BluespaceHarvester.BluespaceHarvesterCategory category) + { + SendMessage(new BluespaceHarvesterBuyMessage(category)); + } +} diff --git a/Content.Client/BluespaceHarvester/BluespaceHarvesterCategory.xaml b/Content.Client/BluespaceHarvester/BluespaceHarvesterCategory.xaml new file mode 100644 index 00000000000..eef4ac89883 --- /dev/null +++ b/Content.Client/BluespaceHarvester/BluespaceHarvesterCategory.xaml @@ -0,0 +1,6 @@ + + + +