]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
New smokable: Vape! (#13072)
authoriller_saver <55444968+illersaver@users.noreply.github.com>
Mon, 1 May 2023 14:34:11 +0000 (17:34 +0300)
committerGitHub <noreply@github.com>
Mon, 1 May 2023 14:34:11 +0000 (00:34 +1000)
13 files changed:
Content.Server/Nutrition/Components/VapeComponent.cs [new file with mode: 0644]
Content.Server/Nutrition/EntitySystems/SmokingSystem.Vape.cs [new file with mode: 0644]
Content.Server/Nutrition/EntitySystems/SmokingSystem.cs
Content.Shared/Nutrition/Events.cs
Resources/Locale/en-US/nutrition/components/vape-component.ftl [new file with mode: 0644]
Resources/Prototypes/Catalog/Research/technologies.yml
Resources/Prototypes/Catalog/VendingMachines/Inventories/cigs.yml
Resources/Prototypes/Entities/Objects/Consumable/Smokeables/Vapes/vape.yml [new file with mode: 0644]
Resources/Prototypes/Entities/Objects/Consumable/Smokeables/base_smokeables.yml
Resources/Prototypes/Entities/Structures/Machines/lathe.yml
Resources/Prototypes/Recipes/Lathes/chemistry.yml
Resources/Textures/Objects/Consumable/Smokeables/Vapes/vape-standart.rsi/icon.png [new file with mode: 0644]
Resources/Textures/Objects/Consumable/Smokeables/Vapes/vape-standart.rsi/meta.json [new file with mode: 0644]

diff --git a/Content.Server/Nutrition/Components/VapeComponent.cs b/Content.Server/Nutrition/Components/VapeComponent.cs
new file mode 100644 (file)
index 0000000..28b2e6e
--- /dev/null
@@ -0,0 +1,51 @@
+using System.Threading;
+using Content.Server.Nutrition.EntitySystems;
+using Content.Shared.Damage;
+using Content.Shared.Atmos;
+
+/// <summary>
+/// Component for vapes
+/// </summary>
+namespace Content.Server.Nutrition.Components
+{
+    [RegisterComponent, Access(typeof(SmokingSystem))] 
+    public sealed class VapeComponent : Component
+    {
+        [DataField("delay")]
+        [ViewVariables(VVAccess.ReadWrite)]
+        public float Delay { get; set; } = 5;
+
+        [DataField("userDelay")]
+        [ViewVariables(VVAccess.ReadWrite)]
+        public float UserDelay { get; set; } = 2;
+
+        [DataField("explosionIntensity")]
+        [ViewVariables(VVAccess.ReadWrite)]
+        public float ExplosionIntensity { get; set; } = 2.5f;
+
+        [DataField("explodeOnUse")]
+        [ViewVariables(VVAccess.ReadWrite)]
+        public bool ExplodeOnUse { get; set; } = false;
+
+        [DataField("damage", required: true)]
+        [ViewVariables(VVAccess.ReadWrite)]
+        public DamageSpecifier Damage = default!;
+
+        [DataField("gasType")]
+        [ViewVariables(VVAccess.ReadWrite)]
+        public Gas GasType { get; set; } = Gas.WaterVapor;
+
+        /// <summary>
+        /// Solution volume will be divided by this number and converted to the gas
+        /// </summary>
+        [DataField("reductionFactor")]
+        [ViewVariables(VVAccess.ReadWrite)]
+        public float ReductionFactor { get; set; } = 300f;
+
+        [DataField("solutionNeeded")]
+        [ViewVariables(VVAccess.ReadWrite)]
+        public string SolutionNeeded = "Water";
+
+        public CancellationTokenSource? CancelToken;
+    }
+}
\ No newline at end of file
diff --git a/Content.Server/Nutrition/EntitySystems/SmokingSystem.Vape.cs b/Content.Server/Nutrition/EntitySystems/SmokingSystem.Vape.cs
new file mode 100644 (file)
index 0000000..1566156
--- /dev/null
@@ -0,0 +1,169 @@
+using Content.Server.Nutrition.Components;
+using Content.Server.Body.Components;
+using Content.Shared.Interaction;
+using Content.Server.DoAfter;
+using System.Threading;
+using Content.Server.Explosion.EntitySystems;
+using Content.Shared.Damage;
+using Content.Server.Popups;
+using Content.Shared.IdentityManagement;
+using Content.Shared.DoAfter;
+using Content.Shared.Emag.Systems;
+using Content.Shared.Emag.Components;
+using Content.Shared.Nutrition;
+using Content.Server.Atmos.EntitySystems;
+using Content.Server.Atmos;
+
+/// <summary>
+/// System for vapes
+/// </summary>
+namespace Content.Server.Nutrition.EntitySystems
+{
+    public sealed partial class SmokingSystem
+    {
+        [Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
+        [Dependency] private readonly DamageableSystem _damageableSystem = default!;
+        [Dependency] private readonly FoodSystem _foodSystem = default!;
+        [Dependency] private readonly ExplosionSystem _explosionSystem = default!;
+        [Dependency] private readonly PopupSystem _popupSystem = default!;
+        [Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
+
+        private void InitializeVapes()
+        {
+            SubscribeLocalEvent<VapeComponent, AfterInteractEvent>(OnVapeInteraction);
+            SubscribeLocalEvent<VapeComponent, VapeDoAfterEvent>(OnVapeDoAfter);
+            SubscribeLocalEvent<VapeComponent, GotEmaggedEvent>(OnEmagged);
+        }
+
+        private void OnVapeInteraction(EntityUid uid, VapeComponent comp, AfterInteractEvent args) 
+        {
+            _solutionContainerSystem.TryGetRefillableSolution(uid, out var solution);
+
+            var delay = comp.Delay;
+            var forced = true;
+            var exploded = false;
+
+            if (!args.CanReach
+            || solution == null
+            || comp.CancelToken != null
+            || !TryComp<BloodstreamComponent>(args.Target, out var _)
+            || _foodSystem.IsMouthBlocked(args.Target.Value, args.User))
+                return;
+
+            if (args.Target == args.User)
+            {
+                delay = comp.UserDelay;
+                forced = false;
+            }
+
+            if (comp.ExplodeOnUse || HasComp<EmaggedComponent>(uid))
+            {
+                _explosionSystem.QueueExplosion(uid, "Default", comp.ExplosionIntensity, 0.5f, 3, canCreateVacuum: false);
+                EntityManager.DeleteEntity(uid);
+                exploded = true;
+            }
+            else
+            {
+                foreach (var name in solution.Contents)
+                {
+                    if (name.ReagentId != comp.SolutionNeeded)
+                    {
+                        exploded = true;
+                        _explosionSystem.QueueExplosion(uid, "Default", comp.ExplosionIntensity, 0.5f, 3, canCreateVacuum: false);
+                        EntityManager.DeleteEntity(uid);
+                        break;
+                    }
+                }
+            }
+
+            if (forced)
+            {
+                var targetName = Identity.Entity(args.Target.Value, EntityManager);
+                var userName = Identity.Entity(args.User, EntityManager);
+
+                _popupSystem.PopupEntity(
+                    Loc.GetString("vape-component-try-use-vape-forced", ("user", userName)), args.Target.Value,
+                    args.Target.Value);
+                
+                _popupSystem.PopupEntity(
+                    Loc.GetString("vape-component-try-use-vape-forced-user", ("target", targetName)), args.User,
+                    args.User);
+            }
+            else
+            {
+                _popupSystem.PopupEntity(
+                    Loc.GetString("vape-component-try-use-vape"), args.User,
+                    args.User);
+            }
+
+            if (!exploded)
+            {
+                comp.CancelToken = new CancellationTokenSource();
+
+                var vapeDoAfterEvent = new VapeDoAfterEvent(solution, forced);
+                _doAfterSystem.TryStartDoAfter(new DoAfterArgs(args.User, delay, vapeDoAfterEvent, uid, target: args.Target, used: uid)
+                {
+                    BreakOnTargetMove = true,
+                    BreakOnUserMove = false,
+                    BreakOnDamage = true
+                });
+            }
+            args.Handled = true;
+               }
+
+        private void OnVapeDoAfter(EntityUid uid, VapeComponent comp, VapeDoAfterEvent args)
+        {
+            if (args.Cancelled)
+            {
+                comp.CancelToken = null;
+                return;
+            }
+
+            comp.CancelToken = null;
+
+            if (args.Handled
+            || args.Args.Target == null)
+                return;
+
+            var environment = _atmosphereSystem.GetContainingMixture(args.Args.Target.Value, true, true);
+            if (environment == null)
+            {
+                return;
+            }
+
+            //Smoking kills(your lungs, but there is no organ damage yet)
+            _damageableSystem.TryChangeDamage(args.Args.Target.Value, comp.Damage, true);
+
+            var merger = new GasMixture(1) { Temperature = args.Solution.Temperature};
+            merger.SetMoles(comp.GasType, args.Solution.Volume.Value / comp.ReductionFactor);
+
+            _atmosphereSystem.Merge(environment, merger);
+
+            args.Solution.RemoveAllSolution();
+            
+            if (args.Forced)
+            {
+                var targetName = Identity.Entity(args.Args.Target.Value, EntityManager);
+                var userName = Identity.Entity(args.Args.User, EntityManager);
+
+                _popupSystem.PopupEntity(
+                    Loc.GetString("vape-component-vape-success-forced", ("user", userName)), args.Args.Target.Value,
+                    args.Args.Target.Value);
+                
+                _popupSystem.PopupEntity(
+                    Loc.GetString("vape-component-vape-success-user-forced", ("target", targetName)), args.Args.User,
+                    args.Args.Target.Value);
+            }
+            else
+            {
+                _popupSystem.PopupEntity(
+                    Loc.GetString("vape-component-vape-success"), args.Args.Target.Value,
+                    args.Args.Target.Value);
+            }
+        }
+        private void OnEmagged(EntityUid uid, VapeComponent component, ref GotEmaggedEvent args)
+        {
+            args.Handled = true;
+        }
+       }
+}
\ No newline at end of file
index a985f39315ae2e659db1bafa0e0637a2f01fbe5e..772e87211053226763fe8d5117274e0bbc57abd8 100644 (file)
@@ -47,6 +47,7 @@ namespace Content.Server.Nutrition.EntitySystems
 
             InitializeCigars();
             InitializePipes();
+            InitializeVapes();
         }
 
         public void SetSmokableState(EntityUid uid, SmokableState state, SmokableComponent? smokable = null,
index 3e3bd93470c24d5f861cfbb7b3220efbf4207feb..bf4acfafa224b27352b9bc1f5fa3a5f393860508 100644 (file)
@@ -1,5 +1,6 @@
 using Content.Shared.DoAfter;
 using Robust.Shared.Serialization;
+using Content.Shared.Chemistry.Components;
 
 namespace Content.Shared.Nutrition;
 
@@ -27,3 +28,28 @@ public sealed class ConsumeDoAfterEvent : DoAfterEvent
 
     public override DoAfterEvent Clone() => this;
 }
+
+/// <summary>
+///     Do after event for vape.
+/// </summary>
+[Serializable, NetSerializable]
+public sealed class VapeDoAfterEvent : DoAfterEvent
+{
+    [DataField("solution", required: true)]
+    public readonly Solution Solution = default!;
+
+    [DataField("forced", required: true)]
+    public readonly bool Forced = default!;
+
+    private VapeDoAfterEvent()
+    {
+    }
+
+    public VapeDoAfterEvent(Solution solution, bool forced)
+    {
+            Solution = solution;
+            Forced = forced;
+    }
+
+    public override DoAfterEvent Clone() => this;
+}
diff --git a/Resources/Locale/en-US/nutrition/components/vape-component.ftl b/Resources/Locale/en-US/nutrition/components/vape-component.ftl
new file mode 100644 (file)
index 0000000..2d25e1a
--- /dev/null
@@ -0,0 +1,6 @@
+vape-component-vape-success = You puffed on the vape.
+vape-component-vape-success-forced = {CAPITALIZE(THE($user))} forced you to puffon the vape.
+vape-component-vape-success-user-forced = You successfully forced to puff {THE($target)}.
+vape-component-try-use-vape-forced = {CAPITALIZE(THE($user))} is trying to make you puff on the vape.
+vape-component-try-use-vape-forced-user = You are forcing {THE($target)} to puff on the vape.
+vape-component-try-use-vape = You are trying to puff on the vape.
\ No newline at end of file
index 65d886054a3df186d2b182645aa0104b8fdf8bb0..d5c8738ea76b339d866d25689897b6f45868a3d6 100644 (file)
@@ -99,6 +99,7 @@
   unlockedRecipes:
   - SeedExtractorMachineCircuitboard
   - HydroponicsTrayMachineCircuitboard
+  - Vape
 
 - type: technology
   name: technologies-virology
index df0687b5b4ba168f19c001d978bcecc30ce8b168..a7f6dbd76d202cb216b132f4591163463b53df20 100644 (file)
@@ -7,6 +7,7 @@
     CigPackBlack: 2
     CigarCase: 1
     SmokingPipeFilledTobacco: 1
+    Vape: 1
     Matchbox: 5
     PackPaperRollingFilters: 3
     CheapLighter: 4
diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Smokeables/Vapes/vape.yml b/Resources/Prototypes/Entities/Objects/Consumable/Smokeables/Vapes/vape.yml
new file mode 100644 (file)
index 0000000..bdb7bb2
--- /dev/null
@@ -0,0 +1,10 @@
+- type: entity
+  id: Vape
+  parent: BaseVape
+  name: vape
+  description: "Like a cigar, but for tough teens. (WARNING:Pour only water into the vape)"
+  components:
+  - type: Sprite
+    sprite: Objects/Consumable/Smokeables/Vapes/vape-standart.rsi
+    netsync: false
+    state: icon
\ No newline at end of file
index 419ab7639152a822788d274e44ec02aecb12ffdf..62af60b66ece5d0212fbc64ee09c47002db98546 100644 (file)
     solutions:
       smokable:
         maxVol: 20
+
+- type: entity
+  parent: BaseItem
+  id: BaseVape
+  abstract: true
+  components:
+  - type: Vape
+    damage:
+      groups:
+        Burn: 2
+  - type: SolutionContainerManager
+    solutions:
+      smokable:
+        maxVol: 10
+  - type: RefillableSolution
+    solution: smokable
+  - type: ExaminableSolution
+    solution: smokable
\ No newline at end of file
index 6a2046dd2d2353d9ac5c7462a6717a2abb7d6b1f..050f225ef2104ba36440692ed98362a7e1bcdd01 100644 (file)
       - ClothingShoesBootsMag
       - NodeScanner
       - HolofanProjector
+      - Vape
 
 - type: entity
   parent: Protolathe
index 3d5807517a93a25e468e949f9bb05564d2439884..709447bd9bdbb13fbbbabf059b481ebee4957b1a 100644 (file)
   completetime: 2
   materials:
     Glass: 50
+
+- type: latheRecipe
+  id: Vape
+  icon:
+    sprite: Objects/Consumable/Smokeables/Vapes/vape-standart.rsi
+    state: icon
+  result: Vape
+  completetime: 2
+  materials:
+    Plastic: 100
+    Steel: 250
diff --git a/Resources/Textures/Objects/Consumable/Smokeables/Vapes/vape-standart.rsi/icon.png b/Resources/Textures/Objects/Consumable/Smokeables/Vapes/vape-standart.rsi/icon.png
new file mode 100644 (file)
index 0000000..0c212d3
Binary files /dev/null and b/Resources/Textures/Objects/Consumable/Smokeables/Vapes/vape-standart.rsi/icon.png differ
diff --git a/Resources/Textures/Objects/Consumable/Smokeables/Vapes/vape-standart.rsi/meta.json b/Resources/Textures/Objects/Consumable/Smokeables/Vapes/vape-standart.rsi/meta.json
new file mode 100644 (file)
index 0000000..6b846e6
--- /dev/null
@@ -0,0 +1,14 @@
+{
+  "version": 1,
+  "license": "CC-BY-SA-3.0",
+  "copyright": "Created by Mozinov",
+  "size": {
+    "x": 32,
+    "y": 32
+  },
+  "states": [
+    {
+      "name": "icon"
+    }
+  ]
+}