diff --git a/Content.Shared/Clothing/Components/EmitsSoundOnMoveComponent.cs b/Content.Shared/Clothing/Components/EmitsSoundOnMoveComponent.cs new file mode 100644 index 00000000000..095b0daf384 --- /dev/null +++ b/Content.Shared/Clothing/Components/EmitsSoundOnMoveComponent.cs @@ -0,0 +1,35 @@ +using Robust.Shared.Audio; +using Robust.Shared.GameStates; +using Robust.Shared.Map; + +namespace Content.Shared.Clothing.Components; + +/// +/// Indicates that the clothing entity emits sound when it moves. +/// +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +public sealed partial class EmitsSoundOnMoveComponent : Component +{ + [ViewVariables(VVAccess.ReadWrite)] + [DataField(required: true), AutoNetworkedField] + public SoundSpecifier SoundCollection = default!; + + [ViewVariables(VVAccess.ReadWrite)] + [DataField("requiresGravity"), AutoNetworkedField] + public bool RequiresGravity = true; + + [ViewVariables(VVAccess.ReadOnly)] + public EntityCoordinates LastPosition = EntityCoordinates.Invalid; + + /// + /// The distance moved since the played sound. + /// + [ViewVariables(VVAccess.ReadOnly)] + public float SoundDistance = 0f; + + /// + /// Whether this item is equipped in a inventory item slot. + /// + [ViewVariables(VVAccess.ReadOnly)] + public bool IsSlotValid = true; +} diff --git a/Content.Shared/Clothing/EntitySystems/EmitsSoundOnMoveSystem.cs b/Content.Shared/Clothing/EntitySystems/EmitsSoundOnMoveSystem.cs new file mode 100644 index 00000000000..3224b5bca32 --- /dev/null +++ b/Content.Shared/Clothing/EntitySystems/EmitsSoundOnMoveSystem.cs @@ -0,0 +1,96 @@ +using System.Numerics; +using Content.Shared.Clothing.Components; +using Content.Shared.Gravity; +using Content.Shared.Inventory; +using Content.Shared.Inventory.Events; +using Content.Shared.Mobs.Components; +using Content.Shared.Movement.Components; +using Robust.Shared.Audio.Systems; +using Robust.Shared.Physics.Components; +using Robust.Shared.Timing; + +namespace Content.Shared.Clothing.Systems; + +public sealed class EmitsSoundOnMoveSystem : EntitySystem +{ + [Dependency] private readonly SharedAudioSystem _audio = default!; + [Dependency] private readonly SharedMapSystem _grid = default!; + [Dependency] private readonly SharedGravitySystem _gravity = default!; + [Dependency] private readonly IGameTiming _timing = default!; + + private EntityQuery _moverQuery; + private EntityQuery _physicsQuery; + private EntityQuery _clothingQuery; + + public override void Initialize() + { + _moverQuery = GetEntityQuery(); + _physicsQuery = GetEntityQuery(); + _clothingQuery = GetEntityQuery(); + + SubscribeLocalEvent(OnEquipped); + SubscribeLocalEvent(OnUnequipped); + } + + private void OnEquipped(EntityUid uid, EmitsSoundOnMoveComponent component, GotEquippedEvent args) + { + component.IsSlotValid = !args.SlotFlags.HasFlag(SlotFlags.POCKET); + } + + private void OnUnequipped(EntityUid uid, EmitsSoundOnMoveComponent component, GotUnequippedEvent args) + { + component.IsSlotValid = true; + } + + public override void Update(float frameTime) + { + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var uid, out var comp)) + { + UpdateSound(uid, comp); + } + query.Dispose(); + } + + private void UpdateSound(EntityUid uid, EmitsSoundOnMoveComponent component) + { + if (!_physicsQuery.TryGetComponent(uid, out var physics)) + return; + + // Space does not transmit sound + if (Transform(uid).GridUid == null) + return; + + if (component.RequiresGravity && _gravity.IsWeightless(uid, physics, Transform(uid))) + return; + + var parent = Transform(uid).ParentUid; + + var isWorn = parent is { Valid: true } && + _clothingQuery.TryGetComponent(uid, out var clothing) + && clothing.InSlot != null + && component.IsSlotValid; + // If this entity is worn by another entity, use that entity's coordinates + var coordinates = isWorn ? Transform(parent).Coordinates : Transform(uid).Coordinates; + var distanceNeeded = (isWorn && _moverQuery.TryGetComponent(parent, out var mover) && mover.Sprinting) + ? 1.5f // The parent is a mob that is currently sprinting + : 2f; // The parent is not a mob or is not sprinting + + if (!coordinates.TryDistance(EntityManager, component.LastPosition, out var distance) || distance > distanceNeeded) + component.SoundDistance = distanceNeeded; + else + component.SoundDistance += distance; + + component.LastPosition = coordinates; + if (component.SoundDistance < distanceNeeded) + return; + component.SoundDistance -= distanceNeeded; + + var sound = component.SoundCollection; + var audioParams = sound.Params + .WithVolume(sound.Params.Volume) + .WithVariation(sound.Params.Variation ?? 0f); + + _audio.PlayPredicted(sound, uid, uid, audioParams); + } +} diff --git a/Resources/Prototypes/Actions/types.yml b/Resources/Prototypes/Actions/types.yml index f5dff1f453a..cf0a99f3bad 100644 --- a/Resources/Prototypes/Actions/types.yml +++ b/Resources/Prototypes/Actions/types.yml @@ -375,4 +375,4 @@ useDelay: 40 event: !type:FabricateActionEvent - fabrication: FoodGumball + fabrication: FoodGumball \ No newline at end of file diff --git a/Resources/Prototypes/Catalog/Cargo/cargo_vending.yml b/Resources/Prototypes/Catalog/Cargo/cargo_vending.yml index 7062b2eb155..f7191df9ab4 100644 --- a/Resources/Prototypes/Catalog/Cargo/cargo_vending.yml +++ b/Resources/Prototypes/Catalog/Cargo/cargo_vending.yml @@ -43,7 +43,7 @@ sprite: Objects/Specific/Service/vending_machine_restock.rsi state: base product: CrateVendingMachineRestockAutoDrobeFilled - cost: 1700 + cost: 1730 category: cargoproduct-category-name-service group: market diff --git a/Resources/Prototypes/Catalog/VendingMachines/Inventories/clothesmate.yml b/Resources/Prototypes/Catalog/VendingMachines/Inventories/clothesmate.yml index bc8f73d618c..6c99f925ee9 100644 --- a/Resources/Prototypes/Catalog/VendingMachines/Inventories/clothesmate.yml +++ b/Resources/Prototypes/Catalog/VendingMachines/Inventories/clothesmate.yml @@ -20,6 +20,7 @@ ClothingEyesGlasses: 6 ClothingHandsGlovesColorBlack: 4 ClothingEyesGlassesCheapSunglasses: 2 + ClothingClothWrap: 4 contrabandInventory: ClothingMaskNeckGaiter: 2 ClothingUniformJumpsuitTacticool: 1 diff --git a/Resources/Prototypes/Catalog/VendingMachines/Inventories/theater.yml b/Resources/Prototypes/Catalog/VendingMachines/Inventories/theater.yml index 79305325bf7..9a1566dab99 100644 --- a/Resources/Prototypes/Catalog/VendingMachines/Inventories/theater.yml +++ b/Resources/Prototypes/Catalog/VendingMachines/Inventories/theater.yml @@ -88,6 +88,8 @@ ClothingShoesBootsCowboyBlack: 1 ClothingShoesBootsCowboyWhite: 1 ClothingMaskNeckGaiterRed: 2 + ClothingNeckBellCollar: 2 + ClothingOuterUnathiRobe: 1 emaggedInventory: ClothingShoesBling: 1 ClothingShoesBootsCowboyFancy: 1 diff --git a/Resources/Prototypes/Entities/Clothing/Neck/mantles.yml b/Resources/Prototypes/Entities/Clothing/Neck/mantles.yml index 7b4ab078911..efdec875e69 100644 --- a/Resources/Prototypes/Entities/Clothing/Neck/mantles.yml +++ b/Resources/Prototypes/Entities/Clothing/Neck/mantles.yml @@ -74,3 +74,25 @@ sprite: Clothing/Neck/mantles/qmmantle.rsi - type: Clothing sprite: Clothing/Neck/mantles/qmmantle.rsi + +- type: entity + parent: ClothingNeckBase + id: ClothingNeckOldMantle + name: old wrap + description: A tattered fabric wrap, faded over the years. Smells faintly of cigars. + components: + - type: Sprite + sprite: Clothing/Neck/mantles/oldmantle.rsi + - type: Clothing + sprite: Clothing/Neck/mantles/oldmantle.rsi + +- type: entity + parent: ClothingNeckBase + id: ClothingNeckUnathiMantle + name: hide mantle + description: A rather grisly selection of cured hides and skin, sewn together to form a ragged mantle. + components: + - type: Sprite + sprite: Clothing/Neck/mantles/unathimantle.rsi + - type: Clothing + sprite: Clothing/Neck/mantles/unathimantle.rsi diff --git a/Resources/Prototypes/Entities/Clothing/Neck/misc.yml b/Resources/Prototypes/Entities/Clothing/Neck/misc.yml index 51325c0bbbd..11921b9a50d 100644 --- a/Resources/Prototypes/Entities/Clothing/Neck/misc.yml +++ b/Resources/Prototypes/Entities/Clothing/Neck/misc.yml @@ -79,3 +79,17 @@ event: !type:StethoscopeActionEvent checkCanInteract: false priority: -1 + +- type: entity + parent: ClothingNeckBase + id: ClothingNeckBellCollar + name: bell collar + description: A way to inform others about your presence, or just to annoy everyone around you! + components: + - type: Sprite + sprite: Clothing/Neck/Misc/bellcollar.rsi + - type: Clothing + sprite: Clothing/Neck/Misc/bellcollar.rsi + - type: EmitsSoundOnMove + soundCollection: + collection: FootstepJester diff --git a/Resources/Prototypes/Entities/Clothing/OuterClothing/misc.yml b/Resources/Prototypes/Entities/Clothing/OuterClothing/misc.yml index d17fb275c13..4b2c3c9c3ff 100644 --- a/Resources/Prototypes/Entities/Clothing/OuterClothing/misc.yml +++ b/Resources/Prototypes/Entities/Clothing/OuterClothing/misc.yml @@ -377,3 +377,14 @@ sprite: Clothing/OuterClothing/Misc/red_racoon.rsi - type: Clothing sprite: Clothing/OuterClothing/Misc/red_racoon.rsi + +- type: entity + parent: ClothingOuterBase + id: ClothingOuterUnathiRobe + name: roughspun robes + description: A traditional Unathi garment. + components: + - type: Sprite + sprite: Clothing/OuterClothing/Misc/unathirobe.rsi + - type: Clothing + sprite: Clothing/OuterClothing/Misc/unathirobe.rsi diff --git a/Resources/Prototypes/Entities/Clothing/clothwarps.yml b/Resources/Prototypes/Entities/Clothing/clothwarps.yml new file mode 100644 index 00000000000..eadeaa0b286 --- /dev/null +++ b/Resources/Prototypes/Entities/Clothing/clothwarps.yml @@ -0,0 +1,38 @@ +- type: entity + parent: Clothing + id: ClothingClothWrap + name: cloth wraps + description: A roll of treated canvas used for wrapping claws or paws. + components: + - type: Item + size: Small + storedRotation: -90 + - type: Sprite + state: icon + sprite: Clothing/Shoes/Misc/clothWrap.rsi + - type: Clothing + slots: + - gloves + - FEET + sprite: Clothing/Shoes/Misc/clothWrap.rsi + - type: Construction + graph: ClothingClothWrap + node: shoes + - type: Butcherable + butcheringType: Knife + spawned: + - id: MaterialCloth1 + amount: 1 + - type: Food + requiresSpecialDigestion: true + - type: SolutionContainerManager + solutions: + food: + maxVol: 10 + reagents: + - ReagentId: Fiber + Quantity: 10 + - type: Tag + tags: + - ClothMade + - WhitelistChameleon diff --git a/Resources/Prototypes/Loadouts/neck.yml b/Resources/Prototypes/Loadouts/neck.yml index c7fc7003653..3e0227d1dae 100644 --- a/Resources/Prototypes/Loadouts/neck.yml +++ b/Resources/Prototypes/Loadouts/neck.yml @@ -6,6 +6,30 @@ items: - ClothingNeckHeadphones +- type: loadout + id: LoadoutNeckBellCollar + category: Neck + cost: 2 + exclusive: true + items: + - ClothingNeckBellCollar + +- type: loadout + id: LoadoutNeckOldMantle + category: Neck + cost: 1 + exclusive: true + items: + - ClothingNeckOldMantle + +- type: loadout + id: LoadoutNeckUnathiMantle + category: Neck + cost: 1 + exclusive: true + items: + - ClothingNeckUnathiMantle + # Scarves - type: loadout id: LoadoutNeckScarfStripedRed @@ -120,7 +144,6 @@ items: - ClothingNeckTieGreen - #Pride Accessories - type: loadout id: LoadoutItemsPrideLGBTPin diff --git a/Resources/Prototypes/Loadouts/shoes.yml b/Resources/Prototypes/Loadouts/shoes.yml index 470cac29834..e67ca70b392 100644 --- a/Resources/Prototypes/Loadouts/shoes.yml +++ b/Resources/Prototypes/Loadouts/shoes.yml @@ -341,7 +341,6 @@ items: - ClothingUnderSocksCoder -# Socks - type: loadout id: LoadoutShoesUnderSocksBee category: Shoes @@ -355,3 +354,11 @@ - Harpy items: - ClothingUnderSocksBee + +- type: loadout + id: LoadoutShoesClothWrap + category: Shoes + cost: 1 + exclusive: true + items: + - ClothingClothWrap diff --git a/Resources/Prototypes/Recipes/Construction/Graphs/clothing/clothwarp.yml b/Resources/Prototypes/Recipes/Construction/Graphs/clothing/clothwarp.yml new file mode 100644 index 00000000000..864d8f18d20 --- /dev/null +++ b/Resources/Prototypes/Recipes/Construction/Graphs/clothing/clothwarp.yml @@ -0,0 +1,13 @@ +- type: constructionGraph + id: ClothingClothWrap + start: start + graph: + - node: start + edges: + - to: shoes + steps: + - material: Cloth + amount: 2 + doAfter: 1 + - node: shoes + entity: ClothingClothWrap diff --git a/Resources/Prototypes/Recipes/Construction/clothing.yml b/Resources/Prototypes/Recipes/Construction/clothing.yml index f1eb270af73..54218d28226 100644 --- a/Resources/Prototypes/Recipes/Construction/clothing.yml +++ b/Resources/Prototypes/Recipes/Construction/clothing.yml @@ -96,3 +96,14 @@ description: Comfy, yet haunted by the ghosts of ducks you fed bread to as a child. icon: { sprite: Clothing/Shoes/Misc/duck-slippers.rsi, state: icon } objectType: Item + +- type: construction + name: cloth wraps + id: ClothingClothWrap + graph: ClothingClothWrap + startNode: start + targetNode: shoes + category: construction-category-clothing + description: A roll of treated canvas used for wrapping claws or paws. + icon: { sprite: Clothing/Shoes/Misc/clothWrap.rsi, state: icon } + objectType: Item diff --git a/Resources/Textures/Clothing/Neck/Misc/bellcollar.rsi/equipped-NECK.png b/Resources/Textures/Clothing/Neck/Misc/bellcollar.rsi/equipped-NECK.png new file mode 100644 index 00000000000..2190dc844db Binary files /dev/null and b/Resources/Textures/Clothing/Neck/Misc/bellcollar.rsi/equipped-NECK.png differ diff --git a/Resources/Textures/Clothing/Neck/Misc/bellcollar.rsi/icon.png b/Resources/Textures/Clothing/Neck/Misc/bellcollar.rsi/icon.png new file mode 100644 index 00000000000..17904840397 Binary files /dev/null and b/Resources/Textures/Clothing/Neck/Misc/bellcollar.rsi/icon.png differ diff --git a/Resources/Textures/Clothing/Neck/Misc/bellcollar.rsi/inhand-left.png b/Resources/Textures/Clothing/Neck/Misc/bellcollar.rsi/inhand-left.png new file mode 100644 index 00000000000..2d727adbb21 Binary files /dev/null and b/Resources/Textures/Clothing/Neck/Misc/bellcollar.rsi/inhand-left.png differ diff --git a/Resources/Textures/Clothing/Neck/Misc/bellcollar.rsi/inhand-right.png b/Resources/Textures/Clothing/Neck/Misc/bellcollar.rsi/inhand-right.png new file mode 100644 index 00000000000..0e2c555c5c1 Binary files /dev/null and b/Resources/Textures/Clothing/Neck/Misc/bellcollar.rsi/inhand-right.png differ diff --git a/Resources/Textures/Clothing/Neck/Misc/bellcollar.rsi/meta.json b/Resources/Textures/Clothing/Neck/Misc/bellcollar.rsi/meta.json new file mode 100644 index 00000000000..464e2e4a352 --- /dev/null +++ b/Resources/Textures/Clothing/Neck/Misc/bellcollar.rsi/meta.json @@ -0,0 +1,26 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Made by mnemotechnician (GitHub)", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + }, + { + "name": "equipped-NECK", + "directions": 4 + }, + { + "name": "inhand-left", + "directions": 4 + }, + { + "name": "inhand-right", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/Clothing/Neck/mantles/oldmantle.rsi/equipped-NECK.png b/Resources/Textures/Clothing/Neck/mantles/oldmantle.rsi/equipped-NECK.png new file mode 100644 index 00000000000..d317412c9dd Binary files /dev/null and b/Resources/Textures/Clothing/Neck/mantles/oldmantle.rsi/equipped-NECK.png differ diff --git a/Resources/Textures/Clothing/Neck/mantles/oldmantle.rsi/icon.png b/Resources/Textures/Clothing/Neck/mantles/oldmantle.rsi/icon.png new file mode 100644 index 00000000000..4cf647611dc Binary files /dev/null and b/Resources/Textures/Clothing/Neck/mantles/oldmantle.rsi/icon.png differ diff --git a/Resources/Textures/Clothing/Neck/mantles/oldmantle.rsi/meta.json b/Resources/Textures/Clothing/Neck/mantles/oldmantle.rsi/meta.json new file mode 100644 index 00000000000..909b986cade --- /dev/null +++ b/Resources/Textures/Clothing/Neck/mantles/oldmantle.rsi/meta.json @@ -0,0 +1,18 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from https://github.com/ParadiseSS13/Paradise/blob/master/icons/mob/clothing/suit.dmi", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + }, + { + "name": "equipped-NECK", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/Clothing/Neck/mantles/unathimantle.rsi/equipped-NECK.png b/Resources/Textures/Clothing/Neck/mantles/unathimantle.rsi/equipped-NECK.png new file mode 100644 index 00000000000..5df12ac9933 Binary files /dev/null and b/Resources/Textures/Clothing/Neck/mantles/unathimantle.rsi/equipped-NECK.png differ diff --git a/Resources/Textures/Clothing/Neck/mantles/unathimantle.rsi/icon.png b/Resources/Textures/Clothing/Neck/mantles/unathimantle.rsi/icon.png new file mode 100644 index 00000000000..d59144a0524 Binary files /dev/null and b/Resources/Textures/Clothing/Neck/mantles/unathimantle.rsi/icon.png differ diff --git a/Resources/Textures/Clothing/Neck/mantles/unathimantle.rsi/meta.json b/Resources/Textures/Clothing/Neck/mantles/unathimantle.rsi/meta.json new file mode 100644 index 00000000000..909b986cade --- /dev/null +++ b/Resources/Textures/Clothing/Neck/mantles/unathimantle.rsi/meta.json @@ -0,0 +1,18 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from https://github.com/ParadiseSS13/Paradise/blob/master/icons/mob/clothing/suit.dmi", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + }, + { + "name": "equipped-NECK", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/Clothing/OuterClothing/Misc/unathirobe.rsi/equipped-OUTERCLOTHING.png b/Resources/Textures/Clothing/OuterClothing/Misc/unathirobe.rsi/equipped-OUTERCLOTHING.png new file mode 100644 index 00000000000..f470372379d Binary files /dev/null and b/Resources/Textures/Clothing/OuterClothing/Misc/unathirobe.rsi/equipped-OUTERCLOTHING.png differ diff --git a/Resources/Textures/Clothing/OuterClothing/Misc/unathirobe.rsi/icon.png b/Resources/Textures/Clothing/OuterClothing/Misc/unathirobe.rsi/icon.png new file mode 100644 index 00000000000..54fd0c07413 Binary files /dev/null and b/Resources/Textures/Clothing/OuterClothing/Misc/unathirobe.rsi/icon.png differ diff --git a/Resources/Textures/Clothing/OuterClothing/Misc/unathirobe.rsi/meta.json b/Resources/Textures/Clothing/OuterClothing/Misc/unathirobe.rsi/meta.json new file mode 100644 index 00000000000..d66d07b5d5e --- /dev/null +++ b/Resources/Textures/Clothing/OuterClothing/Misc/unathirobe.rsi/meta.json @@ -0,0 +1,18 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from https://github.com/ParadiseSS13/Paradise/blob/master/icons/mob/clothing/suit.dmi", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + }, + { + "name": "equipped-OUTERCLOTHING", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/Clothing/Shoes/Misc/clothWrap.rsi/equipped-FEET.png b/Resources/Textures/Clothing/Shoes/Misc/clothWrap.rsi/equipped-FEET.png new file mode 100644 index 00000000000..4a3104fead9 Binary files /dev/null and b/Resources/Textures/Clothing/Shoes/Misc/clothWrap.rsi/equipped-FEET.png differ diff --git a/Resources/Textures/Clothing/Shoes/Misc/clothWrap.rsi/equipped-HAND.png b/Resources/Textures/Clothing/Shoes/Misc/clothWrap.rsi/equipped-HAND.png new file mode 100644 index 00000000000..b78a810df85 Binary files /dev/null and b/Resources/Textures/Clothing/Shoes/Misc/clothWrap.rsi/equipped-HAND.png differ diff --git a/Resources/Textures/Clothing/Shoes/Misc/clothWrap.rsi/icon.png b/Resources/Textures/Clothing/Shoes/Misc/clothWrap.rsi/icon.png new file mode 100644 index 00000000000..8f531e890c1 Binary files /dev/null and b/Resources/Textures/Clothing/Shoes/Misc/clothWrap.rsi/icon.png differ diff --git a/Resources/Textures/Clothing/Shoes/Misc/clothWrap.rsi/meta.json b/Resources/Textures/Clothing/Shoes/Misc/clothWrap.rsi/meta.json new file mode 100644 index 00000000000..02cbb7ef9a0 --- /dev/null +++ b/Resources/Textures/Clothing/Shoes/Misc/clothWrap.rsi/meta.json @@ -0,0 +1,22 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from https://github.com/ParadiseSS13/Paradise/blob/master/icons/mob/clothing/feet.dmi / https://github.com/ParadiseSS13/Paradise/blob/master/icons/mob/clothing/hands.dmi", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + }, + { + "name": "equipped-FEET", + "directions": 4 + }, + { + "name": "equipped-HAND", + "directions": 4 + } + ] +}