Killsign cleanup (#41845)
* init * rsi * review * scale * it * cat, dog, nerd * rsi * I just microbalanced animation speed * raider, stinky resprite * review * HideFromOwner * hidden smite * copyright * Apply suggestions from code review --------- Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>
|
|
@ -1,46 +1,77 @@
|
|||
using System.Numerics;
|
||||
using Content.Shared.Administration.Components;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Shared.Utility;
|
||||
using Robust.Client.Player;
|
||||
|
||||
namespace Content.Client.Administration.Systems;
|
||||
|
||||
public sealed class KillSignSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly SpriteSystem _sprite = default!;
|
||||
[Dependency] private readonly IPlayerManager _player = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SubscribeLocalEvent<KillSignComponent, ComponentStartup>(KillSignAdded);
|
||||
SubscribeLocalEvent<KillSignComponent, ComponentShutdown>(KillSignRemoved);
|
||||
SubscribeLocalEvent<KillSignComponent, AfterAutoHandleStateEvent>(AfterAutoHandleState);
|
||||
}
|
||||
|
||||
private void KillSignRemoved(EntityUid uid, KillSignComponent component, ComponentShutdown args)
|
||||
private void KillSignRemoved(Entity<KillSignComponent> ent, ref ComponentShutdown args)
|
||||
{
|
||||
if (!TryComp<SpriteComponent>(uid, out var sprite))
|
||||
return;
|
||||
|
||||
if (!_sprite.LayerMapTryGet((uid, sprite), KillSignKey.Key, out var layer, false))
|
||||
return;
|
||||
|
||||
_sprite.RemoveLayer((uid, sprite), layer);
|
||||
RemoveKillsign(ent);
|
||||
}
|
||||
|
||||
private void KillSignAdded(EntityUid uid, KillSignComponent component, ComponentStartup args)
|
||||
private void KillSignAdded(Entity<KillSignComponent> ent, ref ComponentStartup args)
|
||||
{
|
||||
if (!TryComp<SpriteComponent>(uid, out var sprite))
|
||||
AddKillsign(ent);
|
||||
}
|
||||
|
||||
private void AfterAutoHandleState(Entity<KillSignComponent> ent, ref AfterAutoHandleStateEvent args)
|
||||
{
|
||||
// After receiving a new state for the component, we remove the old killsign and build a new one.
|
||||
// This is so changes to the sprite can be displayed live and allowing them to be edited via ViewVariables.
|
||||
// This could just update an existing sprite, but this is both easier and runs rarely anyway.
|
||||
RemoveKillsign(ent);
|
||||
AddKillsign(ent);
|
||||
}
|
||||
|
||||
private void AddKillsign(Entity<KillSignComponent> ent)
|
||||
{
|
||||
// If we hide from owner and we ARE the owner, don't add a killsign.
|
||||
// This could use session specific networking to FULLY hide it, but I am too lazy right now.
|
||||
if (ent.Comp.HideFromOwner && _player.LocalEntity == ent)
|
||||
return;
|
||||
|
||||
if (_sprite.LayerMapTryGet((uid, sprite), KillSignKey.Key, out var _, false))
|
||||
if (!TryComp<SpriteComponent>(ent, out var sprite))
|
||||
return;
|
||||
|
||||
var adj = _sprite.GetLocalBounds((uid, sprite)).Height / 2 + ((1.0f / 32) * 6.0f);
|
||||
if (_sprite.LayerMapTryGet((ent, sprite), KillSignKey.Key, out var _, false))
|
||||
return;
|
||||
|
||||
var layer = _sprite.AddLayer((uid, sprite), new SpriteSpecifier.Rsi(new ResPath("Objects/Misc/killsign.rsi"), "sign"));
|
||||
_sprite.LayerMapSet((uid, sprite), KillSignKey.Key, layer);
|
||||
if (ent.Comp.Sprite == null)
|
||||
return;
|
||||
|
||||
_sprite.LayerSetOffset((uid, sprite), layer, new Vector2(0.0f, adj));
|
||||
sprite.LayerSetShader(layer, "unshaded");
|
||||
var adj = _sprite.GetLocalBounds((ent, sprite)).Height / 2 + ((1.0f / 32) * 6.0f);
|
||||
|
||||
var layer = _sprite.AddLayer((ent, sprite), ent.Comp.Sprite);
|
||||
_sprite.LayerMapSet((ent, sprite), KillSignKey.Key, layer);
|
||||
_sprite.LayerSetScale((ent, sprite), layer, ent.Comp.Scale);
|
||||
_sprite.LayerSetOffset((ent, sprite), layer, ent.Comp.DoOffset ? new Vector2(0.0f, adj) : new Vector2(0.0f, 0.0f));
|
||||
|
||||
if (ent.Comp.ForceUnshaded)
|
||||
sprite.LayerSetShader(layer, "unshaded");
|
||||
}
|
||||
|
||||
private void RemoveKillsign(Entity<KillSignComponent> ent)
|
||||
{
|
||||
if (!TryComp<SpriteComponent>(ent, out var sprite))
|
||||
return;
|
||||
|
||||
if (!_sprite.LayerMapTryGet((ent, sprite), KillSignKey.Key, out var layer, false))
|
||||
return;
|
||||
|
||||
_sprite.RemoveLayer((ent, sprite), layer);
|
||||
}
|
||||
|
||||
private enum KillSignKey
|
||||
|
|
|
|||
|
|
@ -573,13 +573,32 @@ public sealed partial class AdminVerbSystem
|
|||
Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Misc/killsign.rsi"), "icon"),
|
||||
Act = () =>
|
||||
{
|
||||
EnsureComp<KillSignComponent>(args.Target);
|
||||
EnsureComp<KillSignComponent>(args.Target, out var comp);
|
||||
comp.HideFromOwner = false; // We set it to false anyway, in case the hidden smite was used beforehand.
|
||||
Dirty(args.Target, comp);
|
||||
},
|
||||
Impact = LogImpact.Extreme,
|
||||
Message = string.Join(": ", killSignName, Loc.GetString("admin-smite-kill-sign-description"))
|
||||
};
|
||||
args.Verbs.Add(killSign);
|
||||
|
||||
var hiddenKillSignName = Loc.GetString("admin-smite-kill-sign-hidden-name").ToLowerInvariant();
|
||||
Verb hiddenKillSign = new()
|
||||
{
|
||||
Text = hiddenKillSignName,
|
||||
Category = VerbCategory.Smite,
|
||||
Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Misc/killsign.rsi"), "icon-hidden"),
|
||||
Act = () =>
|
||||
{
|
||||
EnsureComp<KillSignComponent>(args.Target, out var comp);
|
||||
comp.HideFromOwner = true;
|
||||
Dirty(args.Target, comp);
|
||||
},
|
||||
Impact = LogImpact.Extreme,
|
||||
Message = string.Join(": ", hiddenKillSignName, Loc.GetString("admin-smite-kill-sign-hidden-description"))
|
||||
};
|
||||
args.Verbs.Add(hiddenKillSign);
|
||||
|
||||
var cluwneName = Loc.GetString("admin-smite-cluwne-name").ToLowerInvariant();
|
||||
Verb cluwne = new()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,43 @@
|
|||
using Robust.Shared.GameStates;
|
||||
using System.Numerics;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Shared.Administration.Components;
|
||||
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
public sealed partial class KillSignComponent : Component;
|
||||
/// <summary>
|
||||
/// Displays a sprite above an entity.
|
||||
/// By default a huge sign saying "KILL".
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState(raiseAfterAutoHandleState: true)]
|
||||
public sealed partial class KillSignComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// The sprite show above the entity.
|
||||
/// </summary>
|
||||
[DataField, AutoNetworkedField]
|
||||
public SpriteSpecifier? Sprite = new SpriteSpecifier.Rsi(new ResPath("Objects/Misc/killsign.rsi"), "kill");
|
||||
|
||||
/// <summary>
|
||||
/// Whether the granted layer should always be forced to be unshaded.
|
||||
/// </summary>
|
||||
[DataField, AutoNetworkedField]
|
||||
public bool ForceUnshaded = true;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the granted layer should be offset to be above the entity.
|
||||
/// </summary>
|
||||
[DataField, AutoNetworkedField]
|
||||
public bool DoOffset = true;
|
||||
|
||||
/// <summary>
|
||||
/// Prevents the sign from displaying to the owner of the component, allowing everyone but them to see it.
|
||||
/// </summary>
|
||||
[DataField, AutoNetworkedField]
|
||||
public bool HideFromOwner = false;
|
||||
|
||||
/// <summary>
|
||||
/// The scale of the sprite.
|
||||
/// </summary>
|
||||
[DataField, AutoNetworkedField]
|
||||
public Vector2 Scale = Vector2.One;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ admin-smite-vomit-organs-name = Vomit Organs
|
|||
admin-smite-ghostkick-name = Ghost Kick
|
||||
admin-smite-nyanify-name = Cat Ears
|
||||
admin-smite-kill-sign-name = Kill Sign
|
||||
admin-smite-kill-sign-hidden-name = Hidden Kill Sign
|
||||
admin-smite-omni-accent-name = Omni-Accent
|
||||
admin-smite-crawler-name = Crawler
|
||||
admin-smite-homing-rod-name = Homing Rod
|
||||
|
|
@ -83,6 +84,7 @@ admin-smite-become-bread-description = It turns them into bread. Really, that's
|
|||
admin-smite-ghostkick-description = Silently kicks the user, dropping their connection.
|
||||
admin-smite-nyanify-description = Forcibly add cat ears, there is no escape.
|
||||
admin-smite-kill-sign-description = Marks a player for death by their fellows.
|
||||
admin-smite-kill-sign-hidden-description = Marks a player for death by their fellows. Hidden from the targeted player.
|
||||
admin-smite-cluwne-description = Cluwnes them. The suit cannot be removed and the station's crew may murder them freely.
|
||||
admin-smite-anger-pointing-arrows-description = Angers the pointing arrows, causing them to assault this entity explosively.
|
||||
admin-smite-dust-description = Reduces the target to a small pile of ash.
|
||||
|
|
|
|||
|
After Width: | Height: | Size: 478 B |
|
After Width: | Height: | Size: 444 B |
|
After Width: | Height: | Size: 448 B |
|
After Width: | Height: | Size: 457 B |
|
After Width: | Height: | Size: 248 B |
|
After Width: | Height: | Size: 367 B |
|
Before Width: | Height: | Size: 867 B After Width: | Height: | Size: 867 B |
|
|
@ -1,25 +1,119 @@
|
|||
{
|
||||
"version": 1,
|
||||
"license": "CC-BY-NC-SA-3.0",
|
||||
"copyright": "Created by github user @moonheart08",
|
||||
"copyright": "Created by github user @moonheart08 | bald, cat, dog, furry, it, nerd, peak, raider, stinky and icon-hidden states edited by ScarKy0(Github)",
|
||||
"size": {
|
||||
"x": 32,
|
||||
"y": 32
|
||||
},
|
||||
"states": [
|
||||
{
|
||||
"name": "sign",
|
||||
"name": "bald",
|
||||
"directions": 1,
|
||||
"delays": [
|
||||
[
|
||||
0.1,
|
||||
0.1
|
||||
0.15,
|
||||
0.15
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "cat",
|
||||
"directions": 1,
|
||||
"delays": [
|
||||
[
|
||||
0.15,
|
||||
0.15
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "dog",
|
||||
"directions": 1,
|
||||
"delays": [
|
||||
[
|
||||
0.15,
|
||||
0.15
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "furry",
|
||||
"directions": 1,
|
||||
"delays": [
|
||||
[
|
||||
0.15,
|
||||
0.15
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "it",
|
||||
"directions": 1,
|
||||
"delays": [
|
||||
[
|
||||
0.15,
|
||||
0.15
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "kill",
|
||||
"directions": 1,
|
||||
"delays": [
|
||||
[
|
||||
0.15,
|
||||
0.15
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "nerd",
|
||||
"directions": 1,
|
||||
"delays": [
|
||||
[
|
||||
0.15,
|
||||
0.15
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "peak",
|
||||
"directions": 1,
|
||||
"delays": [
|
||||
[
|
||||
0.15,
|
||||
0.15
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "raider",
|
||||
"directions": 1,
|
||||
"delays": [
|
||||
[
|
||||
0.15,
|
||||
0.15
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "stinky",
|
||||
"directions": 1,
|
||||
"delays": [
|
||||
[
|
||||
0.15,
|
||||
0.15
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "icon",
|
||||
"directions": 1
|
||||
},
|
||||
{
|
||||
"name": "icon-hidden",
|
||||
"directions": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
After Width: | Height: | Size: 490 B |
|
After Width: | Height: | Size: 460 B |
|
After Width: | Height: | Size: 443 B |
|
After Width: | Height: | Size: 423 B |