]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Death Nettle changes (#25253)
authorJames <40279265+ViceEmargo@users.noreply.github.com>
Sat, 29 Mar 2025 09:35:16 +0000 (05:35 -0400)
committerGitHub <noreply@github.com>
Sat, 29 Mar 2025 09:35:16 +0000 (10:35 +0100)
* Added ThornyComponent, ThornyImmuneComponent, and ThornySystem, as well as changed Botanists glove's to have the ThornyImmuneComponent, and for Death Nettle to have the ThornyComponent.

* Added heat damage to the player if they pickup nettle without gloves. Also displays a popup message .

* Revised OnHandPickUp method and reduced whitespace

* Touching death nettle without gloves now does damage split between heat and caustic, and does more damage.

* File-scoped namespace adherence

* Code revisions, and removal of old file.

* Removed thornyImmune key from botanist's gloves in gloves.yml for cleanup / yaml linter

* Adds new generic DamageOnPickup, still very WIP

* Starting on localization, removed _Notes.txt, adds immunity component

* Added OnPickupDamageImmune component to botanists gloves

* Removed botany specific components/system, moved to generic DamageOnPickup. Added code comments. Extra checks in component for whether to toss an item, damage an entity. Still WIP.

* changes to audio and popups

* Removes my system/component/ftl in favor of DamageOnInteract, tweaking values

* me stupid

* Death nettle will 'wilt' after 5 hits

* added interaction delay to stop spam clicking, added a 10% stun (paralyze) chance

* minor changes/cleanup

* more minor changes and cleanup

* Reduced maximum amatoxin within fly amanita spores.

* Readjusted to allow more than 5 amatoxin above 50 potency

* Remove Debug.Log statement from system

* Mark Death Nettle as major contraband.

Content.Shared/Damage/Components/DamageOnInteractComponent.cs
Content.Shared/Damage/Systems/DamageOnInteractSystem.cs
Resources/Prototypes/Entities/Clothing/Hands/gloves.yml
Resources/Prototypes/Entities/Objects/Consumable/Food/produce.yml
Resources/Prototypes/Hydroponics/seeds.yml

index 9487dec8ef963f5d074b912615cc05c3fdf43ef3..d5465f19bda4728f98931d86ebae0e5f5353a9e4 100644 (file)
@@ -44,4 +44,46 @@ public sealed partial class DamageOnInteractComponent : Component
     /// </summary>
     [DataField, AutoNetworkedField]
     public bool IsDamageActive = true;
+
+    /// <summary>
+    /// Whether the thing should be thrown from its current position when they interact with the entity
+    /// </summary>
+    [DataField]
+    public bool Throw = false;
+
+    /// <summary>
+    /// The speed applied to the thing when it is thrown
+    /// </summary>
+    [DataField]
+    public int ThrowSpeed = 10;
+
+    /// <summary>
+    /// Time between being able to interact with this entity
+    /// </summary>
+    [DataField]
+    public uint InteractTimer = 0;
+
+    /// <summary>
+    /// Tracks the last time this entity was interacted with, but only if the interaction resulted in the user taking damage
+    /// </summary>
+    [DataField]
+    public TimeSpan LastInteraction = TimeSpan.Zero;
+
+    /// <summary>
+    /// Tracks the time that this entity can be interacted with, but only if the interaction resulted in the user taking damage
+    /// </summary>
+    [DataField]
+    public TimeSpan NextInteraction = TimeSpan.Zero;
+
+    /// <summary>
+    /// Probability that the user will be stunned when they interact with with this entity and took damage
+    /// </summary>
+    [DataField]
+    public float StunChance = 0.0f;
+
+    /// <summary>
+    /// Duration, in seconds, of the stun applied to the user when they interact with the entity and took damage
+    /// </summary>
+    [DataField]
+    public float StunSeconds = 0.0f;
 }
index cc3b3f6d5d97ea55738e3b772c2d224797086b9e..0f43e93abf3aa151b1245d9d834b0f1051756073 100644 (file)
@@ -4,9 +4,15 @@ using Content.Shared.Database;
 using Content.Shared.Interaction;
 using Content.Shared.Inventory;
 using Content.Shared.Popups;
+using Robust.Shared.Random;
+using Content.Shared.Throwing;
 using Robust.Shared.Audio.Systems;
 using Robust.Shared.Network;
 using Robust.Shared.Timing;
+using Content.Shared.Random;
+using Content.Shared.Movement.Pulling.Components;
+using Content.Shared.Effects;
+using Content.Shared.Stunnable;
 
 namespace Content.Shared.Damage.Systems;
 
@@ -17,6 +23,10 @@ public sealed class DamageOnInteractSystem : EntitySystem
     [Dependency] private readonly SharedAudioSystem _audioSystem = default!;
     [Dependency] private readonly SharedPopupSystem _popupSystem = default!;
     [Dependency] private readonly InventorySystem _inventorySystem = default!;
+    [Dependency] private readonly ThrowingSystem _throwingSystem = default!;
+    [Dependency] private readonly IRobustRandom _random = default!;
+    [Dependency] private readonly IGameTiming _gameTiming = default!;
+    [Dependency] private readonly SharedStunSystem _stun = default!;
 
     public override void Initialize()
     {
@@ -35,6 +45,13 @@ public sealed class DamageOnInteractSystem : EntitySystem
     /// <param name="args">Contains the user that interacted with the entity</param>
     private void OnHandInteract(Entity<DamageOnInteractComponent> entity, ref InteractHandEvent args)
     {
+        // Stop the interaction if the user attempts to interact with the object before the timer is finished
+        if (_gameTiming.CurTime < entity.Comp.NextInteraction)
+        {
+            args.Handled = true;
+            return;
+        }
+
         if (!entity.Comp.IsDamageActive)
             return;
 
@@ -47,9 +64,8 @@ public sealed class DamageOnInteractSystem : EntitySystem
 
             // or checking the entity for  the comp itself if the inventory didn't work
             if (protectiveEntity.Comp == null && TryComp<DamageOnInteractProtectionComponent>(args.User, out var protectiveComp))
-            {
                 protectiveEntity = (args.User, protectiveComp);
-            }
+            
 
             // if protectiveComp isn't null after all that, it means the user has protection,
             // so let's calculate how much they resist
@@ -59,17 +75,31 @@ public sealed class DamageOnInteractSystem : EntitySystem
             }
         }
 
-        totalDamage = _damageableSystem.TryChangeDamage(args.User, totalDamage,  origin: args.Target);
+        totalDamage = _damageableSystem.TryChangeDamage(args.User, totalDamage, origin: args.Target);
 
         if (totalDamage != null && totalDamage.AnyPositive())
         {
+            // Record this interaction and determine when a user is allowed to interact with this entity again
+            entity.Comp.LastInteraction = _gameTiming.CurTime;
+            entity.Comp.NextInteraction = _gameTiming.CurTime + TimeSpan.FromSeconds(entity.Comp.InteractTimer);
+
             args.Handled = true;
             _adminLogger.Add(LogType.Damaged, $"{ToPrettyString(args.User):user} injured their hand by interacting with {ToPrettyString(args.Target):target} and received {totalDamage.GetTotal():damage} damage");
             _audioSystem.PlayPredicted(entity.Comp.InteractSound, args.Target, args.User);
 
             if (entity.Comp.PopupText != null)
                 _popupSystem.PopupClient(Loc.GetString(entity.Comp.PopupText), args.User, args.User);
+
+            // Attempt to paralyze the user after they have taken damage
+            if (_random.Prob(entity.Comp.StunChance))
+                _stun.TryParalyze(args.User, TimeSpan.FromSeconds(entity.Comp.StunSeconds), true);
         }
+        // Check if the entity's Throw bool is false, or if the entity has the PullableComponent, then if the entity is currently being pulled.
+        // BeingPulled must be checked because the entity will be spastically thrown around without this.
+        if (!entity.Comp.Throw || !TryComp<PullableComponent>(entity, out var pullComp) || pullComp.BeingPulled)
+            return;
+
+        _throwingSystem.TryThrow(entity, _random.NextVector2(), entity.Comp.ThrowSpeed, doSpin: true);
     }
 
     public void SetIsDamageActiveTo(Entity<DamageOnInteractComponent> entity, bool mode)
index 20c2488aa75c75c27e20f443863c3533e0c5ea57..6f23003c1af21ce177964c0e57b86b8baec8427f 100644 (file)
     fiberMaterial: fibers-leather
     fiberColor: fibers-brown
   - type: FingerprintMask
+  - type: DamageOnInteractProtection
+    damageProtection:
+      flatReductions:
+        Heat: 10
+        Caustic: 5
 
 - type: entity
   parent: ClothingHandsBase
index ac9757edfbea61e49bec8878674308acc5e72740..0c79c233a41b02089294b7408f58ebed018adab2 100644 (file)
   name: death nettle
   description: This nettle's out for blood.
   id: DeathNettle
-  parent: ProduceBase
+  parent: [ProduceBase, BaseMajorContraband]
   components:
   - type: Sprite
     sprite: Objects/Specific/Hydroponics/death_nettle.rsi
   - type: MeleeWeapon
     damage:
       types:
-        Heat: 8.5
-        Caustic: 8.5
+        Heat: 8
+        Caustic: 8
   - type: SolutionContainerManager
     solutions:
       food:
         reagents:
         - ReagentId: SulfuricAcid
-          Quantity: 3
+          Quantity: 15
         - ReagentId: FluorosulfuricAcid
-          Quantity: 3
+          Quantity: 15
   - type: Produce
     seedId: deathNettle
   - type: MeleeChemicalInjector
-    transferAmount: 2
+    transferAmount: 5
     solution: food
-    pierceArmor: false
+    pierceArmor: true
   - type: Extractable
     grindableSolutionName: food
+  - type: DamageOnInteract
+    damage: 
+      types:
+        Heat: 4
+        Caustic: 4
+    throw: true
+    throwSpeed: 3
+    interactTimer: 2 # Stop the player from spam clicking the entity
+    ignoreResistances: false
+    popupText: powered-light-component-burn-hand
+    interactSound: /Audio/Effects/lightburn.ogg
+    stunChance: 0.10
+    stunSeconds: 1.5
+  - type: Damageable
+    damageContainer: Inorganic
+  - type: Destructible
+    thresholds:
+    - trigger:
+        !type:DamageTrigger
+        damage: 25
+      behaviors:
+      - !type:PlaySoundBehavior
+        sound:
+          path: /Audio/Voice/Diona/diona_salute.ogg
+          params:
+            volume: -5
+      - !type:DoActsBehavior
+        acts: [ "Destruction" ]
+  - type: DamageOnHit 
+    damage:
+      types:
+        Blunt: 5 # The nettle will "wilt" after 5 hits.
 
 - type: entity
   name: banana
   - type: SolutionContainerManager
     solutions:
       food:
-        maxVol: 30
+        maxVol: 15
         reagents:
         - ReagentId: Amatoxin
-          Quantity: 25
+          Quantity: 10
         - ReagentId: Nutriment
           Quantity: 5
   - type: Sprite
index ed5f61922aed51815f7577bbdd06189f1f2bcf4d..68524b15ff2e5ae0aef6c777f35431e91d0ce7c1 100644 (file)
   chemicals:
     Amatoxin:
       Min: 1
-      Max: 25
-      PotencyDivisor: 4
+      Max: 10
+      PotencyDivisor: 12
     Nutriment: ## yumby :)
       Min: 1
       Max: 5