Skip to content

Commit

Permalink
New Trait: Blood Deficiency (Vault-Overseers#686)
Browse files Browse the repository at this point in the history
# Description

**Blood Deficiency** is a +2 points negative Physical trait that makes
you slowly lose blood over time. When left untreated you will die from
blood loss. Inspired by the SS13 trait of the same name.

Slash/Piercing weapons and bleeding are much more lethal against you.

The moment you start taking **any** blood loss damage, you start dying
because you can't regenerate blood. Even just two consecutive kitchen
knife stabs will make you bleed enough to die slowly unless you
immediately apply gauze.

Blood packs, iron pills (or copper for Arachnids), and gauze to stop
bleeding will help you survive with this trait.

Here's how the timeline looks for untreated blood deficiency:
- ~0-21 minutes: losing blood slowly
- ~21-31 minutes: blood level below 90%, start taking bloodloss damage
- ~31-33 minutes: critical
- ~34 minutes: death

## Media

<details><summary>Expand</summary>

**Trait entry**


![image](https://github.com/user-attachments/assets/ea4a0c3c-7c05-45fc-8a32-48957701a246)


![image](https://github.com/user-attachments/assets/37398779-90a4-4f4f-a183-38d806184394)

As shown above, even just reducing the blood volume to less than 90%
means you will die a slow and painful death.

</details>

</p>
</details>

# Changelog

:cl: Skubman
- add: Add the Blood Deficiency trait, a new negative trait that makes
you slowly lose blood over time. You must routinely receive blood loss
treatment to live, and even normally non-lethal bleeding can make you
start dying slowly.
  • Loading branch information
angelofallars authored Aug 6, 2024
1 parent b7d3080 commit 6ab1797
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 6 deletions.
15 changes: 14 additions & 1 deletion Content.Server/Body/Components/BloodstreamComponent.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Content.Server.Body.Systems;
using Content.Server.Chemistry.EntitySystems;
using Content.Server.Traits.Assorted;
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.Damage;
Expand All @@ -11,7 +12,7 @@

namespace Content.Server.Body.Components
{
[RegisterComponent, Access(typeof(BloodstreamSystem), typeof(ReactionMixerSystem))]
[RegisterComponent, Access(typeof(BloodstreamSystem), typeof(ReactionMixerSystem), typeof(BloodDeficiencySystem))]
public sealed partial class BloodstreamComponent : Component
{
public static string DefaultChemicalsSolutionName = "chemicals";
Expand Down Expand Up @@ -171,5 +172,17 @@ public sealed partial class BloodstreamComponent : Component
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
public TimeSpan StatusTime;

/// <summary>
/// If this is true, the entity will not passively regenerate blood,
/// and instead will slowly lose blood.
/// </summary>
public bool HasBloodDeficiency = false;

/// <summary>
/// How much reagent of blood should be removed with blood deficiency in each update interval?
/// </summary>
[DataField]
public FixedPoint2 BloodDeficiencyLossAmount;
}
}
25 changes: 20 additions & 5 deletions Content.Server/Body/Systems/BloodstreamSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,11 +118,14 @@ public override void Update(float frameTime)
if (!_solutionContainerSystem.ResolveSolution(uid, bloodstream.BloodSolutionName, ref bloodstream.BloodSolution, out var bloodSolution))
continue;

// Adds blood to their blood level if it is below the maximum; Blood regeneration. Must be alive.
if (bloodSolution.Volume < bloodSolution.MaxVolume && !_mobStateSystem.IsDead(uid))
{
TryModifyBloodLevel(uid, bloodstream.BloodRefreshAmount, bloodstream);
}
// Removes blood for Blood Deficiency constantly.
if (bloodstream.HasBloodDeficiency)
if (!_mobStateSystem.IsDead(uid))
RemoveBlood(uid, bloodstream.BloodDeficiencyLossAmount, bloodstream);
// Adds blood to their blood level if it is below the maximum.
else if (bloodSolution.Volume < bloodSolution.MaxVolume)
if (!_mobStateSystem.IsDead(uid))
TryModifyBloodLevel(uid, bloodstream.BloodRefreshAmount, bloodstream);

// Removes blood from the bloodstream based on bleed amount (bleed rate)
// as well as stop their bleeding to a certain extent.
Expand Down Expand Up @@ -472,4 +475,16 @@ public void ChangeBloodReagent(EntityUid uid, string reagent, BloodstreamCompone
if (currentVolume > 0)
_solutionContainerSystem.TryAddReagent(component.BloodSolution.Value, component.BloodReagent, currentVolume, out _);
}

/// <summary>
/// Remove blood from an entity, without spilling it.
/// </summary>
private void RemoveBlood(EntityUid uid, FixedPoint2 amount, BloodstreamComponent? component = null)
{
if (!Resolve(uid, ref component, logMissing: false)
|| !_solutionContainerSystem.ResolveSolution(uid, component.BloodSolutionName, ref component.BloodSolution, out var bloodSolution))
return;

bloodSolution.RemoveReagent(component.BloodReagent, amount);
}
}
14 changes: 14 additions & 0 deletions Content.Server/Traits/BloodDeficiencyComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
namespace Content.Server.Traits.Assorted;

/// <summary>
/// This is used for the Blood Deficiency trait.
/// </summary>
[RegisterComponent]
public sealed partial class BloodDeficiencyComponent : Component
{
// <summary>
// How much reagent of blood should be removed in each update interval?
// </summary>
[DataField(required: true)]
public float BloodLossAmount;
}
23 changes: 23 additions & 0 deletions Content.Server/Traits/BloodDeficiencySystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using Content.Server.Body.Systems;
using Content.Server.Body.Components;
using Content.Shared.Damage;

namespace Content.Server.Traits.Assorted;

public sealed class BloodDeficiencySystem : EntitySystem
{
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<BloodDeficiencyComponent, ComponentStartup>(OnStartup);
}

private void OnStartup(EntityUid uid, BloodDeficiencyComponent component, ComponentStartup args)
{
if (!TryComp<BloodstreamComponent>(uid, out var bloodstream))
return;

bloodstream.HasBloodDeficiency = true;
bloodstream.BloodDeficiencyLossAmount = component.BloodLossAmount;
}
}
5 changes: 5 additions & 0 deletions Resources/Locale/en-US/traits/traits.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ trait-description-HeavyweightDrunk = Alcohol is afraid of you.
trait-name-Muted = Muted
trait-description-Muted = You can't speak
trait-name-BloodDeficiency = Blood Deficiency
trait-description-BloodDeficiency =
Your body loses more blood than it can replenish.
You lose blood over time, and when left untreated you will eventually die from blood loss.
trait-name-Paracusia = Paracusia
trait-description-Paracusia = You hear sounds that aren't really there
Expand Down
14 changes: 14 additions & 0 deletions Resources/Prototypes/Traits/disabilities.yml
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,17 @@
- MedicalBorg
components:
- type: Snoring

- type: trait
id: BloodDeficiency
category: Physical
points: 2
requirements:
- !type:CharacterJobRequirement
inverted: true
jobs:
- Borg
- MedicalBorg
components:
- type: BloodDeficiency # 0.07 = start taking bloodloss damage at around ~21.4 minutes,
bloodLossAmount: 0.07 # then become crit ~10 minutes later

0 comments on commit 6ab1797

Please sign in to comment.