Make flashlights, atmos hardsuit, and RGB use the new layer features (#6253)
* Make flashlights, atmos hardsuit, and RGB use the new layer features * avoid self-conflict * fix rgb not updating on add * cleanup * Update Content.Client/Light/RgbLightControllerSystem.cs Co-authored-by: mirrorcult <lunarautomaton6@gmail.com> * cleanup diff Co-authored-by: mirrorcult <lunarautomaton6@gmail.com>
@@ -1,4 +1,5 @@
|
|||||||
using Content.Client.Items.Components;
|
using Content.Client.Items.Components;
|
||||||
|
using Content.Shared.Hands.Components;
|
||||||
using Content.Shared.Light.Component;
|
using Content.Shared.Light.Component;
|
||||||
using Robust.Client.Graphics;
|
using Robust.Client.Graphics;
|
||||||
using Robust.Client.UserInterface;
|
using Robust.Client.UserInterface;
|
||||||
@@ -6,9 +7,11 @@ using Robust.Client.UserInterface.Controls;
|
|||||||
using Robust.Shared.Analyzers;
|
using Robust.Shared.Analyzers;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.Maths;
|
using Robust.Shared.Maths;
|
||||||
|
using Robust.Shared.Serialization.Manager.Attributes;
|
||||||
using Robust.Shared.Timing;
|
using Robust.Shared.Timing;
|
||||||
using Robust.Shared.ViewVariables;
|
using System.Collections.Generic;
|
||||||
using static Robust.Client.UserInterface.Controls.BoxContainer;
|
using static Robust.Client.UserInterface.Controls.BoxContainer;
|
||||||
|
using static Robust.Shared.GameObjects.SharedSpriteComponent;
|
||||||
|
|
||||||
namespace Content.Client.Light.Components
|
namespace Content.Client.Light.Components
|
||||||
{
|
{
|
||||||
@@ -17,6 +20,37 @@ namespace Content.Client.Light.Components
|
|||||||
public sealed class HandheldLightComponent : SharedHandheldLightComponent, IItemStatus
|
public sealed class HandheldLightComponent : SharedHandheldLightComponent, IItemStatus
|
||||||
{
|
{
|
||||||
public byte? Level;
|
public byte? Level;
|
||||||
|
public bool Activated;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether to automatically set item-prefixes when toggling the flashlight.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Flashlights should probably be using explicit unshaded sprite, in-hand and clothing layers, this is
|
||||||
|
/// mostly here for backwards compatibility.
|
||||||
|
/// </remarks>
|
||||||
|
[DataField("addPrefix")]
|
||||||
|
public bool AddPrefix = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sprite layer that will have it's visibility toggled when this item is toggled.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("layer")]
|
||||||
|
public string Layer = "light";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Layers to add to the sprite of the player that is holding this entity.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("inhandVisuals")]
|
||||||
|
public Dictionary<HandLocation, List<PrototypeLayerData>> InhandVisuals = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Layers to add to the sprite of the player that is wearing this entity.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("clothingVisuals")]
|
||||||
|
public readonly Dictionary<string, List<PrototypeLayerData>> ClothingVisuals = new();
|
||||||
|
|
||||||
|
public Color Color { get; internal set; }
|
||||||
|
|
||||||
public Control MakeControl()
|
public Control MakeControl()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,16 +1,77 @@
|
|||||||
|
using Content.Client.Clothing;
|
||||||
|
using Content.Client.Items.Systems;
|
||||||
using Content.Client.Light.Components;
|
using Content.Client.Light.Components;
|
||||||
|
using Content.Shared.Clothing;
|
||||||
|
using Content.Shared.Hands;
|
||||||
|
using Content.Shared.Item;
|
||||||
using Content.Shared.Light.Component;
|
using Content.Shared.Light.Component;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Client.GameObjects;
|
||||||
using Robust.Shared.GameStates;
|
using Robust.Shared.GameStates;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace Content.Client.Light;
|
namespace Content.Client.Light;
|
||||||
|
|
||||||
public sealed class HandheldLightSystem : EntitySystem
|
public sealed class HandheldLightSystem : EntitySystem
|
||||||
{
|
{
|
||||||
|
[Dependency] private readonly ItemSystem _itemSys = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
SubscribeLocalEvent<HandheldLightComponent, ComponentHandleState>(OnHandleState);
|
SubscribeLocalEvent<HandheldLightComponent, ComponentHandleState>(OnHandleState);
|
||||||
|
SubscribeLocalEvent<HandheldLightComponent, GetInhandVisualsEvent>(OnGetHeldVisuals, after: new[] { typeof(ItemSystem) } );
|
||||||
|
SubscribeLocalEvent<HandheldLightComponent, GetEquipmentVisualsEvent>(OnGetEquipmentVisuals, after: new[] { typeof(ClothingSystem)});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add the unshaded light overlays to any clothing sprites.
|
||||||
|
/// </summary>
|
||||||
|
private void OnGetEquipmentVisuals(EntityUid uid, HandheldLightComponent component, GetEquipmentVisualsEvent args)
|
||||||
|
{
|
||||||
|
if (!component.Activated)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!component.ClothingVisuals.TryGetValue(args.Slot, out var layers))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var i = 0;
|
||||||
|
foreach (var layer in layers)
|
||||||
|
{
|
||||||
|
var key = layer.MapKeys?.FirstOrDefault();
|
||||||
|
if (key == null)
|
||||||
|
{
|
||||||
|
key = i == 0 ? $"{args.Slot}-light" : $"{args.Slot}-light-{i}";
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
args.Layers.Add((key, layer));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add the unshaded light overlays to any in-hand sprites.
|
||||||
|
/// </summary>
|
||||||
|
private void OnGetHeldVisuals(EntityUid uid, HandheldLightComponent component, GetInhandVisualsEvent args)
|
||||||
|
{
|
||||||
|
if (!component.Activated)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!component.InhandVisuals.TryGetValue(args.Location, out var layers))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var i = 0;
|
||||||
|
var defaultKey = $"inhand-{args.Location.ToString().ToLowerInvariant()}-light";
|
||||||
|
foreach (var layer in layers)
|
||||||
|
{
|
||||||
|
var key = layer.MapKeys?.FirstOrDefault();
|
||||||
|
if (key == null)
|
||||||
|
{
|
||||||
|
key = i == 0 ? defaultKey : $"{defaultKey}-{i}";
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
args.Layers.Add((key, layer));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnHandleState(EntityUid uid, HandheldLightComponent component, ref ComponentHandleState args)
|
private void OnHandleState(EntityUid uid, HandheldLightComponent component, ref ComponentHandleState args)
|
||||||
@@ -19,5 +80,26 @@ public sealed class HandheldLightSystem : EntitySystem
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
component.Level = state.Charge;
|
component.Level = state.Charge;
|
||||||
|
|
||||||
|
if (state.Activated == component.Activated)
|
||||||
|
return;
|
||||||
|
|
||||||
|
component.Activated = state.Activated;
|
||||||
|
_itemSys.VisualsChanged(uid);
|
||||||
|
|
||||||
|
if (TryComp(component.Owner, out SpriteComponent? sprite))
|
||||||
|
{
|
||||||
|
sprite.LayerSetVisible(component.Layer, state.Activated);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TryComp(uid, out PointLightComponent? light))
|
||||||
|
{
|
||||||
|
light.Enabled = state.Activated;
|
||||||
|
}
|
||||||
|
|
||||||
|
// really hand-held lights should be using a separate unshaded layer. (see FlashlightVisualizer)
|
||||||
|
// this prefix stuff is largely for backwards compatibility with RSIs/yamls that have not been updated.
|
||||||
|
if (component.AddPrefix && TryComp(uid, out SharedItemComponent? item))
|
||||||
|
item.EquippedPrefix = state.Activated ? "on" : "off";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,21 @@
|
|||||||
using System;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Shared.Item;
|
using Content.Client.Items.Systems;
|
||||||
|
using Content.Shared.Clothing;
|
||||||
|
using Content.Shared.Hands;
|
||||||
|
using Content.Shared.Inventory.Events;
|
||||||
using Content.Shared.Light;
|
using Content.Shared.Light;
|
||||||
using Content.Shared.Light.Component;
|
using Content.Shared.Light.Component;
|
||||||
using Robust.Client.GameObjects;
|
using Robust.Client.GameObjects;
|
||||||
using Robust.Shared.GameObjects;
|
|
||||||
using Robust.Shared.GameStates;
|
using Robust.Shared.GameStates;
|
||||||
using Robust.Shared.IoC;
|
|
||||||
using Robust.Shared.Maths;
|
|
||||||
using Robust.Shared.Timing;
|
using Robust.Shared.Timing;
|
||||||
|
using static Robust.Client.GameObjects.SpriteComponent;
|
||||||
|
|
||||||
namespace Content.Client.Light
|
namespace Content.Client.Light
|
||||||
{
|
{
|
||||||
public sealed class RgbLightControllerSystem : SharedRgbLightControllerSystem
|
public sealed class RgbLightControllerSystem : SharedRgbLightControllerSystem
|
||||||
{
|
{
|
||||||
[Dependency] private IGameTiming _gameTiming = default!;
|
[Dependency] private IGameTiming _gameTiming = default!;
|
||||||
|
[Dependency] private ItemSystem _itemSystem = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
@@ -23,77 +24,137 @@ namespace Content.Client.Light
|
|||||||
SubscribeLocalEvent<RgbLightControllerComponent, ComponentHandleState>(OnHandleState);
|
SubscribeLocalEvent<RgbLightControllerComponent, ComponentHandleState>(OnHandleState);
|
||||||
SubscribeLocalEvent<RgbLightControllerComponent, ComponentShutdown>(OnComponentShutdown);
|
SubscribeLocalEvent<RgbLightControllerComponent, ComponentShutdown>(OnComponentShutdown);
|
||||||
SubscribeLocalEvent<RgbLightControllerComponent, ComponentStartup>(OnComponentStart);
|
SubscribeLocalEvent<RgbLightControllerComponent, ComponentStartup>(OnComponentStart);
|
||||||
|
|
||||||
|
SubscribeLocalEvent<RgbLightControllerComponent, GotUnequippedEvent>(OnGotUnequipped);
|
||||||
|
|
||||||
|
SubscribeLocalEvent<RgbLightControllerComponent, EquipmentVisualsUpdatedEvent>(OnEquipmentVisualsUpdated);
|
||||||
|
SubscribeLocalEvent<RgbLightControllerComponent, HeldVisualsUpdatedEvent>(OnHeldVisualsUpdated);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnComponentStart(EntityUid uid, RgbLightControllerComponent rgb, ComponentStartup args)
|
private void OnComponentStart(EntityUid uid, RgbLightControllerComponent rgb, ComponentStartup args)
|
||||||
{
|
{
|
||||||
if (TryComp(uid, out PointLightComponent? light))
|
GetOriginalColors(uid, rgb);
|
||||||
rgb.OriginalLightColor = light.Color;
|
|
||||||
|
|
||||||
if (TryComp(uid, out SharedItemComponent? item))
|
// trigger visuals updated events
|
||||||
rgb.OriginalItemColor = item.Color;
|
_itemSystem.VisualsChanged(uid);
|
||||||
|
|
||||||
GetOriginalSpriteColors(uid, rgb);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnComponentShutdown(EntityUid uid, RgbLightControllerComponent rgb, ComponentShutdown args)
|
private void OnComponentShutdown(EntityUid uid, RgbLightControllerComponent rgb, ComponentShutdown args)
|
||||||
{
|
{
|
||||||
if (TryComp(uid, out PointLightComponent? light))
|
ResetOriginalColors(uid, rgb);
|
||||||
light.Color = rgb.OriginalLightColor;
|
|
||||||
|
|
||||||
if (TryComp(uid, out SharedItemComponent? item))
|
// and reset any in-hands or clothing sprites
|
||||||
item.Color = rgb.OriginalItemColor;
|
_itemSystem.VisualsChanged(uid);
|
||||||
|
|
||||||
ResetSpriteColors(uid, rgb);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnGotUnequipped(EntityUid uid, RgbLightControllerComponent rgb, GotUnequippedEvent args)
|
||||||
|
{
|
||||||
|
rgb.Holder = null;
|
||||||
|
rgb.HolderLayers = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnHeldVisualsUpdated(EntityUid uid, RgbLightControllerComponent rgb, HeldVisualsUpdatedEvent args)
|
||||||
|
{
|
||||||
|
if (args.RevealedLayers.Count == 0)
|
||||||
|
{
|
||||||
|
rgb.Holder = null;
|
||||||
|
rgb.HolderLayers = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rgb.Holder = args.User;
|
||||||
|
rgb.HolderLayers = new();
|
||||||
|
|
||||||
|
if (!TryComp(args.User, out SpriteComponent? sprite))
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (var key in args.RevealedLayers)
|
||||||
|
{
|
||||||
|
if (!sprite.LayerMapTryGet(key, out var index) || sprite[index] is not Layer layer)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (layer.ShaderPrototype == "unshaded")
|
||||||
|
rgb.HolderLayers.Add(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnEquipmentVisualsUpdated(EntityUid uid, RgbLightControllerComponent rgb, EquipmentVisualsUpdatedEvent args)
|
||||||
|
{
|
||||||
|
rgb.Holder = args.Equipee;
|
||||||
|
rgb.HolderLayers = new();
|
||||||
|
|
||||||
|
if (!TryComp(args.Equipee, out SpriteComponent? sprite))
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (var key in args.RevealedLayers)
|
||||||
|
{
|
||||||
|
if (!sprite.LayerMapTryGet(key, out var index) || sprite[index] is not Layer layer)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (layer.ShaderPrototype == "unshaded")
|
||||||
|
rgb.HolderLayers.Add(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
private void OnHandleState(EntityUid uid, RgbLightControllerComponent rgb, ref ComponentHandleState args)
|
private void OnHandleState(EntityUid uid, RgbLightControllerComponent rgb, ref ComponentHandleState args)
|
||||||
{
|
{
|
||||||
if (args.Current is not RgbLightControllerState state)
|
if (args.Current is not RgbLightControllerState state)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ResetSpriteColors(uid, rgb);
|
ResetOriginalColors(uid, rgb);
|
||||||
rgb.CycleRate = state.CycleRate;
|
rgb.CycleRate = state.CycleRate;
|
||||||
rgb.Layers = state.Layers;
|
rgb.Layers = state.Layers;
|
||||||
|
GetOriginalColors(uid, rgb);
|
||||||
|
|
||||||
// get the new original sprite colors (necessary if rgb.Layers was updated).
|
|
||||||
GetOriginalSpriteColors(uid, rgb);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GetOriginalSpriteColors(EntityUid uid, RgbLightControllerComponent? rgb = null, SpriteComponent? sprite = null)
|
private void GetOriginalColors(EntityUid uid, RgbLightControllerComponent? rgb = null, PointLightComponent? light = null, SpriteComponent? sprite = null)
|
||||||
{
|
{
|
||||||
if (!Resolve(uid, ref rgb, ref sprite))
|
if (!Resolve(uid, ref rgb, ref sprite, ref light))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
rgb.OriginalLightColor = light.Color;
|
||||||
|
rgb.OriginalLayerColors = new();
|
||||||
|
|
||||||
|
var layerCount = sprite.AllLayers.Count();
|
||||||
|
|
||||||
|
// if layers is null, get unshaded layers
|
||||||
if (rgb.Layers == null)
|
if (rgb.Layers == null)
|
||||||
{
|
{
|
||||||
rgb.OriginalSpriteColor = sprite.Color;
|
rgb.Layers = new();
|
||||||
rgb.OriginalLayerColors = null;
|
|
||||||
|
for (var i = 0; i < layerCount; i++)
|
||||||
|
{
|
||||||
|
if (sprite[i] is Layer layer && layer.ShaderPrototype == "unshaded")
|
||||||
|
{
|
||||||
|
rgb.Layers.Add(i);
|
||||||
|
rgb.OriginalLayerColors[i] = layer.Color;
|
||||||
|
}
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var spriteLayerCount = sprite.AllLayers.Count();
|
foreach (var index in rgb.Layers.ToArray())
|
||||||
rgb.OriginalLayerColors = new(rgb.Layers.Count);
|
|
||||||
|
|
||||||
foreach (var layer in rgb.Layers.ToArray())
|
|
||||||
{
|
{
|
||||||
if (layer < spriteLayerCount)
|
if (index < layerCount)
|
||||||
rgb.OriginalLayerColors[layer] = sprite[layer].Color;
|
rgb.OriginalLayerColors[index] = sprite[index].Color;
|
||||||
else
|
else
|
||||||
rgb.Layers.Remove(layer);
|
{
|
||||||
|
// admeme fuck-ups or bad yaml?
|
||||||
|
Logger.Warning($"RGB light attempted to use invalid sprite index {index} on entity {ToPrettyString(uid)}");
|
||||||
|
rgb.Layers.Remove(index);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ResetSpriteColors(EntityUid uid, RgbLightControllerComponent? rgb = null, SpriteComponent? sprite = null)
|
private void ResetOriginalColors(EntityUid uid, RgbLightControllerComponent? rgb = null, PointLightComponent? light = null, SpriteComponent? sprite = null)
|
||||||
{
|
{
|
||||||
if (!Resolve(uid, ref rgb, ref sprite))
|
if (!Resolve(uid, ref rgb, ref sprite, ref light))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
light.Color = rgb.OriginalLightColor;
|
||||||
|
|
||||||
if (rgb.Layers == null || rgb.OriginalLayerColors == null)
|
if (rgb.Layers == null || rgb.OriginalLayerColors == null)
|
||||||
{
|
|
||||||
sprite.Color = rgb.OriginalSpriteColor;
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var (layer, color) in rgb.OriginalLayerColors)
|
foreach (var (layer, color) in rgb.OriginalLayerColors)
|
||||||
{
|
{
|
||||||
@@ -109,9 +170,7 @@ namespace Content.Client.Light
|
|||||||
|
|
||||||
light.Color = color;
|
light.Color = color;
|
||||||
|
|
||||||
if (rgb.Layers == null)
|
if (rgb.Layers != null)
|
||||||
sprite.Color = color;
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
foreach (var layer in rgb.Layers)
|
foreach (var layer in rgb.Layers)
|
||||||
{
|
{
|
||||||
@@ -119,9 +178,14 @@ namespace Content.Client.Light
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// not all rgb is hand-held (Hence, not part of EntityQuery)
|
// is the entity being held by someone?
|
||||||
if (TryComp(rgb.Owner, out SharedItemComponent? item))
|
if (rgb.HolderLayers == null || !TryComp(rgb.Holder, out SpriteComponent? holderSprite))
|
||||||
item.Color = color;
|
continue;
|
||||||
|
|
||||||
|
foreach (var layer in rgb.HolderLayers)
|
||||||
|
{
|
||||||
|
holderSprite.LayerSetColor(layer, color);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ using Content.Server.PowerCell;
|
|||||||
using Content.Shared.Actions;
|
using Content.Shared.Actions;
|
||||||
using Content.Shared.Examine;
|
using Content.Shared.Examine;
|
||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
using Content.Shared.Item;
|
|
||||||
using Content.Shared.Light.Component;
|
using Content.Shared.Light.Component;
|
||||||
using Content.Shared.Rounding;
|
using Content.Shared.Rounding;
|
||||||
using Content.Shared.Toggleable;
|
using Content.Shared.Toggleable;
|
||||||
@@ -67,7 +66,7 @@ namespace Content.Server.Light.EntitySystems
|
|||||||
|
|
||||||
private void OnGetState(EntityUid uid, HandheldLightComponent component, ref ComponentGetState args)
|
private void OnGetState(EntityUid uid, HandheldLightComponent component, ref ComponentGetState args)
|
||||||
{
|
{
|
||||||
args.State = new SharedHandheldLightComponent.HandheldLightComponentState(GetLevel(component));
|
args.State = new SharedHandheldLightComponent.HandheldLightComponentState(component.Activated, GetLevel(component));
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte? GetLevel(HandheldLightComponent component)
|
private byte? GetLevel(HandheldLightComponent component)
|
||||||
@@ -169,8 +168,8 @@ namespace Content.Server.Light.EntitySystems
|
|||||||
{
|
{
|
||||||
if (!component.Activated) return false;
|
if (!component.Activated) return false;
|
||||||
|
|
||||||
SetState(component, false);
|
|
||||||
component.Activated = false;
|
component.Activated = false;
|
||||||
|
_actionSystem.SetToggled(component.ToggleAction, false);
|
||||||
_activeLights.Remove(component);
|
_activeLights.Remove(component);
|
||||||
component.LastLevel = null;
|
component.LastLevel = null;
|
||||||
component.Dirty(EntityManager);
|
component.Dirty(EntityManager);
|
||||||
@@ -203,36 +202,15 @@ namespace Content.Server.Light.EntitySystems
|
|||||||
}
|
}
|
||||||
|
|
||||||
component.Activated = true;
|
component.Activated = true;
|
||||||
SetState(component, true);
|
_actionSystem.SetToggled(component.ToggleAction, true);
|
||||||
_activeLights.Add(component);
|
_activeLights.Add(component);
|
||||||
component.LastLevel = GetLevel(component);
|
component.LastLevel = GetLevel(component);
|
||||||
component.Dirty(EntityManager);
|
Dirty(component);
|
||||||
|
|
||||||
SoundSystem.Play(Filter.Pvs(component.Owner), component.TurnOnSound.GetSound(), component.Owner);
|
SoundSystem.Play(Filter.Pvs(component.Owner), component.TurnOnSound.GetSound(), component.Owner);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetState(HandheldLightComponent component, bool on)
|
|
||||||
{
|
|
||||||
// TODO: Oh dear
|
|
||||||
if (EntityManager.TryGetComponent(component.Owner, out SpriteComponent? sprite))
|
|
||||||
{
|
|
||||||
sprite.LayerSetVisible(1, on);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (EntityManager.TryGetComponent(component.Owner, out PointLightComponent? light))
|
|
||||||
{
|
|
||||||
light.Enabled = on;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (EntityManager.TryGetComponent(component.Owner, out SharedItemComponent? item))
|
|
||||||
{
|
|
||||||
item.EquippedPrefix = on ? "on" : "off";
|
|
||||||
}
|
|
||||||
|
|
||||||
_actionSystem.SetToggled(component.ToggleAction, on);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void TryUpdate(HandheldLightComponent component, float frameTime)
|
public void TryUpdate(HandheldLightComponent component, float frameTime)
|
||||||
{
|
{
|
||||||
if (!_powerCell.TryGetBatteryFromSlot(component.Owner, out var battery))
|
if (!_powerCell.TryGetBatteryFromSlot(component.Owner, out var battery))
|
||||||
|
|||||||
@@ -84,9 +84,6 @@ public abstract partial class InventorySystem
|
|||||||
if(!TryGetSlot(uid, args.Container.ID, out var slotDef, inventory: component))
|
if(!TryGetSlot(uid, args.Container.ID, out var slotDef, inventory: component))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// un-rotate entities. needed for things like directional flashlights on hardsuit helmets
|
|
||||||
Transform(args.Entity).LocalRotation = 0;
|
|
||||||
|
|
||||||
var equippedEvent = new DidEquipEvent(uid, args.Entity, slotDef);
|
var equippedEvent = new DidEquipEvent(uid, args.Entity, slotDef);
|
||||||
RaiseLocalEvent(uid, equippedEvent);
|
RaiseLocalEvent(uid, equippedEvent);
|
||||||
|
|
||||||
|
|||||||
@@ -6,12 +6,17 @@ using Robust.Shared.Serialization;
|
|||||||
using Robust.Shared.Serialization.Manager.Attributes;
|
using Robust.Shared.Serialization.Manager.Attributes;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
|
||||||
namespace Content.Shared.Light.Component;
|
namespace Content.Shared.Light.Component;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Networked ~~solely for admemes~~ for completely legitimate reasons, like hacked energy swords.
|
/// Makes the color of lights on an entity fluctuate. Will update point-light color and modulate some or all of the
|
||||||
|
/// sprite layers. Will also modulate the color of any unshaded layers that this entity contributes to a wearer or holder.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Networked ~~solely for admemes~~ for completely legitimate reasons, like hacked energy swords.
|
||||||
|
/// </remarks>
|
||||||
[NetworkedComponent]
|
[NetworkedComponent]
|
||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
[Friend(typeof(SharedRgbLightControllerSystem))]
|
[Friend(typeof(SharedRgbLightControllerSystem))]
|
||||||
@@ -21,23 +26,37 @@ public sealed class RgbLightControllerComponent : Robust.Shared.GameObjects.Comp
|
|||||||
public float CycleRate { get; set; } = 0.1f;
|
public float CycleRate { get; set; } = 0.1f;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// What layers of the sprite to modulate? If null, will affect the whole sprite.
|
/// What layers of the sprite to modulate? If null, will affect only unshaded layers.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("layers")]
|
[DataField("layers")]
|
||||||
public List<int>? Layers;
|
public List<int>? Layers;
|
||||||
|
|
||||||
// original colors when rgb was added. Used to revert Colors when removed.
|
/// <summary>
|
||||||
|
/// Original light color from befor the rgb was aded. Used to revert colors when removed.
|
||||||
|
/// </summary>
|
||||||
public Color OriginalLightColor;
|
public Color OriginalLightColor;
|
||||||
public Color OriginalItemColor;
|
|
||||||
public Color OriginalSpriteColor;
|
/// <summary>
|
||||||
|
/// Original colors of the sprite layersfrom before the rgb was added. Used to revert colors when removed.
|
||||||
|
/// </summary>
|
||||||
public Dictionary<int, Color>? OriginalLayerColors;
|
public Dictionary<int, Color>? OriginalLayerColors;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// User that is holding or wearing this entity
|
||||||
|
/// </summary>
|
||||||
|
public EntityUid? Holder;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// List of unshaded layers on the holder/wearer that are being modulated.
|
||||||
|
/// </summary>
|
||||||
|
public List<string>? HolderLayers;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Serializable, NetSerializable]
|
[Serializable, NetSerializable]
|
||||||
public sealed class RgbLightControllerState : ComponentState
|
public sealed class RgbLightControllerState : ComponentState
|
||||||
{
|
{
|
||||||
public readonly float CycleRate;
|
public readonly float CycleRate;
|
||||||
public readonly List<int>? Layers;
|
public List<int>? Layers;
|
||||||
|
|
||||||
public RgbLightControllerState(float cycleRate, List<int>? layers)
|
public RgbLightControllerState(float cycleRate, List<int>? layers)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -17,8 +17,11 @@ namespace Content.Shared.Light.Component
|
|||||||
{
|
{
|
||||||
public byte? Charge { get; }
|
public byte? Charge { get; }
|
||||||
|
|
||||||
public HandheldLightComponentState(byte? charge)
|
public bool Activated { get; }
|
||||||
|
|
||||||
|
public HandheldLightComponentState(bool activated, byte? charge)
|
||||||
{
|
{
|
||||||
|
Activated = activated;
|
||||||
Charge = charge;
|
Charge = charge;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using Content.Shared.Light.Component;
|
using Content.Shared.Light.Component;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.GameStates;
|
using Robust.Shared.GameStates;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Content.Shared.Light;
|
namespace Content.Shared.Light;
|
||||||
@@ -33,7 +34,7 @@ public abstract class SharedRgbLightControllerSystem : EntitySystem
|
|||||||
if (!Resolve(uid, ref rgb))
|
if (!Resolve(uid, ref rgb))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
rgb.CycleRate = rate;
|
rgb.CycleRate = Math.Clamp(0.01f, rate, 1); // lets not give people seizures
|
||||||
rgb.Dirty();
|
rgb.Dirty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,20 +58,26 @@
|
|||||||
name: base hardsuit helmet with light
|
name: base hardsuit helmet with light
|
||||||
components:
|
components:
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
netsync: true
|
netsync: false
|
||||||
layers:
|
layers:
|
||||||
- state: icon
|
- state: icon
|
||||||
- state: icon-flash
|
- state: icon-flash
|
||||||
visible: false
|
visible: false
|
||||||
|
map: [ "light" ]
|
||||||
- type: Clothing
|
- type: Clothing
|
||||||
HeldPrefix: off
|
HeldPrefix: off
|
||||||
- type: PointLight
|
- type: PointLight
|
||||||
|
netsync: false
|
||||||
enabled: false
|
enabled: false
|
||||||
radius: 3
|
radius: 6
|
||||||
|
energy: 2
|
||||||
|
mask: /Textures/Effects/LightMasks/cone.png
|
||||||
|
autoRot: true
|
||||||
- type: Appearance
|
- type: Appearance
|
||||||
visuals:
|
visuals:
|
||||||
- type: FlashLightVisualizer
|
- type: FlashLightVisualizer
|
||||||
- type: HandheldLight
|
- type: HandheldLight
|
||||||
|
addPrefix: true
|
||||||
toggleAction:
|
toggleAction:
|
||||||
name: action-name-toggle-light
|
name: action-name-toggle-light
|
||||||
description: action-description-toggle-light
|
description: action-description-toggle-light
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
- state: light-icon
|
- state: light-icon
|
||||||
shader: unshaded
|
shader: unshaded
|
||||||
visible: false
|
visible: false
|
||||||
|
map: [ "light" ]
|
||||||
- type: Clothing
|
- type: Clothing
|
||||||
HeldPrefix: off
|
HeldPrefix: off
|
||||||
- type: PointLight
|
- type: PointLight
|
||||||
@@ -19,6 +20,7 @@
|
|||||||
visuals:
|
visuals:
|
||||||
- type: FlashLightVisualizer
|
- type: FlashLightVisualizer
|
||||||
- type: HandheldLight
|
- type: HandheldLight
|
||||||
|
addPrefix: true
|
||||||
toggleAction:
|
toggleAction:
|
||||||
name: action-name-toggle-light
|
name: action-name-toggle-light
|
||||||
description: action-description-toggle-light
|
description: action-description-toggle-light
|
||||||
|
|||||||
@@ -5,9 +5,44 @@
|
|||||||
description: A special hardsuit helmet designed for working in low-pressure, high thermal environments.
|
description: A special hardsuit helmet designed for working in low-pressure, high thermal environments.
|
||||||
components:
|
components:
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
|
netsync: false
|
||||||
sprite: Clothing/Head/Hardsuits/atmospherics.rsi
|
sprite: Clothing/Head/Hardsuits/atmospherics.rsi
|
||||||
|
layers:
|
||||||
|
- state: icon
|
||||||
|
- state: icon-unshaded
|
||||||
|
shader: unshaded
|
||||||
|
- state: light-overlay
|
||||||
|
visible: false
|
||||||
|
shader: unshaded
|
||||||
|
map: [ "light" ]
|
||||||
|
- type: HandheldLight
|
||||||
|
addPrefix: false
|
||||||
|
inhandVisuals:
|
||||||
|
left:
|
||||||
|
- state: inhand-left-light
|
||||||
|
shader: unshaded
|
||||||
|
right:
|
||||||
|
- state: inhand-right-light
|
||||||
|
shader: unshaded
|
||||||
|
clothingVisuals:
|
||||||
|
head:
|
||||||
|
- state: equipped-head-light
|
||||||
|
shader: unshaded
|
||||||
- type: Clothing
|
- type: Clothing
|
||||||
sprite: Clothing/Head/Hardsuits/atmospherics.rsi
|
clothingVisuals:
|
||||||
|
head:
|
||||||
|
- state: equipped-head
|
||||||
|
- state: equipped-head-unshaded
|
||||||
|
shader: unshaded
|
||||||
|
inhandVisuals:
|
||||||
|
left:
|
||||||
|
- state: inhand-left
|
||||||
|
- state: inhand-left-unshaded
|
||||||
|
shader: unshaded
|
||||||
|
right:
|
||||||
|
- state: inhand-right
|
||||||
|
- state: inhand-right-unshaded
|
||||||
|
shader: unshaded
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: ClothingHeadHardsuitBase
|
parent: ClothingHeadHardsuitBase
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
abstract: true
|
abstract: true
|
||||||
components:
|
components:
|
||||||
- type: HandheldLight
|
- type: HandheldLight
|
||||||
|
addPrefix: true
|
||||||
toggleAction:
|
toggleAction:
|
||||||
name: action-name-toggle-light
|
name: action-name-toggle-light
|
||||||
description: action-description-toggle-light
|
description: action-description-toggle-light
|
||||||
@@ -31,6 +32,7 @@
|
|||||||
- state: lamp-on
|
- state: lamp-on
|
||||||
shader: unshaded
|
shader: unshaded
|
||||||
visible: false
|
visible: false
|
||||||
|
map: [ "light" ]
|
||||||
- type: Item
|
- type: Item
|
||||||
sprite: Objects/Misc/Lights/lamp.rsi
|
sprite: Objects/Misc/Lights/lamp.rsi
|
||||||
- type: PointLight
|
- type: PointLight
|
||||||
@@ -53,6 +55,7 @@
|
|||||||
- state: bananalamp_on
|
- state: bananalamp_on
|
||||||
shader: unshaded
|
shader: unshaded
|
||||||
visible: false
|
visible: false
|
||||||
|
map: [ "light" ]
|
||||||
- type: PointLight
|
- type: PointLight
|
||||||
enabled: false
|
enabled: false
|
||||||
radius: 3
|
radius: 3
|
||||||
@@ -74,6 +77,7 @@
|
|||||||
- state: lampgreen-on
|
- state: lampgreen-on
|
||||||
shader: unshaded
|
shader: unshaded
|
||||||
visible: false
|
visible: false
|
||||||
|
map: [ "light" ]
|
||||||
- type: Item
|
- type: Item
|
||||||
sprite: Objects/Misc/Lights/lampgreen.rsi
|
sprite: Objects/Misc/Lights/lampgreen.rsi
|
||||||
- type: PointLight
|
- type: PointLight
|
||||||
@@ -96,6 +100,7 @@
|
|||||||
- state: floodlight_on
|
- state: floodlight_on
|
||||||
shader: unshaded
|
shader: unshaded
|
||||||
visible: false
|
visible: false
|
||||||
|
map: [ "light" ]
|
||||||
- type: Physics
|
- type: Physics
|
||||||
- type: Fixtures
|
- type: Fixtures
|
||||||
fixtures:
|
fixtures:
|
||||||
|
|||||||
@@ -9,6 +9,14 @@
|
|||||||
- Flashlight
|
- Flashlight
|
||||||
- DroneUsable
|
- DroneUsable
|
||||||
- type: HandheldLight
|
- type: HandheldLight
|
||||||
|
addPrefix: false
|
||||||
|
inhandVisuals:
|
||||||
|
left:
|
||||||
|
- state: inhand-left-light
|
||||||
|
shader: unshaded
|
||||||
|
right:
|
||||||
|
- state: inhand-right-light
|
||||||
|
shader: unshaded
|
||||||
toggleAction:
|
toggleAction:
|
||||||
name: action-name-toggle-light
|
name: action-name-toggle-light
|
||||||
description: action-description-toggle-light
|
description: action-description-toggle-light
|
||||||
@@ -26,10 +34,11 @@
|
|||||||
- state: flashlight-overlay
|
- state: flashlight-overlay
|
||||||
shader: unshaded
|
shader: unshaded
|
||||||
visible: false
|
visible: false
|
||||||
|
map: [ "light" ]
|
||||||
- type: Item
|
- type: Item
|
||||||
sprite: Objects/Tools/flashlight.rsi
|
sprite: Objects/Tools/flashlight.rsi
|
||||||
HeldPrefix: off
|
|
||||||
- type: PointLight
|
- type: PointLight
|
||||||
|
netsync: false
|
||||||
enabled: false
|
enabled: false
|
||||||
mask: /Textures/Effects/LightMasks/cone.png
|
mask: /Textures/Effects/LightMasks/cone.png
|
||||||
autoRot: true
|
autoRot: true
|
||||||
@@ -47,6 +56,15 @@
|
|||||||
- type: PowerCellSlot
|
- type: PowerCellSlot
|
||||||
cellSlot:
|
cellSlot:
|
||||||
startingItem: PowerCellSmallSuper
|
startingItem: PowerCellSmallSuper
|
||||||
|
- type: HandheldLight
|
||||||
|
addPrefix: false
|
||||||
|
inhandVisuals:
|
||||||
|
left:
|
||||||
|
- state: inhand-left-light
|
||||||
|
shader: unshaded
|
||||||
|
right:
|
||||||
|
- state: inhand-right-light
|
||||||
|
shader: unshaded
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Objects/Tools/seclite.rsi
|
sprite: Objects/Tools/seclite.rsi
|
||||||
layers:
|
layers:
|
||||||
@@ -54,6 +72,7 @@
|
|||||||
- state: seclite-overlay
|
- state: seclite-overlay
|
||||||
shader: unshaded
|
shader: unshaded
|
||||||
visible: false
|
visible: false
|
||||||
|
map: [ "light" ]
|
||||||
- type: Item
|
- type: Item
|
||||||
sprite: Objects/Tools/seclite.rsi
|
sprite: Objects/Tools/seclite.rsi
|
||||||
- type: PointLight
|
- type: PointLight
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
description: The holy light guides the way.
|
description: The holy light guides the way.
|
||||||
components:
|
components:
|
||||||
- type: HandheldLight
|
- type: HandheldLight
|
||||||
|
addPrefix: true
|
||||||
toggleAction:
|
toggleAction:
|
||||||
name: action-name-toggle-light
|
name: action-name-toggle-light
|
||||||
description: action-description-toggle-light
|
description: action-description-toggle-light
|
||||||
@@ -18,10 +19,12 @@
|
|||||||
- state: lantern-on
|
- state: lantern-on
|
||||||
shader: unshaded
|
shader: unshaded
|
||||||
visible: false
|
visible: false
|
||||||
|
map: [ "light" ]
|
||||||
- type: Item
|
- type: Item
|
||||||
sprite: Objects/Tools/lantern.rsi
|
sprite: Objects/Tools/lantern.rsi
|
||||||
HeldPrefix: off
|
HeldPrefix: off
|
||||||
- type: PointLight
|
- type: PointLight
|
||||||
|
netsync: false
|
||||||
enabled: false
|
enabled: false
|
||||||
radius: 3
|
radius: 3
|
||||||
energy: 2.5
|
energy: 2.5
|
||||||
|
|||||||
|
After Width: | Height: | Size: 5.7 KiB |
|
After Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 485 B After Width: | Height: | Size: 485 B |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 6.9 KiB |
|
After Width: | Height: | Size: 5.0 KiB |
|
Before Width: | Height: | Size: 919 B After Width: | Height: | Size: 919 B |
|
After Width: | Height: | Size: 7.1 KiB |
|
After Width: | Height: | Size: 5.8 KiB |
|
Before Width: | Height: | Size: 994 B After Width: | Height: | Size: 994 B |
|
After Width: | Height: | Size: 2.5 KiB |
@@ -10,31 +10,49 @@
|
|||||||
{
|
{
|
||||||
"name": "icon"
|
"name": "icon"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "icon-unshaded"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "icon-flash"
|
"name": "icon-flash"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "off-equipped-HELMET",
|
"name": "light-overlay"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "equipped-head",
|
||||||
"directions": 4
|
"directions": 4
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "off-inhand-left",
|
"name": "equipped-head-light",
|
||||||
"directions": 4
|
"directions": 4
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "off-inhand-right",
|
"name": "equipped-head-unshaded",
|
||||||
"directions": 4
|
"directions": 4
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "on-equipped-HELMET",
|
"name": "inhand-left",
|
||||||
"directions": 4
|
"directions": 4
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "on-inhand-left",
|
"name": "inhand-left-unshaded",
|
||||||
"directions": 4
|
"directions": 4
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "on-inhand-right",
|
"name": "inhand-left-light",
|
||||||
|
"directions": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "inhand-right",
|
||||||
|
"directions": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "inhand-right-unshaded",
|
||||||
|
"directions": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "inhand-right-light",
|
||||||
"directions": 4
|
"directions": 4
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 305 B After Width: | Height: | Size: 305 B |
|
After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 424 B After Width: | Height: | Size: 424 B |
@@ -17,19 +17,19 @@
|
|||||||
"name": "flashlight-overlay"
|
"name": "flashlight-overlay"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "off-inhand-left",
|
"name": "inhand-left",
|
||||||
"directions": 4
|
"directions": 4
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "off-inhand-right",
|
"name": "inhand-right",
|
||||||
"directions": 4
|
"directions": 4
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "on-inhand-left",
|
"name": "inhand-left-light",
|
||||||
"directions": 4
|
"directions": 4
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "on-inhand-right",
|
"name": "inhand-right-light",
|
||||||
"directions": 4
|
"directions": 4
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 324 B |
|
Before Width: | Height: | Size: 322 B |
|
After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 488 B After Width: | Height: | Size: 488 B |
|
After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 401 B After Width: | Height: | Size: 401 B |
@@ -17,19 +17,19 @@
|
|||||||
"name": "seclite-overlay"
|
"name": "seclite-overlay"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "off-inhand-left",
|
"name": "inhand-left",
|
||||||
"directions": 4
|
"directions": 4
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "off-inhand-right",
|
"name": "inhand-right",
|
||||||
"directions": 4
|
"directions": 4
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "on-inhand-left",
|
"name": "inhand-left-light",
|
||||||
"directions": 4
|
"directions": 4
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "on-inhand-right",
|
"name": "inhand-right-light",
|
||||||
"directions": 4
|
"directions": 4
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 444 B |
|
Before Width: | Height: | Size: 462 B |