Adds even more smites and a bunch of tools. (#9825)
* Adds three new smites, headstand, locker stuff, and reptilian species swap. * Localize all the smites. * save work * More smites... * Final tweaks. * oops * !PLEH * Adds disarm prone and improved hand removal options. * fix chances. * take out the trash. * Add some admin TRICKS instead of more smites. * oop * Implements the admin test arena and associated trick. * Tricks for granting/revoking access. * e * mfw * Implement quick dialogs, for when you don't want to spend 20 minutes writing a simple dialog prompt. * Forgot the rejuv icon. * E * docs * augh * Add rename/redescribe buttons. * Adds objects menu, implements a couple tricks for stations. * 1984 * Adds a trick for effectively infinite power. * fixes some icon uggo. * a * HALT! * Pause/unpause buttons. * Forgor the textures. * they broke every bone in their body. * i added more * more battery actions, touch up battery icon. * Address reviews.
This commit is contained in:
188
Content.Client/Administration/Systems/AdminSystem.Menu.cs
Normal file
188
Content.Client/Administration/Systems/AdminSystem.Menu.cs
Normal file
@@ -0,0 +1,188 @@
|
||||
using Content.Client.Administration.Managers;
|
||||
using Content.Client.Administration.UI;
|
||||
using Content.Client.Administration.UI.Tabs.ObjectsTab;
|
||||
using Content.Client.Administration.UI.Tabs.PlayerTab;
|
||||
using Content.Client.HUD;
|
||||
using Content.Client.Verbs;
|
||||
using Content.Shared.Input;
|
||||
using Robust.Client.Console;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.Input;
|
||||
using Robust.Client.ResourceManagement;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Shared.Input;
|
||||
using Robust.Shared.Input.Binding;
|
||||
using Robust.Shared.Network;
|
||||
|
||||
namespace Content.Client.Administration.Systems
|
||||
{
|
||||
public sealed partial class AdminSystem
|
||||
{
|
||||
[Dependency] private readonly INetManager _netManager = default!;
|
||||
[Dependency] private readonly IInputManager _inputManager = default!;
|
||||
[Dependency] private readonly IGameHud _gameHud = default!;
|
||||
[Dependency] private readonly IClientAdminManager _clientAdminManager = default!;
|
||||
[Dependency] private readonly IClientConGroupController _clientConGroupController = default!;
|
||||
[Dependency] private readonly IOverlayManager _overlayManager = default!;
|
||||
[Dependency] private readonly IResourceCache _resourceCache = default!;
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
[Dependency] private readonly EntityLookupSystem _entityLookup = default!;
|
||||
[Dependency] private readonly IClientConsoleHost _clientConsoleHost = default!;
|
||||
|
||||
[Dependency] private readonly VerbSystem _verbSystem = default!;
|
||||
|
||||
private AdminMenuWindow? _window;
|
||||
private readonly List<BaseWindow> _commandWindows = new();
|
||||
|
||||
private void InitializeMenu()
|
||||
{
|
||||
// Reset the AdminMenu Window on disconnect
|
||||
_netManager.Disconnect += (_, _) => ResetWindow();
|
||||
|
||||
_inputManager.SetInputCommand(ContentKeyFunctions.OpenAdminMenu,
|
||||
InputCmdHandler.FromDelegate(_ => Toggle()));
|
||||
|
||||
_clientAdminManager.AdminStatusUpdated += () =>
|
||||
{
|
||||
// when status changes, show the top button if we can open admin menu.
|
||||
// if we can't or we lost admin status, close it and hide the button.
|
||||
_gameHud.AdminButtonVisible = CanOpen();
|
||||
if (!_gameHud.AdminButtonVisible)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
};
|
||||
_gameHud.AdminButtonToggled += (open) =>
|
||||
{
|
||||
if (open)
|
||||
{
|
||||
TryOpen();
|
||||
}
|
||||
else
|
||||
{
|
||||
Close();
|
||||
}
|
||||
};
|
||||
_gameHud.AdminButtonVisible = CanOpen();
|
||||
_gameHud.AdminButtonDown = false;
|
||||
}
|
||||
|
||||
|
||||
public void ResetWindow()
|
||||
{
|
||||
_window?.Close();
|
||||
_window?.Dispose();
|
||||
_window = null;
|
||||
|
||||
foreach (var window in _commandWindows)
|
||||
{
|
||||
window.Close();
|
||||
window.Dispose();
|
||||
}
|
||||
|
||||
_commandWindows.Clear();
|
||||
}
|
||||
|
||||
public void OpenCommand(BaseWindow window)
|
||||
{
|
||||
_commandWindows.Add(window);
|
||||
window.OpenCentered();
|
||||
}
|
||||
|
||||
public void Open()
|
||||
{
|
||||
if (_window == null)
|
||||
{
|
||||
_window = new AdminMenuWindow();
|
||||
_window.OnClose += Close;
|
||||
}
|
||||
|
||||
_window.PlayerTabControl.OnEntryPressed += PlayerTabEntryPressed;
|
||||
_window.ObjectsTabControl.OnEntryPressed += ObjectsTabEntryPressed;
|
||||
_window.OpenCentered();
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
if (_window != null)
|
||||
{
|
||||
_window.PlayerTabControl.OnEntryPressed -= PlayerTabEntryPressed;
|
||||
_window.ObjectsTabControl.OnEntryPressed -= ObjectsTabEntryPressed;
|
||||
}
|
||||
|
||||
_window?.Close();
|
||||
|
||||
foreach (var window in _commandWindows)
|
||||
window?.Dispose();
|
||||
_commandWindows.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the player can open the window
|
||||
/// </summary>
|
||||
/// <returns>True if the player is allowed</returns>
|
||||
public bool CanOpen()
|
||||
{
|
||||
return _clientConGroupController.CanAdminMenu();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the player can open the window and tries to open it
|
||||
/// </summary>
|
||||
public void TryOpen()
|
||||
{
|
||||
if (CanOpen())
|
||||
Open();
|
||||
}
|
||||
|
||||
public void Toggle()
|
||||
{
|
||||
if (_window != null && _window.IsOpen)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
else
|
||||
{
|
||||
TryOpen();
|
||||
}
|
||||
}
|
||||
|
||||
private void PlayerTabEntryPressed(BaseButton.ButtonEventArgs args)
|
||||
{
|
||||
if (args.Button is not PlayerTabEntry button
|
||||
|| button.PlayerUid == null)
|
||||
return;
|
||||
|
||||
var uid = button.PlayerUid.Value;
|
||||
var function = args.Event.Function;
|
||||
|
||||
if (function == EngineKeyFunctions.UIClick)
|
||||
_clientConsoleHost.ExecuteCommand($"vv {uid}");
|
||||
else if (function == ContentKeyFunctions.OpenContextMenu)
|
||||
_verbSystem.VerbMenu.OpenVerbMenu(uid, true);
|
||||
else
|
||||
return;
|
||||
|
||||
args.Event.Handle();
|
||||
}
|
||||
|
||||
private void ObjectsTabEntryPressed(BaseButton.ButtonEventArgs args)
|
||||
{
|
||||
if (args.Button is not ObjectsTabEntry button)
|
||||
return;
|
||||
|
||||
var uid = button.AssocEntity;
|
||||
var function = args.Event.Function;
|
||||
|
||||
if (function == EngineKeyFunctions.UIClick)
|
||||
_clientConsoleHost.ExecuteCommand($"vv {uid}");
|
||||
else if (function == ContentKeyFunctions.OpenContextMenu)
|
||||
_verbSystem.VerbMenu.OpenVerbMenu(uid, true);
|
||||
else
|
||||
return;
|
||||
|
||||
args.Event.Handle();
|
||||
}
|
||||
}
|
||||
}
|
||||
45
Content.Client/Administration/Systems/AdminSystem.Overlay.cs
Normal file
45
Content.Client/Administration/Systems/AdminSystem.Overlay.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
using Content.Client.Administration.Managers;
|
||||
using Robust.Client.Graphics;
|
||||
|
||||
namespace Content.Client.Administration.Systems
|
||||
{
|
||||
public sealed partial class AdminSystem
|
||||
{
|
||||
[Dependency] private readonly IClientAdminManager _adminManager = default!;
|
||||
[Dependency] private readonly IEyeManager _eyeManager = default!;
|
||||
|
||||
private AdminNameOverlay _adminNameOverlay = default!;
|
||||
|
||||
public event Action? OverlayEnabled;
|
||||
public event Action? OverlayDisabled;
|
||||
|
||||
private void InitializeOverlay()
|
||||
{
|
||||
_adminNameOverlay = new AdminNameOverlay(this, _entityManager, _eyeManager, _resourceCache, _entityLookup);
|
||||
_adminManager.AdminStatusUpdated += OnAdminStatusUpdated;
|
||||
}
|
||||
|
||||
private void ShutdownOverlay()
|
||||
{
|
||||
_adminManager.AdminStatusUpdated -= OnAdminStatusUpdated;
|
||||
}
|
||||
|
||||
private void OnAdminStatusUpdated()
|
||||
{
|
||||
AdminOverlayOff();
|
||||
}
|
||||
|
||||
public void AdminOverlayOn()
|
||||
{
|
||||
if (_overlayManager.HasOverlay<AdminNameOverlay>()) return;
|
||||
_overlayManager.AddOverlay(_adminNameOverlay);
|
||||
OverlayEnabled?.Invoke();
|
||||
}
|
||||
|
||||
public void AdminOverlayOff()
|
||||
{
|
||||
_overlayManager.RemoveOverlay<AdminNameOverlay>();
|
||||
OverlayDisabled?.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
71
Content.Client/Administration/Systems/AdminSystem.cs
Normal file
71
Content.Client/Administration/Systems/AdminSystem.cs
Normal file
@@ -0,0 +1,71 @@
|
||||
using System.Linq;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.Administration.Events;
|
||||
using Content.Shared.GameTicking;
|
||||
using Robust.Shared.Network;
|
||||
|
||||
namespace Content.Client.Administration.Systems
|
||||
{
|
||||
public sealed partial class AdminSystem : EntitySystem
|
||||
{
|
||||
public event Action<List<PlayerInfo>>? PlayerListChanged;
|
||||
|
||||
private Dictionary<NetUserId, PlayerInfo>? _playerList;
|
||||
public IReadOnlyList<PlayerInfo> PlayerList
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_playerList != null) return _playerList.Values.ToList();
|
||||
|
||||
return new List<PlayerInfo>();
|
||||
}
|
||||
}
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
InitializeOverlay();
|
||||
InitializeMenu();
|
||||
SubscribeNetworkEvent<FullPlayerListEvent>(OnPlayerListChanged);
|
||||
SubscribeNetworkEvent<PlayerInfoChangedEvent>(OnPlayerInfoChanged);
|
||||
SubscribeNetworkEvent<RoundRestartCleanupEvent>(OnRoundRestartCleanup);
|
||||
}
|
||||
|
||||
public override void Shutdown()
|
||||
{
|
||||
base.Shutdown();
|
||||
ShutdownOverlay();
|
||||
}
|
||||
|
||||
private void OnRoundRestartCleanup(RoundRestartCleanupEvent msg, EntitySessionEventArgs args)
|
||||
{
|
||||
if (_playerList == null)
|
||||
return;
|
||||
|
||||
foreach (var (id, playerInfo) in _playerList.ToArray())
|
||||
{
|
||||
if (playerInfo.Connected)
|
||||
continue;
|
||||
_playerList.Remove(id);
|
||||
}
|
||||
PlayerListChanged?.Invoke(_playerList.Values.ToList());
|
||||
}
|
||||
|
||||
private void OnPlayerInfoChanged(PlayerInfoChangedEvent ev)
|
||||
{
|
||||
if(ev.PlayerInfo == null) return;
|
||||
|
||||
if (_playerList == null) _playerList = new();
|
||||
|
||||
_playerList[ev.PlayerInfo.SessionId] = ev.PlayerInfo;
|
||||
PlayerListChanged?.Invoke(_playerList.Values.ToList());
|
||||
}
|
||||
|
||||
private void OnPlayerListChanged(FullPlayerListEvent msg)
|
||||
{
|
||||
_playerList = msg.PlayersInfo.ToDictionary(x => x.SessionId, x => x);
|
||||
PlayerListChanged?.Invoke(msg.PlayersInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
36
Content.Client/Administration/Systems/AdminVerbSystem.cs
Normal file
36
Content.Client/Administration/Systems/AdminVerbSystem.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using Content.Shared.Verbs;
|
||||
using Robust.Client.Console;
|
||||
|
||||
namespace Content.Client.Administration.Systems
|
||||
{
|
||||
/// <summary>
|
||||
/// Client-side admin verb system. These usually open some sort of UIs.
|
||||
/// </summary>
|
||||
sealed class AdminVerbSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IClientConGroupController _clientConGroupController = default!;
|
||||
[Dependency] private readonly IClientConsoleHost _clientConsoleHost = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SubscribeLocalEvent<GetVerbsEvent<Verb>>(AddAdminVerbs);
|
||||
}
|
||||
|
||||
private void AddAdminVerbs(GetVerbsEvent<Verb> args)
|
||||
{
|
||||
// Currently this is only the ViewVariables verb, but more admin-UI related verbs can be added here.
|
||||
|
||||
// View variables verbs
|
||||
if (_clientConGroupController.CanViewVar())
|
||||
{
|
||||
Verb verb = new();
|
||||
verb.Category = VerbCategory.Debug;
|
||||
verb.Text = "View Variables";
|
||||
verb.IconTexture = "/Textures/Interface/VerbIcons/vv.svg.192dpi.png";
|
||||
verb.Act = () => _clientConsoleHost.ExecuteCommand($"vv {args.Target}");
|
||||
verb.ClientExclusive = true; // opening VV window is client-side. Don't ask server to run this verb.
|
||||
args.Verbs.Add(verb);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
152
Content.Client/Administration/Systems/BwoinkSystem.cs
Normal file
152
Content.Client/Administration/Systems/BwoinkSystem.cs
Normal file
@@ -0,0 +1,152 @@
|
||||
#nullable enable
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Content.Client.Administration.Managers;
|
||||
using Content.Client.Administration.UI;
|
||||
using Content.Client.Administration.UI.CustomControls;
|
||||
using Content.Client.HUD;
|
||||
using Content.Shared.Administration;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.Player;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Player;
|
||||
|
||||
namespace Content.Client.Administration.Systems
|
||||
{
|
||||
[UsedImplicitly]
|
||||
public sealed class BwoinkSystem : SharedBwoinkSystem
|
||||
{
|
||||
[Dependency] private readonly IClientAdminManager _adminManager = default!;
|
||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||
[Dependency] private readonly IClyde _clyde = default!;
|
||||
[Dependency] private readonly IGameHud _hud = default!;
|
||||
|
||||
private BwoinkWindow? _adminWindow;
|
||||
private DefaultWindow? _plainWindow;
|
||||
private readonly Dictionary<NetUserId, BwoinkPanel> _activePanelMap = new();
|
||||
|
||||
public bool IsOpen => (_adminWindow?.IsOpen ?? false) || (_plainWindow?.IsOpen ?? false);
|
||||
|
||||
protected override void OnBwoinkTextMessage(BwoinkTextMessage message, EntitySessionEventArgs eventArgs)
|
||||
{
|
||||
base.OnBwoinkTextMessage(message, eventArgs);
|
||||
LogBwoink(message);
|
||||
// Actual line
|
||||
var window = EnsurePanel(message.ChannelId);
|
||||
window.ReceiveLine(message);
|
||||
// Play a sound if we didn't send it
|
||||
var localPlayer = _playerManager.LocalPlayer;
|
||||
if (localPlayer?.UserId != message.TrueSender)
|
||||
{
|
||||
SoundSystem.Play("/Audio/Effects/adminhelp.ogg", Filter.Local());
|
||||
_clyde.RequestWindowAttention();
|
||||
}
|
||||
|
||||
// If they're not an admin force it open so they read
|
||||
// If it's admin-admin messaging then eh.
|
||||
if (!_adminManager.HasFlag(AdminFlags.Adminhelp))
|
||||
_plainWindow?.Open();
|
||||
else
|
||||
{
|
||||
_adminWindow?.OnBwoink(message.ChannelId);
|
||||
|
||||
if (_adminWindow?.IsOpen != true)
|
||||
_hud.SetInfoRed(true);
|
||||
}
|
||||
}
|
||||
|
||||
public bool TryGetChannel(NetUserId ch, [NotNullWhen(true)] out BwoinkPanel? bp) => _activePanelMap.TryGetValue(ch, out bp);
|
||||
|
||||
private BwoinkPanel EnsureAdmin(NetUserId channelId)
|
||||
{
|
||||
_adminWindow ??= new BwoinkWindow(this);
|
||||
|
||||
if (!_activePanelMap.TryGetValue(channelId, out var existingPanel))
|
||||
{
|
||||
_activePanelMap[channelId] = existingPanel = new BwoinkPanel(this, channelId);
|
||||
existingPanel.Visible = false;
|
||||
if (!_adminWindow.BwoinkArea.Children.Contains(existingPanel))
|
||||
_adminWindow.BwoinkArea.AddChild(existingPanel);
|
||||
}
|
||||
|
||||
return existingPanel;
|
||||
}
|
||||
|
||||
private BwoinkPanel EnsurePlain(NetUserId channelId)
|
||||
{
|
||||
BwoinkPanel bp;
|
||||
if (_plainWindow is null)
|
||||
{
|
||||
bp = new BwoinkPanel(this, channelId);
|
||||
_plainWindow = new DefaultWindow()
|
||||
{
|
||||
TitleClass="windowTitleAlert",
|
||||
HeaderClass="windowHeaderAlert",
|
||||
Title=Loc.GetString("bwoink-user-title"),
|
||||
SetSize=(400, 200),
|
||||
};
|
||||
|
||||
_plainWindow.Contents.AddChild(bp);
|
||||
}
|
||||
else
|
||||
{
|
||||
bp = (BwoinkPanel) _plainWindow.Contents.GetChild(0);
|
||||
}
|
||||
|
||||
return bp;
|
||||
}
|
||||
|
||||
public BwoinkPanel EnsurePanel(NetUserId channelId)
|
||||
{
|
||||
if (_adminManager.HasFlag(AdminFlags.Adminhelp))
|
||||
return EnsureAdmin(channelId);
|
||||
|
||||
return EnsurePlain(channelId);
|
||||
}
|
||||
|
||||
public void Open(NetUserId? channelId = null)
|
||||
{
|
||||
if (channelId == null)
|
||||
{
|
||||
var localPlayer = _playerManager.LocalPlayer;
|
||||
if (localPlayer != null)
|
||||
Open(localPlayer.UserId);
|
||||
return;
|
||||
}
|
||||
|
||||
_hud.SetInfoRed(false);
|
||||
|
||||
if (_adminManager.HasFlag(AdminFlags.Adminhelp))
|
||||
{
|
||||
SelectChannel(channelId.Value);
|
||||
_adminWindow?.Open();
|
||||
return;
|
||||
}
|
||||
|
||||
EnsurePlain(channelId.Value);
|
||||
_plainWindow?.Open();
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
_adminWindow?.Close();
|
||||
_plainWindow?.Close();
|
||||
}
|
||||
|
||||
private void SelectChannel(NetUserId uid)
|
||||
{
|
||||
_adminWindow ??= new BwoinkWindow(this);
|
||||
_adminWindow.SelectChannel(uid);
|
||||
}
|
||||
|
||||
public void Send(NetUserId channelId, string text)
|
||||
{
|
||||
// Reuse the channel ID as the 'true sender'.
|
||||
// Server will ignore this and if someone makes it not ignore this (which is bad, allows impersonation!!!), that will help.
|
||||
RaiseNetworkEvent(new BwoinkTextMessage(channelId, channelId, text));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
35
Content.Client/Administration/Systems/HeadstandSystem.cs
Normal file
35
Content.Client/Administration/Systems/HeadstandSystem.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using Content.Client.Administration.Components;
|
||||
using Robust.Client.GameObjects;
|
||||
|
||||
namespace Content.Client.Administration.Systems;
|
||||
|
||||
public sealed class HeadstandSystem : EntitySystem
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
SubscribeLocalEvent<HeadstandComponent, ComponentStartup>(OnHeadstandAdded);
|
||||
SubscribeLocalEvent<HeadstandComponent, ComponentShutdown>(OnHeadstandRemoved);
|
||||
}
|
||||
|
||||
private void OnHeadstandAdded(EntityUid uid, HeadstandComponent component, ComponentStartup args)
|
||||
{
|
||||
if (!TryComp<SpriteComponent>(uid, out var sprite))
|
||||
return;
|
||||
|
||||
foreach (var layer in sprite.AllLayers)
|
||||
{
|
||||
layer.Rotation += Angle.FromDegrees(180.0f);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnHeadstandRemoved(EntityUid uid, HeadstandComponent component, ComponentShutdown args)
|
||||
{
|
||||
if (!TryComp<SpriteComponent>(uid, out var sprite))
|
||||
return;
|
||||
|
||||
foreach (var layer in sprite.AllLayers)
|
||||
{
|
||||
layer.Rotation -= Angle.FromDegrees(180.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
47
Content.Client/Administration/Systems/KillSignSystem.cs
Normal file
47
Content.Client/Administration/Systems/KillSignSystem.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
using Content.Client.Administration.Components;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Client.Administration.Systems;
|
||||
|
||||
public sealed class KillSignSystem : EntitySystem
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
SubscribeLocalEvent<KillSignComponent, ComponentStartup>(KillSignAdded);
|
||||
SubscribeLocalEvent<KillSignComponent, ComponentShutdown>(KillSignRemoved);
|
||||
}
|
||||
|
||||
private void KillSignRemoved(EntityUid uid, KillSignComponent component, ComponentShutdown args)
|
||||
{
|
||||
if (!TryComp<SpriteComponent>(uid, out var sprite))
|
||||
return;
|
||||
|
||||
if (!sprite.LayerMapTryGet(KillSignKey.Key, out var layer))
|
||||
return;
|
||||
|
||||
sprite.RemoveLayer(layer);
|
||||
}
|
||||
|
||||
private void KillSignAdded(EntityUid uid, KillSignComponent component, ComponentStartup args)
|
||||
{
|
||||
if (!TryComp<SpriteComponent>(uid, out var sprite))
|
||||
return;
|
||||
|
||||
if (sprite.LayerMapTryGet(KillSignKey.Key, out var _))
|
||||
return;
|
||||
|
||||
var adj = sprite.Bounds.Height / 2 + ((1.0f/32) * 6.0f);
|
||||
|
||||
var layer = sprite.AddLayer(new SpriteSpecifier.Rsi(new ResourcePath("Objects/Misc/killsign.rsi"), "sign"));
|
||||
sprite.LayerMapSet(KillSignKey.Key, layer);
|
||||
|
||||
sprite.LayerSetOffset(layer, new Vector2(0.0f, adj));
|
||||
sprite.LayerSetShader(layer, "unshaded");
|
||||
}
|
||||
|
||||
private enum KillSignKey
|
||||
{
|
||||
Key,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user