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.Item;
using Content.Shared.Clothing.Components;
using Robust.Shared.GameStates;
namespace Content.Client.Clothing
{
[RegisterComponent]
[ComponentReference(typeof(SharedItemComponent))]
[ComponentReference(typeof(ItemComponent))]
[NetworkedComponent()]
public sealed class ClothingComponent : ItemComponent
[ComponentReference(typeof(SharedClothingComponent))]
public sealed class ClothingComponent : SharedClothingComponent
{
[ViewVariables(VVAccess.ReadWrite)]
[DataField("femaleMask")]
public FemaleClothingMask FemaleMask { get; } = FemaleClothingMask.UniformFull;
public FemaleClothingMask FemaleMask = FemaleClothingMask.UniformFull;
public string? InSlot;
}

View File

@@ -4,6 +4,7 @@ using System.Linq;
using Content.Client.Inventory;
using Content.Shared.CharacterAppearance;
using Content.Shared.Clothing;
using Content.Shared.Clothing.Components;
using Content.Shared.Inventory;
using Content.Shared.Inventory.Events;
using Content.Shared.Item;
@@ -16,7 +17,7 @@ using static Robust.Shared.GameObjects.SharedSpriteComponent;
namespace Content.Client.Clothing;
public sealed class ClothingSystem : EntitySystem
public sealed class ClothingVisualsSystem : EntitySystem
{
/// <summary>
/// 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, GotUnequippedEvent>(OnGotUnequipped);
SubscribeLocalEvent<SharedItemComponent, GetEquipmentVisualsEvent>(OnGetVisuals);
SubscribeLocalEvent<ClothingComponent, GetEquipmentVisualsEvent>(OnGetVisuals);
SubscribeLocalEvent<ClientInventoryComponent, VisualsChangedEvent>(OnVisualsChanged);
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))
return;
@@ -99,15 +100,15 @@ public sealed class ClothingSystem : EntitySystem
/// <remarks>
/// Useful for lazily adding clothing sprites without modifying yaml. And for backwards compatibility.
/// </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)
{
layers = null;
RSI? rsi = null;
if (item.RsiPath != null)
rsi = _cache.GetResource<RSIResource>(TextureRoot / item.RsiPath).RSI;
if (clothing.RsiPath != null)
rsi = _cache.GetResource<RSIResource>(TextureRoot / clothing.RsiPath).RSI;
else if (TryComp(uid, out SpriteComponent? sprite))
rsi = sprite.BaseRSI;
@@ -117,9 +118,9 @@ public sealed class ClothingSystem : EntitySystem
var correctedSlot = slot;
TemporarySlotMap.TryGetValue(correctedSlot, out correctedSlot);
var state = (item.EquippedPrefix == null)
var state = (clothing.EquippedPrefix == null)
? $"equipped-{correctedSlot}"
: $"{item.EquippedPrefix}-equipped-{correctedSlot}";
: $"{clothing.EquippedPrefix}-equipped-{correctedSlot}";
// species specific
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 IConfigurationManager _config = default!;
[Dependency] private readonly IItemSlotManager _itemSlotManager = default!;
[Dependency] private readonly ClothingSystem _clothingSystem = default!;
[Dependency] private readonly ClothingVisualsSystem _clothingVisualsSystem = default!;
public const int ButtonSize = 64;
private const int ButtonSeparation = 4;
@@ -165,7 +165,7 @@ namespace Content.Client.Inventory
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,
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.Item;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Client.ResourceManagement;
using Robust.Shared.Containers;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using static Robust.Shared.GameObjects.SharedSpriteComponent;
namespace Content.Client.Items.Systems;
@@ -19,18 +19,16 @@ public sealed class ItemSystem : SharedItemSystem
{
base.Initialize();
SubscribeLocalEvent<SharedItemComponent, GetInhandVisualsEvent>(OnGetVisuals);
SubscribeLocalEvent<ItemComponent, GetInhandVisualsEvent>(OnGetVisuals);
}
#region InhandVisuals
/// <summary>
/// When an items visual state changes, notify and entities that are holding this item that their sprite may need updating.
/// </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 (_containerSystem.TryGetContainingContainer(uid, out var container))
RaiseLocalEvent(container.Owner, new VisualsChangedEvent(uid, container.ID), true);
@@ -39,12 +37,12 @@ public sealed class ItemSystem : SharedItemSystem
/// <summary>
/// An entity holding this item is requesting visual information for in-hand sprites.
/// </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()}";
// 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
if (!TryGetDefaultVisuals(uid, item, defaultKey, out layers))
@@ -71,7 +69,7 @@ public sealed class ItemSystem : SharedItemSystem
/// <remarks>
/// Useful for lazily adding in-hand sprites without modifying yaml. And backwards compatibility.
/// </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;
@@ -85,9 +83,9 @@ public sealed class ItemSystem : SharedItemSystem
if (rsi == null || rsi.Path == null)
return false;
var state = (item.EquippedPrefix == null)
var state = (item.HeldPrefix == null)
? defaultKey
: $"{item.EquippedPrefix}-{defaultKey}";
: $"{item.HeldPrefix}-{defaultKey}";
if (!rsi.TryGetState(state, out var _))
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)
// 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.VisualsChanged(uid);
_itemSys.SetHeldPrefix(uid, state.Activated ? "on" : "off", item);
}
}
}

View File

@@ -1,4 +1,5 @@
using Content.Client.Clothing;
using Content.Shared.Clothing.EntitySystems;
using Content.Shared.Movement.Components;
using Content.Shared.Movement.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 IMapManager _mapManager = default!;
[Dependency] private readonly ClothingSystem _clothing = default!;
public override void Initialize()
{
@@ -35,7 +37,7 @@ public sealed class JetpackSystem : SharedJetpackSystem
args.Sprite?.LayerSetState(0, state);
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)

View File

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

View File

@@ -18,7 +18,7 @@ public sealed class ToggleableLightVisualsSystem : VisualizerSystem<ToggleableLi
{
base.Initialize();
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)

View File

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

View File

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

View File

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

View File

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

View File

@@ -25,7 +25,7 @@ namespace Content.Server.AI.Operators.Inventory
var handsSys = sysMan.GetEntitySystem<SharedHandsSystem>();
if (entMan.Deleted(_target)
|| !entMan.HasComponent<SharedItemComponent>(_target)
|| !entMan.HasComponent<ItemComponent>(_target)
|| _target.IsInContainer()
|| !interactionSystem.InRangeUnobstructed(_owner, _target, popup: true))
{

View File

@@ -29,7 +29,7 @@ namespace Content.Server.AI.Utility.Considerations.Clothing
continue;
}
if ((clothingComponent.SlotFlags & slotDef.SlotFlags) != 0)
if ((clothingComponent.Slots & slotDef.SlotFlags) != 0)
{
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
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;
}

View File

@@ -11,7 +11,7 @@ namespace Content.Server.AI.Utility.Considerations.Inventory
{
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;
}

View File

@@ -35,7 +35,7 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Gloves
foreach (var entity in context.GetState<EnumerableInventoryState>().GetValue())
{
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};
}

View File

@@ -33,7 +33,7 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Gloves
foreach (var entity in context.GetState<NearbyClothingState>().GetValue())
{
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};
}

View File

@@ -34,7 +34,7 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Head
foreach (var entity in context.GetState<EnumerableInventoryState>().GetValue())
{
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};
}

View File

@@ -33,7 +33,7 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Head
foreach (var entity in context.GetState<NearbyClothingState>().GetValue())
{
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};
}

View File

@@ -35,7 +35,7 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.OuterClothing
foreach (var entity in context.GetState<EnumerableInventoryState>().GetValue())
{
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};
}

View File

@@ -34,7 +34,7 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.OuterClothing
foreach (var entity in context.GetState<NearbyClothingState>().GetValue())
{
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};
}

View File

@@ -35,7 +35,7 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Shoes
foreach (var entity in context.GetState<EnumerableInventoryState>().GetValue())
{
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};
}

View File

@@ -34,7 +34,7 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Shoes
foreach (var entity in context.GetState<NearbyClothingState>().GetValue())
{
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};
}

View File

@@ -82,7 +82,7 @@ namespace Content.Server.Chat
return;
}
var itemQuery = GetEntityQuery<SharedItemComponent>();
var itemQuery = GetEntityQuery<ItemComponent>();
// Suicide by nearby entity (ex: Microwave)
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 Robust.Shared.GameStates;
namespace Content.Server.Clothing.Components
{
// Needed for client-side clothing component.
[RegisterComponent]
[ComponentReference(typeof(SharedItemComponent))]
[Virtual]
public class ItemComponent : SharedItemComponent{}
[RegisterComponent]
[NetworkedComponent]
[ComponentReference(typeof(SharedItemComponent))]
public sealed class ClothingComponent : ItemComponent
[ComponentReference(typeof(SharedClothingComponent))]
public sealed class ClothingComponent : SharedClothingComponent
{
[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.Clothing.Components;
using Content.Shared.Alert;
using Content.Shared.Clothing;
using Content.Shared.Clothing.EntitySystems;
using Content.Shared.Inventory;
using Content.Shared.Inventory.Events;
using Robust.Shared.Containers;
using Robust.Shared.GameStates;
using static Content.Shared.Clothing.MagbootsComponent;

View File

@@ -13,6 +13,7 @@ using Content.Server.Disease.Components;
using Content.Server.IdentityManagement;
using Content.Server.Nutrition.EntitySystems;
using Content.Server.Popups;
using Content.Shared.Clothing.EntitySystems;
using Content.Shared.IdentityManagement.Components;
using Robust.Shared.Player;
@@ -26,6 +27,7 @@ namespace Content.Server.Clothing
[Dependency] private readonly InventorySystem _inventorySystem = default!;
[Dependency] private readonly PopupSystem _popupSystem = default!;
[Dependency] private readonly IdentitySystem _identity = default!;
[Dependency] private readonly ClothingSystem _clothing = default!;
public override void Initialize()
{
@@ -79,11 +81,10 @@ namespace Content.Server.Clothing
private void ToggleMaskComponents(EntityUid uid, MaskComponent mask, EntityUid wearer, bool isEquip = false)
{
//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
item.EquippedPrefix = mask.IsToggled ? "toggled" : null;
Dirty(item);
_clothing.SetEquippedPrefix(uid, mask.IsToggled ? "toggled" : null, clothing);
}
// toggle ingestion blocking

View File

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

View File

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

View File

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

View File

@@ -58,7 +58,7 @@ namespace Content.Server.Drone
if (args.Target != null && !HasComp<UnremoveableComponent>(args.Target) && NonDronesInRange(uid, component))
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"))
args.Cancel();

View File

@@ -56,7 +56,7 @@ public sealed class SpillableSystem : EntitySystem
// check if entity was actually used as clothing
// 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 (!_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.
InteractHand(user, target.Value);

View File

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

View File

@@ -107,7 +107,7 @@ namespace Content.Server.Kitchen.EntitySystems
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));
return;

View File

@@ -1,5 +1,6 @@
using Content.Server.Clothing.Components;
using Content.Server.Light.Components;
using Content.Shared.Clothing.EntitySystems;
using Content.Shared.Interaction.Events;
using Content.Shared.Item;
using Content.Shared.Light.Component;
@@ -14,6 +15,9 @@ namespace Content.Server.Light.EntitySystems
[UsedImplicitly]
public sealed class ExpendableLightSystem : EntitySystem
{
[Dependency] private readonly SharedItemSystem _item = default!;
[Dependency] private readonly ClothingSystem _clothing = default!;
public override void Initialize()
{
base.Initialize();
@@ -59,9 +63,9 @@ namespace Content.Server.Light.EntitySystems
UpdateSpriteAndSounds(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;
@@ -76,9 +80,9 @@ namespace Content.Server.Light.EntitySystems
{
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;
@@ -154,15 +158,15 @@ namespace Content.Server.Light.EntitySystems
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)
{
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;

View File

@@ -16,6 +16,7 @@ namespace Content.Server.Light.EntitySystems
private HashSet<MatchstickComponent> _litMatches = new();
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
[Dependency] private readonly TransformSystem _transformSystem = default!;
[Dependency] private readonly SharedItemSystem _item = default!;
public override void Initialize()
{
@@ -94,15 +95,15 @@ namespace Content.Server.Light.EntitySystems
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)
{
case SmokableState.Lit:
item.EquippedPrefix = "lit";
_item.SetHeldPrefix(component.Owner, "lit", item);
break;
default:
item.EquippedPrefix = "unlit";
_item.SetHeldPrefix(component.Owner, "unlit", item);
break;
}
}

View File

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

View File

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

View File

@@ -134,7 +134,7 @@ namespace Content.Server.PneumaticCannon
// this overrides the ServerStorageComponent's insertion stuff because
// 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
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))
{
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
// not just taken in pockets or something
var isCorrectSlot = clothing.SlotFlags.HasFlag(args.SlotFlags);
var isCorrectSlot = clothing.Slots.HasFlag(args.SlotFlags);
if (!isCorrectSlot) return;
// does the user already has this accent?

View File

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

View File

@@ -54,7 +54,7 @@ namespace Content.Server.Storage.EntitySystems
/// </summary>
/// <returns>True if item was hidden inside stash</returns>
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)
{
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.
// 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>();
foreach (var entity in _entityLookupSystem.GetEntitiesInRange(eventArgs.ClickLocation, storageComp.AreaInsertRadius, LookupFlags.None))
{
if (entity == eventArgs.User
|| !HasComp<SharedItemComponent>(entity)
|| !HasComp<ItemComponent>(entity)
|| !_interactionSystem.InRangeUnobstructed(eventArgs.User, entity))
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
if (_containerSystem.IsEntityInContainer(entity)
|| entity == eventArgs.User
|| !HasComp<SharedItemComponent>(entity))
|| !HasComp<ItemComponent>(entity))
continue;
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)
|| target == eventArgs.User
|| !HasComp<SharedItemComponent>(target))
|| !HasComp<ItemComponent>(target))
return;
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)
return;
var itemQuery = GetEntityQuery<SharedItemComponent>();
var itemQuery = GetEntityQuery<ItemComponent>();
foreach (var entity in storageComp.Storage.ContainedEntities)
{
@@ -491,7 +491,7 @@ namespace Content.Server.Storage.EntitySystems
return false;
}
if (TryComp(insertEnt, out SharedItemComponent? itemComp) &&
if (TryComp(insertEnt, out ItemComponent? itemComp) &&
itemComp.Size > storageComp.StorageCapacityMax - storageComp.StorageUsed)
{
reason = "comp-storage-insufficient-capacity";

View File

@@ -24,6 +24,8 @@ namespace Content.Server.Stunnable.Systems
{
public sealed class StunbatonSystem : EntitySystem
{
[Dependency] private readonly SharedItemSystem _item = default!;
public override void Initialize()
{
base.Initialize();
@@ -88,11 +90,12 @@ namespace Content.Server.Stunnable.Systems
if (!comp.Activated)
return;
if (TryComp<SharedItemComponent>(comp.Owner, out var item))
item.EquippedPrefix = "off";
if (TryComp(comp.Owner, out AppearanceComponent? appearance))
if (TryComp<AppearanceComponent>(comp.Owner, out var appearance) &&
TryComp<ItemComponent>(comp.Owner, out var item))
{
_item.SetHeldPrefix(comp.Owner, "off", item);
appearance.SetData(ToggleVisuals.Toggled, false);
}
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;
}
if (TryComp<SharedItemComponent>(comp.Owner, out var item))
item.EquippedPrefix = "on";
if (TryComp(comp.Owner, out AppearanceComponent? appearance))
if (EntityManager.TryGetComponent<AppearanceComponent>(comp.Owner, out var appearance) &&
EntityManager.TryGetComponent<ItemComponent>(comp.Owner, out var item))
{
_item.SetHeldPrefix(comp.Owner, "on", item);
appearance.SetData(ToggleVisuals.Toggled, true);
}
SoundSystem.Play(comp.SparksSound.GetSound(), playerFilter, comp.Owner, AudioHelpers.WithVariation(0.25f));
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
// InventoryComponent but still would have default heat resistance in the future (maybe)
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;
}

View File

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

View File

@@ -5,6 +5,7 @@ using Content.Server.Chemistry.EntitySystems;
using Content.Server.DoAfter;
using Content.Server.Popups;
using Content.Shared.Audio;
using Content.Shared.Item;
using Content.Shared.Tools.Components;
using Robust.Server.GameObjects;
using Robust.Shared.Audio;
@@ -25,7 +26,7 @@ namespace Content.Server.Tools
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
[Dependency] private readonly PopupSystem _popupSystem = default!;
[Dependency] private readonly TransformSystem _transformSystem = default!;
[Dependency] private readonly SharedItemSystem _itemSystem = default!;
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 SharedRgbLightControllerSystem _rgbSystem = default!;
[Dependency] private readonly SharedItemSystem _item = default!;
public override void Initialize()
{
@@ -67,9 +68,9 @@ namespace Content.Server.Weapon.Melee.EnergySword
if (!comp.Activated)
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))
@@ -92,9 +93,9 @@ namespace Content.Server.Weapon.Melee.EnergySword
if (comp.Activated)
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);

View File

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

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

View File

@@ -33,7 +33,7 @@ namespace Content.Shared.Disposal
var otherBody = args.BodyB.Owner;
// Items dropped shouldn't collide but items thrown should
if (EntityManager.HasComponent<SharedItemComponent>(otherBody) &&
if (EntityManager.HasComponent<ItemComponent>(otherBody) &&
!EntityManager.HasComponent<ThrownItemComponent>(otherBody))
{
args.Cancel();
@@ -60,7 +60,7 @@ namespace Content.Shared.Disposal
return false;
// 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))
{
return false;

View File

@@ -1,3 +1,4 @@
using Content.Shared.Clothing.Components;
using Content.Shared.Inventory.Events;
using Content.Shared.Inventory;
using Content.Shared.Item;
@@ -16,10 +17,10 @@ namespace Content.Shared.Eye.Blinding
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;
// Is the clothing in its actual slot?
if (!clothing.SlotFlags.HasFlag(args.SlotFlags))
if (!clothing.Slots.HasFlag(args.SlotFlags))
return;
component.IsActive = true;

View File

@@ -12,7 +12,7 @@ public abstract partial class SharedHandsSystem : EntitySystem
/// <summary>
/// Tries to pick up an entity to a specific hand. If no explicit hand is specified, defaults to using the currently active hand.
/// </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))
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
/// restrictions are added, there a might need to be a TryPickupAllHands or something like that.
/// </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))
return false;
@@ -45,7 +45,7 @@ public abstract partial class SharedHandsSystem : EntitySystem
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))
return false;
@@ -67,7 +67,7 @@ public abstract partial class SharedHandsSystem : EntitySystem
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))
return false;
@@ -81,7 +81,7 @@ public abstract partial class SharedHandsSystem : EntitySystem
/// <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.
/// </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))
return false;
@@ -90,7 +90,7 @@ public abstract partial class SharedHandsSystem : EntitySystem
if (handContainer == null || handContainer.ContainedEntity != null)
return false;
if (!Resolve(entity, ref item, false) || !item.CanPickup)
if (!Resolve(entity, ref item, false))
return false;
if (TryComp(entity, out PhysicsComponent? physics) && physics.BodyType == BodyType.Static)
@@ -106,7 +106,7 @@ public abstract partial class SharedHandsSystem : EntitySystem
/// <summary>
/// Puts an item into any hand, preferring the active hand, or puts it on the floor.
/// </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
|| !Resolve(uid.Value, ref handsComp, false)

View File

@@ -470,7 +470,7 @@ namespace Content.Shared.Interaction
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
// inside of walls, users can still pick them up.

View File

@@ -38,7 +38,7 @@ public abstract partial class InventorySystem
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)
|| !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))
{
// 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;
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,
InventoryComponent? inventory = null, SharedItemComponent? item = null) =>
TryEquip(uid, uid, itemUid, slot, silent, force, predicted, inventory, item);
InventoryComponent? inventory = null, SharedClothingComponent? clothing = null) =>
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,
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)
_popup.PopupCursor(Loc.GetString("inventory-component-can-equip-cannot"), Filter.Local());
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(!silent && _gameTiming.IsFirstTimePredicted)
@@ -177,7 +181,7 @@ public abstract partial class InventorySystem
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)
_popup.PopupCursor(Loc.GetString(reason), Filter.Local());
@@ -191,7 +195,7 @@ public abstract partial class InventorySystem
return false;
}
if(!silent && item.EquipSound != null && _gameTiming.IsFirstTimePredicted)
if(!silent && clothing != null && clothing.EquipSound != null && _gameTiming.IsFirstTimePredicted)
{
Filter filter;
@@ -206,7 +210,7 @@ public abstract partial class InventorySystem
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();
@@ -245,22 +249,27 @@ public abstract partial class InventorySystem
public bool CanEquip(EntityUid uid, EntityUid itemUid, string slot, [NotNullWhen(false)] out string? reason,
SlotDefinition? slotDefinition = null, InventoryComponent? inventory = null,
SharedItemComponent? item = null) =>
CanEquip(uid, uid, itemUid, slot, out reason, slotDefinition, inventory, item);
SharedClothingComponent? clothing = null, ItemComponent? item = null) =>
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";
if (!Resolve(target, ref inventory, false) || !Resolve(itemUid, ref item, false))
if (!Resolve(target, ref inventory, false))
return false;
Resolve(itemUid, ref clothing, ref item, false);
if (slotDefinition == null && !TryGetSlot(target, slot, out slotDefinition, inventory: inventory))
return false;
if (slotDefinition.DependsOn != null && !TryGetSlotEntity(target, slotDefinition.DependsOn, out _, inventory))
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";
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,
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,
bool force = false, bool predicted = false, InventoryComponent? inventory = null, SharedItemComponent? item = null) =>
TryUnequip(actor, target, slot, out _, silent, force, predicted, inventory, item);
bool force = false, bool predicted = false, InventoryComponent? inventory = null, SharedClothingComponent? clothing = null) =>
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,
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,
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;
if (!Resolve(target, ref inventory, false))
@@ -370,7 +379,7 @@ public abstract partial class InventorySystem
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;
@@ -385,7 +394,7 @@ public abstract partial class InventorySystem
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();

View File

@@ -1,4 +1,5 @@
using Content.Shared.Item;
using Content.Shared.Clothing.Components;
using Content.Shared.Item;
using Robust.Shared.Prototypes;
namespace Content.Shared.Inventory;
@@ -32,10 +33,6 @@ public partial class InventorySystem
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.
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,49 +1,73 @@
using Content.Shared.Hands.EntitySystems;
using Content.Shared.Hands.EntitySystems;
using Content.Shared.Interaction;
using Content.Shared.Inventory.Events;
using Content.Shared.Verbs;
using Robust.Shared.Containers;
using Robust.Shared.GameStates;
namespace Content.Shared.Item
{
namespace Content.Shared.Item;
public abstract class SharedItemSystem : EntitySystem
{
[Dependency] private readonly SharedHandsSystem _handsSystem = default!;
[Dependency] private readonly SharedContainerSystem _container = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<SharedItemComponent, GetVerbsEvent<InteractionVerb>>(AddPickupVerb);
SubscribeLocalEvent<ItemComponent, GetVerbsEvent<InteractionVerb>>(AddPickupVerb);
SubscribeLocalEvent<SharedSpriteComponent, GotEquippedEvent>(OnEquipped);
SubscribeLocalEvent<SharedSpriteComponent, GotUnequippedEvent>(OnUnequipped);
SubscribeLocalEvent<SharedItemComponent, InteractHandEvent>(OnHandInteract);
SubscribeLocalEvent<ItemComponent, InteractHandEvent>(OnHandInteract);
SubscribeLocalEvent<SharedItemComponent, ComponentGetState>(OnGetState);
SubscribeLocalEvent<SharedItemComponent, ComponentHandleState>(OnHandleState);
SubscribeLocalEvent<ItemComponent, ComponentGetState>(OnGetState);
SubscribeLocalEvent<ItemComponent, ComponentHandleState>(OnHandleState);
}
private void OnHandInteract(EntityUid uid, SharedItemComponent component, InteractHandEvent args)
#region Public API
public void SetSize(EntityUid uid, int size, ItemComponent? component = null)
{
if (args.Handled || !component.CanPickup)
if (!Resolve(uid, ref component))
return;
component.Size = size;
Dirty(component);
}
public void SetHeldPrefix(EntityUid uid, string? heldPrefix, ItemComponent? component = null)
{
if (!Resolve(uid, ref component))
return;
component.HeldPrefix = heldPrefix;
Dirty(component);
VisualsChanged(uid);
}
#endregion
private void OnHandInteract(EntityUid uid, ItemComponent component, InteractHandEvent args)
{
if (args.Handled)
return;
args.Handled = _handsSystem.TryPickup(args.User, uid, animateUser: false);
}
private void OnHandleState(EntityUid uid, SharedItemComponent component, ref ComponentHandleState args)
private void OnHandleState(EntityUid uid, ItemComponent component, ref ComponentHandleState args)
{
if (args.Current is not ItemComponentState state)
return;
component.Size = state.Size;
component.EquippedPrefix = state.EquippedPrefix;
component.HeldPrefix = state.HeldPrefix;
}
private void OnGetState(EntityUid uid, SharedItemComponent component, ref ComponentGetState args)
private void OnGetState(EntityUid uid, ItemComponent component, ref ComponentGetState args)
{
args.State = new ItemComponentState(component.Size, component.EquippedPrefix);
args.State = new ItemComponentState(component.Size, component.HeldPrefix);
}
// Although netsync is being set to false for items client can still update these
@@ -61,24 +85,25 @@ namespace Content.Shared.Item
component.Visible = false;
}
private void AddPickupVerb(EntityUid uid, SharedItemComponent component, GetVerbsEvent<InteractionVerb> args)
private void AddPickupVerb(EntityUid uid, ItemComponent component, GetVerbsEvent<InteractionVerb> args)
{
if (args.Hands == null ||
args.Using != null ||
!args.CanAccess ||
!args.CanInteract ||
!component.CanPickup ||
!_handsSystem.CanPickupAnyHand(args.User, args.Target, handsComp: args.Hands, item: component))
!args.CanInteract) //||
//!_handsSystem.CanPickupAnyHand(args.User, args.Target, handsComp: args.Hands, item: component))
return;
InteractionVerb verb = new();
verb.Act = () => _handsSystem.TryPickupAnyHand(args.User, args.Target, checkActionBlocker: false, handsComp: args.Hands, item: component);
// 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
args.User.TryGetContainer(out var userContainer);
if (args.Target.TryGetContainer(out var container) && container != userContainer)
_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");
@@ -89,7 +114,11 @@ namespace Content.Shared.Item
/// <summary>
/// Notifies any entity that is holding or wearing this item that they may need to update their sprite.
/// </summary>
public virtual void VisualsChanged(EntityUid owner, SharedItemComponent? item = null)
{ }
/// <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: heart
- type: Item
HeldPrefix: hug
heldPrefix: hug
- type: StorageFill
contents:
- id: ClothingMaskBreath

View File

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

View File

@@ -7,10 +7,12 @@
- type: Sprite
sprite: Clothing/Back/Backpacks/backpack.rsi
state: icon
- type: Clothing
- type: Item
size: 9999
sprite: Clothing/Back/Backpacks/backpack.rsi
- type: Clothing
quickEquip: false
Slots:
slots:
- back
sprite: Clothing/Back/Backpacks/backpack.rsi
- type: Storage
@@ -88,10 +90,6 @@
sprite: Clothing/Back/Backpacks/mime.rsi
- type: Clothing
sprite: Clothing/Back/Backpacks/mime.rsi
storageOpenSound:
collection: null
storageInsertSound:
collection: null
- type: entity
parent: ClothingBackpack

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -4,7 +4,7 @@
id: ClothingHeadBase
components:
- type: Clothing
Slots:
slots:
- HEAD
- type: Sprite
state: icon
@@ -18,18 +18,54 @@
id: HatBase
components:
- type: Clothing
Slots:
slots:
- HEAD
- type: Sprite
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
abstract: true
parent: ClothingHeadBase
id: ClothingHeadEVAHelmetBase
name: base space helmet
components:
- type: Clothing
- type: Item
size: 10
- type: PressureProtection
highPressureMultiplier: 0.6
@@ -46,18 +82,19 @@
- type: entity
abstract: true
parent: ClothingHeadBase
# No parent since we aren't actually an item.
id: ClothingHeadHardsuitBase
name: base hardsuit helmet
noSpawn: true
components:
- type: Clickable
- type: InteractionOutline
- type: Clothing
#Apparently the hardsuit helmet equip sound is from a walking mech?
equipSound: /Audio/Mecha/mechmove03.ogg
unequipSound: /Audio/Mecha/mechmove03.ogg
size: 15
canPickup: false # attached to suit.
quickEquip: false
slots: [ HEAD ]
- type: PressureProtection
highPressureMultiplier: 0.3
lowPressureMultiplier: 1000
@@ -94,7 +131,7 @@
visible: false
map: [ "light" ]
- type: Clothing
HeldPrefix: off
equippedPrefix: off
- type: ToggleableLightVisuals
- type: PointLight
netsync: false

View File

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

View File

@@ -20,13 +20,6 @@
addPrefix: false
- type: ToggleableLightVisuals
spriteLayer: light
inhandVisuals:
left:
- state: inhand-left-light
shader: unshaded
right:
- state: inhand-right-light
shader: unshaded
clothingVisuals:
head:
- state: equipped-head-light
@@ -37,15 +30,6 @@
- state: equipped-head
- state: equipped-head-unshaded
shader: unshaded
inhandVisuals:
left:
- state: inhand-left
- state: inhand-left-unshaded
shader: unshaded
right:
- state: inhand-right
- state: inhand-right-unshaded
shader: unshaded
- type: PressureProtection
highPressureMultiplier: 0.08
lowPressureMultiplier: 10000
@@ -308,13 +292,6 @@
map: [ "light" ]
- type: HandheldLight
addPrefix: false
inhandVisuals:
left:
- state: inhand-left-light
shader: unshaded
right:
- state: inhand-right-light
shader: unshaded
clothingVisuals:
head:
- state: equipped-head-light
@@ -325,15 +302,6 @@
- state: equipped-head
- state: equipped-head-unshaded
shader: unshaded
inhandVisuals:
left:
- state: inhand-left
- state: inhand-left-unshaded
shader: unshaded
right:
- state: inhand-right
- state: inhand-right-unshaded
shader: unshaded
- type: PressureProtection
highPressureMultiplier: 0.72
lowPressureMultiplier: 10000
@@ -429,15 +397,6 @@
- state: equipped-head
- state: equipped-head-unshaded
shader: unshaded
inhandVisuals:
left:
- state: inhand-left
- state: inhand-left-unshaded
shader: unshaded
right:
- state: inhand-right
- state: inhand-right-unshaded
shader: unshaded
- type: PointLight
color: orange
- type: PressureProtection

View File

@@ -196,7 +196,7 @@
- type: IdentityBlocker
- type: entity
parent: ClothingHeadHardsuitWithLightBase
parent: ClothingHeadLightBase
id: ClothingHeadHelmetFire
name: fire helmet
description: An atmos techs best friend. Provides some heat resistance and looks cool.
@@ -205,8 +205,6 @@
sprite: Clothing/Head/Helmets/firehelmet.rsi
- type: Clothing
sprite: Clothing/Head/Helmets/firehelmet.rsi
size: 5
canPickup: true
quickEquip: true
- type: IngestionBlocker
- type: PowerCellSlot
@@ -228,7 +226,7 @@
- type: IdentityBlocker
- type: entity
parent: ClothingHeadHardsuitWithLightBase
parent: ClothingHeadLightBase
id: ClothingHeadHelmetAtmosFire
name: atmos fire helmet
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
- type: Clothing
sprite: Clothing/Head/Helmets/atmos_firehelmet.rsi
size: 5
canPickup: true
quickEquip: true
- type: IngestionBlocker
- type: TemperatureProtection

View File

@@ -6,7 +6,7 @@
- type: Sprite
state: icon
- type: Clothing
Slots: [mask]
slots: [mask]
- type: entity
abstract: true

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -18,7 +18,7 @@
Quantity: 10
- type: Item
sprite: Objects/Consumable/Food/snacks.rsi
HeldPrefix: packet
heldPrefix: packet
size: 3
# Snacks
@@ -34,7 +34,6 @@
- type: Sprite
state: boritos
- type: Item
color: blue
- type: Food
trash: FoodPacketBoritosTrash
@@ -47,7 +46,6 @@
- type: Sprite
state: cheesiehonkers
- type: Item
color: orange
- type: Food
trash: FoodPacketCheesieTrash
@@ -60,7 +58,6 @@
- type: Sprite
state: chips
- type: Item
color: green
- type: Food
trash: FoodPacketChipsTrash
@@ -75,7 +72,7 @@
state: chocolatebar
netsync: false
- type: Item
HeldPrefix: chocolatebar
heldPrefix: chocolatebar
size: 3
- type: SpawnItemsOnUse
items:
@@ -93,7 +90,6 @@
- type: Sprite
state: chocolatebar-open
- type: Item
color: brown
- type: SolutionContainerManager
solutions:
food:
@@ -113,7 +109,6 @@
- type: Sprite
state: energybar
- type: Item
color: lime
- type: SpawnItemsOnUse
items:
- id: FoodPacketEnergyTrash
@@ -130,7 +125,6 @@
- type: Sprite
state: energybar-open
- type: Item
color: yellow
- type: entity
name: popcorn
@@ -141,7 +135,7 @@
- type: Sprite
state: popcorn
- type: Item
HeldPrefix: popcorn
heldPrefix: popcorn
- type: Food
trash: FoodPacketPopcornTrash
@@ -154,7 +148,6 @@
- type: Sprite
state: raisins
- type: Item
color: red
- type: Food
trash: FoodPacketRaisinsTrash
@@ -167,7 +160,6 @@
- type: Sprite
state: susjerky
- type: Item
color: red
- type: Food
trash: FoodPacketSusTrash
@@ -180,7 +172,6 @@
- type: Sprite
state: syndicakes
- type: Item
color: white
- type: Food
trash: FoodPacketSyndiTrash
@@ -193,7 +184,6 @@
- type: Sprite
state: chinese1
- type: Item
color: red
- type: SolutionContainerManager
solutions:
food:
@@ -246,7 +236,7 @@
Quantity: 1
- type: Item
sprite: Objects/Consumable/Food/snacks.rsi
HeldPrefix: packet
heldPrefix: packet
size: 1
- type: Food
trash: FoodCookieFortune
@@ -339,7 +329,7 @@
netsync: false
- type: Item
sprite: Objects/Consumable/Food/snacks.rsi
HeldPrefix: packet
heldPrefix: packet
- type: Tag
tags:
- Trash
@@ -355,7 +345,6 @@
- type: Sprite
state: boritos-trash
- type: Item
color: blue
- type: entity
noSpawn: true
@@ -366,7 +355,6 @@
- type: Sprite
state: cheesiehonkers-trash
- type: Item
color: orange
- type: entity
noSpawn: true
@@ -377,7 +365,6 @@
- type: Sprite
state: chips-trash
- type: Item
color: green
- type: entity
noSpawn: true
@@ -388,7 +375,6 @@
- type: Sprite
state: chocolatebar-trash
- type: Item
color: red
- type: entity
noSpawn: true
@@ -399,7 +385,6 @@
- type: Sprite
state: energybar-trash
- type: Item
color: green
- type: entity
noSpawn: true
@@ -410,7 +395,6 @@
- type: Sprite
state: pistachio-trash
- type: Item
color: green
- type: entity
noSpawn: true
@@ -421,7 +405,6 @@
- type: Sprite
state: popcorn-trash
- type: Item
state: blue
- type: entity
noSpawn: true
@@ -432,7 +415,6 @@
- type: Sprite
state: raisins-trash
- type: Item
color: red
- type: entity
noSpawn: true
@@ -443,7 +425,6 @@
- type: Sprite
state: semki-trash
- type: Item
color: orange
- type: entity
noSpawn: true
@@ -454,7 +435,6 @@
- type: Sprite
state: susjerky-trash
- type: Item
color: red
- type: entity
noSpawn: true
@@ -465,7 +445,6 @@
- type: Sprite
state: syndicakes-trash
- type: Item
color: white
- type: entity
noSpawn: true
@@ -476,7 +455,6 @@
- type: Sprite
state: chinese1
- type: Item
color: red
- type: entity
noSpawn: true
@@ -487,7 +465,6 @@
- type: Sprite
state: chinese2
- type: Item
color: white
- type: entity
noSpawn: true
@@ -499,7 +476,6 @@
- type: Sprite
state: fortune
- type: Item
color: white
- type: entity
noSpawn: true

View File

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

View File

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

View File

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

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