Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 8 additions & 13 deletions 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;
using Content.Server.Traits.Assorted;
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.Reagent;
Expand Down Expand Up @@ -83,6 +84,13 @@ public sealed partial class BloodstreamComponent : Component
[DataField]
public FixedPoint2 BloodRefreshAmount = 1.0f;

/// <summary>
/// How much hunger/thirst is used to regenerate one unit of blood. Set to zero to disable.
/// The actual thirst/hunger rate will scale with <see cref="BloodRefreshAmount"/>.
/// </summary>
/// <remarks>Those will have no effect if the entity has no hunger/thirst components.</remarks>
public float BloodRegenerationHunger = 1f, BloodRegenerationThirst = 1f;

/// <summary>
/// How much blood needs to be in the temporary solution in order to create a puddle?
/// </summary>
Expand Down Expand Up @@ -172,18 +180,5 @@ 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>
[DataField]
public bool HasBloodDeficiency = false;

/// <summary>
/// How much percentage of max blood volume should be removed with blood deficiency in each update interval?
/// </summary>
[DataField]
public float BloodDeficiencyLossPercentage;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using Content.Shared.FixedPoint;

namespace Content.Server.Body.Events;

/// <summary>
/// Raised on a mob when its bloodstream tries to perform natural blood regeneration.
/// </summary>
[ByRefEvent]
public sealed class NaturalBloodRegenerationAttemptEvent : CancellableEntityEventArgs
{
/// <summary>
/// How much blood the mob will regenerate on this tick. Can be negative.
/// </summary>
public FixedPoint2 Amount;
}
50 changes: 39 additions & 11 deletions Content.Server/Body/Systems/BloodstreamSystem.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Content.Server.Body.Components;
using Content.Server.Body.Events;
using Content.Server.Chemistry.Containers.EntitySystems;
using Content.Server.Chemistry.ReactionEffects;
using Content.Server.Fluids.EntitySystems;
Expand All @@ -14,6 +15,8 @@
using Content.Shared.Drunk;
using Content.Shared.FixedPoint;
using Content.Shared.Mobs.Systems;
using Content.Shared.Nutrition.Components;
using Content.Shared.Nutrition.EntitySystems;
using Content.Shared.Popups;
using Content.Shared.Rejuvenate;
using Content.Shared.Speech.EntitySystems;
Expand All @@ -39,6 +42,8 @@ public sealed class BloodstreamSystem : EntitySystem
[Dependency] private readonly SharedStutteringSystem _stutteringSystem = default!;
[Dependency] private readonly AlertsSystem _alertsSystem = default!;
[Dependency] private readonly ForensicsSystem _forensicsSystem = default!;
[Dependency] private readonly HungerSystem _hunger = default!;
[Dependency] private readonly ThirstSystem _thirst = default!;

public override void Initialize()
{
Expand Down Expand Up @@ -118,17 +123,9 @@ public override void Update(float frameTime)
if (!_solutionContainerSystem.ResolveSolution(uid, bloodstream.BloodSolutionName, ref bloodstream.BloodSolution, out var bloodSolution))
continue;

// Removes blood for Blood Deficiency constantly.
if (bloodstream.HasBloodDeficiency)
{
if (!_mobStateSystem.IsDead(uid))
RemoveBlood(uid, bloodstream.BloodMaxVolume * bloodstream.BloodDeficiencyLossPercentage, bloodstream);
}
// Adds blood to their blood level if it is below the maximum.
else if (bloodSolution.Volume < bloodSolution.MaxVolume && !_mobStateSystem.IsDead(uid))
{
TryModifyBloodLevel(uid, bloodstream.BloodRefreshAmount, bloodstream);
}
// Try to apply natural blood regeneration/bloodloss
if (!_mobStateSystem.IsDead(uid))
TryDoNaturalRegeneration((uid, bloodstream), bloodSolution);

// 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 @@ -498,4 +495,35 @@ private void RemoveBlood(EntityUid uid, FixedPoint2 amount, BloodstreamComponent

bloodSolution.RemoveReagent(component.BloodReagent, amount);
}

/// <summary>
/// Tries to apply natural blood regeneration/loss to the entity. Returns true if succesful.
/// </summary>
private bool TryDoNaturalRegeneration(Entity<BloodstreamComponent> ent, Solution bloodSolution)
{
var ev = new NaturalBloodRegenerationAttemptEvent { Amount = ent.Comp.BloodRefreshAmount };
RaiseLocalEvent(ent, ref ev);

if (ev.Cancelled || (ev.Amount > 0 && bloodSolution.Volume >= bloodSolution.MaxVolume))
return false;

var usedHunger = ev.Amount * ent.Comp.BloodRegenerationHunger;
var usedThirst = ev.Amount * ent.Comp.BloodRegenerationThirst;

// First, check if the entity has enough hunger/thirst
var hungerComp = CompOrNull<HungerComponent>(ent);
var thirstComp = CompOrNull<ThirstComponent>(ent);
if (usedHunger > 0 && hungerComp is not null && (hungerComp.CurrentHunger < usedHunger || hungerComp.CurrentThreshold <= HungerThreshold.Starving)
|| usedThirst > 0 && thirstComp is not null && (thirstComp.CurrentThirst < usedThirst || thirstComp.CurrentThirstThreshold <= ThirstThreshold.Parched))
return false;

// Then actually expend hunger and thirst (if necessary) and regenerate blood.
if (usedHunger > 0 && hungerComp is not null)
_hunger.ModifyHunger(ent, (float) -usedHunger, hungerComp);

if (usedThirst > 0 && thirstComp is not null)
_thirst.ModifyThirst(ent, thirstComp, (float) -usedThirst);

return TryModifyBloodLevel(ent, ev.Amount, ent.Comp);
}
}
6 changes: 6 additions & 0 deletions Content.Server/Traits/BloodDeficiencyComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,10 @@ public sealed partial class BloodDeficiencyComponent : Component
// </summary>
[DataField(required: true)]
public float BloodLossPercentage;

/// <summary>
/// Whether the effects of this trait should be active.
/// </summary>
[DataField]
public bool Active = true;
}
17 changes: 9 additions & 8 deletions Content.Server/Traits/BloodDeficiencySystem.cs
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
using Content.Server.Body.Systems;
using Content.Server.Body.Components;
using Content.Shared.Damage;
using Content.Server.Body.Events;
using Content.Server.Traits.Assorted;
using Content.Shared.FixedPoint;

namespace Content.Server.Traits.Assorted;
namespace Content.Server.Traits;

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

private void OnStartup(EntityUid uid, BloodDeficiencyComponent component, ComponentStartup args)
private void OnBloodRegen(Entity<BloodDeficiencyComponent> ent, ref NaturalBloodRegenerationAttemptEvent args)
{
if (!TryComp<BloodstreamComponent>(uid, out var bloodstream))
if (!ent.Comp.Active || !TryComp<BloodstreamComponent>(ent.Owner, out var bloodstream))
return;

bloodstream.HasBloodDeficiency = true;
bloodstream.BloodDeficiencyLossPercentage = component.BloodLossPercentage;
args.Amount = FixedPoint2.Min(args.Amount, 0) // If the blood regen amount already was negative, we keep it.
- bloodstream.BloodMaxVolume * ent.Comp.BloodLossPercentage;
}
}
1 change: 1 addition & 0 deletions Resources/Prototypes/Entities/Mobs/Species/arachne.yml
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@
- DoorBumpOpener
- type: Bloodstream
bloodReagent: DemonsBlood
bloodRegenerationThirst: 4 # 1 unit of demon's blood satiates 4 thirst
- type: BloodSucker
webRequired: true
- type: Arachne
Expand Down
2 changes: 2 additions & 0 deletions Resources/Prototypes/Entities/Mobs/Species/diona.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
amount: 5
- type: Bloodstream
bloodReagent: Sap
bloodRegenerationHunger: 1
bloodRegenerationThirst: 1 # 1 unit of sap satiates 1 hunger and thirst
- type: Reactive
groups:
Flammable: [ Touch ]
Expand Down
2 changes: 2 additions & 0 deletions Resources/Prototypes/Entities/Mobs/Species/slime.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
color: "#2cf274"
- type: Bloodstream
bloodReagent: Slime # TODO Color slime blood based on their slime color or smth
bloodRegenerationHunger: 2
bloodRegenerationThirst: 2 # 1 of slime satiates 2 hunger
- type: Barotrauma
damage:
types:
Expand Down
2 changes: 2 additions & 0 deletions Resources/Prototypes/Entities/Mobs/base.yml
Original file line number Diff line number Diff line change
Expand Up @@ -233,3 +233,5 @@
bloodlossHealDamage:
types:
Bloodloss: -1
bloodRegenerationHunger: 1
bloodRegenerationThirst: 1.5 # 1 unit of normal blood satiates 1t, 0.3t for vampires, 0.75h, and restores 0.25 blood for non-humans...
16 changes: 10 additions & 6 deletions Resources/Prototypes/Reagents/biological.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
Drink:
effects:
- !type:SatiateThirst
factor: 1.5
factor: 0.5
conditions:
- !type:OrganType
type: Human
Expand All @@ -39,7 +39,7 @@
- !type:OrganType
type: Vampiric
reagent: Protein
amount: 0.15
amount: 0.125 # See below
- !type:AdjustReagent
conditions:
- !type:OrganType
Expand All @@ -50,7 +50,11 @@
effects:
- !type:AdjustReagent
reagent: UncookedAnimalProteins
amount: 0.5
amount: 0.125 # 0.25 proteins for 1u of blood - restores 0.75 hunger, adds 0.25 blood per unit
conditions:
- !type:OrganType
type: Vampiric
shouldHave: false
Medicine:
effects:
- !type:HealthChange
Expand Down Expand Up @@ -99,7 +103,7 @@
# Delicious!
effects:
- !type:SatiateHunger
factor: 1.5
factor: 1
footstepSound:
collection: FootstepBlood
params:
Expand All @@ -123,9 +127,9 @@
# Sweet!
effects:
- !type:SatiateHunger
factor: 1
factor: 0.5
- !type:SatiateThirst
factor: 1
factor: 0.5
footstepSound:
collection: FootstepBlood
params:
Expand Down