Clothing/item ECS & cleanup (#9706)

This commit is contained in:
Kara
2022-07-27 03:53:47 -07:00
committed by GitHub
parent 0f0420eca9
commit 258ec0cac1
164 changed files with 938 additions and 918 deletions

View File

@@ -1,18 +1,15 @@
using Content.Client.Items.Components; using Content.Shared.Clothing.Components;
using Content.Shared.Item;
using Robust.Shared.GameStates; using Robust.Shared.GameStates;
namespace Content.Client.Clothing namespace Content.Client.Clothing
{ {
[RegisterComponent] [RegisterComponent]
[ComponentReference(typeof(SharedItemComponent))] [ComponentReference(typeof(SharedClothingComponent))]
[ComponentReference(typeof(ItemComponent))] public sealed class ClothingComponent : SharedClothingComponent
[NetworkedComponent()]
public sealed class ClothingComponent : ItemComponent
{ {
[ViewVariables(VVAccess.ReadWrite)] [ViewVariables(VVAccess.ReadWrite)]
[DataField("femaleMask")] [DataField("femaleMask")]
public FemaleClothingMask FemaleMask { get; } = FemaleClothingMask.UniformFull; public FemaleClothingMask FemaleMask = FemaleClothingMask.UniformFull;
public string? InSlot; public string? InSlot;
} }

View File

@@ -4,6 +4,7 @@ using System.Linq;
using Content.Client.Inventory; using Content.Client.Inventory;
using Content.Shared.CharacterAppearance; using Content.Shared.CharacterAppearance;
using Content.Shared.Clothing; using Content.Shared.Clothing;
using Content.Shared.Clothing.Components;
using Content.Shared.Inventory; using Content.Shared.Inventory;
using Content.Shared.Inventory.Events; using Content.Shared.Inventory.Events;
using Content.Shared.Item; using Content.Shared.Item;
@@ -16,7 +17,7 @@ using static Robust.Shared.GameObjects.SharedSpriteComponent;
namespace Content.Client.Clothing; namespace Content.Client.Clothing;
public sealed class ClothingSystem : EntitySystem public sealed class ClothingVisualsSystem : EntitySystem
{ {
/// <summary> /// <summary>
/// This is a shitty hotfix written by me (Paul) to save me from renaming all files. /// This is a shitty hotfix written by me (Paul) to save me from renaming all files.
@@ -52,13 +53,13 @@ public sealed class ClothingSystem : EntitySystem
SubscribeLocalEvent<ClothingComponent, GotEquippedEvent>(OnGotEquipped); SubscribeLocalEvent<ClothingComponent, GotEquippedEvent>(OnGotEquipped);
SubscribeLocalEvent<ClothingComponent, GotUnequippedEvent>(OnGotUnequipped); SubscribeLocalEvent<ClothingComponent, GotUnequippedEvent>(OnGotUnequipped);
SubscribeLocalEvent<SharedItemComponent, GetEquipmentVisualsEvent>(OnGetVisuals); SubscribeLocalEvent<ClothingComponent, GetEquipmentVisualsEvent>(OnGetVisuals);
SubscribeLocalEvent<ClientInventoryComponent, VisualsChangedEvent>(OnVisualsChanged); SubscribeLocalEvent<ClientInventoryComponent, VisualsChangedEvent>(OnVisualsChanged);
SubscribeLocalEvent<SpriteComponent, DidUnequipEvent>(OnDidUnequip); SubscribeLocalEvent<SpriteComponent, DidUnequipEvent>(OnDidUnequip);
} }
private void OnGetVisuals(EntityUid uid, SharedItemComponent item, GetEquipmentVisualsEvent args) private void OnGetVisuals(EntityUid uid, ClothingComponent item, GetEquipmentVisualsEvent args)
{ {
if (!TryComp(args.Equipee, out ClientInventoryComponent? inventory)) if (!TryComp(args.Equipee, out ClientInventoryComponent? inventory))
return; return;
@@ -99,15 +100,15 @@ public sealed class ClothingSystem : EntitySystem
/// <remarks> /// <remarks>
/// Useful for lazily adding clothing sprites without modifying yaml. And for backwards compatibility. /// Useful for lazily adding clothing sprites without modifying yaml. And for backwards compatibility.
/// </remarks> /// </remarks>
private bool TryGetDefaultVisuals(EntityUid uid, SharedItemComponent item, string slot, string? speciesId, private bool TryGetDefaultVisuals(EntityUid uid, ClothingComponent clothing, string slot, string? speciesId,
[NotNullWhen(true)] out List<PrototypeLayerData>? layers) [NotNullWhen(true)] out List<PrototypeLayerData>? layers)
{ {
layers = null; layers = null;
RSI? rsi = null; RSI? rsi = null;
if (item.RsiPath != null) if (clothing.RsiPath != null)
rsi = _cache.GetResource<RSIResource>(TextureRoot / item.RsiPath).RSI; rsi = _cache.GetResource<RSIResource>(TextureRoot / clothing.RsiPath).RSI;
else if (TryComp(uid, out SpriteComponent? sprite)) else if (TryComp(uid, out SpriteComponent? sprite))
rsi = sprite.BaseRSI; rsi = sprite.BaseRSI;
@@ -117,9 +118,9 @@ public sealed class ClothingSystem : EntitySystem
var correctedSlot = slot; var correctedSlot = slot;
TemporarySlotMap.TryGetValue(correctedSlot, out correctedSlot); TemporarySlotMap.TryGetValue(correctedSlot, out correctedSlot);
var state = (item.EquippedPrefix == null) var state = (clothing.EquippedPrefix == null)
? $"equipped-{correctedSlot}" ? $"equipped-{correctedSlot}"
: $"{item.EquippedPrefix}-equipped-{correctedSlot}"; : $"{clothing.EquippedPrefix}-equipped-{correctedSlot}";
// species specific // species specific
if (speciesId != null && rsi.TryGetState($"{state}-{speciesId}", out _)) if (speciesId != null && rsi.TryGetState($"{state}-{speciesId}", out _))

View File

@@ -36,7 +36,7 @@ namespace Content.Client.Inventory
[Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IConfigurationManager _config = default!; [Dependency] private readonly IConfigurationManager _config = default!;
[Dependency] private readonly IItemSlotManager _itemSlotManager = default!; [Dependency] private readonly IItemSlotManager _itemSlotManager = default!;
[Dependency] private readonly ClothingSystem _clothingSystem = default!; [Dependency] private readonly ClothingVisualsSystem _clothingVisualsSystem = default!;
public const int ButtonSize = 64; public const int ButtonSize = 64;
private const int ButtonSeparation = 4; private const int ButtonSeparation = 4;
@@ -165,7 +165,7 @@ namespace Content.Client.Inventory
private void OnInit(EntityUid uid, ClientInventoryComponent component, ComponentInit args) private void OnInit(EntityUid uid, ClientInventoryComponent component, ComponentInit args)
{ {
_clothingSystem.InitClothing(uid, component); _clothingVisualsSystem.InitClothing(uid, component);
if (!TryGetUIElements(uid, out var window, out var bottomLeft, out var bottomRight, out var topQuick, if (!TryGetUIElements(uid, out var window, out var bottomLeft, out var bottomRight, out var topQuick,
component)) component))

View File

@@ -1,11 +0,0 @@
using Content.Shared.Item;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
namespace Content.Client.Items.Components
{
[RegisterComponent]
[ComponentReference(typeof(SharedItemComponent))]
[Virtual]
public class ItemComponent : SharedItemComponent { }
}

View File

@@ -1,11 +1,11 @@
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Content.Shared.Hands; using Content.Shared.Hands;
using Content.Shared.Item; using Content.Shared.Item;
using Robust.Client.GameObjects; using Robust.Client.GameObjects;
using Robust.Client.Graphics; using Robust.Client.Graphics;
using Robust.Client.ResourceManagement; using Robust.Client.ResourceManagement;
using Robust.Shared.Containers; using Robust.Shared.Containers;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using static Robust.Shared.GameObjects.SharedSpriteComponent; using static Robust.Shared.GameObjects.SharedSpriteComponent;
namespace Content.Client.Items.Systems; namespace Content.Client.Items.Systems;
@@ -19,18 +19,16 @@ public sealed class ItemSystem : SharedItemSystem
{ {
base.Initialize(); base.Initialize();
SubscribeLocalEvent<SharedItemComponent, GetInhandVisualsEvent>(OnGetVisuals); SubscribeLocalEvent<ItemComponent, GetInhandVisualsEvent>(OnGetVisuals);
} }
#region InhandVisuals #region InhandVisuals
/// <summary> /// <summary>
/// When an items visual state changes, notify and entities that are holding this item that their sprite may need updating. /// When an items visual state changes, notify and entities that are holding this item that their sprite may need updating.
/// </summary> /// </summary>
public override void VisualsChanged(EntityUid uid, SharedItemComponent? item = null) public override void VisualsChanged(EntityUid uid)
{ {
if (!Resolve(uid, ref item, false))
return;
// if the item is in a container, it might be equipped to hands or inventory slots --> update visuals. // if the item is in a container, it might be equipped to hands or inventory slots --> update visuals.
if (_containerSystem.TryGetContainingContainer(uid, out var container)) if (_containerSystem.TryGetContainingContainer(uid, out var container))
RaiseLocalEvent(container.Owner, new VisualsChangedEvent(uid, container.ID), true); RaiseLocalEvent(container.Owner, new VisualsChangedEvent(uid, container.ID), true);
@@ -39,12 +37,12 @@ public sealed class ItemSystem : SharedItemSystem
/// <summary> /// <summary>
/// An entity holding this item is requesting visual information for in-hand sprites. /// An entity holding this item is requesting visual information for in-hand sprites.
/// </summary> /// </summary>
private void OnGetVisuals(EntityUid uid, SharedItemComponent item, GetInhandVisualsEvent args) private void OnGetVisuals(EntityUid uid, ItemComponent item, GetInhandVisualsEvent args)
{ {
var defaultKey = $"inhand-{args.Location.ToString().ToLowerInvariant()}"; var defaultKey = $"inhand-{args.Location.ToString().ToLowerInvariant()}";
// try get explicit visuals // try get explicit visuals
if (item.InhandVisuals == null || !item.InhandVisuals.TryGetValue(args.Location, out var layers)) if (!item.InhandVisuals.TryGetValue(args.Location, out var layers))
{ {
// get defaults // get defaults
if (!TryGetDefaultVisuals(uid, item, defaultKey, out layers)) if (!TryGetDefaultVisuals(uid, item, defaultKey, out layers))
@@ -71,7 +69,7 @@ public sealed class ItemSystem : SharedItemSystem
/// <remarks> /// <remarks>
/// Useful for lazily adding in-hand sprites without modifying yaml. And backwards compatibility. /// Useful for lazily adding in-hand sprites without modifying yaml. And backwards compatibility.
/// </remarks> /// </remarks>
private bool TryGetDefaultVisuals(EntityUid uid, SharedItemComponent item, string defaultKey, [NotNullWhen(true)] out List<PrototypeLayerData>? result) private bool TryGetDefaultVisuals(EntityUid uid, ItemComponent item, string defaultKey, [NotNullWhen(true)] out List<PrototypeLayerData>? result)
{ {
result = null; result = null;
@@ -85,9 +83,9 @@ public sealed class ItemSystem : SharedItemSystem
if (rsi == null || rsi.Path == null) if (rsi == null || rsi.Path == null)
return false; return false;
var state = (item.EquippedPrefix == null) var state = (item.HeldPrefix == null)
? defaultKey ? defaultKey
: $"{item.EquippedPrefix}-{defaultKey}"; : $"{item.HeldPrefix}-{defaultKey}";
if (!rsi.TryGetState(state, out var _)) if (!rsi.TryGetState(state, out var _))
return false; return false;

View File

@@ -30,10 +30,9 @@ public sealed class HandheldLightSystem : EntitySystem
// really hand-held lights should be using a separate unshaded layer. (see FlashlightVisualizer) // 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. // this prefix stuff is largely for backwards compatibility with RSIs/yamls that have not been updated.
if (component.AddPrefix && TryComp(uid, out SharedItemComponent? item)) if (component.AddPrefix && TryComp(uid, out ItemComponent? item))
{ {
item.EquippedPrefix = state.Activated ? "on" : "off"; _itemSys.SetHeldPrefix(uid, state.Activated ? "on" : "off", item);
_itemSys.VisualsChanged(uid);
} }
} }
} }

View File

@@ -1,4 +1,5 @@
using Content.Client.Clothing; using Content.Client.Clothing;
using Content.Shared.Clothing.EntitySystems;
using Content.Shared.Movement.Components; using Content.Shared.Movement.Components;
using Content.Shared.Movement.Systems; using Content.Shared.Movement.Systems;
using Content.Shared.Weapons.Ranged.Systems; using Content.Shared.Weapons.Ranged.Systems;
@@ -14,6 +15,7 @@ public sealed class JetpackSystem : SharedJetpackSystem
{ {
[Dependency] private readonly IGameTiming _timing = default!; [Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly IMapManager _mapManager = default!; [Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly ClothingSystem _clothing = default!;
public override void Initialize() public override void Initialize()
{ {
@@ -35,7 +37,7 @@ public sealed class JetpackSystem : SharedJetpackSystem
args.Sprite?.LayerSetState(0, state); args.Sprite?.LayerSetState(0, state);
if (TryComp<ClothingComponent>(uid, out var clothing)) if (TryComp<ClothingComponent>(uid, out var clothing))
clothing.EquippedPrefix = enabled ? "on" : null; _clothing.SetEquippedPrefix(uid, enabled ? "on" : null, clothing);
} }
public override void Update(float frameTime) public override void Update(float frameTime)

View File

@@ -4,6 +4,7 @@ using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls; using Robust.Client.UserInterface.CustomControls;
using Content.Client.Items.Components; using Content.Client.Items.Components;
using Content.Client.UserInterface.Controls; using Content.Client.UserInterface.Controls;
using Content.Shared.Item;
using Robust.Client.UserInterface; using Robust.Client.UserInterface;
using static Robust.Client.UserInterface.Controls.BoxContainer; using static Robust.Client.UserInterface.Controls.BoxContainer;
using static Content.Shared.Storage.SharedStorageComponent; using static Content.Shared.Storage.SharedStorageComponent;

View File

@@ -18,7 +18,7 @@ public sealed class ToggleableLightVisualsSystem : VisualizerSystem<ToggleableLi
{ {
base.Initialize(); base.Initialize();
SubscribeLocalEvent<ToggleableLightVisualsComponent, GetInhandVisualsEvent>(OnGetHeldVisuals, after: new[] { typeof(ItemSystem) }); SubscribeLocalEvent<ToggleableLightVisualsComponent, GetInhandVisualsEvent>(OnGetHeldVisuals, after: new[] { typeof(ItemSystem) });
SubscribeLocalEvent<ToggleableLightVisualsComponent, GetEquipmentVisualsEvent>(OnGetEquipmentVisuals, after: new[] { typeof(ClothingSystem) }); SubscribeLocalEvent<ToggleableLightVisualsComponent, GetEquipmentVisualsEvent>(OnGetEquipmentVisuals, after: new[] { typeof(ClothingVisualsSystem) });
} }
protected override void OnAppearanceChange(EntityUid uid, ToggleableLightVisualsComponent component, ref AppearanceChangeEvent args) protected override void OnAppearanceChange(EntityUid uid, ToggleableLightVisualsComponent component, ref AppearanceChangeEvent args)

View File

@@ -2,6 +2,7 @@
using Content.Server.Clothing.Components; using Content.Server.Clothing.Components;
using Content.Server.Inventory; using Content.Server.Inventory;
using Content.Shared.Inventory; using Content.Shared.Inventory;
using Content.Shared.Item;
using NUnit.Framework; using NUnit.Framework;
using Robust.Shared.Containers; using Robust.Shared.Containers;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
@@ -35,8 +36,8 @@ namespace Content.IntegrationTests.Tests
entMgr.AddComponent<ContainerManagerComponent>(container); entMgr.AddComponent<ContainerManagerComponent>(container);
var child = entMgr.SpawnEntity(null, MapCoordinates.Nullspace); var child = entMgr.SpawnEntity(null, MapCoordinates.Nullspace);
var item = entMgr.AddComponent<ItemComponent>(child); var item = entMgr.AddComponent<ClothingComponent>(child);
item.SlotFlags = SlotFlags.HEAD; item.Slots = SlotFlags.HEAD;
// Equip item. // Equip item.
Assert.That(invSystem.TryEquip(container, child, "head"), Is.True); Assert.That(invSystem.TryEquip(container, child, "head"), Is.True);

View File

@@ -26,7 +26,8 @@ namespace Content.IntegrationTests.Tests
id: UniformDummy id: UniformDummy
components: components:
- type: Clothing - type: Clothing
Slots: [innerclothing] slots: [innerclothing]
- type: Item
size: 5 size: 5
- type: entity - type: entity
@@ -34,8 +35,9 @@ namespace Content.IntegrationTests.Tests
id: IDCardDummy id: IDCardDummy
components: components:
- type: Clothing - type: Clothing
Slots: slots:
- idcard - idcard
- type: Item
size: 5 size: 5
- type: IdCard - type: IdCard

View File

@@ -5,6 +5,7 @@ using Content.Server.Interaction;
using Content.Shared.Hands.Components; using Content.Shared.Hands.Components;
using Content.Shared.Hands.EntitySystems; using Content.Shared.Hands.EntitySystems;
using Content.Shared.Interaction; using Content.Shared.Interaction;
using Content.Shared.Item;
using Content.Shared.Weapons.Melee; using Content.Shared.Weapons.Melee;
using NUnit.Framework; using NUnit.Framework;
using Robust.Shared.Containers; using Robust.Shared.Containers;
@@ -13,7 +14,6 @@ using Robust.Shared.IoC;
using Robust.Shared.Map; using Robust.Shared.Map;
using Robust.Shared.Maths; using Robust.Shared.Maths;
using Robust.Shared.Reflection; using Robust.Shared.Reflection;
using ItemComponent = Content.Server.Clothing.Components.ItemComponent;
namespace Content.IntegrationTests.Tests.Interaction.Click namespace Content.IntegrationTests.Tests.Interaction.Click
{ {

View File

@@ -28,7 +28,7 @@ namespace Content.IntegrationTests.Tests
id: InventoryJumpsuitJanitorDummy id: InventoryJumpsuitJanitorDummy
components: components:
- type: Clothing - type: Clothing
Slots: [innerclothing] slots: [innerclothing]
- type: entity - type: entity
name: InventoryIDCardDummy name: InventoryIDCardDummy
@@ -36,7 +36,7 @@ namespace Content.IntegrationTests.Tests
components: components:
- type: Clothing - type: Clothing
QuickEquip: false QuickEquip: false
Slots: slots:
- idcard - idcard
- type: PDA - type: PDA
"; ";

View File

@@ -25,7 +25,7 @@ namespace Content.Server.AI.Operators.Inventory
var handsSys = sysMan.GetEntitySystem<SharedHandsSystem>(); var handsSys = sysMan.GetEntitySystem<SharedHandsSystem>();
if (entMan.Deleted(_target) if (entMan.Deleted(_target)
|| !entMan.HasComponent<SharedItemComponent>(_target) || !entMan.HasComponent<ItemComponent>(_target)
|| _target.IsInContainer() || _target.IsInContainer()
|| !interactionSystem.InRangeUnobstructed(_owner, _target, popup: true)) || !interactionSystem.InRangeUnobstructed(_owner, _target, popup: true))
{ {
@@ -35,7 +35,7 @@ namespace Content.Server.AI.Operators.Inventory
// select empty hand // select empty hand
if (!handsSys.TrySelectEmptyHand(_owner)) if (!handsSys.TrySelectEmptyHand(_owner))
return Outcome.Failed; return Outcome.Failed;
interactionSystem.InteractHand(_owner, _target); interactionSystem.InteractHand(_owner, _target);
return Outcome.Success; return Outcome.Success;
} }

View File

@@ -29,7 +29,7 @@ namespace Content.Server.AI.Utility.Considerations.Clothing
continue; continue;
} }
if ((clothingComponent.SlotFlags & slotDef.SlotFlags) != 0) if ((clothingComponent.Slots & slotDef.SlotFlags) != 0)
{ {
return 1.0f; return 1.0f;
} }

View File

@@ -14,7 +14,7 @@ namespace Content.Server.AI.Utility.Considerations.Inventory
// If not then check if we have a free hand // If not then check if we have a free hand
var target = context.GetState<TargetEntityState>().GetValue(); var target = context.GetState<TargetEntityState>().GetValue();
if (target == null || !IoCManager.Resolve<IEntityManager>().HasComponent<SharedItemComponent>(target)) if (target == null || !IoCManager.Resolve<IEntityManager>().HasComponent<ItemComponent>(target))
{ {
return 0.0f; return 0.0f;
} }

View File

@@ -11,7 +11,7 @@ namespace Content.Server.AI.Utility.Considerations.Inventory
{ {
var target = context.GetState<TargetEntityState>().GetValue(); var target = context.GetState<TargetEntityState>().GetValue();
if (target == null || !IoCManager.Resolve<IEntityManager>().HasComponent<SharedItemComponent>(target)) if (target == null || !IoCManager.Resolve<IEntityManager>().HasComponent<ItemComponent>(target))
{ {
return 0.0f; return 0.0f;
} }

View File

@@ -35,7 +35,7 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Gloves
foreach (var entity in context.GetState<EnumerableInventoryState>().GetValue()) foreach (var entity in context.GetState<EnumerableInventoryState>().GetValue())
{ {
if (IoCManager.Resolve<IEntityManager>().TryGetComponent(entity, out ClothingComponent? clothing) && if (IoCManager.Resolve<IEntityManager>().TryGetComponent(entity, out ClothingComponent? clothing) &&
(clothing.SlotFlags & SlotFlags.GLOVES) != 0) (clothing.Slots & SlotFlags.GLOVES) != 0)
{ {
yield return new EquipGloves {Owner = owner, Target = entity, Bonus = Bonus}; yield return new EquipGloves {Owner = owner, Target = entity, Bonus = Bonus};
} }

View File

@@ -33,7 +33,7 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Gloves
foreach (var entity in context.GetState<NearbyClothingState>().GetValue()) foreach (var entity in context.GetState<NearbyClothingState>().GetValue())
{ {
if (IoCManager.Resolve<IEntityManager>().TryGetComponent(entity, out ClothingComponent? clothing) && if (IoCManager.Resolve<IEntityManager>().TryGetComponent(entity, out ClothingComponent? clothing) &&
(clothing.SlotFlags & SlotFlags.GLOVES) != 0) (clothing.Slots & SlotFlags.GLOVES) != 0)
{ {
yield return new PickUpGloves {Owner = owner, Target = entity, Bonus = Bonus}; yield return new PickUpGloves {Owner = owner, Target = entity, Bonus = Bonus};
} }

View File

@@ -34,7 +34,7 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Head
foreach (var entity in context.GetState<EnumerableInventoryState>().GetValue()) foreach (var entity in context.GetState<EnumerableInventoryState>().GetValue())
{ {
if (IoCManager.Resolve<IEntityManager>().TryGetComponent(entity, out ClothingComponent? clothing) && if (IoCManager.Resolve<IEntityManager>().TryGetComponent(entity, out ClothingComponent? clothing) &&
(clothing.SlotFlags & SlotFlags.HEAD) != 0) (clothing.Slots & SlotFlags.HEAD) != 0)
{ {
yield return new EquipHead {Owner = owner, Target = entity, Bonus = Bonus}; yield return new EquipHead {Owner = owner, Target = entity, Bonus = Bonus};
} }

View File

@@ -33,7 +33,7 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Head
foreach (var entity in context.GetState<NearbyClothingState>().GetValue()) foreach (var entity in context.GetState<NearbyClothingState>().GetValue())
{ {
if (IoCManager.Resolve<IEntityManager>().TryGetComponent(entity, out ClothingComponent? clothing) && if (IoCManager.Resolve<IEntityManager>().TryGetComponent(entity, out ClothingComponent? clothing) &&
(clothing.SlotFlags & SlotFlags.HEAD) != 0) (clothing.Slots & SlotFlags.HEAD) != 0)
{ {
yield return new PickUpHead {Owner = owner, Target = entity, Bonus = Bonus}; yield return new PickUpHead {Owner = owner, Target = entity, Bonus = Bonus};
} }

View File

@@ -35,7 +35,7 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.OuterClothing
foreach (var entity in context.GetState<EnumerableInventoryState>().GetValue()) foreach (var entity in context.GetState<EnumerableInventoryState>().GetValue())
{ {
if (IoCManager.Resolve<IEntityManager>().TryGetComponent(entity, out ClothingComponent? clothing) && if (IoCManager.Resolve<IEntityManager>().TryGetComponent(entity, out ClothingComponent? clothing) &&
(clothing.SlotFlags & SlotFlags.OUTERCLOTHING) != 0) (clothing.Slots & SlotFlags.OUTERCLOTHING) != 0)
{ {
yield return new EquipOuterClothing {Owner = owner, Target = entity, Bonus = Bonus}; yield return new EquipOuterClothing {Owner = owner, Target = entity, Bonus = Bonus};
} }

View File

@@ -34,7 +34,7 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.OuterClothing
foreach (var entity in context.GetState<NearbyClothingState>().GetValue()) foreach (var entity in context.GetState<NearbyClothingState>().GetValue())
{ {
if (IoCManager.Resolve<IEntityManager>().TryGetComponent(entity, out ClothingComponent? clothing) && if (IoCManager.Resolve<IEntityManager>().TryGetComponent(entity, out ClothingComponent? clothing) &&
(clothing.SlotFlags & SlotFlags.OUTERCLOTHING) != 0) (clothing.Slots & SlotFlags.OUTERCLOTHING) != 0)
{ {
yield return new PickUpOuterClothing {Owner = owner, Target = entity, Bonus = Bonus}; yield return new PickUpOuterClothing {Owner = owner, Target = entity, Bonus = Bonus};
} }

View File

@@ -35,7 +35,7 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Shoes
foreach (var entity in context.GetState<EnumerableInventoryState>().GetValue()) foreach (var entity in context.GetState<EnumerableInventoryState>().GetValue())
{ {
if (IoCManager.Resolve<IEntityManager>().TryGetComponent(entity, out ClothingComponent? clothing) && if (IoCManager.Resolve<IEntityManager>().TryGetComponent(entity, out ClothingComponent? clothing) &&
(clothing.SlotFlags & SlotFlags.FEET) != 0) (clothing.Slots & SlotFlags.FEET) != 0)
{ {
yield return new EquipShoes {Owner = owner, Target = entity, Bonus = Bonus}; yield return new EquipShoes {Owner = owner, Target = entity, Bonus = Bonus};
} }

View File

@@ -34,7 +34,7 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Shoes
foreach (var entity in context.GetState<NearbyClothingState>().GetValue()) foreach (var entity in context.GetState<NearbyClothingState>().GetValue())
{ {
if (IoCManager.Resolve<IEntityManager>().TryGetComponent(entity, out ClothingComponent? clothing) && if (IoCManager.Resolve<IEntityManager>().TryGetComponent(entity, out ClothingComponent? clothing) &&
(clothing.SlotFlags & SlotFlags.FEET) != 0) (clothing.Slots & SlotFlags.FEET) != 0)
{ {
yield return new PickUpShoes {Owner = owner, Target = entity, Bonus = Bonus}; yield return new PickUpShoes {Owner = owner, Target = entity, Bonus = Bonus};
} }

View File

@@ -82,7 +82,7 @@ namespace Content.Server.Chat
return; return;
} }
var itemQuery = GetEntityQuery<SharedItemComponent>(); var itemQuery = GetEntityQuery<ItemComponent>();
// Suicide by nearby entity (ex: Microwave) // Suicide by nearby entity (ex: Microwave)
foreach (var entity in _entityLookupSystem.GetEntitiesInRange(victim, 1, LookupFlags.Approximate | LookupFlags.Anchored)) foreach (var entity in _entityLookupSystem.GetEntitiesInRange(victim, 1, LookupFlags.Approximate | LookupFlags.Anchored))

View File

@@ -1,22 +1,13 @@
using Content.Shared.Clothing.Components;
using Content.Shared.Item; using Content.Shared.Item;
using Robust.Shared.GameStates; using Robust.Shared.GameStates;
namespace Content.Server.Clothing.Components namespace Content.Server.Clothing.Components
{ {
// Needed for client-side clothing component.
[RegisterComponent] [RegisterComponent]
[ComponentReference(typeof(SharedItemComponent))] [ComponentReference(typeof(SharedClothingComponent))]
[Virtual] public sealed class ClothingComponent : SharedClothingComponent
public class ItemComponent : SharedItemComponent{}
[RegisterComponent]
[NetworkedComponent]
[ComponentReference(typeof(SharedItemComponent))]
public sealed class ClothingComponent : ItemComponent
{ {
[DataField("HeatResistance")]
private int _heatResistance = 323;
[ViewVariables(VVAccess.ReadWrite)]
public int HeatResistance => _heatResistance;
} }
} }

View File

@@ -0,0 +1,12 @@
namespace Content.Server.Clothing.Components;
/// <summary>
/// TODO this needs removed somehow.
/// Handles 'heat resistance' for gloves touching bulbs and that's it, ick.
/// </summary>
[RegisterComponent]
public sealed class GloveHeatResistanceComponent : Component
{
[DataField("heatResistance")]
public int HeatResistance = 323;
}

View File

@@ -1,7 +1,11 @@
using Content.Server.Atmos.Components; using Content.Server.Atmos.Components;
using Content.Server.Clothing.Components;
using Content.Shared.Alert; using Content.Shared.Alert;
using Content.Shared.Clothing; using Content.Shared.Clothing;
using Content.Shared.Clothing.EntitySystems;
using Content.Shared.Inventory;
using Content.Shared.Inventory.Events; using Content.Shared.Inventory.Events;
using Robust.Shared.Containers;
using Robust.Shared.GameStates; using Robust.Shared.GameStates;
using static Content.Shared.Clothing.MagbootsComponent; using static Content.Shared.Clothing.MagbootsComponent;

View File

@@ -13,6 +13,7 @@ using Content.Server.Disease.Components;
using Content.Server.IdentityManagement; using Content.Server.IdentityManagement;
using Content.Server.Nutrition.EntitySystems; using Content.Server.Nutrition.EntitySystems;
using Content.Server.Popups; using Content.Server.Popups;
using Content.Shared.Clothing.EntitySystems;
using Content.Shared.IdentityManagement.Components; using Content.Shared.IdentityManagement.Components;
using Robust.Shared.Player; using Robust.Shared.Player;
@@ -26,6 +27,7 @@ namespace Content.Server.Clothing
[Dependency] private readonly InventorySystem _inventorySystem = default!; [Dependency] private readonly InventorySystem _inventorySystem = default!;
[Dependency] private readonly PopupSystem _popupSystem = default!; [Dependency] private readonly PopupSystem _popupSystem = default!;
[Dependency] private readonly IdentitySystem _identity = default!; [Dependency] private readonly IdentitySystem _identity = default!;
[Dependency] private readonly ClothingSystem _clothing = default!;
public override void Initialize() public override void Initialize()
{ {
@@ -79,11 +81,10 @@ namespace Content.Server.Clothing
private void ToggleMaskComponents(EntityUid uid, MaskComponent mask, EntityUid wearer, bool isEquip = false) private void ToggleMaskComponents(EntityUid uid, MaskComponent mask, EntityUid wearer, bool isEquip = false)
{ {
//toggle visuals //toggle visuals
if (TryComp<SharedItemComponent>(mask.Owner, out var item)) if (TryComp<ClothingComponent>(mask.Owner, out var clothing))
{ {
//TODO: sprites for 'pulled down' state. defaults to invisible due to no sprite with this prefix //TODO: sprites for 'pulled down' state. defaults to invisible due to no sprite with this prefix
item.EquippedPrefix = mask.IsToggled ? "toggled" : null; _clothing.SetEquippedPrefix(uid, mask.IsToggled ? "toggled" : null, clothing);
Dirty(item);
} }
// toggle ingestion blocking // toggle ingestion blocking

View File

@@ -68,7 +68,7 @@ namespace Content.Server.Conveyor
public bool CanRun(ConveyorComponent component) public bool CanRun(ConveyorComponent component)
{ {
return component.State != ConveyorState.Off && return component.State != ConveyorState.Off &&
!EntityManager.HasComponent<SharedItemComponent>(component.Owner) && !EntityManager.HasComponent<ItemComponent>(component.Owner) &&
this.IsPowered(component.Owner, EntityManager); this.IsPowered(component.Owner, EntityManager);
} }
} }

View File

@@ -199,7 +199,7 @@ namespace Content.Server.Disease
if (!TryComp<ClothingComponent>(uid, out var clothing)) if (!TryComp<ClothingComponent>(uid, out var clothing))
return; return;
// Is the clothing in its actual slot? // Is the clothing in its actual slot?
if (!clothing.SlotFlags.HasFlag(args.SlotFlags)) if (!clothing.Slots.HasFlag(args.SlotFlags))
return; return;
// Give the user the component's disease resist // Give the user the component's disease resist
if(TryComp<DiseaseCarrierComponent>(args.Equipee, out var carrier)) if(TryComp<DiseaseCarrierComponent>(args.Equipee, out var carrier))

View File

@@ -73,7 +73,7 @@ namespace Content.Server.Disposal.Unit.Components
return false; return false;
} }
return _entMan.HasComponent<SharedItemComponent>(entity) || return _entMan.HasComponent<ItemComponent>(entity) ||
_entMan.HasComponent<SharedBodyComponent>(entity); _entMan.HasComponent<SharedBodyComponent>(entity);
} }

View File

@@ -455,7 +455,7 @@ namespace Content.Server.Disposal.Unit.EntitySystems
{ {
// TODO: We need to use a specific collision method (which sloth hasn't coded yet) for actual bounds overlaps. // TODO: We need to use a specific collision method (which sloth hasn't coded yet) for actual bounds overlaps.
// Check for itemcomp as we won't just block the disposal unit "sleeping" for something it can't collide with anyway. // Check for itemcomp as we won't just block the disposal unit "sleeping" for something it can't collide with anyway.
if (!EntityManager.HasComponent<SharedItemComponent>(uid) && body.GetWorldAABB().Intersects(disposalsBounds!.Value)) continue; if (!EntityManager.HasComponent<ItemComponent>(uid) && body.GetWorldAABB().Intersects(disposalsBounds!.Value)) continue;
component.RecentlyEjected.RemoveAt(i); component.RecentlyEjected.RemoveAt(i);
} }
} }

View File

@@ -58,7 +58,7 @@ namespace Content.Server.Drone
if (args.Target != null && !HasComp<UnremoveableComponent>(args.Target) && NonDronesInRange(uid, component)) if (args.Target != null && !HasComp<UnremoveableComponent>(args.Target) && NonDronesInRange(uid, component))
args.Cancel(); args.Cancel();
if (HasComp<SharedItemComponent>(args.Target) && !HasComp<UnremoveableComponent>(args.Target)) if (HasComp<ItemComponent>(args.Target) && !HasComp<UnremoveableComponent>(args.Target))
{ {
if (!_tagSystem.HasAnyTag(args.Target.Value, "DroneUsable", "Trash")) if (!_tagSystem.HasAnyTag(args.Target.Value, "DroneUsable", "Trash"))
args.Cancel(); args.Cancel();

View File

@@ -56,7 +56,7 @@ public sealed class SpillableSystem : EntitySystem
// check if entity was actually used as clothing // check if entity was actually used as clothing
// not just taken in pockets or something // not just taken in pockets or something
var isCorrectSlot = clothing.SlotFlags.HasFlag(args.SlotFlags); var isCorrectSlot = clothing.Slots.HasFlag(args.SlotFlags);
if (!isCorrectSlot) return; if (!isCorrectSlot) return;
if (!_solutionContainerSystem.TryGetSolution(uid, component.SolutionName, out var solution)) if (!_solutionContainerSystem.TryGetSolution(uid, component.SolutionName, out var solution))

View File

@@ -252,7 +252,7 @@ namespace Content.Server.Interaction
} }
} }
} }
else if (!wideAttack && target != null && HasComp<SharedItemComponent>(target.Value)) else if (!wideAttack && target != null && HasComp<ItemComponent>(target.Value))
{ {
// We pick up items if our hand is empty, even if we're in combat mode. // We pick up items if our hand is empty, even if we're in combat mode.
InteractHand(user, target.Value); InteractHand(user, target.Value);

View File

@@ -1,8 +1,7 @@
using Content.Shared.Item; using Content.Shared.Item;
namespace Content.Server.Item; namespace Content.Server.Item;
public sealed class ItemSystem : SharedItemSystem public sealed class ItemSystem : SharedItemSystem
{ {
// Ello Guvna
} }

View File

@@ -107,7 +107,7 @@ namespace Content.Server.Kitchen.EntitySystems
return; return;
} }
if (!HasComp<SharedItemComponent>(args.Used)) if (!HasComp<ItemComponent>(args.Used))
{ {
_popupSystem.PopupEntity(Loc.GetString("microwave-component-interact-using-transfer-fail"), uid, Filter.Entities(args.User)); _popupSystem.PopupEntity(Loc.GetString("microwave-component-interact-using-transfer-fail"), uid, Filter.Entities(args.User));
return; return;

View File

@@ -1,5 +1,6 @@
using Content.Server.Clothing.Components; using Content.Server.Clothing.Components;
using Content.Server.Light.Components; using Content.Server.Light.Components;
using Content.Shared.Clothing.EntitySystems;
using Content.Shared.Interaction.Events; using Content.Shared.Interaction.Events;
using Content.Shared.Item; using Content.Shared.Item;
using Content.Shared.Light.Component; using Content.Shared.Light.Component;
@@ -14,6 +15,9 @@ namespace Content.Server.Light.EntitySystems
[UsedImplicitly] [UsedImplicitly]
public sealed class ExpendableLightSystem : EntitySystem public sealed class ExpendableLightSystem : EntitySystem
{ {
[Dependency] private readonly SharedItemSystem _item = default!;
[Dependency] private readonly ClothingSystem _clothing = default!;
public override void Initialize() public override void Initialize()
{ {
base.Initialize(); base.Initialize();
@@ -59,9 +63,9 @@ namespace Content.Server.Light.EntitySystems
UpdateSpriteAndSounds(component); UpdateSpriteAndSounds(component);
UpdateVisualizer(component); UpdateVisualizer(component);
if (TryComp<SharedItemComponent>(component.Owner, out var item)) if (TryComp<ItemComponent>(component.Owner, out var item))
{ {
item.EquippedPrefix = "unlit"; _item.SetHeldPrefix(component.Owner, "unlit", item);
} }
break; break;
@@ -76,9 +80,9 @@ namespace Content.Server.Light.EntitySystems
{ {
if (!component.Activated && component.CurrentState == ExpendableLightState.BrandNew) if (!component.Activated && component.CurrentState == ExpendableLightState.BrandNew)
{ {
if (TryComp<SharedItemComponent>(component.Owner, out var item)) if (TryComp<ItemComponent>(component.Owner, out var item))
{ {
item.EquippedPrefix = "lit"; _item.SetHeldPrefix(component.Owner, "lit", item);
} }
component.CurrentState = ExpendableLightState.Lit; component.CurrentState = ExpendableLightState.Lit;
@@ -154,15 +158,15 @@ namespace Content.Server.Light.EntitySystems
if (TryComp<ClothingComponent>(component.Owner, out var clothing)) if (TryComp<ClothingComponent>(component.Owner, out var clothing))
{ {
clothing.EquippedPrefix = component.Activated ? "Activated" : string.Empty; _clothing.SetEquippedPrefix(component.Owner, component.Activated ? "Activated" : string.Empty, clothing);
} }
} }
private void OnExpLightInit(EntityUid uid, ExpendableLightComponent component, ComponentInit args) private void OnExpLightInit(EntityUid uid, ExpendableLightComponent component, ComponentInit args)
{ {
if (TryComp<SharedItemComponent?>(uid, out var item)) if (TryComp<ItemComponent?>(uid, out var item))
{ {
item.EquippedPrefix = "unlit"; _item.SetHeldPrefix(uid, "unlit", item);
} }
component.CurrentState = ExpendableLightState.BrandNew; component.CurrentState = ExpendableLightState.BrandNew;

View File

@@ -16,6 +16,7 @@ namespace Content.Server.Light.EntitySystems
private HashSet<MatchstickComponent> _litMatches = new(); private HashSet<MatchstickComponent> _litMatches = new();
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!; [Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
[Dependency] private readonly TransformSystem _transformSystem = default!; [Dependency] private readonly TransformSystem _transformSystem = default!;
[Dependency] private readonly SharedItemSystem _item = default!;
public override void Initialize() public override void Initialize()
{ {
@@ -94,15 +95,15 @@ namespace Content.Server.Light.EntitySystems
pointLightComponent.Enabled = component.CurrentState == SmokableState.Lit; pointLightComponent.Enabled = component.CurrentState == SmokableState.Lit;
} }
if (EntityManager.TryGetComponent(component.Owner, out SharedItemComponent? item)) if (EntityManager.TryGetComponent(component.Owner, out ItemComponent? item))
{ {
switch (component.CurrentState) switch (component.CurrentState)
{ {
case SmokableState.Lit: case SmokableState.Lit:
item.EquippedPrefix = "lit"; _item.SetHeldPrefix(component.Owner, "lit", item);
break; break;
default: default:
item.EquippedPrefix = "unlit"; _item.SetHeldPrefix(component.Owner, "unlit", item);
break; break;
} }
} }

View File

@@ -41,7 +41,7 @@ namespace Content.Server.Medical
if (!TryComp<ClothingComponent>(uid, out var clothing)) if (!TryComp<ClothingComponent>(uid, out var clothing))
return; return;
// Is the clothing in its actual slot? // Is the clothing in its actual slot?
if (!clothing.SlotFlags.HasFlag(args.SlotFlags)) if (!clothing.Slots.HasFlag(args.SlotFlags))
return; return;
component.IsActive = true; component.IsActive = true;

View File

@@ -7,6 +7,7 @@ using Content.Server.Clothing.Components;
using Content.Server.Nutrition.Components; using Content.Server.Nutrition.Components;
using Content.Shared.Chemistry; using Content.Shared.Chemistry;
using Content.Shared.Chemistry.Reagent; using Content.Shared.Chemistry.Reagent;
using Content.Shared.Clothing.EntitySystems;
using Content.Shared.FixedPoint; using Content.Shared.FixedPoint;
using Content.Shared.Inventory; using Content.Shared.Inventory;
using Content.Shared.Smoking; using Content.Shared.Smoking;
@@ -24,6 +25,8 @@ namespace Content.Server.Nutrition.EntitySystems
[Dependency] private readonly AtmosphereSystem _atmos = default!; [Dependency] private readonly AtmosphereSystem _atmos = default!;
[Dependency] private readonly TransformSystem _transformSystem = default!; [Dependency] private readonly TransformSystem _transformSystem = default!;
[Dependency] private readonly InventorySystem _inventorySystem = default!; [Dependency] private readonly InventorySystem _inventorySystem = default!;
[Dependency] private readonly ClothingSystem _clothing = default!;
private const float UpdateTimer = 3f; private const float UpdateTimer = 3f;
private float _timer = 0f; private float _timer = 0f;
@@ -50,13 +53,15 @@ namespace Content.Server.Nutrition.EntitySystems
smokable.State = state; smokable.State = state;
appearance.SetData(SmokingVisuals.Smoking, state); appearance.SetData(SmokingVisuals.Smoking, state);
clothing.EquippedPrefix = state switch var newState = state switch
{ {
SmokableState.Lit => smokable.LitPrefix, SmokableState.Lit => smokable.LitPrefix,
SmokableState.Burnt => smokable.BurntPrefix, SmokableState.Burnt => smokable.BurntPrefix,
_ => smokable.UnlitPrefix _ => smokable.UnlitPrefix
}; };
_clothing.SetEquippedPrefix(uid, newState, clothing);
if (state == SmokableState.Lit) if (state == SmokableState.Lit)
_active.Add(uid); _active.Add(uid);
else else

View File

@@ -134,7 +134,7 @@ namespace Content.Server.PneumaticCannon
// this overrides the ServerStorageComponent's insertion stuff because // this overrides the ServerStorageComponent's insertion stuff because
// it's not event-based yet and I can't cancel it, so tools and stuff // it's not event-based yet and I can't cancel it, so tools and stuff
// will modify mode/power then get put in anyway // will modify mode/power then get put in anyway
if (EntityManager.TryGetComponent<SharedItemComponent?>(args.Used, out var item) if (EntityManager.TryGetComponent<ItemComponent?>(args.Used, out var item)
&& EntityManager.TryGetComponent<ServerStorageComponent?>(component.Owner, out var storage)) && EntityManager.TryGetComponent<ServerStorageComponent?>(component.Owner, out var storage))
{ {
if (_storageSystem.CanInsert(component.Owner, args.Used, out _, storage)) if (_storageSystem.CanInsert(component.Owner, args.Used, out _, storage))

View File

@@ -22,7 +22,7 @@ public sealed class AddAccentClothingSystem : EntitySystem
// check if entity was actually used as clothing // check if entity was actually used as clothing
// not just taken in pockets or something // not just taken in pockets or something
var isCorrectSlot = clothing.SlotFlags.HasFlag(args.SlotFlags); var isCorrectSlot = clothing.Slots.HasFlag(args.SlotFlags);
if (!isCorrectSlot) return; if (!isCorrectSlot) return;
// does the user already has this accent? // does the user already has this accent?

View File

@@ -305,10 +305,10 @@ public sealed class EntityStorageSystem : EntitySystem
return false; return false;
var targetIsMob = HasComp<SharedBodyComponent>(toInsert); var targetIsMob = HasComp<SharedBodyComponent>(toInsert);
var storageIsItem = HasComp<SharedItemComponent>(container); var storageIsItem = HasComp<ItemComponent>(container);
var allowedToEat = whitelist == null var allowedToEat = whitelist == null
? HasComp<SharedItemComponent>(toInsert) ? HasComp<ItemComponent>(toInsert)
: whitelist.IsValid(toInsert); : whitelist.IsValid(toInsert);
// BEFORE REPLACING THIS WITH, I.E. A PROPERTY: // BEFORE REPLACING THIS WITH, I.E. A PROPERTY:

View File

@@ -54,7 +54,7 @@ namespace Content.Server.Storage.EntitySystems
/// </summary> /// </summary>
/// <returns>True if item was hidden inside stash</returns> /// <returns>True if item was hidden inside stash</returns>
public bool TryHideItem(EntityUid uid, EntityUid userUid, EntityUid itemToHideUid, public bool TryHideItem(EntityUid uid, EntityUid userUid, EntityUid itemToHideUid,
SecretStashComponent? component = null, SharedItemComponent? item = null, SecretStashComponent? component = null, ItemComponent? item = null,
MetaDataComponent? itemMeta = null, SharedHandsComponent? hands = null) MetaDataComponent? itemMeta = null, SharedHandsComponent? hands = null)
{ {
if (!Resolve(uid, ref component)) if (!Resolve(uid, ref component))

View File

@@ -236,13 +236,13 @@ namespace Content.Server.Storage.EntitySystems
// Pick up all entities in a radius around the clicked location. // Pick up all entities in a radius around the clicked location.
// The last half of the if is because carpets exist and this is terrible // The last half of the if is because carpets exist and this is terrible
if (storageComp.AreaInsert && (eventArgs.Target == null || !HasComp<SharedItemComponent>(eventArgs.Target.Value))) if (storageComp.AreaInsert && (eventArgs.Target == null || !HasComp<ItemComponent>(eventArgs.Target.Value)))
{ {
var validStorables = new List<EntityUid>(); var validStorables = new List<EntityUid>();
foreach (var entity in _entityLookupSystem.GetEntitiesInRange(eventArgs.ClickLocation, storageComp.AreaInsertRadius, LookupFlags.None)) foreach (var entity in _entityLookupSystem.GetEntitiesInRange(eventArgs.ClickLocation, storageComp.AreaInsertRadius, LookupFlags.None))
{ {
if (entity == eventArgs.User if (entity == eventArgs.User
|| !HasComp<SharedItemComponent>(entity) || !HasComp<ItemComponent>(entity)
|| !_interactionSystem.InRangeUnobstructed(eventArgs.User, entity)) || !_interactionSystem.InRangeUnobstructed(eventArgs.User, entity))
continue; continue;
@@ -272,7 +272,7 @@ namespace Content.Server.Storage.EntitySystems
// Check again, situation may have changed for some entities, but we'll still pick up any that are valid // Check again, situation may have changed for some entities, but we'll still pick up any that are valid
if (_containerSystem.IsEntityInContainer(entity) if (_containerSystem.IsEntityInContainer(entity)
|| entity == eventArgs.User || entity == eventArgs.User
|| !HasComp<SharedItemComponent>(entity)) || !HasComp<ItemComponent>(entity))
continue; continue;
if (TryComp<TransformComponent>(uid, out var transformOwner) && TryComp<TransformComponent>(entity, out var transformEnt)) if (TryComp<TransformComponent>(uid, out var transformOwner) && TryComp<TransformComponent>(entity, out var transformEnt))
@@ -304,7 +304,7 @@ namespace Content.Server.Storage.EntitySystems
if (_containerSystem.IsEntityInContainer(target) if (_containerSystem.IsEntityInContainer(target)
|| target == eventArgs.User || target == eventArgs.User
|| !HasComp<SharedItemComponent>(target)) || !HasComp<ItemComponent>(target))
return; return;
if (TryComp<TransformComponent>(uid, out var transformOwner) && TryComp<TransformComponent>(target, out var transformEnt)) if (TryComp<TransformComponent>(uid, out var transformOwner) && TryComp<TransformComponent>(target, out var transformEnt))
@@ -432,7 +432,7 @@ namespace Content.Server.Storage.EntitySystems
if (storageComp.Storage == null) if (storageComp.Storage == null)
return; return;
var itemQuery = GetEntityQuery<SharedItemComponent>(); var itemQuery = GetEntityQuery<ItemComponent>();
foreach (var entity in storageComp.Storage.ContainedEntities) foreach (var entity in storageComp.Storage.ContainedEntities)
{ {
@@ -491,7 +491,7 @@ namespace Content.Server.Storage.EntitySystems
return false; return false;
} }
if (TryComp(insertEnt, out SharedItemComponent? itemComp) && if (TryComp(insertEnt, out ItemComponent? itemComp) &&
itemComp.Size > storageComp.StorageCapacityMax - storageComp.StorageUsed) itemComp.Size > storageComp.StorageCapacityMax - storageComp.StorageUsed)
{ {
reason = "comp-storage-insufficient-capacity"; reason = "comp-storage-insufficient-capacity";

View File

@@ -24,6 +24,8 @@ namespace Content.Server.Stunnable.Systems
{ {
public sealed class StunbatonSystem : EntitySystem public sealed class StunbatonSystem : EntitySystem
{ {
[Dependency] private readonly SharedItemSystem _item = default!;
public override void Initialize() public override void Initialize()
{ {
base.Initialize(); base.Initialize();
@@ -88,11 +90,12 @@ namespace Content.Server.Stunnable.Systems
if (!comp.Activated) if (!comp.Activated)
return; return;
if (TryComp<SharedItemComponent>(comp.Owner, out var item)) if (TryComp<AppearanceComponent>(comp.Owner, out var appearance) &&
item.EquippedPrefix = "off"; TryComp<ItemComponent>(comp.Owner, out var item))
{
if (TryComp(comp.Owner, out AppearanceComponent? appearance)) _item.SetHeldPrefix(comp.Owner, "off", item);
appearance.SetData(ToggleVisuals.Toggled, false); appearance.SetData(ToggleVisuals.Toggled, false);
}
SoundSystem.Play(comp.SparksSound.GetSound(), Filter.Pvs(comp.Owner), comp.Owner, AudioHelpers.WithVariation(0.25f)); SoundSystem.Play(comp.SparksSound.GetSound(), Filter.Pvs(comp.Owner), comp.Owner, AudioHelpers.WithVariation(0.25f));
@@ -112,12 +115,12 @@ namespace Content.Server.Stunnable.Systems
return; return;
} }
if (EntityManager.TryGetComponent<AppearanceComponent>(comp.Owner, out var appearance) &&
if (TryComp<SharedItemComponent>(comp.Owner, out var item)) EntityManager.TryGetComponent<ItemComponent>(comp.Owner, out var item))
item.EquippedPrefix = "on"; {
_item.SetHeldPrefix(comp.Owner, "on", item);
if (TryComp(comp.Owner, out AppearanceComponent? appearance))
appearance.SetData(ToggleVisuals.Toggled, true); appearance.SetData(ToggleVisuals.Toggled, true);
}
SoundSystem.Play(comp.SparksSound.GetSound(), playerFilter, comp.Owner, AudioHelpers.WithVariation(0.25f)); SoundSystem.Play(comp.SparksSound.GetSound(), playerFilter, comp.Owner, AudioHelpers.WithVariation(0.25f));
comp.Activated = true; comp.Activated = true;

View File

@@ -11,7 +11,7 @@ namespace Content.Server.Temperature.Components
// TODO: When making into system: Any animal that touches bulb that has no // TODO: When making into system: Any animal that touches bulb that has no
// InventoryComponent but still would have default heat resistance in the future (maybe) // InventoryComponent but still would have default heat resistance in the future (maybe)
if (EntitySystem.Get<InventorySystem>().TryGetSlotEntity(Owner, "gloves", out var slotEntity) && if (EntitySystem.Get<InventorySystem>().TryGetSlotEntity(Owner, "gloves", out var slotEntity) &&
IoCManager.Resolve<IEntityManager>().TryGetComponent<ClothingComponent>(slotEntity, out var gloves)) IoCManager.Resolve<IEntityManager>().TryGetComponent<GloveHeatResistanceComponent>(slotEntity, out var gloves))
{ {
return gloves.HeatResistance; return gloves.HeatResistance;
} }

View File

@@ -59,7 +59,7 @@ namespace Content.Server.Tools
public bool TryToggleWelder(EntityUid uid, EntityUid? user, public bool TryToggleWelder(EntityUid uid, EntityUid? user,
WelderComponent? welder = null, WelderComponent? welder = null,
SolutionContainerManagerComponent? solutionContainer = null, SolutionContainerManagerComponent? solutionContainer = null,
SharedItemComponent? item = null, ItemComponent? item = null,
PointLightComponent? light = null, PointLightComponent? light = null,
AppearanceComponent? appearance = null) AppearanceComponent? appearance = null)
{ {
@@ -76,7 +76,7 @@ namespace Content.Server.Tools
public bool TryTurnWelderOn(EntityUid uid, EntityUid? user, public bool TryTurnWelderOn(EntityUid uid, EntityUid? user,
WelderComponent? welder = null, WelderComponent? welder = null,
SolutionContainerManagerComponent? solutionContainer = null, SolutionContainerManagerComponent? solutionContainer = null,
SharedItemComponent? item = null, ItemComponent? item = null,
PointLightComponent? light = null, PointLightComponent? light = null,
AppearanceComponent? appearance = null, AppearanceComponent? appearance = null,
TransformComponent? transform = null) TransformComponent? transform = null)
@@ -105,7 +105,7 @@ namespace Content.Server.Tools
welder.Lit = true; welder.Lit = true;
if(item != null) if(item != null)
item.EquippedPrefix = "on"; _itemSystem.SetHeldPrefix(uid, "on", item);
appearance?.SetData(WelderVisuals.Lit, true); appearance?.SetData(WelderVisuals.Lit, true);
@@ -128,7 +128,7 @@ namespace Content.Server.Tools
public bool TryTurnWelderOff(EntityUid uid, EntityUid? user, public bool TryTurnWelderOff(EntityUid uid, EntityUid? user,
WelderComponent? welder = null, WelderComponent? welder = null,
SharedItemComponent? item = null, ItemComponent? item = null,
PointLightComponent? light = null, PointLightComponent? light = null,
AppearanceComponent? appearance = null) AppearanceComponent? appearance = null)
{ {
@@ -142,7 +142,7 @@ namespace Content.Server.Tools
// TODO: Make all this use visualizers. // TODO: Make all this use visualizers.
if (item != null) if (item != null)
item.EquippedPrefix = "off"; _itemSystem.SetHeldPrefix(uid, "off", item);
// Layer 1 is the flame. // Layer 1 is the flame.
appearance?.SetData(WelderVisuals.Lit, false); appearance?.SetData(WelderVisuals.Lit, false);

View File

@@ -5,6 +5,7 @@ using Content.Server.Chemistry.EntitySystems;
using Content.Server.DoAfter; using Content.Server.DoAfter;
using Content.Server.Popups; using Content.Server.Popups;
using Content.Shared.Audio; using Content.Shared.Audio;
using Content.Shared.Item;
using Content.Shared.Tools.Components; using Content.Shared.Tools.Components;
using Robust.Server.GameObjects; using Robust.Server.GameObjects;
using Robust.Shared.Audio; using Robust.Shared.Audio;
@@ -25,7 +26,7 @@ namespace Content.Server.Tools
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!; [Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
[Dependency] private readonly PopupSystem _popupSystem = default!; [Dependency] private readonly PopupSystem _popupSystem = default!;
[Dependency] private readonly TransformSystem _transformSystem = default!; [Dependency] private readonly TransformSystem _transformSystem = default!;
[Dependency] private readonly SharedItemSystem _itemSystem = default!;
public override void Initialize() public override void Initialize()
{ {

View File

@@ -19,6 +19,7 @@ namespace Content.Server.Weapon.Melee.EnergySword
{ {
[Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly SharedRgbLightControllerSystem _rgbSystem = default!; [Dependency] private readonly SharedRgbLightControllerSystem _rgbSystem = default!;
[Dependency] private readonly SharedItemSystem _item = default!;
public override void Initialize() public override void Initialize()
{ {
@@ -67,9 +68,9 @@ namespace Content.Server.Weapon.Melee.EnergySword
if (!comp.Activated) if (!comp.Activated)
return; return;
if (TryComp(comp.Owner, out SharedItemComponent? item)) if (TryComp(comp.Owner, out ItemComponent? item))
{ {
item.Size = 5; _item.SetSize(comp.Owner, 5, item);
} }
if (TryComp<DisarmMalusComponent>(comp.Owner, out var malus)) if (TryComp<DisarmMalusComponent>(comp.Owner, out var malus))
@@ -92,9 +93,9 @@ namespace Content.Server.Weapon.Melee.EnergySword
if (comp.Activated) if (comp.Activated)
return; return;
if (TryComp(comp.Owner, out SharedItemComponent? item)) if (TryComp(comp.Owner, out ItemComponent? item))
{ {
item.Size = 9999; _item.SetSize(comp.Owner, 9999, item);
} }
EnsureComp<SharpComponent>(comp.Owner); EnsureComp<SharpComponent>(comp.Owner);

View File

@@ -22,6 +22,7 @@ namespace Content.Server.Wieldable
[Dependency] private readonly DoAfterSystem _doAfter = default!; [Dependency] private readonly DoAfterSystem _doAfter = default!;
[Dependency] private readonly HandVirtualItemSystem _virtualItemSystem = default!; [Dependency] private readonly HandVirtualItemSystem _virtualItemSystem = default!;
[Dependency] private readonly SharedHandsSystem _handsSystem = default!; [Dependency] private readonly SharedHandsSystem _handsSystem = default!;
[Dependency] private readonly SharedItemSystem _itemSystem = default!;
public override void Initialize() public override void Initialize()
{ {
@@ -167,10 +168,10 @@ namespace Content.Server.Wieldable
if (!CanWield(uid, component, args.User.Value) || component.Wielded) if (!CanWield(uid, component, args.User.Value) || component.Wielded)
return; return;
if (TryComp<SharedItemComponent>(uid, out var item)) if (TryComp<ItemComponent>(uid, out var item))
{ {
component.OldInhandPrefix = item.EquippedPrefix; component.OldInhandPrefix = item.HeldPrefix;
item.EquippedPrefix = component.WieldedInhandPrefix; _itemSystem.SetHeldPrefix(uid, component.WieldedInhandPrefix, item);
} }
component.Wielded = true; component.Wielded = true;
@@ -196,9 +197,9 @@ namespace Content.Server.Wieldable
if (!component.Wielded) if (!component.Wielded)
return; return;
if (TryComp<SharedItemComponent>(uid, out var item)) if (TryComp<ItemComponent>(uid, out var item))
{ {
item.EquippedPrefix = component.OldInhandPrefix; _itemSystem.SetHeldPrefix(uid, component.OldInhandPrefix, item);
} }
component.Wielded = false; component.Wielded = false;

View File

@@ -0,0 +1,53 @@
using Content.Shared.Clothing.EntitySystems;
using Content.Shared.Inventory;
using Content.Shared.Sound;
using Robust.Shared.GameStates;
using Robust.Shared.Serialization;
namespace Content.Shared.Clothing.Components;
/// <summary>
/// This handles entities which can be equipped.
/// </summary>
[NetworkedComponent]
public abstract class SharedClothingComponent : Component
{
[DataField("clothingVisuals")]
public Dictionary<string, List<SharedSpriteComponent.PrototypeLayerData>> ClothingVisuals = new();
[ViewVariables(VVAccess.ReadWrite)]
[DataField("quickEquip")]
public bool QuickEquip = true;
[ViewVariables(VVAccess.ReadWrite)]
[DataField("slots", required: true)]
public SlotFlags Slots = SlotFlags.NONE;
[ViewVariables(VVAccess.ReadWrite)]
[DataField("equipSound")]
public SoundSpecifier? EquipSound;
[ViewVariables(VVAccess.ReadWrite)]
[DataField("unequipSound")]
public SoundSpecifier? UnequipSound;
[Access(typeof(ClothingSystem))]
[ViewVariables(VVAccess.ReadWrite)]
[DataField("equippedPrefix")]
public string? EquippedPrefix;
[ViewVariables(VVAccess.ReadWrite)]
[DataField("sprite")]
public string? RsiPath;
}
[Serializable, NetSerializable]
public sealed class ClothingComponentState : ComponentState
{
public string? EquippedPrefix;
public ClothingComponentState(string? equippedPrefix)
{
EquippedPrefix = equippedPrefix;
}
}

View File

@@ -0,0 +1,39 @@
using Content.Shared.Clothing.Components;
using Robust.Shared.GameStates;
namespace Content.Shared.Clothing.EntitySystems;
public sealed class ClothingSystem : EntitySystem
{
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<SharedClothingComponent, ComponentGetState>(OnGetState);
SubscribeLocalEvent<SharedClothingComponent, ComponentHandleState>(OnHandleState);
}
private void OnGetState(EntityUid uid, SharedClothingComponent component, ref ComponentGetState args)
{
args.State = new ClothingComponentState(component.EquippedPrefix);
}
private void OnHandleState(EntityUid uid, SharedClothingComponent component, ref ComponentHandleState args)
{
if (args.Current is ClothingComponentState state)
component.EquippedPrefix = state.EquippedPrefix;
}
#region Public API
public void SetEquippedPrefix(EntityUid uid, string? prefix, SharedClothingComponent? clothing = null)
{
if (!Resolve(uid, ref clothing))
return;
clothing.EquippedPrefix = prefix;
Dirty(clothing);
}
#endregion
}

View File

@@ -1,4 +1,5 @@
using Content.Shared.Actions; using Content.Shared.Actions;
using Content.Shared.Clothing.EntitySystems;
using Content.Shared.Inventory; using Content.Shared.Inventory;
using Content.Shared.Item; using Content.Shared.Item;
using Content.Shared.Slippery; using Content.Shared.Slippery;
@@ -13,6 +14,8 @@ public abstract class SharedMagbootsSystem : EntitySystem
[Dependency] private readonly SharedActionsSystem _sharedActions = default!; [Dependency] private readonly SharedActionsSystem _sharedActions = default!;
[Dependency] private readonly ClothingSpeedModifierSystem _clothingSpeedModifier = default!; [Dependency] private readonly ClothingSpeedModifierSystem _clothingSpeedModifier = default!;
[Dependency] private readonly InventorySystem _inventory = default!; [Dependency] private readonly InventorySystem _inventory = default!;
[Dependency] private readonly SharedItemSystem _item = default!;
[Dependency] private readonly ClothingSystem _clothing = default!;
[Dependency] private readonly SharedContainerSystem _sharedContainer = default!; [Dependency] private readonly SharedContainerSystem _sharedContainer = default!;
public override void Initialize() public override void Initialize()
@@ -37,8 +40,11 @@ public abstract class SharedMagbootsSystem : EntitySystem
_inventory.TryGetSlotEntity(container.Owner, "shoes", out var entityUid) && entityUid == component.Owner) _inventory.TryGetSlotEntity(container.Owner, "shoes", out var entityUid) && entityUid == component.Owner)
UpdateMagbootEffects(container.Owner, uid, true, component); UpdateMagbootEffects(container.Owner, uid, true, component);
if (TryComp<SharedItemComponent>(uid, out var item)) if (TryComp<ItemComponent>(uid, out var item))
item.EquippedPrefix = component.On ? "on" : null; {
_item.SetHeldPrefix(uid, component.On ? "on" : null, item);
_clothing.SetEquippedPrefix(uid, component.On ? "on" : null);
}
if (TryComp(uid, out AppearanceComponent? appearance)) if (TryComp(uid, out AppearanceComponent? appearance))
appearance.SetData(ToggleVisuals.Toggled, component.On); appearance.SetData(ToggleVisuals.Toggled, component.On);

View File

@@ -33,7 +33,7 @@ namespace Content.Shared.Disposal
var otherBody = args.BodyB.Owner; var otherBody = args.BodyB.Owner;
// Items dropped shouldn't collide but items thrown should // Items dropped shouldn't collide but items thrown should
if (EntityManager.HasComponent<SharedItemComponent>(otherBody) && if (EntityManager.HasComponent<ItemComponent>(otherBody) &&
!EntityManager.HasComponent<ThrownItemComponent>(otherBody)) !EntityManager.HasComponent<ThrownItemComponent>(otherBody))
{ {
args.Cancel(); args.Cancel();
@@ -60,7 +60,7 @@ namespace Content.Shared.Disposal
return false; return false;
// TODO: Probably just need a disposable tag. // TODO: Probably just need a disposable tag.
if (!EntityManager.TryGetComponent(entity, out SharedItemComponent? storable) && if (!EntityManager.TryGetComponent(entity, out ItemComponent? storable) &&
!EntityManager.HasComponent<SharedBodyComponent>(entity)) !EntityManager.HasComponent<SharedBodyComponent>(entity))
{ {
return false; return false;

View File

@@ -1,3 +1,4 @@
using Content.Shared.Clothing.Components;
using Content.Shared.Inventory.Events; using Content.Shared.Inventory.Events;
using Content.Shared.Inventory; using Content.Shared.Inventory;
using Content.Shared.Item; using Content.Shared.Item;
@@ -16,10 +17,10 @@ namespace Content.Shared.Eye.Blinding
private void OnEquipped(EntityUid uid, BlindfoldComponent component, GotEquippedEvent args) private void OnEquipped(EntityUid uid, BlindfoldComponent component, GotEquippedEvent args)
{ {
if (!TryComp<SharedItemComponent>(uid, out var clothing) || clothing.SlotFlags == SlotFlags.PREVENTEQUIP) // we live in a society if (!TryComp<SharedClothingComponent>(uid, out var clothing) || clothing.Slots == SlotFlags.PREVENTEQUIP) // we live in a society
return; return;
// Is the clothing in its actual slot? // Is the clothing in its actual slot?
if (!clothing.SlotFlags.HasFlag(args.SlotFlags)) if (!clothing.Slots.HasFlag(args.SlotFlags))
return; return;
component.IsActive = true; component.IsActive = true;

View File

@@ -12,7 +12,7 @@ public abstract partial class SharedHandsSystem : EntitySystem
/// <summary> /// <summary>
/// Tries to pick up an entity to a specific hand. If no explicit hand is specified, defaults to using the currently active hand. /// Tries to pick up an entity to a specific hand. If no explicit hand is specified, defaults to using the currently active hand.
/// </summary> /// </summary>
public bool TryPickup(EntityUid uid, EntityUid entity, string? handName = null, bool checkActionBlocker = true, bool animateUser = false, SharedHandsComponent? handsComp = null, SharedItemComponent? item = null) public bool TryPickup(EntityUid uid, EntityUid entity, string? handName = null, bool checkActionBlocker = true, bool animateUser = false, SharedHandsComponent? handsComp = null, ItemComponent? item = null)
{ {
if (!Resolve(uid, ref handsComp, false)) if (!Resolve(uid, ref handsComp, false))
return false; return false;
@@ -34,7 +34,7 @@ public abstract partial class SharedHandsSystem : EntitySystem
/// If one empty hand fails to pick up the item, this will NOT check other hands. If ever hand-specific item /// If one empty hand fails to pick up the item, this will NOT check other hands. If ever hand-specific item
/// restrictions are added, there a might need to be a TryPickupAllHands or something like that. /// restrictions are added, there a might need to be a TryPickupAllHands or something like that.
/// </remarks> /// </remarks>
public bool TryPickupAnyHand(EntityUid uid, EntityUid entity, bool checkActionBlocker = true, bool animateUser = false, SharedHandsComponent? handsComp = null, SharedItemComponent? item = null) public bool TryPickupAnyHand(EntityUid uid, EntityUid entity, bool checkActionBlocker = true, bool animateUser = false, SharedHandsComponent? handsComp = null, ItemComponent? item = null)
{ {
if (!Resolve(uid, ref handsComp, false)) if (!Resolve(uid, ref handsComp, false))
return false; return false;
@@ -45,7 +45,7 @@ public abstract partial class SharedHandsSystem : EntitySystem
return TryPickup(uid, entity, hand, checkActionBlocker, animateUser, handsComp, item); return TryPickup(uid, entity, hand, checkActionBlocker, animateUser, handsComp, item);
} }
public bool TryPickup(EntityUid uid, EntityUid entity, Hand hand, bool checkActionBlocker = true, bool animateUser = false, SharedHandsComponent? handsComp = null, SharedItemComponent? item = null) public bool TryPickup(EntityUid uid, EntityUid entity, Hand hand, bool checkActionBlocker = true, bool animateUser = false, SharedHandsComponent? handsComp = null, ItemComponent? item = null)
{ {
if (!Resolve(uid, ref handsComp, false)) if (!Resolve(uid, ref handsComp, false))
return false; return false;
@@ -67,7 +67,7 @@ public abstract partial class SharedHandsSystem : EntitySystem
return true; return true;
} }
public bool CanPickupAnyHand(EntityUid uid, EntityUid entity, bool checkActionBlocker = true, SharedHandsComponent? handsComp = null, SharedItemComponent? item = null) public bool CanPickupAnyHand(EntityUid uid, EntityUid entity, bool checkActionBlocker = true, SharedHandsComponent? handsComp = null, ItemComponent? item = null)
{ {
if (!Resolve(uid, ref handsComp, false)) if (!Resolve(uid, ref handsComp, false))
return false; return false;
@@ -81,7 +81,7 @@ public abstract partial class SharedHandsSystem : EntitySystem
/// <summary> /// <summary>
/// Checks whether a given item will fit into a specific user's hand. Unless otherwise specified, this will also check the general CanPickup action blocker. /// Checks whether a given item will fit into a specific user's hand. Unless otherwise specified, this will also check the general CanPickup action blocker.
/// </summary> /// </summary>
public bool CanPickupToHand(EntityUid uid, EntityUid entity, Hand hand, bool checkActionBlocker = true, SharedHandsComponent? handsComp = null, SharedItemComponent? item = null) public bool CanPickupToHand(EntityUid uid, EntityUid entity, Hand hand, bool checkActionBlocker = true, SharedHandsComponent? handsComp = null, ItemComponent? item = null)
{ {
if (!Resolve(uid, ref handsComp, false)) if (!Resolve(uid, ref handsComp, false))
return false; return false;
@@ -90,7 +90,7 @@ public abstract partial class SharedHandsSystem : EntitySystem
if (handContainer == null || handContainer.ContainedEntity != null) if (handContainer == null || handContainer.ContainedEntity != null)
return false; return false;
if (!Resolve(entity, ref item, false) || !item.CanPickup) if (!Resolve(entity, ref item, false))
return false; return false;
if (TryComp(entity, out PhysicsComponent? physics) && physics.BodyType == BodyType.Static) if (TryComp(entity, out PhysicsComponent? physics) && physics.BodyType == BodyType.Static)
@@ -106,7 +106,7 @@ public abstract partial class SharedHandsSystem : EntitySystem
/// <summary> /// <summary>
/// Puts an item into any hand, preferring the active hand, or puts it on the floor. /// Puts an item into any hand, preferring the active hand, or puts it on the floor.
/// </summary> /// </summary>
public void PickupOrDrop(EntityUid? uid, EntityUid entity, bool checkActionBlocker = true, bool animateUser = false, SharedHandsComponent? handsComp = null, SharedItemComponent? item = null) public void PickupOrDrop(EntityUid? uid, EntityUid entity, bool checkActionBlocker = true, bool animateUser = false, SharedHandsComponent? handsComp = null, ItemComponent? item = null)
{ {
if (uid == null if (uid == null
|| !Resolve(uid.Value, ref handsComp, false) || !Resolve(uid.Value, ref handsComp, false)

View File

@@ -470,7 +470,7 @@ namespace Content.Shared.Interaction
bool ignoreAnchored = false; bool ignoreAnchored = false;
if (HasComp<SharedItemComponent>(target) && TryComp(target, out PhysicsComponent? physics) && physics.CanCollide) if (HasComp<ItemComponent>(target) && TryComp(target, out PhysicsComponent? physics) && physics.CanCollide)
{ {
// If the target is an item, we ignore any colliding entities. Currently done so that if items get stuck // If the target is an item, we ignore any colliding entities. Currently done so that if items get stuck
// inside of walls, users can still pick them up. // inside of walls, users can still pick them up.

View File

@@ -38,7 +38,7 @@ public abstract partial class InventorySystem
SubscribeAllEvent<UseSlotNetworkMessage>(OnUseSlot); SubscribeAllEvent<UseSlotNetworkMessage>(OnUseSlot);
} }
protected void QuickEquip(EntityUid uid, SharedItemComponent component, UseInHandEvent args) protected void QuickEquip(EntityUid uid, SharedClothingComponent component, UseInHandEvent args)
{ {
if (!TryComp(args.User, out InventoryComponent? inv) if (!TryComp(args.User, out InventoryComponent? inv)
|| !TryComp(args.User, out SharedHandsComponent? hands) || !TryComp(args.User, out SharedHandsComponent? hands)
@@ -53,7 +53,7 @@ public abstract partial class InventorySystem
if (TryGetSlotEntity(args.User, slotDef.Name, out var slotEntity, inv)) if (TryGetSlotEntity(args.User, slotDef.Name, out var slotEntity, inv))
{ {
// Item in slot has to be quick equipable as well // Item in slot has to be quick equipable as well
if (TryComp(slotEntity, out SharedItemComponent? item) && !item.QuickEquip) if (TryComp(slotEntity, out SharedClothingComponent? item) && !item.QuickEquip)
continue; continue;
if (!TryUnequip(args.User, slotDef.Name, true, inventory: inv)) if (!TryUnequip(args.User, slotDef.Name, true, inventory: inv))
@@ -157,19 +157,23 @@ public abstract partial class InventorySystem
} }
public bool TryEquip(EntityUid uid, EntityUid itemUid, string slot, bool silent = false, bool force = false, bool predicted = false, public bool TryEquip(EntityUid uid, EntityUid itemUid, string slot, bool silent = false, bool force = false, bool predicted = false,
InventoryComponent? inventory = null, SharedItemComponent? item = null) => InventoryComponent? inventory = null, SharedClothingComponent? clothing = null) =>
TryEquip(uid, uid, itemUid, slot, silent, force, predicted, inventory, item); TryEquip(uid, uid, itemUid, slot, silent, force, predicted, inventory, clothing);
public bool TryEquip(EntityUid actor, EntityUid target, EntityUid itemUid, string slot, bool silent = false, bool force = false, bool predicted = false, public bool TryEquip(EntityUid actor, EntityUid target, EntityUid itemUid, string slot, bool silent = false, bool force = false, bool predicted = false,
InventoryComponent? inventory = null, SharedItemComponent? item = null) InventoryComponent? inventory = null, SharedClothingComponent? clothing = null)
{ {
if (!Resolve(target, ref inventory, false) || !Resolve(itemUid, ref item, false)) if (!Resolve(target, ref inventory, false))
{ {
if(!silent && _gameTiming.IsFirstTimePredicted) if(!silent && _gameTiming.IsFirstTimePredicted)
_popup.PopupCursor(Loc.GetString("inventory-component-can-equip-cannot"), Filter.Local()); _popup.PopupCursor(Loc.GetString("inventory-component-can-equip-cannot"), Filter.Local());
return false; return false;
} }
// Not required to have, since pockets can take any item.
// CanEquip will still check, so we don't have to worry about it.
Resolve(itemUid, ref clothing, false);
if (!TryGetSlotContainer(target, slot, out var slotContainer, out var slotDefinition, inventory)) if (!TryGetSlotContainer(target, slot, out var slotContainer, out var slotDefinition, inventory))
{ {
if(!silent && _gameTiming.IsFirstTimePredicted) if(!silent && _gameTiming.IsFirstTimePredicted)
@@ -177,7 +181,7 @@ public abstract partial class InventorySystem
return false; return false;
} }
if (!force && !CanEquip(actor, target, itemUid, slot, out var reason, slotDefinition, inventory, item)) if (!force && !CanEquip(actor, target, itemUid, slot, out var reason, slotDefinition, inventory, clothing))
{ {
if(!silent && _gameTiming.IsFirstTimePredicted) if(!silent && _gameTiming.IsFirstTimePredicted)
_popup.PopupCursor(Loc.GetString(reason), Filter.Local()); _popup.PopupCursor(Loc.GetString(reason), Filter.Local());
@@ -191,7 +195,7 @@ public abstract partial class InventorySystem
return false; return false;
} }
if(!silent && item.EquipSound != null && _gameTiming.IsFirstTimePredicted) if(!silent && clothing != null && clothing.EquipSound != null && _gameTiming.IsFirstTimePredicted)
{ {
Filter filter; Filter filter;
@@ -206,7 +210,7 @@ public abstract partial class InventorySystem
filter.RemoveWhereAttachedEntity(entity => entity == actor); filter.RemoveWhereAttachedEntity(entity => entity == actor);
} }
SoundSystem.Play(item.EquipSound.GetSound(), filter, target, item.EquipSound.Params.WithVolume(-2f)); SoundSystem.Play(clothing.EquipSound.GetSound(), filter, target, clothing.EquipSound.Params.WithVolume(-2f));
} }
inventory.Dirty(); inventory.Dirty();
@@ -245,22 +249,27 @@ public abstract partial class InventorySystem
public bool CanEquip(EntityUid uid, EntityUid itemUid, string slot, [NotNullWhen(false)] out string? reason, public bool CanEquip(EntityUid uid, EntityUid itemUid, string slot, [NotNullWhen(false)] out string? reason,
SlotDefinition? slotDefinition = null, InventoryComponent? inventory = null, SlotDefinition? slotDefinition = null, InventoryComponent? inventory = null,
SharedItemComponent? item = null) => SharedClothingComponent? clothing = null, ItemComponent? item = null) =>
CanEquip(uid, uid, itemUid, slot, out reason, slotDefinition, inventory, item); CanEquip(uid, uid, itemUid, slot, out reason, slotDefinition, inventory, clothing, item);
public bool CanEquip(EntityUid actor, EntityUid target, EntityUid itemUid, string slot, [NotNullWhen(false)] out string? reason, SlotDefinition? slotDefinition = null, InventoryComponent? inventory = null, SharedItemComponent? item = null) public bool CanEquip(EntityUid actor, EntityUid target, EntityUid itemUid, string slot, [NotNullWhen(false)] out string? reason, SlotDefinition? slotDefinition = null,
InventoryComponent? inventory = null, SharedClothingComponent? clothing = null, ItemComponent? item = null)
{ {
reason = "inventory-component-can-equip-cannot"; reason = "inventory-component-can-equip-cannot";
if (!Resolve(target, ref inventory, false) || !Resolve(itemUid, ref item, false)) if (!Resolve(target, ref inventory, false))
return false; return false;
Resolve(itemUid, ref clothing, ref item, false);
if (slotDefinition == null && !TryGetSlot(target, slot, out slotDefinition, inventory: inventory)) if (slotDefinition == null && !TryGetSlot(target, slot, out slotDefinition, inventory: inventory))
return false; return false;
if (slotDefinition.DependsOn != null && !TryGetSlotEntity(target, slotDefinition.DependsOn, out _, inventory)) if (slotDefinition.DependsOn != null && !TryGetSlotEntity(target, slotDefinition.DependsOn, out _, inventory))
return false; return false;
if(!item.SlotFlags.HasFlag(slotDefinition.SlotFlags) && (!slotDefinition.SlotFlags.HasFlag(SlotFlags.POCKET) || item.Size > (int) ReferenceSizes.Pocket)) var fittingInPocket = slotDefinition.SlotFlags.HasFlag(SlotFlags.POCKET) && item is { Size: <= (int) ReferenceSizes.Pocket };
if (clothing == null && !fittingInPocket
|| clothing != null && !clothing.Slots.HasFlag(slotDefinition.SlotFlags) && !fittingInPocket)
{ {
reason = "inventory-component-can-equip-does-not-fit"; reason = "inventory-component-can-equip-does-not-fit";
return false; return false;
@@ -304,17 +313,17 @@ public abstract partial class InventorySystem
} }
public bool TryUnequip(EntityUid uid, string slot, bool silent = false, bool force = false, bool predicted = false, public bool TryUnequip(EntityUid uid, string slot, bool silent = false, bool force = false, bool predicted = false,
InventoryComponent? inventory = null, SharedItemComponent? item = null) => TryUnequip(uid, uid, slot, silent, force, predicted, inventory, item); InventoryComponent? inventory = null, SharedClothingComponent? clothing = null) => TryUnequip(uid, uid, slot, silent, force, predicted, inventory, clothing);
public bool TryUnequip(EntityUid actor, EntityUid target, string slot, bool silent = false, public bool TryUnequip(EntityUid actor, EntityUid target, string slot, bool silent = false,
bool force = false, bool predicted = false, InventoryComponent? inventory = null, SharedItemComponent? item = null) => bool force = false, bool predicted = false, InventoryComponent? inventory = null, SharedClothingComponent? clothing = null) =>
TryUnequip(actor, target, slot, out _, silent, force, predicted, inventory, item); TryUnequip(actor, target, slot, out _, silent, force, predicted, inventory, clothing);
public bool TryUnequip(EntityUid uid, string slot, [NotNullWhen(true)] out EntityUid? removedItem, bool silent = false, bool force = false, bool predicted = false, public bool TryUnequip(EntityUid uid, string slot, [NotNullWhen(true)] out EntityUid? removedItem, bool silent = false, bool force = false, bool predicted = false,
InventoryComponent? inventory = null, SharedItemComponent? item = null) => TryUnequip(uid, uid, slot, out removedItem, silent, force, predicted, inventory, item); InventoryComponent? inventory = null, SharedClothingComponent? clothing = null) => TryUnequip(uid, uid, slot, out removedItem, silent, force, predicted, inventory, clothing);
public bool TryUnequip(EntityUid actor, EntityUid target, string slot, [NotNullWhen(true)] out EntityUid? removedItem, bool silent = false, public bool TryUnequip(EntityUid actor, EntityUid target, string slot, [NotNullWhen(true)] out EntityUid? removedItem, bool silent = false,
bool force = false, bool predicted = false, InventoryComponent? inventory = null, SharedItemComponent? item = null) bool force = false, bool predicted = false, InventoryComponent? inventory = null, SharedClothingComponent? clothing = null)
{ {
removedItem = null; removedItem = null;
if (!Resolve(target, ref inventory, false)) if (!Resolve(target, ref inventory, false))
@@ -370,7 +379,7 @@ public abstract partial class InventorySystem
Transform(removedItem.Value).Coordinates = Transform(target).Coordinates; Transform(removedItem.Value).Coordinates = Transform(target).Coordinates;
if (!silent && Resolve(removedItem.Value, ref item) && item.UnequipSound != null && _gameTiming.IsFirstTimePredicted) if (!silent && Resolve(removedItem.Value, ref clothing, false) && clothing.UnequipSound != null && _gameTiming.IsFirstTimePredicted)
{ {
Filter filter; Filter filter;
@@ -385,7 +394,7 @@ public abstract partial class InventorySystem
filter.RemoveWhereAttachedEntity(entity => entity == actor); filter.RemoveWhereAttachedEntity(entity => entity == actor);
} }
SoundSystem.Play(item.UnequipSound.GetSound(), filter, target, item.UnequipSound.Params.WithVolume(-2f)); SoundSystem.Play(clothing.UnequipSound.GetSound(), filter, target, clothing.UnequipSound.Params.WithVolume(-2f));
} }
inventory.Dirty(); inventory.Dirty();

View File

@@ -1,4 +1,5 @@
using Content.Shared.Item; using Content.Shared.Clothing.Components;
using Content.Shared.Item;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
namespace Content.Shared.Inventory; namespace Content.Shared.Inventory;
@@ -32,10 +33,6 @@ public partial class InventorySystem
return false; return false;
} }
// If this doesn't have an item component, then we can't do anything with it.
if (!HasComp<SharedItemComponent>(item))
return DeleteItem();
// We finally try to equip the item, otherwise we delete it. // We finally try to equip the item, otherwise we delete it.
return TryEquip(uid, item, slot, silent, force) || DeleteItem(); return TryEquip(uid, item, slot, silent, force) || DeleteItem();
} }

View File

@@ -0,0 +1,76 @@
using Content.Shared.Hands.Components;
using Robust.Shared.Serialization;
namespace Content.Shared.Item;
/// <summary>
/// Handles items which can be picked up to hands and placed in pockets, as well as storage containers
/// like backpacks.
/// </summary>
[RegisterComponent]
public sealed class ItemComponent : Component
{
[Access(typeof(SharedItemSystem), Other = AccessPermissions.ReadExecute)]
[ViewVariables(VVAccess.ReadWrite)]
[DataField("size")]
public int Size = 5;
[DataField("inhandVisuals")]
public Dictionary<HandLocation, List<SharedSpriteComponent.PrototypeLayerData>> InhandVisuals = new();
[Access(typeof(SharedItemSystem))]
[ViewVariables(VVAccess.ReadWrite)]
[DataField("heldPrefix")]
public string? HeldPrefix;
/// <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>
[ViewVariables(VVAccess.ReadWrite)]
[DataField("sprite")]
public readonly string? RsiPath;
}
[Serializable, NetSerializable]
public sealed class ItemComponentState : ComponentState
{
public int Size { get; }
public string? HeldPrefix { get; }
public ItemComponentState(int size, string? heldPrefix)
{
Size = size;
HeldPrefix = heldPrefix;
}
}
/// <summary>
/// Raised when an item's visual state is changed. The event is directed at the entity that contains this item, so
/// that it can properly update its hands or inventory sprites and GUI.
/// </summary>
[Serializable, NetSerializable]
public sealed class VisualsChangedEvent : EntityEventArgs
{
public readonly EntityUid Item;
public readonly string ContainerId;
public VisualsChangedEvent(EntityUid item, string containerId)
{
Item = item;
ContainerId = containerId;
}
}
/// <summary>
/// Reference sizes for common containers and items.
/// </summary>
public enum ReferenceSizes
{
Wallet = 4,
Pocket = 12,
Box = 24,
Belt = 30,
Toolbox = 60,
Backpack = 100,
NoStoring = 9999
}

View File

@@ -1,147 +0,0 @@
using Content.Shared.Hands.Components;
using Content.Shared.Inventory;
using Content.Shared.Sound;
using Robust.Shared.GameStates;
using Robust.Shared.Serialization;
using static Robust.Shared.GameObjects.SharedSpriteComponent;
namespace Content.Shared.Item
{
/// <summary>
/// Players can pick up, drop, and put items in bags, and they can be seen in player's hands.
/// </summary>
[NetworkedComponent()]
public abstract class SharedItemComponent : Component
{
[Dependency] private readonly IEntityManager _entMan = default!;
/// <summary>
/// How much big this item is.
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
public int Size
{
get => _size;
set
{
_size = value;
Dirty();
}
}
[DataField("size")]
private int _size;
[DataField("inhandVisuals")]
public Dictionary<HandLocation, List<PrototypeLayerData>> InhandVisuals = new();
[DataField("clothingVisuals")]
public Dictionary<string, List<PrototypeLayerData>> ClothingVisuals = new();
/// <summary>
/// Whether or not this item can be picked up.
/// </summary>
/// <remarks>
/// This should almost always be true for items. But in some special cases, an item can be equipped but not
/// picked up. E.g., hardsuit helmets are attached to the suit, so we want to disable things like the pickup
/// verb.
/// </remarks>
[DataField("canPickup")]
public bool CanPickup = true;
[DataField("quickEquip")]
public bool QuickEquip = true;
/// <summary>
/// Part of the state of the sprite shown on the player when this item is in their hands or inventory.
/// </summary>
/// <remarks>
/// Only used if <see cref="InhandVisuals"/> or <see cref="ClothingVisuals"/> are unspecified.
/// </remarks>
[ViewVariables(VVAccess.ReadWrite)]
public string? EquippedPrefix
{
get => _equippedPrefix;
set
{
_equippedPrefix = value;
EntitySystem.Get<SharedItemSystem>().VisualsChanged(Owner, this);
Dirty();
}
}
[DataField("HeldPrefix")]
private string? _equippedPrefix;
[ViewVariables]
[DataField("Slots")]
public SlotFlags SlotFlags = SlotFlags.PREVENTEQUIP; //Different from None, NONE allows equips if no slot flags are required
[DataField("equipSound")]
public SoundSpecifier? EquipSound { get; set; } = default!;
[DataField("unequipSound")]
public SoundSpecifier? UnequipSound = default!;
/// <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>
[ViewVariables(VVAccess.ReadWrite)]
[DataField("sprite")]
public readonly string? RsiPath;
public void RemovedFromSlot()
{
if (_entMan.TryGetComponent(Owner, out SharedSpriteComponent? component))
component.Visible = true;
}
public virtual void EquippedToSlot()
{
if (_entMan.TryGetComponent(Owner, out SharedSpriteComponent? component))
component.Visible = false;
}
}
[Serializable, NetSerializable]
public sealed class ItemComponentState : ComponentState
{
public int Size { get; }
public string? EquippedPrefix { get; }
public ItemComponentState(int size, string? equippedPrefix)
{
Size = size;
EquippedPrefix = equippedPrefix;
}
}
/// <summary>
/// Raised when an item's visual state is changed. The event is directed at the entity that contains this item, so
/// that it can properly update its hands or inventory sprites and GUI.
/// </summary>
[Serializable, NetSerializable]
public sealed class VisualsChangedEvent : EntityEventArgs
{
public readonly EntityUid Item;
public readonly string ContainerId;
public VisualsChangedEvent(EntityUid item, string containerId)
{
Item = item;
ContainerId = containerId;
}
}
/// <summary>
/// Reference sizes for common containers and items.
/// </summary>
public enum ReferenceSizes
{
Wallet = 4,
Pocket = 12,
Box = 24,
Belt = 30,
Toolbox = 60,
Backpack = 100,
NoStoring = 9999
}
}

View File

@@ -1,95 +1,124 @@
using Content.Shared.Hands.EntitySystems; using Content.Shared.Hands.EntitySystems;
using Content.Shared.Interaction; using Content.Shared.Interaction;
using Content.Shared.Inventory.Events; using Content.Shared.Inventory.Events;
using Content.Shared.Verbs; using Content.Shared.Verbs;
using Robust.Shared.Containers; using Robust.Shared.Containers;
using Robust.Shared.GameStates; using Robust.Shared.GameStates;
namespace Content.Shared.Item namespace Content.Shared.Item;
public abstract class SharedItemSystem : EntitySystem
{ {
public abstract class SharedItemSystem : EntitySystem [Dependency] private readonly SharedHandsSystem _handsSystem = default!;
[Dependency] private readonly SharedContainerSystem _container = default!;
public override void Initialize()
{ {
[Dependency] private readonly SharedHandsSystem _handsSystem = default!; base.Initialize();
SubscribeLocalEvent<ItemComponent, GetVerbsEvent<InteractionVerb>>(AddPickupVerb);
public override void Initialize() SubscribeLocalEvent<SharedSpriteComponent, GotEquippedEvent>(OnEquipped);
{ SubscribeLocalEvent<SharedSpriteComponent, GotUnequippedEvent>(OnUnequipped);
base.Initialize(); SubscribeLocalEvent<ItemComponent, InteractHandEvent>(OnHandInteract);
SubscribeLocalEvent<SharedItemComponent, GetVerbsEvent<InteractionVerb>>(AddPickupVerb);
SubscribeLocalEvent<SharedSpriteComponent, GotEquippedEvent>(OnEquipped); SubscribeLocalEvent<ItemComponent, ComponentGetState>(OnGetState);
SubscribeLocalEvent<SharedSpriteComponent, GotUnequippedEvent>(OnUnequipped); SubscribeLocalEvent<ItemComponent, ComponentHandleState>(OnHandleState);
SubscribeLocalEvent<SharedItemComponent, InteractHandEvent>(OnHandInteract); }
SubscribeLocalEvent<SharedItemComponent, ComponentGetState>(OnGetState); #region Public API
SubscribeLocalEvent<SharedItemComponent, ComponentHandleState>(OnHandleState);
}
private void OnHandInteract(EntityUid uid, SharedItemComponent component, InteractHandEvent args) public void SetSize(EntityUid uid, int size, ItemComponent? component = null)
{ {
if (args.Handled || !component.CanPickup) if (!Resolve(uid, ref component))
return; return;
args.Handled = _handsSystem.TryPickup(args.User, uid, animateUser: false); component.Size = size;
} Dirty(component);
}
private void OnHandleState(EntityUid uid, SharedItemComponent component, ref ComponentHandleState args) public void SetHeldPrefix(EntityUid uid, string? heldPrefix, ItemComponent? component = null)
{ {
if (args.Current is not ItemComponentState state) if (!Resolve(uid, ref component))
return; return;
component.Size = state.Size; component.HeldPrefix = heldPrefix;
component.EquippedPrefix = state.EquippedPrefix; Dirty(component);
} VisualsChanged(uid);
}
private void OnGetState(EntityUid uid, SharedItemComponent component, ref ComponentGetState args) #endregion
{
args.State = new ItemComponentState(component.Size, component.EquippedPrefix);
}
// Although netsync is being set to false for items client can still update these private void OnHandInteract(EntityUid uid, ItemComponent component, InteractHandEvent args)
// Realistically: {
// Container should already hide these if (args.Handled)
// Client is the only thing that matters. return;
private void OnUnequipped(EntityUid uid, SharedSpriteComponent component, GotUnequippedEvent args) args.Handled = _handsSystem.TryPickup(args.User, uid, animateUser: false);
{ }
component.Visible = true;
}
private void OnEquipped(EntityUid uid, SharedSpriteComponent component, GotEquippedEvent args) private void OnHandleState(EntityUid uid, ItemComponent component, ref ComponentHandleState args)
{ {
component.Visible = false; if (args.Current is not ItemComponentState state)
} return;
private void AddPickupVerb(EntityUid uid, SharedItemComponent component, GetVerbsEvent<InteractionVerb> args) component.Size = state.Size;
{ component.HeldPrefix = state.HeldPrefix;
if (args.Hands == null || }
args.Using != null ||
!args.CanAccess ||
!args.CanInteract ||
!component.CanPickup ||
!_handsSystem.CanPickupAnyHand(args.User, args.Target, handsComp: args.Hands, item: component))
return;
InteractionVerb verb = new(); private void OnGetState(EntityUid uid, ItemComponent component, ref ComponentGetState args)
verb.Act = () => _handsSystem.TryPickupAnyHand(args.User, args.Target, checkActionBlocker: false, handsComp: args.Hands, item: component); {
verb.IconTexture = "/Textures/Interface/VerbIcons/pickup.svg.192dpi.png"; args.State = new ItemComponentState(component.Size, component.HeldPrefix);
}
// if the item already in a container (that is not the same as the user's), then change the text. // Although netsync is being set to false for items client can still update these
// this occurs when the item is in their inventory or in an open backpack // Realistically:
args.User.TryGetContainer(out var userContainer); // Container should already hide these
if (args.Target.TryGetContainer(out var container) && container != userContainer) // Client is the only thing that matters.
verb.Text = Loc.GetString("pick-up-verb-get-data-text-inventory");
else
verb.Text = Loc.GetString("pick-up-verb-get-data-text");
args.Verbs.Add(verb); private void OnUnequipped(EntityUid uid, SharedSpriteComponent component, GotUnequippedEvent args)
} {
component.Visible = true;
}
/// <summary> private void OnEquipped(EntityUid uid, SharedSpriteComponent component, GotEquippedEvent args)
/// Notifies any entity that is holding or wearing this item that they may need to update their sprite. {
/// </summary> component.Visible = false;
public virtual void VisualsChanged(EntityUid owner, SharedItemComponent? item = null) }
{ }
private void AddPickupVerb(EntityUid uid, ItemComponent component, GetVerbsEvent<InteractionVerb> args)
{
if (args.Hands == null ||
args.Using != null ||
!args.CanAccess ||
!args.CanInteract) //||
//!_handsSystem.CanPickupAnyHand(args.User, args.Target, handsComp: args.Hands, item: component))
return;
InteractionVerb verb = new();
// TODO ITEM
//verb.Act = () => _handsSystem.TryPickupAnyHand(args.User, args.Target, checkActionBlocker: false,
// handsComp: args.Hands, item: component);
verb.IconTexture = "/Textures/Interface/VerbIcons/pickup.svg.192dpi.png";
// if the item already in a container (that is not the same as the user's), then change the text.
// this occurs when the item is in their inventory or in an open backpack
_container.TryGetContainingContainer(args.User, out var userContainer);
if (_container.TryGetContainingContainer(args.Target, out var container) && container != userContainer)
verb.Text = Loc.GetString("pick-up-verb-get-data-text-inventory");
else
verb.Text = Loc.GetString("pick-up-verb-get-data-text");
args.Verbs.Add(verb);
}
/// <summary>
/// Notifies any entity that is holding or wearing this item that they may need to update their sprite.
/// </summary>
/// <remarks>
/// This is used for updating both inhand sprites and clothing sprites, but it's here just cause it needs to
/// be in one place.
/// </remarks>
public virtual void VisualsChanged(EntityUid owner)
{
} }
} }

View File

@@ -87,7 +87,7 @@
- state: box_hug - state: box_hug
- state: heart - state: heart
- type: Item - type: Item
HeldPrefix: hug heldPrefix: hug
- type: StorageFill - type: StorageFill
contents: contents:
- id: ClothingMaskBreath - id: ClothingMaskBreath

View File

@@ -177,7 +177,7 @@
- state: box_hug - state: box_hug
- state: heart - state: heart
- type: Item - type: Item
HeldPrefix: hug heldPrefix: hug
- type: StorageFill - type: StorageFill
contents: contents:
- id: Brutepack - id: Brutepack

View File

@@ -7,10 +7,12 @@
- type: Sprite - type: Sprite
sprite: Clothing/Back/Backpacks/backpack.rsi sprite: Clothing/Back/Backpacks/backpack.rsi
state: icon state: icon
- type: Clothing - type: Item
size: 9999 size: 9999
sprite: Clothing/Back/Backpacks/backpack.rsi
- type: Clothing
quickEquip: false quickEquip: false
Slots: slots:
- back - back
sprite: Clothing/Back/Backpacks/backpack.rsi sprite: Clothing/Back/Backpacks/backpack.rsi
- type: Storage - type: Storage
@@ -32,7 +34,7 @@
sprite: Clothing/Back/Backpacks/clown.rsi sprite: Clothing/Back/Backpacks/clown.rsi
- type: Storage - type: Storage
storageOpenSound: storageOpenSound:
collection: BikeHorn collection: BikeHorn
- type: entity - type: entity
parent: ClothingBackpack parent: ClothingBackpack
@@ -88,11 +90,7 @@
sprite: Clothing/Back/Backpacks/mime.rsi sprite: Clothing/Back/Backpacks/mime.rsi
- type: Clothing - type: Clothing
sprite: Clothing/Back/Backpacks/mime.rsi sprite: Clothing/Back/Backpacks/mime.rsi
storageOpenSound:
collection: null
storageInsertSound:
collection: null
- type: entity - type: entity
parent: ClothingBackpack parent: ClothingBackpack
id: ClothingBackpackChemistry id: ClothingBackpackChemistry
@@ -136,7 +134,7 @@
sprite: Clothing/Back/Backpacks/virology.rsi sprite: Clothing/Back/Backpacks/virology.rsi
- type: Clothing - type: Clothing
sprite: Clothing/Back/Backpacks/virology.rsi sprite: Clothing/Back/Backpacks/virology.rsi
#ERT #ERT
- type: entity - type: entity
parent: ClothingBackpack parent: ClothingBackpack

View File

@@ -7,11 +7,13 @@
- type: Sprite - type: Sprite
sprite: Clothing/Back/Duffels/duffel.rsi sprite: Clothing/Back/Duffels/duffel.rsi
state: icon state: icon
- type: Clothing - type: Item
sprite: Clothing/Back/Duffels/duffel.rsi sprite: Clothing/Back/Duffels/duffel.rsi
size: 9999 size: 9999
- type: Clothing
sprite: Clothing/Back/Duffels/duffel.rsi
quickEquip: false quickEquip: false
Slots: slots:
- back - back
- type: Storage - type: Storage
capacity: 120 capacity: 120
@@ -66,6 +68,7 @@
sprite: Clothing/Back/Duffels/clown.rsi sprite: Clothing/Back/Duffels/clown.rsi
- type: Clothing - type: Clothing
sprite: Clothing/Back/Duffels/clown.rsi sprite: Clothing/Back/Duffels/clown.rsi
- type: Storage
storageOpenSound: storageOpenSound:
collection: BikeHorn collection: BikeHorn
@@ -102,9 +105,9 @@
- type: Clothing - type: Clothing
sprite: Clothing/Back/Duffels/mime.rsi sprite: Clothing/Back/Duffels/mime.rsi
storageOpenSound: storageOpenSound:
collection: null collection: null
storageInsertSound: storageInsertSound:
collection: null collection: null
- type: entity - type: entity
parent: ClothingBackpackDuffel parent: ClothingBackpackDuffel
@@ -140,7 +143,7 @@
state: icon-ammo state: icon-ammo
- type: Clothing - type: Clothing
sprite: Clothing/Back/Duffels/syndicate.rsi sprite: Clothing/Back/Duffels/syndicate.rsi
HeldPrefix: ammo heldPrefix: ammo
- type: entity - type: entity
parent: ClothingBackpackDuffelSyndicate parent: ClothingBackpackDuffelSyndicate
@@ -152,7 +155,7 @@
state: icon-med state: icon-med
- type: Clothing - type: Clothing
sprite: Clothing/Back/Duffels/syndicate.rsi sprite: Clothing/Back/Duffels/syndicate.rsi
HeldPrefix: med heldPrefix: med
- type: entity - type: entity
parent: ClothingBackpackDuffel parent: ClothingBackpackDuffel

View File

@@ -7,10 +7,11 @@
- type: Sprite - type: Sprite
sprite: Clothing/Back/Satchels/satchel.rsi sprite: Clothing/Back/Satchels/satchel.rsi
state: icon state: icon
- type: Clothing - type: Item
size: 9999 size: 9999
- type: Clothing
quickEquip: false quickEquip: false
Slots: slots:
- back - back
sprite: Clothing/Back/Satchels/satchel.rsi sprite: Clothing/Back/Satchels/satchel.rsi
- type: Storage - type: Storage

View File

@@ -5,10 +5,12 @@
components: components:
- type: Sprite - type: Sprite
state: icon state: icon
- type: Clothing - type: Item
Slots: [belt]
size: 50 size: 50
- type: Clothing
slots: [belt]
quickEquip: false quickEquip: false
- type: Storage
equipSound: equipSound:
path: /Audio/Items/belt_equip.ogg path: /Audio/Items/belt_equip.ogg

View File

@@ -9,7 +9,7 @@
- type: Sprite - type: Sprite
state: icon state: icon
- type: Clothing - type: Clothing
Slots: slots:
- ears - ears
sprite: Clothing/Ears/Headsets/base.rsi sprite: Clothing/Ears/Headsets/base.rsi

View File

@@ -9,7 +9,7 @@
- type: Sprite - type: Sprite
state: icon_alt state: icon_alt
- type: Clothing - type: Clothing
Slots: slots:
- ears - ears
- type: entity - type: entity

View File

@@ -6,4 +6,4 @@
- type: Sprite - type: Sprite
state: icon state: icon
- type: Clothing - type: Clothing
Slots: [eyes] slots: [eyes]

View File

@@ -35,7 +35,9 @@
state: icon-alt state: icon-alt
- type: Clothing - type: Clothing
sprite: Clothing/Eyes/Glasses/gar.rsi sprite: Clothing/Eyes/Glasses/gar.rsi
HeldPrefix: alt equippedPrefix: alt
- type: Item
heldPrefix: alt
- type: MeleeWeapon - type: MeleeWeapon
damage: damage:
types: types:
@@ -52,7 +54,9 @@
state: icon-super state: icon-super
- type: Clothing - type: Clothing
sprite: Clothing/Eyes/Glasses/gar.rsi sprite: Clothing/Eyes/Glasses/gar.rsi
HeldPrefix: super equippedPrefix: super
- type: Item
heldPrefix: super
- type: MeleeWeapon - type: MeleeWeapon
damage: damage:
types: types:

View File

@@ -6,6 +6,6 @@
- type: Sprite - type: Sprite
state: icon state: icon
- type: Clothing - type: Clothing
Slots: [gloves] slots: [gloves]
- type: DiseaseProtection - type: DiseaseProtection
protection: 0.05 protection: 0.05

View File

@@ -38,7 +38,8 @@
sprite: Clothing/Hands/Gloves/Color/black.rsi sprite: Clothing/Hands/Gloves/Color/black.rsi
- type: Clothing - type: Clothing
sprite: Clothing/Hands/Gloves/Color/black.rsi sprite: Clothing/Hands/Gloves/Color/black.rsi
HeatResistance: 1400 - type: GloveHeatResistance
heatResistance: 1400
- type: Fiber - type: Fiber
fiberMaterial: fibers-synthetic fiberMaterial: fibers-synthetic
fiberColor: fibers-black fiberColor: fibers-black
@@ -159,7 +160,8 @@
sprite: Clothing/Hands/Gloves/Color/yellow.rsi sprite: Clothing/Hands/Gloves/Color/yellow.rsi
- type: Clothing - type: Clothing
sprite: Clothing/Hands/Gloves/Color/yellow.rsi sprite: Clothing/Hands/Gloves/Color/yellow.rsi
HeatResistance: 1400 - type: GloveHeatResistance
heatResistance: 1400
- type: Insulated - type: Insulated
- type: Fiber - type: Fiber
fiberMaterial: fibers-insulative fiberMaterial: fibers-insulative
@@ -173,7 +175,8 @@
description: These gloves are cheap knockoffs of the coveted ones - no way this can end badly. description: These gloves are cheap knockoffs of the coveted ones - no way this can end badly.
components: components:
- type: Clothing - type: Clothing
HeatResistance: 0 - type: GloveHeatResistance
heatResistance: 0
- type: Insulated - type: Insulated
- type: Fiber - type: Fiber
fiberMaterial: fibers-insulative fiberMaterial: fibers-insulative

View File

@@ -34,7 +34,7 @@
state: icon-blue state: icon-blue
- type: Clothing - type: Clothing
sprite: Clothing/Hands/Gloves/boxing.rsi sprite: Clothing/Hands/Gloves/boxing.rsi
HeldPrefix: blue heldPrefix: blue
- type: Fiber - type: Fiber
fiberMaterial: fibers-leather fiberMaterial: fibers-leather
fiberColor: fibers-blue fiberColor: fibers-blue
@@ -51,7 +51,7 @@
state: icon-green state: icon-green
- type: Clothing - type: Clothing
sprite: Clothing/Hands/Gloves/boxing.rsi sprite: Clothing/Hands/Gloves/boxing.rsi
HeldPrefix: green heldPrefix: green
- type: Fiber - type: Fiber
fiberMaterial: fibers-leather fiberMaterial: fibers-leather
fiberColor: fibers-green fiberColor: fibers-green
@@ -68,7 +68,7 @@
state: icon-yellow state: icon-yellow
- type: Clothing - type: Clothing
sprite: Clothing/Hands/Gloves/boxing.rsi sprite: Clothing/Hands/Gloves/boxing.rsi
HeldPrefix: yellow heldPrefix: yellow
- type: Fiber - type: Fiber
fiberMaterial: fibers-leather fiberMaterial: fibers-leather
fiberColor: fibers-yellow fiberColor: fibers-yellow
@@ -84,7 +84,8 @@
sprite: Clothing/Hands/Gloves/captain.rsi sprite: Clothing/Hands/Gloves/captain.rsi
- type: Clothing - type: Clothing
sprite: Clothing/Hands/Gloves/captain.rsi sprite: Clothing/Hands/Gloves/captain.rsi
HeatResistance: 1400 - type: GloveHeatResistance
heatResistance: 1400
- type: Insulated - type: Insulated
- type: Fiber - type: Fiber
fiberMaterial: fibers-durathread fiberMaterial: fibers-durathread
@@ -148,7 +149,8 @@
sprite: Clothing/Hands/Gloves/leather.rsi sprite: Clothing/Hands/Gloves/leather.rsi
- type: Clothing - type: Clothing
sprite: Clothing/Hands/Gloves/leather.rsi sprite: Clothing/Hands/Gloves/leather.rsi
HeatResistance: 1400 - type: GloveHeatResistance
heatResistance: 1400
- type: Fiber - type: Fiber
fiberMaterial: fibers-leather fiberMaterial: fibers-leather
fiberColor: fibers-brown fiberColor: fibers-brown
@@ -193,7 +195,8 @@
sprite: Clothing/Hands/Gloves/spaceninja.rsi sprite: Clothing/Hands/Gloves/spaceninja.rsi
- type: Clothing - type: Clothing
sprite: Clothing/Hands/Gloves/spaceninja.rsi sprite: Clothing/Hands/Gloves/spaceninja.rsi
HeatResistance: 1400 - type: GloveHeatResistance
heatResistance: 1400
- type: Insulated - type: Insulated
- type: Fiber - type: Fiber
fiberMaterial: fibers-nanomachines fiberMaterial: fibers-nanomachines
@@ -212,7 +215,8 @@
sprite: Clothing/Hands/Gloves/Color/black.rsi sprite: Clothing/Hands/Gloves/Color/black.rsi
- type: Clothing - type: Clothing
sprite: Clothing/Hands/Gloves/Color/black.rsi sprite: Clothing/Hands/Gloves/Color/black.rsi
HeatResistance: 1400 - type: GloveHeatResistance
heatResistance: 1400
- type: Insulated - type: Insulated
- type: Fiber - type: Fiber
fiberMaterial: fibers-insulative fiberMaterial: fibers-insulative

View File

@@ -4,7 +4,7 @@
id: ClothingHeadBase id: ClothingHeadBase
components: components:
- type: Clothing - type: Clothing
Slots: slots:
- HEAD - HEAD
- type: Sprite - type: Sprite
state: icon state: icon
@@ -18,18 +18,54 @@
id: HatBase id: HatBase
components: components:
- type: Clothing - type: Clothing
Slots: slots:
- HEAD - HEAD
- type: Sprite - type: Sprite
state: icon state: icon
- type: entity
abstract: true
parent: ClothingHeadBase
id: ClothingHeadLightBase
name: base helmet with light
noSpawn: true
components:
- type: Sprite
netsync: false
layers:
- state: icon
- state: icon-flash
visible: false
map: [ "light" ]
- type: Clothing
heldPrefix: off
- type: ToggleableLightVisuals
- type: PointLight
netsync: false
enabled: false
radius: 6
energy: 2
mask: /Textures/Effects/LightMasks/cone.png
autoRot: true
- type: Appearance
visuals:
- type: FlashLightVisualizer
- type: HandheldLight
addPrefix: true
- type: Battery
maxCharge: 600 #lights drain 3/s but recharge of 2 makes this 1/s. Therefore 600 is 10 minutes of light.
startingCharge: 600
- type: BatterySelfRecharger
autoRecharge: true
autoRechargeRate: 2 #recharge of 2 makes total drain 1w / s so max charge is 1:1 with time. Time to fully charge should be 5 minutes. Having recharge gives light an extended flicker period which gives you some warning to return to light area.
- type: entity - type: entity
abstract: true abstract: true
parent: ClothingHeadBase parent: ClothingHeadBase
id: ClothingHeadEVAHelmetBase id: ClothingHeadEVAHelmetBase
name: base space helmet name: base space helmet
components: components:
- type: Clothing - type: Item
size: 10 size: 10
- type: PressureProtection - type: PressureProtection
highPressureMultiplier: 0.6 highPressureMultiplier: 0.6
@@ -46,18 +82,19 @@
- type: entity - type: entity
abstract: true abstract: true
parent: ClothingHeadBase # No parent since we aren't actually an item.
id: ClothingHeadHardsuitBase id: ClothingHeadHardsuitBase
name: base hardsuit helmet name: base hardsuit helmet
noSpawn: true noSpawn: true
components: components:
- type: Clickable
- type: InteractionOutline
- type: Clothing - type: Clothing
#Apparently the hardsuit helmet equip sound is from a walking mech? #Apparently the hardsuit helmet equip sound is from a walking mech?
equipSound: /Audio/Mecha/mechmove03.ogg equipSound: /Audio/Mecha/mechmove03.ogg
unequipSound: /Audio/Mecha/mechmove03.ogg unequipSound: /Audio/Mecha/mechmove03.ogg
size: 15
canPickup: false # attached to suit.
quickEquip: false quickEquip: false
slots: [ HEAD ]
- type: PressureProtection - type: PressureProtection
highPressureMultiplier: 0.3 highPressureMultiplier: 0.3
lowPressureMultiplier: 1000 lowPressureMultiplier: 1000
@@ -94,7 +131,7 @@
visible: false visible: false
map: [ "light" ] map: [ "light" ]
- type: Clothing - type: Clothing
HeldPrefix: off equippedPrefix: off
- type: ToggleableLightVisuals - type: ToggleableLightVisuals
- type: PointLight - type: PointLight
netsync: false netsync: false

View File

@@ -12,7 +12,7 @@
visible: false visible: false
map: [ "light" ] map: [ "light" ]
- type: Clothing - type: Clothing
HeldPrefix: off equippedPrefix: off
- type: PointLight - type: PointLight
netsync: false netsync: false
enabled: false enabled: false

View File

@@ -20,13 +20,6 @@
addPrefix: false addPrefix: false
- type: ToggleableLightVisuals - type: ToggleableLightVisuals
spriteLayer: light spriteLayer: light
inhandVisuals:
left:
- state: inhand-left-light
shader: unshaded
right:
- state: inhand-right-light
shader: unshaded
clothingVisuals: clothingVisuals:
head: head:
- state: equipped-head-light - state: equipped-head-light
@@ -37,15 +30,6 @@
- state: equipped-head - state: equipped-head
- state: equipped-head-unshaded - state: equipped-head-unshaded
shader: 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: PressureProtection - type: PressureProtection
highPressureMultiplier: 0.08 highPressureMultiplier: 0.08
lowPressureMultiplier: 10000 lowPressureMultiplier: 10000
@@ -59,7 +43,7 @@
Radiation: 0.5 Radiation: 0.5
- type: TemperatureProtection - type: TemperatureProtection
coefficient: 0.005 coefficient: 0.005
- type: entity - type: entity
parent: ClothingHeadHardsuitBase parent: ClothingHeadHardsuitBase
id: ClothingHeadHelmetHardsuitCap id: ClothingHeadHelmetHardsuitCap
@@ -186,7 +170,7 @@
coefficients: coefficients:
Blunt: 0.8 Blunt: 0.8
Slash: 0.8 Slash: 0.8
Piercing: 0.8 Piercing: 0.8
- type: PointLight - type: PointLight
radius: 7 radius: 7
energy: 3 energy: 3
@@ -211,7 +195,7 @@
Blunt: 0.8 Blunt: 0.8
Slash: 0.8 Slash: 0.8
Piercing: 0.8 Piercing: 0.8
- type: entity - type: entity
parent: ClothingHeadHardsuitWithLightBase parent: ClothingHeadHardsuitWithLightBase
id: ClothingHeadHelmetHardsuitSecurityRed id: ClothingHeadHelmetHardsuitSecurityRed
@@ -287,13 +271,13 @@
- type: PressureProtection - type: PressureProtection
highPressureMultiplier: 0.225 highPressureMultiplier: 0.225
lowPressureMultiplier: 10000 lowPressureMultiplier: 10000
- type: entity - type: entity
parent: ClothingHeadHardsuitWithLightBase parent: ClothingHeadHardsuitWithLightBase
id: ClothingHeadHelmetHardsuitSpatio id: ClothingHeadHelmetHardsuitSpatio
noSpawn: true noSpawn: true
name: spationaut hardsuit helmet name: spationaut hardsuit helmet
description: A sturdy helmet designed for complex industrial operations in space. description: A sturdy helmet designed for complex industrial operations in space.
components: components:
- type: Sprite - type: Sprite
netsync: false netsync: false
@@ -308,13 +292,6 @@
map: [ "light" ] map: [ "light" ]
- type: HandheldLight - type: HandheldLight
addPrefix: false addPrefix: false
inhandVisuals:
left:
- state: inhand-left-light
shader: unshaded
right:
- state: inhand-right-light
shader: unshaded
clothingVisuals: clothingVisuals:
head: head:
- state: equipped-head-light - state: equipped-head-light
@@ -325,15 +302,6 @@
- state: equipped-head - state: equipped-head
- state: equipped-head-unshaded - state: equipped-head-unshaded
shader: 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: PressureProtection - type: PressureProtection
highPressureMultiplier: 0.72 highPressureMultiplier: 0.72
lowPressureMultiplier: 10000 lowPressureMultiplier: 10000
@@ -351,7 +319,7 @@
sprite: Clothing/Head/Hardsuits/cybersun.rsi sprite: Clothing/Head/Hardsuits/cybersun.rsi
- type: PressureProtection - type: PressureProtection
highPressureMultiplier: 0.3 highPressureMultiplier: 0.3
lowPressureMultiplier: 1000 lowPressureMultiplier: 1000
- type: entity - type: entity
parent: ClothingHeadHardsuitWithLightBase parent: ClothingHeadHardsuitWithLightBase
@@ -395,7 +363,7 @@
highPressureMultiplier: 0.08 highPressureMultiplier: 0.08
lowPressureMultiplier: 1000 lowPressureMultiplier: 1000
- type: TemperatureProtection - type: TemperatureProtection
coefficient: 0.005 coefficient: 0.005
- type: Armor - type: Armor
modifiers: modifiers:
coefficients: coefficients:
@@ -429,22 +397,13 @@
- state: equipped-head - state: equipped-head
- state: equipped-head-unshaded - state: equipped-head-unshaded
shader: 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: PointLight - type: PointLight
color: orange color: orange
- type: PressureProtection - type: PressureProtection
highPressureMultiplier: 0.08 highPressureMultiplier: 0.08
lowPressureMultiplier: 1000 lowPressureMultiplier: 1000
- type: TemperatureProtection - type: TemperatureProtection
coefficient: 0.005 coefficient: 0.005
- type: Armor - type: Armor
modifiers: modifiers:
coefficients: coefficients:
@@ -467,7 +426,7 @@
sprite: Clothing/Head/Hardsuits/ERThelmets/ertleader.rsi sprite: Clothing/Head/Hardsuits/ERThelmets/ertleader.rsi
- type: Clothing - type: Clothing
sprite: Clothing/Head/Hardsuits/ERThelmets/ertleader.rsi sprite: Clothing/Head/Hardsuits/ERThelmets/ertleader.rsi
- type: entity - type: entity
parent: ClothingHeadHelmetHardsuitERTLeader parent: ClothingHeadHelmetHardsuitERTLeader
id: ClothingHeadHelmetHardsuitERTEngineer id: ClothingHeadHelmetHardsuitERTEngineer
@@ -477,7 +436,7 @@
sprite: Clothing/Head/Hardsuits/ERThelmets/ertengineer.rsi sprite: Clothing/Head/Hardsuits/ERThelmets/ertengineer.rsi
- type: Clothing - type: Clothing
sprite: Clothing/Head/Hardsuits/ERThelmets/ertengineer.rsi sprite: Clothing/Head/Hardsuits/ERThelmets/ertengineer.rsi
- type: entity - type: entity
parent: ClothingHeadHelmetHardsuitERTLeader parent: ClothingHeadHelmetHardsuitERTLeader
id: ClothingHeadHelmetHardsuitERTMedical id: ClothingHeadHelmetHardsuitERTMedical
@@ -487,7 +446,7 @@
sprite: Clothing/Head/Hardsuits/ERThelmets/ertmedical.rsi sprite: Clothing/Head/Hardsuits/ERThelmets/ertmedical.rsi
- type: Clothing - type: Clothing
sprite: Clothing/Head/Hardsuits/ERThelmets/ertmedical.rsi sprite: Clothing/Head/Hardsuits/ERThelmets/ertmedical.rsi
- type: entity - type: entity
parent: ClothingHeadHelmetHardsuitERTLeader parent: ClothingHeadHelmetHardsuitERTLeader
id: ClothingHeadHelmetHardsuitERTSecurity id: ClothingHeadHelmetHardsuitERTSecurity
@@ -497,7 +456,7 @@
sprite: Clothing/Head/Hardsuits/ERThelmets/ertsecurity.rsi sprite: Clothing/Head/Hardsuits/ERThelmets/ertsecurity.rsi
- type: Clothing - type: Clothing
sprite: Clothing/Head/Hardsuits/ERThelmets/ertsecurity.rsi sprite: Clothing/Head/Hardsuits/ERThelmets/ertsecurity.rsi
- type: entity - type: entity
parent: ClothingHeadHelmetHardsuitERTLeader parent: ClothingHeadHelmetHardsuitERTLeader
id: ClothingHeadHelmetHardsuitERTJanitor id: ClothingHeadHelmetHardsuitERTJanitor

View File

@@ -196,7 +196,7 @@
- type: IdentityBlocker - type: IdentityBlocker
- type: entity - type: entity
parent: ClothingHeadHardsuitWithLightBase parent: ClothingHeadLightBase
id: ClothingHeadHelmetFire id: ClothingHeadHelmetFire
name: fire helmet name: fire helmet
description: An atmos techs best friend. Provides some heat resistance and looks cool. description: An atmos techs best friend. Provides some heat resistance and looks cool.
@@ -205,8 +205,6 @@
sprite: Clothing/Head/Helmets/firehelmet.rsi sprite: Clothing/Head/Helmets/firehelmet.rsi
- type: Clothing - type: Clothing
sprite: Clothing/Head/Helmets/firehelmet.rsi sprite: Clothing/Head/Helmets/firehelmet.rsi
size: 5
canPickup: true
quickEquip: true quickEquip: true
- type: IngestionBlocker - type: IngestionBlocker
- type: PowerCellSlot - type: PowerCellSlot
@@ -228,7 +226,7 @@
- type: IdentityBlocker - type: IdentityBlocker
- type: entity - type: entity
parent: ClothingHeadHardsuitWithLightBase parent: ClothingHeadLightBase
id: ClothingHeadHelmetAtmosFire id: ClothingHeadHelmetAtmosFire
name: atmos fire helmet name: atmos fire helmet
description: An atmos fire helmet, able to keep the user cool in any situation. description: An atmos fire helmet, able to keep the user cool in any situation.
@@ -237,8 +235,6 @@
sprite: Clothing/Head/Helmets/atmos_firehelmet.rsi sprite: Clothing/Head/Helmets/atmos_firehelmet.rsi
- type: Clothing - type: Clothing
sprite: Clothing/Head/Helmets/atmos_firehelmet.rsi sprite: Clothing/Head/Helmets/atmos_firehelmet.rsi
size: 5
canPickup: true
quickEquip: true quickEquip: true
- type: IngestionBlocker - type: IngestionBlocker
- type: TemperatureProtection - type: TemperatureProtection

View File

@@ -6,7 +6,7 @@
- type: Sprite - type: Sprite
state: icon state: icon
- type: Clothing - type: Clothing
Slots: [mask] slots: [mask]
- type: entity - type: entity
abstract: true abstract: true
@@ -19,4 +19,4 @@
description: action-description-mask-toggle description: action-description-mask-toggle
icon: Clothing/Mask/gas.rsi/icon.png icon: Clothing/Mask/gas.rsi/icon.png
iconOn: Interface/Inventory/blocked.png iconOn: Interface/Inventory/blocked.png
event: !type:ToggleMaskEvent event: !type:ToggleMaskEvent

View File

@@ -3,10 +3,11 @@
parent: Clothing parent: Clothing
id: ClothingNeckBase id: ClothingNeckBase
components: components:
- type: Clothing - type: Item
size: 10 size: 10
- type: Clothing
quickEquip: true quickEquip: true
Slots: slots:
- neck - neck
- type: Sprite - type: Sprite
state: icon state: icon

View File

@@ -4,7 +4,7 @@
id: ClothingOuterBase id: ClothingOuterBase
components: components:
- type: Clothing - type: Clothing
Slots: slots:
- outerClothing - outerClothing
- type: Sprite - type: Sprite
state: icon state: icon
@@ -14,9 +14,10 @@
parent: ClothingOuterBase parent: ClothingOuterBase
id: ClothingOuterBaseLarge id: ClothingOuterBaseLarge
components: components:
- type: Item
size: 80
- type: Clothing - type: Clothing
Size: 80 slots:
Slots:
- outerClothing - outerClothing
- type: ClothingSpeedModifier - type: ClothingSpeedModifier
walkModifier: 0.9 walkModifier: 0.9
@@ -48,7 +49,7 @@
- type: ClothingSpeedModifier - type: ClothingSpeedModifier
walkModifier: 0.4 walkModifier: 0.4
sprintModifier: 0.6 sprintModifier: 0.6
- type: Clothing - type: Item
size: 121 size: 121
- type: Armor - type: Armor
modifiers: modifiers:
@@ -76,7 +77,7 @@
- type: ClothingSpeedModifier - type: ClothingSpeedModifier
walkModifier: 0.8 walkModifier: 0.8
sprintModifier: 0.8 sprintModifier: 0.8
- type: Clothing - type: Item
size: 80 size: 80
- type: DiseaseProtection - type: DiseaseProtection
protection: 0.05 protection: 0.05

View File

@@ -4,7 +4,7 @@
id: ClothingShoesBase id: ClothingShoesBase
components: components:
- type: Clothing - type: Clothing
Slots: slots:
- FEET - FEET
- type: Sprite - type: Sprite
state: icon state: icon

View File

@@ -18,7 +18,7 @@
- type: Sprite - type: Sprite
state: icon state: icon
- type: Clothing - type: Clothing
Slots: [innerclothing] slots: [innerclothing]
equipSound: equipSound:
path: /Audio/Items/jumpsuit_equip.ogg path: /Audio/Items/jumpsuit_equip.ogg
- type: Butcherable - type: Butcherable
@@ -35,7 +35,7 @@
- type: Sprite - type: Sprite
state: icon state: icon
- type: Clothing - type: Clothing
Slots: [innerclothing] slots: [innerclothing]
femaleMask: UniformTop femaleMask: UniformTop
equipSound: equipSound:
path: /Audio/Items/jumpsuit_equip.ogg path: /Audio/Items/jumpsuit_equip.ogg

View File

@@ -5,5 +5,3 @@
components: components:
- type: Sprite - type: Sprite
netsync: false netsync: false
- type: Clothing
size: 5

View File

@@ -83,7 +83,6 @@
- type: Item - type: Item
size: 1 size: 1
sprite: Objects/Weapons/Melee/debug.rsi sprite: Objects/Weapons/Melee/debug.rsi
prefix: inhand
- type: entity - type: entity
name: bang stick 100dmg name: bang stick 100dmg

View File

@@ -14,7 +14,7 @@
- type: Clothing - type: Clothing
sprite: Objects/Tools/debug.rsi sprite: Objects/Tools/debug.rsi
quickEquip: false quickEquip: false
Slots: slots:
- Belt - Belt
- type: MeleeWeapon - type: MeleeWeapon
damage: damage:

View File

@@ -756,12 +756,13 @@
layers: layers:
- map: ["enum.DamageStateVisualLayers.Base"] - map: ["enum.DamageStateVisualLayers.Base"]
state: mouse-0 state: mouse-0
- type: Clothing - type: Item
size: 5 size: 5
- type: Clothing
quickEquip: false quickEquip: false
sprite: Mobs/Animals/mouse.rsi sprite: Mobs/Animals/mouse.rsi
HeldPrefix: 0 equippedPrefix: 0
Slots: slots:
- HEAD - HEAD
- type: Physics - type: Physics
- type: Fixtures - type: Fixtures
@@ -861,7 +862,7 @@
state: mouse-1 state: mouse-1
sprite: Mobs/Animals/mouse.rsi sprite: Mobs/Animals/mouse.rsi
- type: Clothing - type: Clothing
HeldPrefix: 1 equippedPrefix: 1
- type: Appearance - type: Appearance
- type: DamageStateVisuals - type: DamageStateVisuals
states: states:
@@ -887,7 +888,7 @@
state: mouse-2 state: mouse-2
sprite: Mobs/Animals/mouse.rsi sprite: Mobs/Animals/mouse.rsi
- type: Clothing - type: Clothing
HeldPrefix: 1 equippedPrefix: 1
- type: Appearance - type: Appearance
- type: DamageStateVisuals - type: DamageStateVisuals
states: states:

View File

@@ -69,7 +69,7 @@
- type: Sprite - type: Sprite
state: homer state: homer
- type: Item - type: Item
HeldPrefix: pink heldPrefix: pink
- type: entity - type: entity
name: chaos donut name: chaos donut
@@ -100,7 +100,7 @@
- type: Sprite - type: Sprite
state: pink state: pink
- type: Item - type: Item
HeldPrefix: pink heldPrefix: pink
- type: entity - type: entity
name: spaceman's donut name: spaceman's donut
@@ -202,7 +202,7 @@
- type: Sprite - type: Sprite
state: jelly-homer state: jelly-homer
- type: Item - type: Item
HeldPrefix: pink heldPrefix: pink
- type: SolutionContainerManager - type: SolutionContainerManager
solutions: solutions:
food: food:
@@ -222,7 +222,7 @@
- type: Sprite - type: Sprite
state: jelly-pink state: jelly-pink
- type: Item - type: Item
HeldPrefix: pink heldPrefix: pink
- type: SolutionContainerManager - type: SolutionContainerManager
solutions: solutions:
food: food:

View File

@@ -23,7 +23,7 @@
- type: Item - type: Item
sprite: Objects/Consumable/Food/Baked/donut.rsi sprite: Objects/Consumable/Food/Baked/donut.rsi
size: 6 size: 6
HeldPrefix: box heldPrefix: box
- type: StorageFill - type: StorageFill
contents: contents:
- id: FoodDonutPink - id: FoodDonutPink
@@ -66,7 +66,6 @@
- Egg - Egg
- type: Item - type: Item
sprite: Objects/Consumable/Food/egg.rsi sprite: Objects/Consumable/Food/egg.rsi
state: box-closed
size: 12 size: 12
- type: StorageFill - type: StorageFill
contents: contents:
@@ -159,7 +158,7 @@
- Pizza - Pizza
- type: Item - type: Item
sprite: Objects/Consumable/Food/Baked/pizza.rsi sprite: Objects/Consumable/Food/Baked/pizza.rsi
HeldPrefix: box heldPrefix: box
- type: Appearance - type: Appearance
visuals: visuals:
- type: StorageVisualizer - type: StorageVisualizer
@@ -224,7 +223,7 @@
- type: Item - type: Item
sprite: Objects/Consumable/Food/Baked/nuggets.rsi sprite: Objects/Consumable/Food/Baked/nuggets.rsi
size: 6 size: 6
HeldPrefix: box heldPrefix: box
- type: StorageFill - type: StorageFill
contents: contents:
- id: FoodBakedNugget - id: FoodBakedNugget
@@ -266,7 +265,6 @@
- type: Item - type: Item
sprite: Objects/Consumable/Food/Baked/donkpocket.rsi sprite: Objects/Consumable/Food/Baked/donkpocket.rsi
size: 6 size: 6
color: red
- type: StorageFill - type: StorageFill
contents: contents:
- id: FoodDonkpocket - id: FoodDonkpocket
@@ -309,7 +307,6 @@
state: pizza-box state: pizza-box
- type: Item - type: Item
sprite: Objects/Consumable/Food/Baked/donkpocket.rsi sprite: Objects/Consumable/Food/Baked/donkpocket.rsi
color: white
- type: StorageFill - type: StorageFill
contents: contents:
- id: FoodDonkpocketPizza - id: FoodDonkpocketPizza
@@ -324,7 +321,6 @@
state: gondola-box state: gondola-box
- type: Item - type: Item
sprite: Objects/Consumable/Food/Baked/donkpocket.rsi sprite: Objects/Consumable/Food/Baked/donkpocket.rsi
color: brown
- type: StorageFill - type: StorageFill
contents: contents:
- id: FoodDonkpocketGondola - id: FoodDonkpocketGondola
@@ -353,7 +349,6 @@
state: banana-box state: banana-box
- type: Item - type: Item
sprite: Objects/Consumable/Food/Baked/donkpocket.rsi sprite: Objects/Consumable/Food/Baked/donkpocket.rsi
color: yellow
- type: StorageFill - type: StorageFill
contents: contents:
- id: FoodDonkpocketHonk - id: FoodDonkpocketHonk
@@ -369,7 +364,6 @@
state: dink-box state: dink-box
- type: Item - type: Item
sprite: Objects/Consumable/Food/Baked/donkpocket.rsi sprite: Objects/Consumable/Food/Baked/donkpocket.rsi
color: green
- type: StorageFill - type: StorageFill
contents: contents:
- id: FoodDonkpocketDink - id: FoodDonkpocketDink

View File

@@ -16,9 +16,8 @@
netsync: false netsync: false
- type: Item - type: Item
sprite: Objects/Consumable/Food/snacks.rsi sprite: Objects/Consumable/Food/snacks.rsi
HeldPrefix: packet heldPrefix: packet
size: 3 size: 3
color: gray
- type: DamageOnLand - type: DamageOnLand
damage: damage:
types: types:
@@ -42,8 +41,7 @@
netsync: false netsync: false
- type: Item - type: Item
sprite: Objects/Consumable/Food/snacks.rsi sprite: Objects/Consumable/Food/snacks.rsi
HeldPrefix: packet heldPrefix: packet
color: gray
size: 3 size: 3
# Tins # Tins

View File

@@ -118,7 +118,6 @@
- type: Item - type: Item
size: 10 size: 10
sprite: Objects/Specific/Hydroponics/nettle.rsi sprite: Objects/Specific/Hydroponics/nettle.rsi
prefix: inhand
- type: MeleeWeapon - type: MeleeWeapon
damage: damage:
types: types:
@@ -175,7 +174,7 @@
state: peel state: peel
- type: Item - type: Item
sprite: Objects/Specific/Hydroponics/banana.rsi sprite: Objects/Specific/Hydroponics/banana.rsi
HeldPrefix: peel heldPrefix: peel
- type: Slippery - type: Slippery
launchForwardsMultiplier: 1.5 launchForwardsMultiplier: 1.5
- type: StepTrigger - type: StepTrigger
@@ -723,7 +722,7 @@
grindableSolutionName: food grindableSolutionName: food
- type: Clothing - type: Clothing
sprite: Objects/Specific/Hydroponics/ambrosia_vulgaris.rsi sprite: Objects/Specific/Hydroponics/ambrosia_vulgaris.rsi
Slots: slots:
- HEAD - HEAD
- type: entity - type: entity

View File

@@ -18,7 +18,7 @@
Quantity: 10 Quantity: 10
- type: Item - type: Item
sprite: Objects/Consumable/Food/snacks.rsi sprite: Objects/Consumable/Food/snacks.rsi
HeldPrefix: packet heldPrefix: packet
size: 3 size: 3
# Snacks # Snacks
@@ -34,7 +34,6 @@
- type: Sprite - type: Sprite
state: boritos state: boritos
- type: Item - type: Item
color: blue
- type: Food - type: Food
trash: FoodPacketBoritosTrash trash: FoodPacketBoritosTrash
@@ -47,7 +46,6 @@
- type: Sprite - type: Sprite
state: cheesiehonkers state: cheesiehonkers
- type: Item - type: Item
color: orange
- type: Food - type: Food
trash: FoodPacketCheesieTrash trash: FoodPacketCheesieTrash
@@ -60,7 +58,6 @@
- type: Sprite - type: Sprite
state: chips state: chips
- type: Item - type: Item
color: green
- type: Food - type: Food
trash: FoodPacketChipsTrash trash: FoodPacketChipsTrash
@@ -75,7 +72,7 @@
state: chocolatebar state: chocolatebar
netsync: false netsync: false
- type: Item - type: Item
HeldPrefix: chocolatebar heldPrefix: chocolatebar
size: 3 size: 3
- type: SpawnItemsOnUse - type: SpawnItemsOnUse
items: items:
@@ -93,7 +90,6 @@
- type: Sprite - type: Sprite
state: chocolatebar-open state: chocolatebar-open
- type: Item - type: Item
color: brown
- type: SolutionContainerManager - type: SolutionContainerManager
solutions: solutions:
food: food:
@@ -113,7 +109,6 @@
- type: Sprite - type: Sprite
state: energybar state: energybar
- type: Item - type: Item
color: lime
- type: SpawnItemsOnUse - type: SpawnItemsOnUse
items: items:
- id: FoodPacketEnergyTrash - id: FoodPacketEnergyTrash
@@ -130,7 +125,6 @@
- type: Sprite - type: Sprite
state: energybar-open state: energybar-open
- type: Item - type: Item
color: yellow
- type: entity - type: entity
name: popcorn name: popcorn
@@ -141,7 +135,7 @@
- type: Sprite - type: Sprite
state: popcorn state: popcorn
- type: Item - type: Item
HeldPrefix: popcorn heldPrefix: popcorn
- type: Food - type: Food
trash: FoodPacketPopcornTrash trash: FoodPacketPopcornTrash
@@ -154,7 +148,6 @@
- type: Sprite - type: Sprite
state: raisins state: raisins
- type: Item - type: Item
color: red
- type: Food - type: Food
trash: FoodPacketRaisinsTrash trash: FoodPacketRaisinsTrash
@@ -167,7 +160,6 @@
- type: Sprite - type: Sprite
state: susjerky state: susjerky
- type: Item - type: Item
color: red
- type: Food - type: Food
trash: FoodPacketSusTrash trash: FoodPacketSusTrash
@@ -180,10 +172,9 @@
- type: Sprite - type: Sprite
state: syndicakes state: syndicakes
- type: Item - type: Item
color: white
- type: Food - type: Food
trash: FoodPacketSyndiTrash trash: FoodPacketSyndiTrash
- type: entity - type: entity
name: chow mein name: chow mein
parent: FoodSnackBase parent: FoodSnackBase
@@ -193,7 +184,6 @@
- type: Sprite - type: Sprite
state: chinese1 state: chinese1
- type: Item - type: Item
color: red
- type: SolutionContainerManager - type: SolutionContainerManager
solutions: solutions:
food: food:
@@ -205,7 +195,7 @@
Quantity: 2 Quantity: 2
- type: Food - type: Food
trash: FoodPacketChowMeinTrash trash: FoodPacketChowMeinTrash
- type: entity - type: entity
name: dan dan noodles name: dan dan noodles
parent: FoodSnackBase parent: FoodSnackBase
@@ -246,7 +236,7 @@
Quantity: 1 Quantity: 1
- type: Item - type: Item
sprite: Objects/Consumable/Food/snacks.rsi sprite: Objects/Consumable/Food/snacks.rsi
HeldPrefix: packet heldPrefix: packet
size: 1 size: 1
- type: Food - type: Food
trash: FoodCookieFortune trash: FoodCookieFortune
@@ -291,7 +281,7 @@
- type: entity - type: entity
id: FoodSnackMREBrownie id: FoodSnackMREBrownie
parent: BaseItem parent: BaseItem
name: brownie name: brownie
description: A precisely mixed brownie, made to withstand blunt trauma and harsh conditions. Tastes like shit. description: A precisely mixed brownie, made to withstand blunt trauma and harsh conditions. Tastes like shit.
components: components:
@@ -305,7 +295,7 @@
- id: FoodSnackMREBrownieOpen - id: FoodSnackMREBrownieOpen
sound: sound:
path: /Audio/Effects/unwrap.ogg path: /Audio/Effects/unwrap.ogg
- type: entity - type: entity
id: FoodSnackMREBrownieOpen id: FoodSnackMREBrownieOpen
@@ -339,7 +329,7 @@
netsync: false netsync: false
- type: Item - type: Item
sprite: Objects/Consumable/Food/snacks.rsi sprite: Objects/Consumable/Food/snacks.rsi
HeldPrefix: packet heldPrefix: packet
- type: Tag - type: Tag
tags: tags:
- Trash - Trash
@@ -355,7 +345,6 @@
- type: Sprite - type: Sprite
state: boritos-trash state: boritos-trash
- type: Item - type: Item
color: blue
- type: entity - type: entity
noSpawn: true noSpawn: true
@@ -366,7 +355,6 @@
- type: Sprite - type: Sprite
state: cheesiehonkers-trash state: cheesiehonkers-trash
- type: Item - type: Item
color: orange
- type: entity - type: entity
noSpawn: true noSpawn: true
@@ -377,7 +365,6 @@
- type: Sprite - type: Sprite
state: chips-trash state: chips-trash
- type: Item - type: Item
color: green
- type: entity - type: entity
noSpawn: true noSpawn: true
@@ -388,7 +375,6 @@
- type: Sprite - type: Sprite
state: chocolatebar-trash state: chocolatebar-trash
- type: Item - type: Item
color: red
- type: entity - type: entity
noSpawn: true noSpawn: true
@@ -399,7 +385,6 @@
- type: Sprite - type: Sprite
state: energybar-trash state: energybar-trash
- type: Item - type: Item
color: green
- type: entity - type: entity
noSpawn: true noSpawn: true
@@ -410,7 +395,6 @@
- type: Sprite - type: Sprite
state: pistachio-trash state: pistachio-trash
- type: Item - type: Item
color: green
- type: entity - type: entity
noSpawn: true noSpawn: true
@@ -421,7 +405,6 @@
- type: Sprite - type: Sprite
state: popcorn-trash state: popcorn-trash
- type: Item - type: Item
state: blue
- type: entity - type: entity
noSpawn: true noSpawn: true
@@ -432,7 +415,6 @@
- type: Sprite - type: Sprite
state: raisins-trash state: raisins-trash
- type: Item - type: Item
color: red
- type: entity - type: entity
noSpawn: true noSpawn: true
@@ -443,7 +425,6 @@
- type: Sprite - type: Sprite
state: semki-trash state: semki-trash
- type: Item - type: Item
color: orange
- type: entity - type: entity
noSpawn: true noSpawn: true
@@ -454,7 +435,6 @@
- type: Sprite - type: Sprite
state: susjerky-trash state: susjerky-trash
- type: Item - type: Item
color: red
- type: entity - type: entity
noSpawn: true noSpawn: true
@@ -465,7 +445,6 @@
- type: Sprite - type: Sprite
state: syndicakes-trash state: syndicakes-trash
- type: Item - type: Item
color: white
- type: entity - type: entity
noSpawn: true noSpawn: true
@@ -476,8 +455,7 @@
- type: Sprite - type: Sprite
state: chinese1 state: chinese1
- type: Item - type: Item
color: red
- type: entity - type: entity
noSpawn: true noSpawn: true
parent: FoodPacketTrash parent: FoodPacketTrash
@@ -487,8 +465,7 @@
- type: Sprite - type: Sprite
state: chinese2 state: chinese2
- type: Item - type: Item
color: white
- type: entity - type: entity
noSpawn: true noSpawn: true
parent: FoodPacketTrash parent: FoodPacketTrash
@@ -499,7 +476,6 @@
- type: Sprite - type: Sprite
state: fortune state: fortune
- type: Item - type: Item
color: white
- type: entity - type: entity
noSpawn: true noSpawn: true

View File

@@ -19,8 +19,9 @@
- type: SpaceGarbage - type: SpaceGarbage
- type: Clothing - type: Clothing
sprite: Objects/Consumable/Smokeables/Cigarettes/cigarette.rsi sprite: Objects/Consumable/Smokeables/Cigarettes/cigarette.rsi
Slots: [ mask ] slots: [ mask ]
HeldPrefix: unlit equippedPrefix: unlit
- type: Item
size: 1 size: 1
- type: Construction - type: Construction
graph: smokeableCigarette graph: smokeableCigarette

View File

@@ -16,8 +16,9 @@
- type: SpaceGarbage - type: SpaceGarbage
- type: Clothing - type: Clothing
sprite: Objects/Consumable/Smokeables/Cigarettes/blunt.rsi sprite: Objects/Consumable/Smokeables/Cigarettes/blunt.rsi
Slots: [ mask ] slots: [ mask ]
HeldPrefix: unlit equippedPrefix: unlit
- type: Item
size: 1 size: 1
- type: Construction - type: Construction
graph: smokeableJoint graph: smokeableJoint
@@ -48,8 +49,9 @@
- type: SpaceGarbage - type: SpaceGarbage
- type: Clothing - type: Clothing
sprite: Objects/Consumable/Smokeables/Cigarettes/blunt.rsi sprite: Objects/Consumable/Smokeables/Cigarettes/blunt.rsi
Slots: [ mask ] slots: [ mask ]
HeldPrefix: unlit equippedPrefix: unlit
- type: Item
size: 1 size: 1
- type: Construction - type: Construction
graph: smokeableBlunt graph: smokeableBlunt

View File

@@ -17,8 +17,9 @@
- Trash - Trash
- type: Clothing - type: Clothing
sprite: Objects/Consumable/Smokeables/Cigars/cigar.rsi sprite: Objects/Consumable/Smokeables/Cigars/cigar.rsi
Slots: [ mask ] slots: [ mask ]
HeldPrefix: unlit equippedPrefix: unlit
- type: Item
size: 1 size: 1
- type: entity - type: entity
@@ -33,6 +34,7 @@
state: unlit-icon state: unlit-icon
- type: Clothing - type: Clothing
sprite: Objects/Consumable/Smokeables/Cigars/cigar-gold.rsi sprite: Objects/Consumable/Smokeables/Cigars/cigar-gold.rsi
Slots: [ mask ] slots: [ mask ]
HeldPrefix: unlit equippedPrefix: unlit
- type: Item
size: 1 size: 1

Some files were not shown because too many files have changed in this diff Show More