diff --git a/Content.Server/Damage/Components/DamageOtherOnHitComponent.cs b/Content.Server/Damage/Components/DamageOtherOnHitComponent.cs index 3123e251af..3dc78f6a2a 100644 --- a/Content.Server/Damage/Components/DamageOtherOnHitComponent.cs +++ b/Content.Server/Damage/Components/DamageOtherOnHitComponent.cs @@ -15,5 +15,19 @@ public sealed partial class DamageOtherOnHitComponent : Component [ViewVariables(VVAccess.ReadWrite)] public DamageSpecifier Damage = default!; + [DataField("damageMultiplierOverTime")] + [ViewVariables(VVAccess.ReadWrite)] + public float DamageMultiplierOverTime = 1f; + + [DataField("timeTillMaxDamage")] + [ViewVariables(VVAccess.ReadWrite)] + public float TimeTillMaxDamage = 0f; + + [ViewVariables(VVAccess.ReadOnly)] + public TimeSpan TimeThrown = TimeSpan.Zero; + + [ViewVariables(VVAccess.ReadOnly)] + public TimeSpan TimeToMaxDamage = TimeSpan.Zero; + } } diff --git a/Content.Server/Damage/Systems/DamageOtherOnHitSystem.cs b/Content.Server/Damage/Systems/DamageOtherOnHitSystem.cs index 50c69f3829..5e83338aeb 100644 --- a/Content.Server/Damage/Systems/DamageOtherOnHitSystem.cs +++ b/Content.Server/Damage/Systems/DamageOtherOnHitSystem.cs @@ -13,6 +13,7 @@ using Content.Shared.Wires; using Robust.Shared.Physics.Components; using Robust.Shared.Player; +using Robust.Shared.Timing; namespace Content.Server.Damage.Systems { @@ -24,12 +25,14 @@ public sealed class DamageOtherOnHitSystem : EntitySystem [Dependency] private readonly DamageExamineSystem _damageExamine = default!; [Dependency] private readonly SharedCameraRecoilSystem _sharedCameraRecoil = default!; [Dependency] private readonly SharedColorFlashEffectSystem _color = default!; + [Dependency] private readonly IGameTiming _gameTiming = default!; public override void Initialize() { SubscribeLocalEvent(OnDoHit); SubscribeLocalEvent(OnDamageExamine); SubscribeLocalEvent(OnAttemptPacifiedThrow); + SubscribeLocalEvent(OnThrow); } private void OnDoHit(EntityUid uid, DamageOtherOnHitComponent component, ThrowDoHitEvent args) @@ -37,7 +40,15 @@ private void OnDoHit(EntityUid uid, DamageOtherOnHitComponent component, ThrowDo if (TerminatingOrDeleted(args.Target)) return; - var dmg = _damageable.TryChangeDamage(args.Target, component.Damage, component.IgnoreResistances, origin: args.Component.Thrower); + var currentTime = _gameTiming.CurTime; + var timeSinceThrown = (currentTime - component.TimeThrown).TotalSeconds; + float scaleFactor = MathHelper.Clamp((float)(timeSinceThrown / component.TimeTillMaxDamage), 0f, 1f); + + var scaledDamage = new DamageSpecifier(); + foreach (var (damageType, baseDamage) in component.Damage.DamageDict) + scaledDamage.DamageDict[damageType] = baseDamage * (1f - scaleFactor) + baseDamage * component.DamageMultiplierOverTime * scaleFactor; + + var dmg = _damageable.TryChangeDamage(args.Target, scaledDamage, component.IgnoreResistances, origin: args.Component.Thrower); // Log damage only for mobs. Useful for when people throw spears at each other, but also avoids log-spam when explosions send glass shards flying. if (dmg != null && HasComp(args.Target)) @@ -68,5 +79,12 @@ private void OnAttemptPacifiedThrow(Entity ent, ref A { args.Cancel("pacified-cannot-throw"); } + + private void OnThrow(EntityUid uid, DamageOtherOnHitComponent component, ref ThrownEvent args) + { + component.TimeThrown = _gameTiming.CurTime; + component.TimeToMaxDamage = component.TimeThrown + TimeSpan.FromSeconds(component.TimeTillMaxDamage); + } + } } diff --git a/Resources/Locale/en-US/_SSS/store_items.ftl b/Resources/Locale/en-US/_SSS/store_items.ftl index e7ea71d1f5..8a5fd3c088 100644 --- a/Resources/Locale/en-US/_SSS/store_items.ftl +++ b/Resources/Locale/en-US/_SSS/store_items.ftl @@ -7,3 +7,6 @@ uplink-disruptive-throwable-desc = A set of 1 flash, smoke and stinger grenades. uplink-exploding-syndicate-bomb-SSS-desc = A big, anchored bomb that can create a huge explosion if not defused in time. Useful as a distraction. Has an adjustable timer with a minimum setting of 90 seconds. Stays quiet for 30 seconds upon activation. uplink-armour-upgrade-name = Armour Upgrade Kit uplink-armour-upgrade-desc = An armour upgrade kit. Use on your armour to upgrade the protection. Armour will drop if equipped! + +uplink-one-shot-knife-name = Throwing Knife +uplink-one-shot-knife-desc = A combat knife that appears to be normal, but its damage scales with how long its been in the air, dealing up to 100 damage. Destroyed after use, so use it wisely! diff --git a/Resources/Prototypes/_SSS/Catalog/sss_uplink.yml b/Resources/Prototypes/_SSS/Catalog/sss_uplink.yml index 154d829d24..e7e7e2b4ff 100644 --- a/Resources/Prototypes/_SSS/Catalog/sss_uplink.yml +++ b/Resources/Prototypes/_SSS/Catalog/sss_uplink.yml @@ -84,6 +84,17 @@ cost: Telecrystal: 4 +- type: listing + id: UplinkOneShotKnifeSSS + name: uplink-one-shot-knife-name + description: uplink-one-shot-knife-desc + icon: { sprite: /Textures/Objects/Weapons/Melee/combat_knife.rsi, state: icon } + productEntity: CombatKnifeOneShotThrowing + categories: + - SSSTraitorWeapons + cost: + Telecrystal: 2 + - type: listing id: UplinkExplosiveGrenadeSSS name: uplink-explosive-grenade-name diff --git a/Resources/Prototypes/_SSS/Entities/Objects/Weapons/Melee/knife.yml b/Resources/Prototypes/_SSS/Entities/Objects/Weapons/Melee/knife.yml new file mode 100644 index 0000000000..22c647b1e3 --- /dev/null +++ b/Resources/Prototypes/_SSS/Entities/Objects/Weapons/Melee/knife.yml @@ -0,0 +1,17 @@ +- type: entity + name: combat knife + suffix: 1-Hit Throw + parent: CombatKnife + id: CombatKnifeOneShotThrowing + description: A deadly knife intended for melee confrontations. + components: + - type: DamageOtherOnHit + damage: + types: + Slash: 5 + damageMultiplierOverTime: 20 + timeTillMaxDamage: 0.475 + - type: EmbeddableProjectile + sound: /Audio/Weapons/star_hit.ogg + offset: -0.15,0.0 + deleteOnRemove: true