Chameleon clothing (#8444)
Co-authored-by: Moony <moonheart08@users.noreply.github.com> Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
This commit is contained in:
@@ -7,17 +7,6 @@ namespace Content.Client.Clothing
|
||||
[ComponentReference(typeof(SharedClothingComponent))]
|
||||
public sealed class ClothingComponent : SharedClothingComponent
|
||||
{
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField("femaleMask")]
|
||||
public FemaleClothingMask FemaleMask = FemaleClothingMask.UniformFull;
|
||||
|
||||
public string? InSlot;
|
||||
}
|
||||
|
||||
public enum FemaleClothingMask : byte
|
||||
{
|
||||
NoMask = 0,
|
||||
UniformFull,
|
||||
UniformTop
|
||||
}
|
||||
}
|
||||
|
||||
110
Content.Client/Clothing/Systems/ChameleonClothingSystem.cs
Normal file
110
Content.Client/Clothing/Systems/ChameleonClothingSystem.cs
Normal file
@@ -0,0 +1,110 @@
|
||||
using System.Linq;
|
||||
using Content.Shared.Clothing.Components;
|
||||
using Content.Shared.Clothing.EntitySystems;
|
||||
using Content.Shared.Inventory;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Client.Clothing.Systems;
|
||||
|
||||
// All valid items for chameleon are calculated on client startup and stored in dictionary.
|
||||
public sealed class ChameleonClothingSystem : SharedChameleonClothingSystem
|
||||
{
|
||||
[Dependency] private readonly IPrototypeManager _proto = default!;
|
||||
[Dependency] private readonly IComponentFactory _factory = default!;
|
||||
|
||||
private static readonly SlotFlags[] IgnoredSlots =
|
||||
{
|
||||
SlotFlags.All,
|
||||
SlotFlags.PREVENTEQUIP,
|
||||
SlotFlags.NONE
|
||||
};
|
||||
private static readonly SlotFlags[] Slots = Enum.GetValues<SlotFlags>().Except(IgnoredSlots).ToArray();
|
||||
|
||||
private readonly Dictionary<SlotFlags, List<string>> _data = new();
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<ChameleonClothingComponent, ComponentHandleState>(HandleState);
|
||||
|
||||
PrepareAllVariants();
|
||||
_proto.PrototypesReloaded += OnProtoReloaded;
|
||||
}
|
||||
|
||||
public override void Shutdown()
|
||||
{
|
||||
base.Shutdown();
|
||||
_proto.PrototypesReloaded -= OnProtoReloaded;
|
||||
}
|
||||
|
||||
private void OnProtoReloaded(PrototypesReloadedEventArgs _)
|
||||
{
|
||||
PrepareAllVariants();
|
||||
}
|
||||
|
||||
private void HandleState(EntityUid uid, ChameleonClothingComponent component, ref ComponentHandleState args)
|
||||
{
|
||||
if (args.Current is not ChameleonClothingComponentState state)
|
||||
return;
|
||||
component.SelectedId = state.SelectedId;
|
||||
|
||||
UpdateVisuals(uid, component);
|
||||
}
|
||||
|
||||
protected override void UpdateSprite(EntityUid uid, EntityPrototype proto)
|
||||
{
|
||||
base.UpdateSprite(uid, proto);
|
||||
if (TryComp(uid, out SpriteComponent? sprite)
|
||||
&& proto.TryGetComponent(out SpriteComponent? otherSprite, _factory))
|
||||
{
|
||||
sprite.CopyFrom(otherSprite);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a list of valid chameleon targets for these slots.
|
||||
/// </summary>
|
||||
public IEnumerable<string> GetValidTargets(SlotFlags slot)
|
||||
{
|
||||
var set = new HashSet<string>();
|
||||
foreach (var availableSlot in _data.Keys)
|
||||
{
|
||||
if (slot.HasFlag(availableSlot))
|
||||
{
|
||||
set.UnionWith(_data[availableSlot]);
|
||||
}
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
private void PrepareAllVariants()
|
||||
{
|
||||
_data.Clear();
|
||||
var prototypes = _proto.EnumeratePrototypes<EntityPrototype>();
|
||||
|
||||
foreach (var proto in prototypes)
|
||||
{
|
||||
// check if this is valid clothing
|
||||
if (!IsValidTarget(proto))
|
||||
continue;
|
||||
if (!proto.TryGetComponent(out ClothingComponent? item, _factory))
|
||||
continue;
|
||||
|
||||
// sort item by their slot flags
|
||||
// one item can be placed in several buckets
|
||||
foreach (var slot in Slots)
|
||||
{
|
||||
if (!item.Slots.HasFlag(slot))
|
||||
continue;
|
||||
|
||||
if (!_data.ContainsKey(slot))
|
||||
{
|
||||
_data.Add(slot, new List<string>());
|
||||
}
|
||||
_data[slot].Add(proto.ID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
57
Content.Client/Clothing/UI/ChameleonBoundUserInterface.cs
Normal file
57
Content.Client/Clothing/UI/ChameleonBoundUserInterface.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
using Content.Client.Clothing.Systems;
|
||||
using Content.Shared.Clothing.Components;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.GameObjects;
|
||||
|
||||
namespace Content.Client.Clothing.UI;
|
||||
|
||||
[UsedImplicitly]
|
||||
public sealed class ChameleonBoundUserInterface : BoundUserInterface
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
private readonly ChameleonClothingSystem _chameleon;
|
||||
|
||||
private ChameleonMenu? _menu;
|
||||
|
||||
public ChameleonBoundUserInterface(ClientUserInterfaceComponent owner, Enum uiKey) : base(owner, uiKey)
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
_chameleon = _entityManager.System<ChameleonClothingSystem>();
|
||||
}
|
||||
|
||||
protected override void Open()
|
||||
{
|
||||
base.Open();
|
||||
|
||||
_menu = new ChameleonMenu();
|
||||
_menu.OnClose += Close;
|
||||
_menu.OnIdSelected += OnIdSelected;
|
||||
_menu.OpenCentered();
|
||||
}
|
||||
|
||||
protected override void UpdateState(BoundUserInterfaceState state)
|
||||
{
|
||||
base.UpdateState(state);
|
||||
if (state is not ChameleonBoundUserInterfaceState st)
|
||||
return;
|
||||
|
||||
var targets = _chameleon.GetValidTargets(st.Slot);
|
||||
_menu?.UpdateState(targets, st.SelectedId);
|
||||
}
|
||||
|
||||
private void OnIdSelected(string selectedId)
|
||||
{
|
||||
SendMessage(new ChameleonPrototypeSelectedMessage(selectedId));
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
base.Dispose(disposing);
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
_menu?.Close();
|
||||
_menu = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
12
Content.Client/Clothing/UI/ChameleonMenu.xaml
Normal file
12
Content.Client/Clothing/UI/ChameleonMenu.xaml
Normal file
@@ -0,0 +1,12 @@
|
||||
<DefaultWindow xmlns="https://spacestation14.io"
|
||||
Title="{Loc 'chameleon-component-ui-window-name'}"
|
||||
MinSize="250 300"
|
||||
SetSize="250 300">
|
||||
<BoxContainer Orientation="Vertical">
|
||||
<LineEdit Name="Search" PlaceHolder = "{Loc 'chameleon-component-ui-search-placeholder'}"/>
|
||||
<ScrollContainer VerticalExpand="True">
|
||||
<GridContainer Name="Grid" Columns="3" Margin="0 5" >
|
||||
</GridContainer>
|
||||
</ScrollContainer>
|
||||
</BoxContainer>
|
||||
</DefaultWindow>
|
||||
90
Content.Client/Clothing/UI/ChameleonMenu.xaml.cs
Normal file
90
Content.Client/Clothing/UI/ChameleonMenu.xaml.cs
Normal file
@@ -0,0 +1,90 @@
|
||||
using System.Linq;
|
||||
using Content.Client.Clothing.Systems;
|
||||
using Content.Client.Stylesheets;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Client.Clothing.UI;
|
||||
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class ChameleonMenu : DefaultWindow
|
||||
{
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
private readonly SpriteSystem _sprite;
|
||||
public event Action<string>? OnIdSelected;
|
||||
|
||||
private IEnumerable<string> _possibleIds = Enumerable.Empty<string>();
|
||||
private string? _selectedId;
|
||||
private string _searchFilter = "";
|
||||
|
||||
public ChameleonMenu()
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
IoCManager.InjectDependencies(this);
|
||||
_sprite = _entityManager.System<SpriteSystem>();
|
||||
|
||||
Search.OnTextChanged += OnSearchEntered;
|
||||
}
|
||||
|
||||
public void UpdateState(IEnumerable<string> possibleIds, string? selectedId)
|
||||
{
|
||||
_possibleIds = possibleIds;
|
||||
_selectedId = selectedId;
|
||||
UpdateGrid();
|
||||
}
|
||||
|
||||
private void OnSearchEntered(LineEdit.LineEditEventArgs obj)
|
||||
{
|
||||
_searchFilter = obj.Text;
|
||||
UpdateGrid();
|
||||
}
|
||||
|
||||
private void UpdateGrid()
|
||||
{
|
||||
ClearGrid();
|
||||
|
||||
var group = new ButtonGroup();
|
||||
var searchFilterLow = _searchFilter.ToLowerInvariant();
|
||||
|
||||
foreach (var id in _possibleIds)
|
||||
{
|
||||
if (!_prototypeManager.TryIndex(id, out EntityPrototype? proto))
|
||||
continue;
|
||||
|
||||
var lowId = id.ToLowerInvariant();
|
||||
var lowName = proto.Name.ToLowerInvariant();
|
||||
if (!lowId.Contains(searchFilterLow) && !lowName.Contains(_searchFilter))
|
||||
continue;
|
||||
|
||||
var button = new Button
|
||||
{
|
||||
MinSize = new Vector2(48, 48),
|
||||
HorizontalExpand = true,
|
||||
Group = group,
|
||||
StyleClasses = {StyleBase.ButtonSquare},
|
||||
ToggleMode = true,
|
||||
Pressed = _selectedId == id,
|
||||
ToolTip = proto.Name
|
||||
};
|
||||
button.OnPressed += _ => OnIdSelected?.Invoke(id);
|
||||
Grid.AddChild(button);
|
||||
|
||||
var texture = _sprite.GetPrototypeIcon(proto);
|
||||
button.AddChild(new TextureRect
|
||||
{
|
||||
Stretch = TextureRect.StretchMode.KeepAspectCentered,
|
||||
Texture = texture.Default
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void ClearGrid()
|
||||
{
|
||||
Grid.RemoveAllChildren();
|
||||
}
|
||||
}
|
||||
98
Content.Server/Clothing/Systems/ChameleonClothingSystem.cs
Normal file
98
Content.Server/Clothing/Systems/ChameleonClothingSystem.cs
Normal file
@@ -0,0 +1,98 @@
|
||||
using Content.Shared.Clothing.Components;
|
||||
using Content.Shared.Clothing.EntitySystems;
|
||||
using Content.Shared.Verbs;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Clothing.Systems;
|
||||
|
||||
public sealed class ChameleonClothingSystem : SharedChameleonClothingSystem
|
||||
{
|
||||
[Dependency] private readonly IPrototypeManager _proto = default!;
|
||||
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<ChameleonClothingComponent, ComponentInit>(OnInit);
|
||||
SubscribeLocalEvent<ChameleonClothingComponent, ComponentGetState>(GetState);
|
||||
SubscribeLocalEvent<ChameleonClothingComponent, GetVerbsEvent<InteractionVerb>>(OnVerb);
|
||||
SubscribeLocalEvent<ChameleonClothingComponent, ChameleonPrototypeSelectedMessage>(OnSelected);
|
||||
}
|
||||
|
||||
private void OnInit(EntityUid uid, ChameleonClothingComponent component, ComponentInit args)
|
||||
{
|
||||
SetSelectedPrototype(uid, component.SelectedId, true, component);
|
||||
}
|
||||
|
||||
private void GetState(EntityUid uid, ChameleonClothingComponent component, ref ComponentGetState args)
|
||||
{
|
||||
args.State = new ChameleonClothingComponentState
|
||||
{
|
||||
SelectedId = component.SelectedId
|
||||
};
|
||||
}
|
||||
|
||||
private void OnVerb(EntityUid uid, ChameleonClothingComponent component, GetVerbsEvent<InteractionVerb> args)
|
||||
{
|
||||
if (!args.CanAccess || !args.CanInteract)
|
||||
return;
|
||||
|
||||
args.Verbs.Add(new InteractionVerb()
|
||||
{
|
||||
Text = Loc.GetString("chameleon-component-verb-text"),
|
||||
IconTexture = "/Textures/Interface/VerbIcons/settings.svg.192dpi.png",
|
||||
Act = () => TryOpenUi(uid, args.User, component)
|
||||
});
|
||||
}
|
||||
|
||||
private void OnSelected(EntityUid uid, ChameleonClothingComponent component, ChameleonPrototypeSelectedMessage args)
|
||||
{
|
||||
SetSelectedPrototype(uid, args.SelectedId, component: component);
|
||||
}
|
||||
|
||||
private void TryOpenUi(EntityUid uid, EntityUid user, ChameleonClothingComponent? component = null)
|
||||
{
|
||||
if (!Resolve(uid, ref component))
|
||||
return;
|
||||
if (!TryComp(user, out ActorComponent? actor))
|
||||
return;
|
||||
_uiSystem.TryToggleUi(uid, ChameleonUiKey.Key, actor.PlayerSession);
|
||||
}
|
||||
|
||||
private void UpdateUi(EntityUid uid, ChameleonClothingComponent? component = null)
|
||||
{
|
||||
if (!Resolve(uid, ref component))
|
||||
return;
|
||||
|
||||
var state = new ChameleonBoundUserInterfaceState(component.Slot, component.SelectedId);
|
||||
_uiSystem.TrySetUiState(uid, ChameleonUiKey.Key, state);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Change chameleon items name, description and sprite to mimic other entity prototype.
|
||||
/// </summary>
|
||||
public void SetSelectedPrototype(EntityUid uid, string? protoId, bool forceUpdate = false,
|
||||
ChameleonClothingComponent? component = null)
|
||||
{
|
||||
if (!Resolve(uid, ref component, false))
|
||||
return;
|
||||
|
||||
// check that wasn't already selected
|
||||
// forceUpdate on component init ignores this check
|
||||
if (component.SelectedId == protoId && !forceUpdate)
|
||||
return;
|
||||
|
||||
// make sure that it is valid change
|
||||
if (string.IsNullOrEmpty(protoId) || !_proto.TryIndex(protoId, out EntityPrototype? proto))
|
||||
return;
|
||||
if (!IsValidTarget(proto, component.Slot))
|
||||
return;
|
||||
component.SelectedId = protoId;
|
||||
|
||||
UpdateVisuals(uid, component);
|
||||
UpdateUi(uid, component);
|
||||
Dirty(component);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
using Content.Shared.Clothing.EntitySystems;
|
||||
using Content.Shared.Inventory;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
|
||||
namespace Content.Shared.Clothing.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Allow players to change clothing sprite to any other clothing prototype.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
[Access(typeof(SharedChameleonClothingSystem))]
|
||||
public sealed class ChameleonClothingComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// Filter possible chameleon options by their slot flag.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadOnly)]
|
||||
[DataField("slot", required: true)]
|
||||
public SlotFlags Slot;
|
||||
|
||||
/// <summary>
|
||||
/// EntityPrototype id that chameleon item is trying to mimic.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadOnly)]
|
||||
[DataField("default", required: true, customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
public string? SelectedId;
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class ChameleonClothingComponentState : ComponentState
|
||||
{
|
||||
public string? SelectedId;
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class ChameleonBoundUserInterfaceState : BoundUserInterfaceState
|
||||
{
|
||||
public readonly SlotFlags Slot;
|
||||
public readonly string? SelectedId;
|
||||
|
||||
public ChameleonBoundUserInterfaceState(SlotFlags slot, string? selectedId)
|
||||
{
|
||||
Slot = slot;
|
||||
SelectedId = selectedId;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class ChameleonPrototypeSelectedMessage: BoundUserInterfaceMessage
|
||||
{
|
||||
public readonly string SelectedId;
|
||||
|
||||
public ChameleonPrototypeSelectedMessage(string selectedId)
|
||||
{
|
||||
SelectedId = selectedId;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum ChameleonUiKey : byte
|
||||
{
|
||||
Key
|
||||
}
|
||||
@@ -42,6 +42,10 @@ public abstract class SharedClothingComponent : Component
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField("sprite")]
|
||||
public string? RsiPath;
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField("femaleMask")]
|
||||
public FemaleClothingMask FemaleMask = FemaleClothingMask.UniformFull;
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
@@ -54,3 +58,10 @@ public sealed class ClothingComponentState : ComponentState
|
||||
EquippedPrefix = equippedPrefix;
|
||||
}
|
||||
}
|
||||
|
||||
public enum FemaleClothingMask : byte
|
||||
{
|
||||
NoMask = 0,
|
||||
UniformFull,
|
||||
UniformTop
|
||||
}
|
||||
|
||||
@@ -52,5 +52,22 @@ public sealed class ClothingSystem : EntitySystem
|
||||
Dirty(clothing);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copy all clothing specific visuals from another item.
|
||||
/// </summary>
|
||||
public void CopyVisuals(EntityUid uid, SharedClothingComponent otherClothing, SharedClothingComponent? clothing = null)
|
||||
{
|
||||
if (!Resolve(uid, ref clothing))
|
||||
return;
|
||||
|
||||
clothing.ClothingVisuals = otherClothing.ClothingVisuals;
|
||||
clothing.EquippedPrefix = otherClothing.EquippedPrefix;
|
||||
clothing.RsiPath = otherClothing.RsiPath;
|
||||
clothing.FemaleMask = otherClothing.FemaleMask;
|
||||
|
||||
_itemSys.VisualsChanged(uid);
|
||||
Dirty(clothing);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
using Content.Shared.Clothing.Components;
|
||||
using Content.Shared.Inventory;
|
||||
using Content.Shared.Item;
|
||||
using Content.Shared.Tag;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared.Clothing.EntitySystems;
|
||||
|
||||
public abstract class SharedChameleonClothingSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IComponentFactory _factory = default!;
|
||||
[Dependency] private readonly IPrototypeManager _proto = default!;
|
||||
[Dependency] private readonly SharedItemSystem _itemSystem = default!;
|
||||
[Dependency] private readonly ClothingSystem _clothingSystem = default!;
|
||||
|
||||
// Updates chameleon visuals and meta information.
|
||||
// This function is called on a server after user selected new outfit.
|
||||
// And after that on a client after state was updated.
|
||||
// This 100% makes sure that server and client have exactly same data.
|
||||
protected void UpdateVisuals(EntityUid uid, ChameleonClothingComponent component)
|
||||
{
|
||||
if (string.IsNullOrEmpty(component.SelectedId) ||
|
||||
!_proto.TryIndex(component.SelectedId, out EntityPrototype? proto))
|
||||
return;
|
||||
|
||||
// world sprite icon
|
||||
UpdateSprite(uid, proto);
|
||||
|
||||
// copy name and description
|
||||
var meta = MetaData(uid);
|
||||
meta.EntityName = proto.Name;
|
||||
meta.EntityDescription = proto.Description;
|
||||
|
||||
// item sprite logic
|
||||
if (TryComp(uid, out ItemComponent? item) &&
|
||||
proto.TryGetComponent(out ItemComponent? otherItem, _factory))
|
||||
{
|
||||
_itemSystem.CopyVisuals(uid, otherItem, item);
|
||||
}
|
||||
|
||||
// clothing sprite logic
|
||||
if (TryComp(uid, out SharedClothingComponent? clothing) &&
|
||||
proto.TryGetComponent("Clothing", out SharedClothingComponent? otherClothing))
|
||||
{
|
||||
_clothingSystem.CopyVisuals(uid, otherClothing, clothing);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void UpdateSprite(EntityUid uid, EntityPrototype proto) { }
|
||||
|
||||
/// <summary>
|
||||
/// Check if this entity prototype is valid target for chameleon item.
|
||||
/// </summary>
|
||||
public bool IsValidTarget(EntityPrototype proto, SlotFlags chameleonSlot = SlotFlags.NONE)
|
||||
{
|
||||
// check if entity is valid
|
||||
if (proto.Abstract || proto.NoSpawn)
|
||||
return false;
|
||||
|
||||
// check if it is marked as valid chameleon target
|
||||
if (!proto.TryGetComponent(out TagComponent? tags, _factory) || !tags.Tags.Contains("WhitelistChameleon"))
|
||||
return false;
|
||||
|
||||
// check if it's valid clothing
|
||||
if (!proto.TryGetComponent("Clothing", out SharedClothingComponent? clothing))
|
||||
return false;
|
||||
if (!clothing.Slots.HasFlag(chameleonSlot))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@ public sealed class ItemComponent : Component
|
||||
[Access(typeof(SharedItemSystem), Other = AccessPermissions.ReadExecute)]
|
||||
public int Size = 5;
|
||||
|
||||
[Access(typeof(SharedItemSystem))]
|
||||
[DataField("inhandVisuals")]
|
||||
public Dictionary<HandLocation, List<SharedSpriteComponent.PrototypeLayerData>> InhandVisuals = new();
|
||||
|
||||
@@ -29,9 +30,10 @@ public sealed class ItemComponent : Component
|
||||
/// <summary>
|
||||
/// Rsi of the sprite shown on the player when this item is in their hands. Used to generate a default entry for <see cref="InhandVisuals"/>
|
||||
/// </summary>
|
||||
[Access(typeof(SharedItemSystem))]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField("sprite")]
|
||||
public readonly string? RsiPath;
|
||||
public string? RsiPath;
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
|
||||
@@ -49,6 +49,22 @@ public abstract class SharedItemSystem : EntitySystem
|
||||
VisualsChanged(uid);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copy all item specific visuals from another item.
|
||||
/// </summary>
|
||||
public void CopyVisuals(EntityUid uid, ItemComponent otherItem, ItemComponent? item = null)
|
||||
{
|
||||
if (!Resolve(uid, ref item))
|
||||
return;
|
||||
|
||||
item.RsiPath = otherItem.RsiPath;
|
||||
item.InhandVisuals = otherItem.InhandVisuals;
|
||||
item.HeldPrefix = otherItem.HeldPrefix;
|
||||
|
||||
Dirty(item);
|
||||
VisualsChanged(uid);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private void OnHandInteract(EntityUid uid, ItemComponent component, InteractHandEvent args)
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
|
||||
## UI
|
||||
chameleon-component-ui-window-name = Chameleon Settings
|
||||
chameleon-component-ui-search-placeholder = Search...
|
||||
|
||||
## Verb
|
||||
chameleon-component-verb-text = Chameleon
|
||||
@@ -8,6 +8,7 @@ fibers-durathread = durathread
|
||||
fibers-latex = latex
|
||||
fibers-nitrile = nitrile
|
||||
fibers-nanomachines = insulative nanomachine
|
||||
fibers-chameleon = holographic chameleon
|
||||
|
||||
fibers-purple = purple
|
||||
fibers-red = red
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
amount: 5
|
||||
|
||||
- type: entity
|
||||
parent: ClothingBackpackDuffelSyndicateMedical
|
||||
parent: ClothingBackpackDuffelSyndicateMedicalBundle
|
||||
id: ClothingBackpackDuffelSyndicateFilledMedical
|
||||
name: syndicate surgical duffel bag
|
||||
description: "A large duffel bag for holding extra medical supplies - this one seems to be designed for holding surgical tools."
|
||||
@@ -45,7 +45,7 @@
|
||||
- id: ScalpelAdvanced
|
||||
|
||||
- type: entity
|
||||
parent: ClothingBackpackDuffelSyndicateAmmo
|
||||
parent: ClothingBackpackDuffelSyndicateAmmoBundle
|
||||
id: ClothingBackpackDuffelSyndicateFilledShotgun
|
||||
name: Bulldog bundle
|
||||
description: "Lean and mean: Contains the popular Bulldog Shotgun, a 12g beanbag drum and 2 12g buckshot drums." #, and a pair of Thermal Imaging Goggles.
|
||||
@@ -58,7 +58,7 @@
|
||||
# - id: ThermalImagingGoggles
|
||||
|
||||
- type: entity
|
||||
parent: ClothingBackpackDuffelSyndicateAmmo
|
||||
parent: ClothingBackpackDuffelSyndicateAmmoBundle
|
||||
id: ClothingBackpackDuffelSyndicateFilledSMG
|
||||
name: C-20r bundle
|
||||
description: "Old faithful: The classic C-20r Submachine Gun, bundled with three magazines." #, and a Suppressor.
|
||||
@@ -71,7 +71,7 @@
|
||||
# - id: SMGSuppressor
|
||||
|
||||
- type: entity
|
||||
parent: ClothingBackpackDuffelSyndicateAmmo
|
||||
parent: ClothingBackpackDuffelSyndicateAmmoBundle
|
||||
id: ClothingBackpackDuffelSyndicateFilledRevolver
|
||||
name: Python bundle
|
||||
description: "Go loud and proud with a fully loaded Magnum Python, bundled with two speed loaders."
|
||||
@@ -83,7 +83,7 @@
|
||||
amount: 2
|
||||
|
||||
- type: entity
|
||||
parent: ClothingBackpackDuffelSyndicateAmmo
|
||||
parent: ClothingBackpackDuffelSyndicateAmmoBundle
|
||||
id: ClothingBackpackDuffelSyndicateFilledLMG
|
||||
name: L6 Saw bundle
|
||||
description: "More dakka: The iconic L6 lightmachinegun, bundled with 2 box magazines."
|
||||
@@ -94,7 +94,7 @@
|
||||
- id: MagazineLightRifleBox
|
||||
|
||||
- type: entity
|
||||
parent: ClothingBackpackDuffelSyndicateAmmo
|
||||
parent: ClothingBackpackDuffelSyndicateAmmoBundle
|
||||
id: ClothingBackpackDuffelSyndicateFilledGrenadeLauncher
|
||||
name: China-Lake bundle
|
||||
description: "An old China-Lake grenade launcher bundled with 8 rounds of various destruction capability."
|
||||
@@ -108,7 +108,7 @@
|
||||
amount: 4
|
||||
|
||||
- type: entity
|
||||
parent: ClothingBackpackDuffelSyndicateAmmo
|
||||
parent: ClothingBackpackDuffelSyndicateAmmoBundle
|
||||
id: ClothingBackpackDuffelSyndicateFilledCarbine
|
||||
name: M-90gl bundle
|
||||
description: "A versatile battle rifle with an attached grenade launcher, bundled with 3 magazines and 6 grenades of various capabilities."
|
||||
@@ -131,6 +131,8 @@
|
||||
name: CentCom official costume duffel bag
|
||||
description: "Contains a full CentCom Official uniform set, headset and clipboard included. The headset comes without an encryption key."
|
||||
components:
|
||||
- type: Tag
|
||||
tags: [] # ignore "WhitelistChameleon" tag
|
||||
- type: StorageFill
|
||||
contents:
|
||||
- id: ClothingHeadHatCaptain
|
||||
@@ -150,6 +152,8 @@
|
||||
name: clown costume duffel bag
|
||||
description: "Contains a complete Clown outfit."
|
||||
components:
|
||||
- type: Tag
|
||||
tags: [] # ignore "WhitelistChameleon" tag
|
||||
- type: StorageFill
|
||||
contents:
|
||||
- id: ClothingUniformJumpsuitClown
|
||||
@@ -160,7 +164,7 @@
|
||||
- id: ClothingHeadsetService
|
||||
|
||||
- type: entity
|
||||
parent: ClothingBackpackDuffelSyndicate
|
||||
parent: ClothingBackpackDuffelSyndicateBundle
|
||||
id: ClothingBackpackDuffelSyndicatePyjamaBundle
|
||||
name: syndicate pyjama duffel bag
|
||||
description: "Contains 3 syndicate pyjamas."
|
||||
@@ -182,7 +186,7 @@
|
||||
- id: PlushieLizard
|
||||
|
||||
- type: entity
|
||||
parent: ClothingBackpackDuffelSyndicate
|
||||
parent: ClothingBackpackDuffelSyndicateBundle
|
||||
id: ClothingBackpackDuffelSyndicateC4tBundle
|
||||
name: syndicate C-4 bundle
|
||||
description: "Contains a lot of C-4 charges."
|
||||
@@ -193,7 +197,24 @@
|
||||
amount: 8
|
||||
|
||||
- type: entity
|
||||
parent: ClothingBackpackDuffelSyndicate
|
||||
parent: ClothingBackpackChameleon
|
||||
id: ClothingBackpackChameleonFill
|
||||
suffix: Fill, Chameleon
|
||||
components:
|
||||
- type: StorageFill
|
||||
contents:
|
||||
- id: ClothingUniformJumpsuitChameleon
|
||||
- id: ClothingOuterChameleon
|
||||
- id: ClothingNeckChameleon
|
||||
- id: ClothingMaskGasChameleon
|
||||
- id: ClothingHeadHatChameleon
|
||||
- id: ClothingHandsChameleon
|
||||
- id: ClothingEyesChameleon
|
||||
- id: ClothingHeadsetChameleon
|
||||
- id: ClothingShoesChameleon
|
||||
|
||||
- type: entity
|
||||
parent: ClothingBackpackDuffelSyndicateBundle
|
||||
id: ClothingBackpackDuffelSyndicateEVABundle
|
||||
name: syndicate EVA bundle
|
||||
description: "Contains the Syndicate approved EVA suit."
|
||||
@@ -204,7 +225,7 @@
|
||||
- id: ClothingOuterHardsuitSyndicate
|
||||
|
||||
- type: entity
|
||||
parent: ClothingBackpackDuffelSyndicate
|
||||
parent: ClothingBackpackDuffelSyndicateBundle
|
||||
id: ClothingBackpackDuffelSyndicateHardsuitBundle
|
||||
name: syndicate hardsuit bundle
|
||||
description: "Contains the Syndicate's signature blood red hardsuit."
|
||||
@@ -214,7 +235,7 @@
|
||||
- id: ClothingOuterHardsuitSyndie
|
||||
|
||||
- type: entity
|
||||
parent: ClothingBackpackDuffelSyndicate
|
||||
parent: ClothingBackpackDuffelSyndicateBundle
|
||||
id: ClothingBackpackDuffelZombieBundle
|
||||
name: syndicate zombie bundle
|
||||
description: "An all-in-one kit for unleashing the undead upon a station."
|
||||
@@ -228,7 +249,7 @@
|
||||
amount: 3
|
||||
|
||||
- type: entity
|
||||
parent: ClothingBackpackDuffelSyndicate
|
||||
parent: ClothingBackpackDuffelSyndicateBundle
|
||||
id: ClothingBackpackDuffelSyndicateOperative
|
||||
name: operative duffelbag
|
||||
components:
|
||||
@@ -241,7 +262,7 @@
|
||||
|
||||
|
||||
- type: entity
|
||||
parent: ClothingBackpackDuffelSyndicateMedical
|
||||
parent: ClothingBackpackDuffelSyndicateMedicalBundle
|
||||
id: ClothingBackpackDuffelSyndicateOperativeMedic
|
||||
name: operative medic duffelbag
|
||||
description: A large duffel bag for holding extra medical supplies.
|
||||
|
||||
@@ -428,7 +428,17 @@
|
||||
|
||||
# Armor
|
||||
|
||||
# Should be cameleon shoes, change when implemented.
|
||||
- type: listing
|
||||
id: UplinkChameleon
|
||||
name: Chameleon Kit
|
||||
description: A backpack full of items that contain chameleon technology allowing you to disguise as pretty much anything on the station, and more!
|
||||
productEntity: ClothingBackpackChameleonFill
|
||||
icon: /Textures/Clothing/Uniforms/Jumpsuit/rainbow.rsi/icon.png
|
||||
cost:
|
||||
Telecrystal: 4
|
||||
categories:
|
||||
- UplinkArmor
|
||||
|
||||
- type: listing
|
||||
id: UplinkClothingNoSlipsShoes
|
||||
name: no-slip shoes
|
||||
|
||||
@@ -117,6 +117,14 @@
|
||||
- type: Storage
|
||||
capacity: 131
|
||||
|
||||
- type: entity
|
||||
parent: ClothingBackpackDuffelSyndicate
|
||||
id: ClothingBackpackDuffelSyndicateBundle
|
||||
abstract: true
|
||||
components:
|
||||
- type: Tag
|
||||
tags: [] # ignore "WhitelistChameleon" tag
|
||||
|
||||
- type: entity
|
||||
parent: ClothingBackpackDuffelSyndicate
|
||||
id: ClothingBackpackDuffelSyndicateAmmo
|
||||
@@ -130,6 +138,14 @@
|
||||
- type: Clothing
|
||||
equippedPrefix: ammo
|
||||
|
||||
- type: entity
|
||||
parent: ClothingBackpackDuffelSyndicate
|
||||
id: ClothingBackpackDuffelSyndicateAmmoBundle
|
||||
abstract: true
|
||||
components:
|
||||
- type: Tag
|
||||
tags: [] # ignore "WhitelistChameleon" tag
|
||||
|
||||
- type: entity
|
||||
parent: ClothingBackpackDuffelSyndicate
|
||||
id: ClothingBackpackDuffelSyndicateMedical
|
||||
@@ -143,6 +159,14 @@
|
||||
- type: Clothing
|
||||
equippedPrefix: med
|
||||
|
||||
- type: entity
|
||||
parent: ClothingBackpackDuffelSyndicate
|
||||
id: ClothingBackpackDuffelSyndicateMedicalBundle
|
||||
abstract: true
|
||||
components:
|
||||
- type: Tag
|
||||
tags: [] # ignore "WhitelistChameleon" tag
|
||||
|
||||
- type: entity
|
||||
parent: ClothingBackpackDuffel
|
||||
id: ClothingBackpackDuffelHolding
|
||||
|
||||
23
Resources/Prototypes/Entities/Clothing/Back/specific.yml
Normal file
23
Resources/Prototypes/Entities/Clothing/Back/specific.yml
Normal file
@@ -0,0 +1,23 @@
|
||||
- type: entity
|
||||
parent: ClothingBackpack
|
||||
id: ClothingBackpackChameleon
|
||||
name: backpack
|
||||
description: You wear this on your back and put items into it.
|
||||
suffix: Chameleon
|
||||
components:
|
||||
- type: Tag
|
||||
tags: [] # ignore "WhitelistChameleon" tag
|
||||
- type: Sprite
|
||||
sprite: Clothing/Back/Backpacks/backpack.rsi
|
||||
netsync: false
|
||||
- type: Clothing
|
||||
sprite: Clothing/Back/Backpacks/backpack.rsi
|
||||
- type: ChameleonClothing
|
||||
slot: [back]
|
||||
default: ClothingBackpack
|
||||
- type: UserInterface
|
||||
interfaces:
|
||||
- key: enum.StorageUiKey.Key
|
||||
type: StorageBoundUserInterface
|
||||
- key: enum.ChameleonUiKey.Key
|
||||
type: ChameleonBoundUserInterface
|
||||
21
Resources/Prototypes/Entities/Clothing/Ears/specific.yml
Normal file
21
Resources/Prototypes/Entities/Clothing/Ears/specific.yml
Normal file
@@ -0,0 +1,21 @@
|
||||
- type: entity
|
||||
parent: ClothingHeadsetGrey
|
||||
id: ClothingHeadsetChameleon
|
||||
name: passenger headset
|
||||
description: An updated, modular intercom that fits over the head. Takes encryption keys.
|
||||
suffix: Chameleon
|
||||
components:
|
||||
- type: Tag
|
||||
tags: [] # ignore "WhitelistChameleon" tag
|
||||
- type: Sprite
|
||||
sprite: Clothing/Ears/Headsets/base.rsi
|
||||
netsync: false
|
||||
- type: Clothing
|
||||
sprite: Clothing/Ears/Headsets/base.rsi
|
||||
- type: ChameleonClothing
|
||||
slot: [ears]
|
||||
default: ClothingHeadsetGrey
|
||||
- type: UserInterface
|
||||
interfaces:
|
||||
- key: enum.ChameleonUiKey.Key
|
||||
type: ChameleonBoundUserInterface
|
||||
21
Resources/Prototypes/Entities/Clothing/Eyes/specific.yml
Normal file
21
Resources/Prototypes/Entities/Clothing/Eyes/specific.yml
Normal file
@@ -0,0 +1,21 @@
|
||||
- type: entity
|
||||
parent: ClothingEyesBase
|
||||
id: ClothingEyesChameleon # no flash immunity, sorry
|
||||
name: sun glasses
|
||||
description: Useful both for security and cargonia.
|
||||
suffix: Chameleon
|
||||
components:
|
||||
- type: Tag
|
||||
tags: [] # ignore "WhitelistChameleon" tag
|
||||
- type: Sprite
|
||||
sprite: Clothing/Eyes/Glasses/sunglasses.rsi
|
||||
netsync: false
|
||||
- type: Clothing
|
||||
sprite: Clothing/Eyes/Glasses/sunglasses.rsi
|
||||
- type: ChameleonClothing
|
||||
slot: [eyes]
|
||||
default: ClothingEyesGlassesSunglasses
|
||||
- type: UserInterface
|
||||
interfaces:
|
||||
- key: enum.ChameleonUiKey.Key
|
||||
type: ChameleonBoundUserInterface
|
||||
@@ -242,6 +242,8 @@
|
||||
name: black gloves #Intentionally named after regular gloves, they're meant to be sneaky.
|
||||
description: Seemingly regular black gloves. The fingertips are outfitted with nanotech that makes stealing a breeze.
|
||||
components:
|
||||
- type: Tag
|
||||
tags: [] # ignore "WhitelistChameleon" tag
|
||||
- type: Sprite
|
||||
sprite: Clothing/Hands/Gloves/Color/black.rsi
|
||||
- type: Clothing
|
||||
|
||||
24
Resources/Prototypes/Entities/Clothing/Hands/specific.yml
Normal file
24
Resources/Prototypes/Entities/Clothing/Hands/specific.yml
Normal file
@@ -0,0 +1,24 @@
|
||||
- type: entity
|
||||
parent: ClothingHandsBase
|
||||
id: ClothingHandsChameleon # doesn't protect from electricity or heat
|
||||
name: black gloves
|
||||
description: Regular black gloves that do not keep you from frying.
|
||||
suffix: Chameleon
|
||||
components:
|
||||
- type: Tag
|
||||
tags: [] # ignore "WhitelistChameleon" tag
|
||||
- type: Sprite
|
||||
sprite: Clothing/Hands/Gloves/Color/black.rsi
|
||||
netsync: false
|
||||
- type: Clothing
|
||||
sprite: Clothing/Hands/Gloves/Color/black.rsi
|
||||
- type: ChameleonClothing
|
||||
slot: [gloves]
|
||||
default: ClothingHandsGlovesColorBlack
|
||||
- type: Fiber
|
||||
fiberMaterial: fibers-chameleon
|
||||
- type: FingerprintMask
|
||||
- type: UserInterface
|
||||
interfaces:
|
||||
- key: enum.ChameleonUiKey.Key
|
||||
type: ChameleonBoundUserInterface
|
||||
@@ -11,6 +11,7 @@
|
||||
- type: Tag
|
||||
tags:
|
||||
- DroneUsable
|
||||
- WhitelistChameleon
|
||||
|
||||
- type: entity
|
||||
abstract: true
|
||||
@@ -22,6 +23,9 @@
|
||||
- HEAD
|
||||
- type: Sprite
|
||||
state: icon
|
||||
- type: Tag
|
||||
tags:
|
||||
- WhitelistChameleon
|
||||
|
||||
- type: entity
|
||||
abstract: true
|
||||
@@ -78,6 +82,7 @@
|
||||
- type: Tag
|
||||
tags:
|
||||
- HidesHair
|
||||
- WhitelistChameleon
|
||||
- type: DiseaseProtection
|
||||
protection: 0.05
|
||||
- type: IdentityBlocker
|
||||
@@ -116,6 +121,7 @@
|
||||
- type: Tag
|
||||
tags:
|
||||
- HidesHair
|
||||
- WhitelistChameleon
|
||||
- type: DiseaseProtection
|
||||
protection: 0.05
|
||||
- type: IdentityBlocker
|
||||
|
||||
@@ -37,6 +37,8 @@
|
||||
- type: PowerCellSlot
|
||||
cellSlot:
|
||||
startingItem: PowerCellMedium
|
||||
- type: Item
|
||||
heldPrefix: off
|
||||
- type: ContainerContainer
|
||||
containers:
|
||||
cell_slot: !type:ContainerSlot
|
||||
|
||||
@@ -255,6 +255,7 @@
|
||||
- type: Tag
|
||||
tags:
|
||||
- HidesHair
|
||||
- WhitelistChameleon
|
||||
|
||||
- type: entity
|
||||
parent: ClothingHeadBase
|
||||
|
||||
21
Resources/Prototypes/Entities/Clothing/Head/specific.yml
Normal file
21
Resources/Prototypes/Entities/Clothing/Head/specific.yml
Normal file
@@ -0,0 +1,21 @@
|
||||
- type: entity
|
||||
parent: ClothingHeadBase
|
||||
id: ClothingHeadHatChameleon
|
||||
name: beret
|
||||
description: A beret, an artists favorite headwear.
|
||||
suffix: Chameleon
|
||||
components:
|
||||
- type: Tag
|
||||
tags: [] # ignore "WhitelistChameleon" tag
|
||||
- type: Sprite
|
||||
sprite: Clothing/Head/Hats/beret.rsi
|
||||
netsync: false
|
||||
- type: Clothing
|
||||
sprite: Clothing/Head/Hats/beret.rsi
|
||||
- type: ChameleonClothing
|
||||
slot: [HEAD]
|
||||
default: ClothingHeadHatBeret
|
||||
- type: UserInterface
|
||||
interfaces:
|
||||
- key: enum.ChameleonUiKey.Key
|
||||
type: ChameleonBoundUserInterface
|
||||
21
Resources/Prototypes/Entities/Clothing/Masks/specific.yml
Normal file
21
Resources/Prototypes/Entities/Clothing/Masks/specific.yml
Normal file
@@ -0,0 +1,21 @@
|
||||
- type: entity
|
||||
parent: ClothingMaskBase
|
||||
id: ClothingMaskGasChameleon
|
||||
name: gas mask
|
||||
description: A face-covering mask that can be connected to an air supply.
|
||||
suffix: Chameleon
|
||||
components:
|
||||
- type: Tag
|
||||
tags: [] # ignore "WhitelistChameleon" tag
|
||||
- type: Sprite
|
||||
sprite: Clothing/Mask/gas.rsi
|
||||
netsync: false
|
||||
- type: Clothing
|
||||
sprite: Clothing/Mask/gas.rsi
|
||||
- type: ChameleonClothing
|
||||
slot: [mask]
|
||||
default: ClothingMaskGas
|
||||
- type: UserInterface
|
||||
interfaces:
|
||||
- key: enum.ChameleonUiKey.Key
|
||||
type: ChameleonBoundUserInterface
|
||||
21
Resources/Prototypes/Entities/Clothing/Neck/specific.yml
Normal file
21
Resources/Prototypes/Entities/Clothing/Neck/specific.yml
Normal file
@@ -0,0 +1,21 @@
|
||||
- type: entity
|
||||
parent: ClothingNeckBase
|
||||
id: ClothingNeckChameleon
|
||||
name: striped red scarf
|
||||
description: A stylish striped red scarf. The perfect winter accessory for those with a keen fashion sense, and those who just can't handle a cold breeze on their necks.
|
||||
suffix: Chameleon
|
||||
components:
|
||||
- type: Tag
|
||||
tags: [] # ignore "WhitelistChameleon" tag
|
||||
- type: Sprite
|
||||
sprite: Clothing/Neck/Scarfs/red.rsi
|
||||
netsync: false
|
||||
- type: Clothing
|
||||
sprite: Clothing/Neck/Scarfs/red.rsi
|
||||
- type: ChameleonClothing
|
||||
slot: [neck]
|
||||
default: ClothingNeckScarfStripedRed
|
||||
- type: UserInterface
|
||||
interfaces:
|
||||
- key: enum.ChameleonUiKey.Key
|
||||
type: ChameleonBoundUserInterface
|
||||
@@ -0,0 +1,21 @@
|
||||
- type: entity
|
||||
parent: ClothingOuterBase
|
||||
id: ClothingOuterChameleon
|
||||
name: vest
|
||||
description: A thick vest with a rubbery, water-resistant shell.
|
||||
suffix: Chameleon
|
||||
components:
|
||||
- type: Tag
|
||||
tags: [] # ignore "WhitelistChameleon" tag
|
||||
- type: Sprite
|
||||
sprite: Clothing/OuterClothing/Vests/vest.rsi
|
||||
netsync: false
|
||||
- type: Clothing
|
||||
sprite: Clothing/OuterClothing/Vests/vest.rsi
|
||||
- type: ChameleonClothing
|
||||
slot: [outerClothing]
|
||||
default: ClothingOuterVest
|
||||
- type: UserInterface
|
||||
interfaces:
|
||||
- key: enum.ChameleonUiKey.Key
|
||||
type: ChameleonBoundUserInterface
|
||||
@@ -101,10 +101,32 @@
|
||||
sprite: Clothing/Shoes/Specific/wizard.rsi
|
||||
|
||||
- type: entity
|
||||
parent: ClothingShoesColorBlack
|
||||
parent: ClothingShoesBase
|
||||
id: ClothingShoesChameleon
|
||||
name: black shoes
|
||||
suffix: Chameleon
|
||||
description: Stylish black shoes.
|
||||
components:
|
||||
- type: Tag
|
||||
tags: [] # ignore "WhitelistChameleon" tag
|
||||
- type: Sprite
|
||||
sprite: Clothing/Shoes/Color/black.rsi
|
||||
netsync: false
|
||||
- type: Clothing
|
||||
sprite: Clothing/Shoes/Color/black.rsi
|
||||
- type: ChameleonClothing
|
||||
slot: [FEET]
|
||||
default: ClothingShoesColorBlack
|
||||
- type: UserInterface
|
||||
interfaces:
|
||||
- key: enum.ChameleonUiKey.Key
|
||||
type: ChameleonBoundUserInterface
|
||||
|
||||
- type: entity
|
||||
parent: ClothingShoesChameleon
|
||||
id: ClothingShoesChameleonNoSlips
|
||||
name: black shoes #actual name and description in uplink_catalog.yml
|
||||
suffix: no-slip
|
||||
suffix: No-slip, Chameleon
|
||||
description: Stylish black shoes.
|
||||
components:
|
||||
- type: NoSlip
|
||||
|
||||
24
Resources/Prototypes/Entities/Clothing/Uniforms/specific.yml
Normal file
24
Resources/Prototypes/Entities/Clothing/Uniforms/specific.yml
Normal file
@@ -0,0 +1,24 @@
|
||||
- type: entity
|
||||
parent: ClothingUniformBase
|
||||
id: ClothingUniformJumpsuitChameleon
|
||||
name: black jumpsuit
|
||||
description: A generic black jumpsuit with no rank markings.
|
||||
suffix: Chameleon
|
||||
components:
|
||||
- type: Tag
|
||||
tags: [] # ignore "WhitelistChameleon" tag
|
||||
- type: Sprite
|
||||
sprite: Clothing/Uniforms/Jumpsuit/Color/black.rsi
|
||||
netsync: false
|
||||
- type: Clothing
|
||||
sprite: Clothing/Uniforms/Jumpsuit/Color/black.rsi
|
||||
- type: SuitSensor
|
||||
randomMode: false
|
||||
mode: SensorOff
|
||||
- type: ChameleonClothing
|
||||
slot: [innerclothing]
|
||||
default: ClothingUniformJumpsuitColorBlack
|
||||
- type: UserInterface
|
||||
interfaces:
|
||||
- key: enum.ChameleonUiKey.Key
|
||||
type: ChameleonBoundUserInterface
|
||||
@@ -5,3 +5,6 @@
|
||||
components:
|
||||
- type: Sprite
|
||||
netsync: false
|
||||
- type: Tag
|
||||
tags:
|
||||
- WhitelistChameleon
|
||||
|
||||
@@ -195,6 +195,9 @@
|
||||
- type: Tag
|
||||
id: FireAxe
|
||||
|
||||
- type: Tag
|
||||
id: WhitelistChameleon
|
||||
|
||||
- type: Tag
|
||||
id: FirelockElectronics
|
||||
|
||||
|
||||
Reference in New Issue
Block a user