From 79b3190683300e9f53a825b3a09afff019c62238 Mon Sep 17 00:00:00 2001 From: VMSolidus Date: Sat, 10 Aug 2024 17:36:09 -0400 Subject: [PATCH] NyanoCombat 2, Part 3: Physical Traits (#607) # Description Done in partnership with @OldDanceJacket This PR adds 9 additional physical traits to the game, 5 positive, and 4 negative. While this PR is intended to go with NyanoCombat 2, Part 1 and 2, I have made this PR function completely standalone. It does not require either of the two other PRs. ## Positive Traits - **Will To Live**: Increases your Dead threshold by 10 - **Tenacity**: Increases your Crit threshold by 5 - **Vigor**: Increases your maximum Stamina by 10 - **High Adrenaline**: You gain up to 10% more damage with all melee attacks when injured. - **Masochism**: You ignore the first 10% of stamina damage penalties to melee attacks. If NyanoCombat 2 Part 1 isn't merged yet, this makes you deal up to 10% more melee damage when you receive stamina damage. - **Martial Artist**: Your unarmed melee attacks have bonus range, and deal 50% more damage(for every species in the game, this means 7.5 instead of 5 damage). This trait is identical to one that the Boxer job receives for free, thus it cannot be taken by Boxers. ## Negative Traits - **Will To Die**: Decreases your Dead threshold by 15 - **Glass Jaw**: Decreases your Crit Threshold by 10 - **Lethargy**: Decreases your maximum Stamina by 15 - **Adrenal Dysfunction**: Your melee attacks are penalized by up to 20% when injured. If NyanoCombat 2 Part 1 is merged, this cancels out the natural bonus everyone globally gets to melee when injured. - **Low Pain Tolerance**: Your melee attacks are penalized by up to 15% when receiving stamina damage. If NyanoCombat 2 Part 1 is merged, this stacks with the natural penalties everyone globally gets to melee when taking stamina damage. # TODO - [ ] Let ODJ look over these for balance. # Media ![image](https://github.com/user-attachments/assets/242e8b50-8a5e-4079-bf1d-f952ceeade38) # Changelog :cl: VMSolidus and Skubman - add: 11 new Physical Traits have been added to the game! 6 positive traits, and 5 negative traits. --------- Signed-off-by: Danger Revolution! <142105406+DangerRevolution@users.noreply.github.com> Co-authored-by: Angelo Fallaria Co-authored-by: Danger Revolution! <142105406+DangerRevolution@users.noreply.github.com> --- .../Components/AdrenalineComponent.cs | 28 +++ .../Components/CritModifierComponent.cs | 16 ++ .../Components/DeadModifierComponent.cs | 16 ++ .../Components/PainToleranceComponent.cs | 28 +++ .../StaminaCritModifierComponent.cs | 16 ++ .../Systems/TraitStatModifierSystem.cs | 63 ++++++ Resources/Locale/en-US/traits/traits.ftl | 59 +++++ Resources/Prototypes/Traits/physical.yml | 208 ++++++++++++++++++ 8 files changed, 434 insertions(+) create mode 100644 Content.Shared/Traits/Assorted/Components/AdrenalineComponent.cs create mode 100644 Content.Shared/Traits/Assorted/Components/CritModifierComponent.cs create mode 100644 Content.Shared/Traits/Assorted/Components/DeadModifierComponent.cs create mode 100644 Content.Shared/Traits/Assorted/Components/PainToleranceComponent.cs create mode 100644 Content.Shared/Traits/Assorted/Components/StaminaCritModifierComponent.cs create mode 100644 Content.Shared/Traits/Assorted/Systems/TraitStatModifierSystem.cs create mode 100644 Resources/Prototypes/Traits/physical.yml diff --git a/Content.Shared/Traits/Assorted/Components/AdrenalineComponent.cs b/Content.Shared/Traits/Assorted/Components/AdrenalineComponent.cs new file mode 100644 index 00000000000..a0c58edb106 --- /dev/null +++ b/Content.Shared/Traits/Assorted/Components/AdrenalineComponent.cs @@ -0,0 +1,28 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared.Traits.Assorted.Components; + +/// +/// This is used for any trait that modifies the Melee System implementation of Health Contest +/// +[RegisterComponent, NetworkedComponent] +public sealed partial class AdrenalineComponent : Component +{ + /// + /// When true, multiplies by the inverse of the resulting Contest. + /// + [DataField] + public bool Inverse { get; private set; } = false; + + /// + /// Used as the RangeModifier input for a Health Contest. + /// + [DataField] + public float RangeModifier { get; private set; } = 1; + + /// + /// Used as the BypassClamp input for a Health Contest. + /// + [DataField] + public bool BypassClamp { get; private set; } = false; +} \ No newline at end of file diff --git a/Content.Shared/Traits/Assorted/Components/CritModifierComponent.cs b/Content.Shared/Traits/Assorted/Components/CritModifierComponent.cs new file mode 100644 index 00000000000..6cf11e3f7fb --- /dev/null +++ b/Content.Shared/Traits/Assorted/Components/CritModifierComponent.cs @@ -0,0 +1,16 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared.Traits.Assorted.Components; + +/// +/// This is used for any trait that modifies CritThreshold +/// +[RegisterComponent, NetworkedComponent] +public sealed partial class CritModifierComponent : Component +{ + /// + /// The amount that an entity's critical threshold will be incremented by. + /// + [DataField] + public int CritThresholdModifier { get; private set; } = 0; +} \ No newline at end of file diff --git a/Content.Shared/Traits/Assorted/Components/DeadModifierComponent.cs b/Content.Shared/Traits/Assorted/Components/DeadModifierComponent.cs new file mode 100644 index 00000000000..b4ac1bf64fc --- /dev/null +++ b/Content.Shared/Traits/Assorted/Components/DeadModifierComponent.cs @@ -0,0 +1,16 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared.Traits.Assorted.Components; + +/// +/// This is used for any trait that modifies DeadThreshold +/// +[RegisterComponent, NetworkedComponent] +public sealed partial class DeadModifierComponent : Component +{ + /// + /// The amount that an entity's DeadThreshold will be incremented by. + /// + [DataField] + public int DeadThresholdModifier { get; private set; } = 0; +} \ No newline at end of file diff --git a/Content.Shared/Traits/Assorted/Components/PainToleranceComponent.cs b/Content.Shared/Traits/Assorted/Components/PainToleranceComponent.cs new file mode 100644 index 00000000000..03b3bb116a8 --- /dev/null +++ b/Content.Shared/Traits/Assorted/Components/PainToleranceComponent.cs @@ -0,0 +1,28 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared.Traits.Assorted.Components; + +/// +/// This is used for any trait that modifies the Melee System implementation of Stamina Contest +/// +[RegisterComponent, NetworkedComponent] +public sealed partial class PainToleranceComponent : Component +{ + /// + /// When true, multiplies by the inverse of the resulting Contest. + /// + [DataField] + public bool Inverse { get; private set; } = false; + + /// + /// Used as the RangeModifier input for a Stamina Contest. + /// + [DataField] + public float RangeModifier { get; private set; } = 1; + + /// + /// Used as the BypassClamp input for a Stamina Contest. + /// + [DataField] + public bool BypassClamp { get; private set; } = false; +} \ No newline at end of file diff --git a/Content.Shared/Traits/Assorted/Components/StaminaCritModifierComponent.cs b/Content.Shared/Traits/Assorted/Components/StaminaCritModifierComponent.cs new file mode 100644 index 00000000000..28c8ab9b089 --- /dev/null +++ b/Content.Shared/Traits/Assorted/Components/StaminaCritModifierComponent.cs @@ -0,0 +1,16 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared.Traits.Assorted.Components; + +/// +/// This is used for any trait that modifies stamina CritThreshold +/// +[RegisterComponent, NetworkedComponent] +public sealed partial class StaminaCritModifierComponent : Component +{ + /// + /// The amount that an entity's stamina critical threshold will be incremented by. + /// + [DataField] + public int CritThresholdModifier { get; private set; } = 0; +} diff --git a/Content.Shared/Traits/Assorted/Systems/TraitStatModifierSystem.cs b/Content.Shared/Traits/Assorted/Systems/TraitStatModifierSystem.cs new file mode 100644 index 00000000000..85ecf151dd9 --- /dev/null +++ b/Content.Shared/Traits/Assorted/Systems/TraitStatModifierSystem.cs @@ -0,0 +1,63 @@ +using Content.Shared.Contests; +using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; +using Content.Shared.Traits.Assorted.Components; +using Content.Shared.Weapons.Melee.Events; +using Content.Shared.Damage.Components; + +namespace Content.Shared.Traits.Assorted.Systems; + +public sealed partial class TraitStatModifierSystem : EntitySystem +{ + [Dependency] private readonly ContestsSystem _contests = default!; + [Dependency] private readonly MobThresholdSystem _threshold = default!; + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnCritStartup); + SubscribeLocalEvent(OnDeadStartup); + SubscribeLocalEvent(OnStaminaCritStartup); + SubscribeLocalEvent(OnAdrenalineGetDamage); + SubscribeLocalEvent(OnPainToleranceGetDamage); + } + + private void OnCritStartup(EntityUid uid, CritModifierComponent component, ComponentStartup args) + { + if (!TryComp(uid, out var threshold)) + return; + + var critThreshold = _threshold.GetThresholdForState(uid, Mobs.MobState.Critical, threshold); + if (critThreshold != 0) + _threshold.SetMobStateThreshold(uid, critThreshold + component.CritThresholdModifier, Mobs.MobState.Critical); + } + + private void OnDeadStartup(EntityUid uid, DeadModifierComponent component, ComponentStartup args) + { + if (!TryComp(uid, out var threshold)) + return; + + var deadThreshold = _threshold.GetThresholdForState(uid, Mobs.MobState.Dead, threshold); + if (deadThreshold != 0) + _threshold.SetMobStateThreshold(uid, deadThreshold + component.DeadThresholdModifier, Mobs.MobState.Dead); + } + + private void OnStaminaCritStartup(EntityUid uid, StaminaCritModifierComponent component, ComponentStartup args) + { + if (!TryComp(uid, out var stamina)) + return; + + stamina.CritThreshold += component.CritThresholdModifier; + } + + private void OnAdrenalineGetDamage(EntityUid uid, AdrenalineComponent component, ref GetMeleeDamageEvent args) + { + var modifier = _contests.HealthContest(uid, component.BypassClamp, component.RangeModifier); + args.Damage *= component.Inverse ? 1 / modifier : modifier; + } + + private void OnPainToleranceGetDamage(EntityUid uid, PainToleranceComponent component, ref GetMeleeDamageEvent args) + { + var modifier = _contests.StaminaContest(uid, component.BypassClamp, component.RangeModifier); + args.Damage *= component.Inverse ? 1 / modifier : modifier; + } +} diff --git a/Resources/Locale/en-US/traits/traits.ftl b/Resources/Locale/en-US/traits/traits.ftl index ac4eb206c6e..46ee8572a0b 100644 --- a/Resources/Locale/en-US/traits/traits.ftl +++ b/Resources/Locale/en-US/traits/traits.ftl @@ -86,6 +86,64 @@ trait-description-Foreigner = For one reason or another you do not speak this station's primary language. Instead, you have a translator issued to you that only you can use. +trait-name-WillToLive = Will To Live +trait-description-WillToLive = + You have an unusually strong "will to live", and will resist death more than others. + Your damage threshold for becoming Dead is increased by 10 points. + +trait-name-WillToDie = Will To Die +trait-description-WillToDie = + You have an unusually weak "will to live", and will succumb to injuries sooner than others. + Your damage threshold for becoming Dead is decreased by 15 points. + +trait-name-Tenacity = Tenacity +trait-description-Tenacity = + Whether it be through raw grit, willpower, or subtle bionic augmentations, you are hardier than others. + Your damage threshold for becoming Critical is increased by 5 points. + +trait-name-GlassJaw = Glass Jaw +trait-description-GlassJaw = + Your body is more fragile than others, resulting in a greater susceptibility to critical injuries + Your damage threshold for becoming Critical is decreased by 10 points. + +trait-name-HighAdrenaline = High Adrenaline +trait-description-HighAdrenaline = + Whether by natural causes, genetic or bionic augmentation, you have a more potent adrenal gland. + When injured, your melee attacks deal up to 10% more damage, in addition to the natural bonuses from adrenaline. + The standard adrenaline bonuses to melee damage are up to a 20% increase. + +trait-name-AdrenalDysfunction = Adrenal Dysfunction +trait-description-AdrenalDysfunction = + Your adrenal gland is completely nonfunctional, or potentially missing outright. + Your melee attacks do not benefit from Adrenaline when injured. + The standard adrenaline bonuses to melee damage are up to a 20% increase. + +trait-name-Masochism = Masochism +trait-description-Masochism = + Deriving enjoyment from your own pain, you are not as inhibited by it as others. + You ignore the first 10% of stamina damage penalties to your melee attacks. + +trait-name-LowPainTolerance = Low Pain Tolerance +trait-description-LowPainTolerance = + Your tolerance for pain is far below average, and its effects are more inhibiting. + Your melee damage is penalized by up to an additional 15% when taking stamina damage. + +trait-name-MartialArtist = Martial Artist +trait-description-MartialArtist = + You have received formal training in unarmed combat, whether with Fists, Feet, or Claws. + Your unarmed melee attacks have a small range increase, and deal 50% more damage. + This does not apply to any form of armed melee, only the weapons you were naturally born with. + +trait-name-Vigor = Vigor +trait-description-Vigor = + Whether by pure determination, fitness, or bionic augmentations, your endurance is enhanced. + Your stamina is increased by 10 points. + +trait-name-Lethargy = Lethargy +trait-description-Lethargy = + You become tired faster than others, making you more vulnerable to exhaustion and fatigue. + Your stamina is decreased by 15 points. + trait-name-SignLanguage = Sign Language trait-description-SignLanguage = You can understand and use Galactic Sign Language (GSL). @@ -129,3 +187,4 @@ trait-name-WeaponsGeneralist = Weapons Generalist trait-description-WeaponsGeneralist = You are a jack of all trades with melee weapons, enabling you to be versatile with your weapon arsenal. Your melee damage bonus for all Brute damage types (Blunt, Slash, Piercing) becomes 25%. + diff --git a/Resources/Prototypes/Traits/physical.yml b/Resources/Prototypes/Traits/physical.yml new file mode 100644 index 00000000000..85d074ffe95 --- /dev/null +++ b/Resources/Prototypes/Traits/physical.yml @@ -0,0 +1,208 @@ +- type: trait + id: WillToLive + category: Physical + points: -2 + requirements: + - !type:CharacterJobRequirement + inverted: true + jobs: + - Borg + - MedicalBorg + - !type:CharacterTraitRequirement + inverted: true + traits: + - WillToDie + components: + - type: DeadModifier + deadThresholdModifier: 10 + +- type: trait + id: WillToDie + category: Physical + points: 1 + requirements: + - !type:CharacterJobRequirement + inverted: true + jobs: + - Borg + - MedicalBorg + - !type:CharacterTraitRequirement + inverted: true + traits: + - WillToLive + components: + - type: DeadModifier + deadThresholdModifier: -15 + +- type: trait + id: Tenacity + category: Physical + points: -2 + requirements: + - !type:CharacterJobRequirement + inverted: true + jobs: + - Borg + - MedicalBorg + - !type:CharacterTraitRequirement + inverted: true + traits: + - GlassJaw + components: + - type: CritModifier + critThresholdModifier: 5 + +- type: trait + id: GlassJaw + category: Physical + points: 1 + requirements: + - !type:CharacterJobRequirement + inverted: true + jobs: + - Borg + - MedicalBorg + - !type:CharacterTraitRequirement + inverted: true + traits: + - Tenacity + components: + - type: CritModifier + critThresholdModifier: -10 + +- type: trait + id: Vigor + category: Physical + points: -3 + requirements: + - !type:CharacterJobRequirement + inverted: true + jobs: + - Borg + - MedicalBorg + - !type:CharacterTraitRequirement + inverted: true + traits: + - Lethargy + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Oni + components: + - type: StaminaCritModifier + critThresholdModifier: 10 + +- type: trait + id: Lethargy + category: Physical + points: 1 + requirements: + - !type:CharacterJobRequirement + inverted: true + jobs: + - Borg + - MedicalBorg + - !type:CharacterTraitRequirement + inverted: true + traits: + - Vigor + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Felinid + components: + - type: StaminaCritModifier + critThresholdModifier: -15 + +- type: trait + id: HighAdrenaline + category: Physical + points: -3 + requirements: + - !type:CharacterJobRequirement + inverted: true + jobs: + - Borg + - MedicalBorg + - !type:CharacterTraitRequirement + inverted: true + traits: + - AdrenalDysfunction + components: + - type: Adrenaline + rangeModifier: 0.4 + inverse: true + +- type: trait + id: AdrenalDysfunction + category: Physical + points: 1 + requirements: + - !type:CharacterJobRequirement + inverted: true + jobs: + - Borg + - MedicalBorg + - !type:CharacterTraitRequirement + inverted: true + traits: + - HighAdrenaline + components: + - type: Adrenaline + rangeModifier: 0.8 + +- type: trait + id: Masochism + category: Physical + points: -3 + requirements: + - !type:CharacterJobRequirement + inverted: true + jobs: + - Borg + - MedicalBorg + - !type:CharacterTraitRequirement + inverted: true + traits: + - LowPainTolerance + components: + - type: PainTolerance + rangeModifier: 0.4 + inverse: true + +- type: trait + id: LowPainTolerance + category: Physical + points: 1 + requirements: + - !type:CharacterJobRequirement + inverted: true + jobs: + - Borg + - MedicalBorg + - !type:CharacterTraitRequirement + inverted: true + traits: + - Masochism + components: + - type: PainTolerance + rangeModifier: 0.6 + +- type: trait + id: MartialArtist + category: Physical + points: -2 + requirements: + - !type:CharacterJobRequirement + inverted: true + jobs: + - Borg + - MedicalBorg + - Boxer + components: + - type: Boxer + modifiers: + coefficients: + Blunt: 1.5 + Slash: 1.5 + Piercing: 1.5