diff --git a/Content.Server/Nutrition/Components/SmokingPipeComponent.cs b/Content.Server/Nutrition/Components/SmokingPipeComponent.cs new file mode 100644 index 0000000000..feafd72a0b --- /dev/null +++ b/Content.Server/Nutrition/Components/SmokingPipeComponent.cs @@ -0,0 +1,17 @@ +using Content.Server.Nutrition.EntitySystems; +using Content.Shared.Containers.ItemSlots; + +namespace Content.Server.Nutrition.Components +{ + /// + /// A reusable vessel for smoking + /// + [RegisterComponent, Access(typeof(SmokingSystem))] + public sealed class SmokingPipeComponent : Component + { + public const string BowlSlotId = "bowl_slot"; + + [DataField("bowl_slot")] + public ItemSlot BowlSlot = new(); + } +} diff --git a/Content.Server/Nutrition/EntitySystems/SmokingSystem.SmokingPipe.cs b/Content.Server/Nutrition/EntitySystems/SmokingSystem.SmokingPipe.cs new file mode 100644 index 0000000000..86bc93a286 --- /dev/null +++ b/Content.Server/Nutrition/EntitySystems/SmokingSystem.SmokingPipe.cs @@ -0,0 +1,100 @@ +using Content.Server.Chemistry.Components.SolutionManager; +using Content.Server.Nutrition.Components; +using Content.Shared.Containers.ItemSlots; +using Content.Shared.Interaction; +using Content.Shared.PDA; +using Content.Shared.Smoking; +using Content.Shared.Temperature; + +namespace Content.Server.Nutrition.EntitySystems +{ + public sealed partial class SmokingSystem + { + [Dependency] private readonly ItemSlotsSystem _itemSlotsSystem = default!; + + private void InitializePipes() + { + SubscribeLocalEvent(OnPipeInteractUsingEvent); + SubscribeLocalEvent(OnPipeSolutionEmptyEvent); + SubscribeLocalEvent(OnPipeAfterInteract); + SubscribeLocalEvent(OnComponentInit); + } + + public void OnComponentInit(EntityUid uid, SmokingPipeComponent pipe, ComponentInit args) + { + _itemSlotsSystem.AddItemSlot(uid, SmokingPipeComponent.BowlSlotId, pipe.BowlSlot); + } + + private void OnPipeInteractUsingEvent(EntityUid uid, SmokingPipeComponent component, InteractUsingEvent args) + { + if (args.Handled) + return; + + if (!EntityManager.TryGetComponent(uid, out SmokableComponent? smokable)) + return; + + if (smokable.State != SmokableState.Unlit) + return; + + var isHotEvent = new IsHotEvent(); + RaiseLocalEvent(args.Used, isHotEvent, false); + + if (!isHotEvent.IsHot) + return; + + if (TryTransferReagents(component, smokable)) + SetSmokableState(uid, SmokableState.Lit, smokable); + args.Handled = true; + } + + public void OnPipeAfterInteract(EntityUid uid, SmokingPipeComponent component, AfterInteractEvent args) + { + var targetEntity = args.Target; + if (targetEntity == null || + !args.CanReach || + !EntityManager.TryGetComponent(uid, out SmokableComponent? smokable) || + smokable.State == SmokableState.Lit) + return; + + var isHotEvent = new IsHotEvent(); + RaiseLocalEvent(targetEntity.Value, isHotEvent, true); + + if (!isHotEvent.IsHot) + return; + + if(TryTransferReagents(component, smokable)) + SetSmokableState(uid, SmokableState.Lit, smokable); + args.Handled = true; + } + + private void OnPipeSolutionEmptyEvent(EntityUid uid, SmokingPipeComponent component, SmokableSolutionEmptyEvent args) + { + _itemSlotsSystem.SetLock(component.Owner, component.BowlSlot, false); + SetSmokableState(uid, SmokableState.Unlit); + } + + // Convert smokable item into reagents to be smoked + private bool TryTransferReagents(SmokingPipeComponent component, SmokableComponent smokable) + { + if (component.BowlSlot.Item == null) + return false; + + EntityUid contents = component.BowlSlot.Item.Value; + + if (!TryComp(contents, out var reagents) || + !_solutionContainerSystem.TryGetSolution(smokable.Owner, smokable.Solution, out var pipeSolution)) + return false; + + foreach (var reagentSolution in reagents.Solutions) + { + _solutionContainerSystem.TryAddSolution(smokable.Owner, pipeSolution, reagentSolution.Value); + } + + EntityManager.DeleteEntity(contents); + + _itemSlotsSystem.SetLock(component.Owner, component.BowlSlot, true); //no inserting more until current runs out + + return true; + } + } +} diff --git a/Content.Server/Nutrition/EntitySystems/SmokingSystem.cs b/Content.Server/Nutrition/EntitySystems/SmokingSystem.cs index e51456f539..3eb2e7db22 100644 --- a/Content.Server/Nutrition/EntitySystems/SmokingSystem.cs +++ b/Content.Server/Nutrition/EntitySystems/SmokingSystem.cs @@ -44,6 +44,7 @@ namespace Content.Server.Nutrition.EntitySystems SubscribeLocalEvent(OnSmokableShutdownEvent); InitializeCigars(); + InitializePipes(); } public void SetSmokableState(EntityUid uid, SmokableState state, SmokableComponent? smokable = null, diff --git a/Resources/Prototypes/Catalog/Fills/Crates/service.yml b/Resources/Prototypes/Catalog/Fills/Crates/service.yml index 89847e1b01..e046d51a17 100644 --- a/Resources/Prototypes/Catalog/Fills/Crates/service.yml +++ b/Resources/Prototypes/Catalog/Fills/Crates/service.yml @@ -74,6 +74,7 @@ amount: 8 - id: GroundTobacco amount: 4 + - id: SmokingPipe - id: Matchbox - type: entity diff --git a/Resources/Prototypes/Catalog/VendingMachines/Inventories/cigs.yml b/Resources/Prototypes/Catalog/VendingMachines/Inventories/cigs.yml index df481b2095..1e418bf3d9 100644 --- a/Resources/Prototypes/Catalog/VendingMachines/Inventories/cigs.yml +++ b/Resources/Prototypes/Catalog/VendingMachines/Inventories/cigs.yml @@ -6,6 +6,7 @@ CigPackBlue: 2 CigPackBlack: 2 CigarCase: 1 + SmokingPipeFilledTobacco: 1 Matchbox: 5 PackPaperRollingFilters: 3 CheapLighter: 4 diff --git a/Resources/Prototypes/Entities/Clothing/OuterClothing/coats.yml b/Resources/Prototypes/Entities/Clothing/OuterClothing/coats.yml index 322007f5ae..8a867bf9f9 100644 --- a/Resources/Prototypes/Entities/Clothing/OuterClothing/coats.yml +++ b/Resources/Prototypes/Entities/Clothing/OuterClothing/coats.yml @@ -19,6 +19,9 @@ sprite: Clothing/OuterClothing/Coats/detective.rsi - type: Clothing sprite: Clothing/OuterClothing/Coats/detective.rsi + - type: StorageFill + contents: + - id: SmokingPipeFilledTobacco - type: Armor modifiers: coefficients: diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Smokeables/Pipes/pipe.yml b/Resources/Prototypes/Entities/Objects/Consumable/Smokeables/Pipes/pipe.yml new file mode 100644 index 0000000000..95c7b22a4e --- /dev/null +++ b/Resources/Prototypes/Entities/Objects/Consumable/Smokeables/Pipes/pipe.yml @@ -0,0 +1,65 @@ +- type: entity + id: SmokingPipe + parent: BaseSmokingPipe + name: pipe + description: Just like grandpappy used to smoke. + components: + - type: Sprite + sprite: Objects/Consumable/Smokeables/Pipes/pipe.rsi + netsync: false + state: unlit-icon + - type: Clothing + sprite: Objects/Consumable/Smokeables/Pipes/pipe.rsi + slots: [ mask ] + equippedPrefix: unlit + - type: Item + size: 3 + sprite: Objects/Consumable/Smokeables/Pipes/pipe.rsi + - type: Appearance + visuals: + - type: BurnStateVisualizer + unlitIcon: unlit-icon + +- type: entity + id: SmokingPipeFilledTobacco + parent: SmokingPipe + name: pipe + description: Just like grandpappy used to smoke. + components: + - type: ContainerContainer + containers: + bowl_slot: !type:ContainerSlot + - type: ItemSlots + - type: SmokingPipe + bowl_slot: + name: Bowl + startingItem: GroundTobacco + whitelist: + tags: + - Smokable + insertSound: + path: /Audio/Weapons/Guns/Empty/empty.ogg + ejectSound: + path: /Audio/Weapons/Guns/Empty/empty.ogg + +- type: entity + id: SmokingPipeFilledCannabis + parent: SmokingPipe + name: pipe + description: Just like grandpappy used to smoke. + components: + - type: ContainerContainer + containers: + bowl_slot: !type:ContainerSlot + - type: ItemSlots + - type: SmokingPipe + bowl_slot: + name: Bowl + startingItem: GroundCannabis + whitelist: + tags: + - Smokable + insertSound: + path: /Audio/Weapons/Guns/Empty/empty.ogg + ejectSound: + path: /Audio/Weapons/Guns/Empty/empty.ogg \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Smokeables/base_smokeables.yml b/Resources/Prototypes/Entities/Objects/Consumable/Smokeables/base_smokeables.yml index cf9bfa476b..ef58235903 100644 --- a/Resources/Prototypes/Entities/Objects/Consumable/Smokeables/base_smokeables.yml +++ b/Resources/Prototypes/Entities/Objects/Consumable/Smokeables/base_smokeables.yml @@ -37,3 +37,29 @@ reagents: - ReagentId: Nicotine Quantity: 10 + +- type: entity + parent: BaseSmokable + id: BaseSmokingPipe + abstract: true + components: + - type: Smokable + exposeTemperature: 1173.15 + - type: ContainerContainer + containers: + bowl_slot: !type:ContainerSlot + - type: ItemSlots + - type: SmokingPipe + bowl_slot: + name: Bowl + whitelist: + tags: + - Smokable + insertSound: + path: /Audio/Weapons/Guns/Empty/empty.ogg + ejectSound: + path: /Audio/Weapons/Guns/Empty/empty.ogg + - type: SolutionContainerManager + solutions: + smokable: + maxVol: 20 diff --git a/Resources/Prototypes/Entities/Objects/Specific/Hydroponics/leaves.yml b/Resources/Prototypes/Entities/Objects/Specific/Hydroponics/leaves.yml index a8f323ce49..bf2a4127c3 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/Hydroponics/leaves.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/Hydroponics/leaves.yml @@ -61,6 +61,9 @@ - type: Construction graph: smokeableGroundCannabis node: ground + - type: Tag + tags: + - Smokable - type: entity name: tobacco leaves @@ -116,3 +119,6 @@ - type: Construction graph: smokeableGroundTobacco node: ground + - type: Tag + tags: + - Smokable diff --git a/Resources/Prototypes/tags.yml b/Resources/Prototypes/tags.yml index 817a60ccc5..f08b1ab1da 100644 --- a/Resources/Prototypes/tags.yml +++ b/Resources/Prototypes/tags.yml @@ -444,6 +444,9 @@ - type: Tag id: Shovel +- type: Tag + id: Smokable + - type: Tag id: Soap