From d375879a3a3d4035998dca85b665f7f3d93b8bab Mon Sep 17 00:00:00 2001
From: DrakiaXYZ <565558+DrakiaXYZ@users.noreply.github.com>
Date: Sun, 26 Oct 2025 01:47:40 -0700
Subject: [PATCH] Fix post-raid health (#661)
* Fix post-raid health
- Re-add death penalty for limbs
- Correctly set body part HP to 1 for cursed death only
- Use the server profile body part max HP for calculating penalties
- Never modify the body part max HP on the profile
- Remove ResetMaxLimbHp as it's unnecessary if we never update max HP elsewhere
* Formatting
* Remove unnecessary null coalescing
* Stupid formatting
---------
Co-authored-by: DrakiaXYZ <565558+TheDgtl@users.noreply.github.com>
---
.../SPT_Data/configs/health.json | 3 +-
.../Extensions/ProfileExtensions.cs | 13 -------
.../Helpers/HealthHelper.cs | 34 ++++++++++++-------
.../Models/Spt/Config/HealthConfig.cs | 3 ++
.../Services/LocationLifecycleService.cs | 6 +---
5 files changed, 28 insertions(+), 31 deletions(-)
diff --git a/Libraries/SPTarkov.Server.Assets/SPT_Data/configs/health.json b/Libraries/SPTarkov.Server.Assets/SPT_Data/configs/health.json
index 239dfdce..1e762a3d 100644
--- a/Libraries/SPTarkov.Server.Assets/SPT_Data/configs/health.json
+++ b/Libraries/SPTarkov.Server.Assets/SPT_Data/configs/health.json
@@ -1,6 +1,7 @@
{
"healthMultipliers": {
- "blacked": 0.1
+ "blacked": 0.1,
+ "death": 0.3
},
"save": {
"health": true
diff --git a/Libraries/SPTarkov.Server.Core/Extensions/ProfileExtensions.cs b/Libraries/SPTarkov.Server.Core/Extensions/ProfileExtensions.cs
index 1f17c7bf..46b265e2 100644
--- a/Libraries/SPTarkov.Server.Core/Extensions/ProfileExtensions.cs
+++ b/Libraries/SPTarkov.Server.Core/Extensions/ProfileExtensions.cs
@@ -254,19 +254,6 @@ public static class ProfileExtensions
return quest?.Status ?? QuestStatusEnum.Locked;
}
- ///
- /// Use values from the profiles template to reset all body part max values
- ///
- /// Profile to update
- /// Template used to create profile
- public static void ResetMaxLimbHp(this PmcData profile, TemplateSide profileTemplate)
- {
- foreach (var (partKey, bodyPart) in profile.Health.BodyParts)
- {
- bodyPart.Health.Maximum = profileTemplate.Character.Health.BodyParts[partKey].Health.Maximum;
- }
- }
-
///
/// Handle Remove event
/// Remove item from player inventory + insured items array
diff --git a/Libraries/SPTarkov.Server.Core/Helpers/HealthHelper.cs b/Libraries/SPTarkov.Server.Core/Helpers/HealthHelper.cs
index 9fbf43a9..f14b4341 100644
--- a/Libraries/SPTarkov.Server.Core/Helpers/HealthHelper.cs
+++ b/Libraries/SPTarkov.Server.Core/Helpers/HealthHelper.cs
@@ -3,6 +3,7 @@ using SPTarkov.Server.Core.Exceptions.Helpers;
using SPTarkov.Server.Core.Models.Common;
using SPTarkov.Server.Core.Models.Eft.Common;
using SPTarkov.Server.Core.Models.Eft.Common.Tables;
+using SPTarkov.Server.Core.Models.Eft.Health;
using SPTarkov.Server.Core.Models.Spt.Config;
using SPTarkov.Server.Core.Models.Utils;
using SPTarkov.Server.Core.Servers;
@@ -23,7 +24,7 @@ public class HealthHelper(ISptLogger logger, TimeUtil timeUtil, Co
/// Session id
/// Player profile to apply changes to
/// Changes to apply
- public void ApplyHealthChangesToProfile(MongoId sessionId, PmcData pmcProfileToUpdate, BotBaseHealth healthChanges)
+ public void ApplyHealthChangesToProfile(MongoId sessionId, PmcData pmcProfileToUpdate, BotBaseHealth healthChanges, bool isDead)
{
/* TODO: Not used here, need to check node or a live profile, commented out for now to avoid the potential alloc - Cj
var fullProfile = saveServer.GetProfile(sessionId);
@@ -44,7 +45,7 @@ public class HealthHelper(ISptLogger logger, TimeUtil timeUtil, Co
var playerWasCursed = !PlayerHadGearOnRaidStart(pmcProfileToUpdate.Inventory);
// Alter saved profiles Health with values from post-raid client data
- ModifyProfileHealthProperties(pmcProfileToUpdate, healthChanges.BodyParts, EffectsToSkip, playerWasCursed);
+ ModifyProfileHealthProperties(pmcProfileToUpdate, healthChanges.BodyParts, EffectsToSkip, isDead, playerWasCursed);
// Adjust hydration/energy/temperature
AdjustProfileHydrationEnergyTemperature(pmcProfileToUpdate, healthChanges);
@@ -103,11 +104,13 @@ public class HealthHelper(ISptLogger logger, TimeUtil timeUtil, Co
/// Player profile on server
/// Changes to apply
///
+ ///
/// Did player enter raid with no equipment
protected void ModifyProfileHealthProperties(
PmcData profileToAdjust,
Dictionary bodyPartChanges,
HashSet? effectsToSkip = null,
+ bool isDead = false,
bool playerWasCursed = false
)
{
@@ -131,17 +134,24 @@ public class HealthHelper(ISptLogger logger, TimeUtil timeUtil, Co
if (HealthConfig.Save.Health)
{
// Apply hp changes to profile
- matchingProfilePart.Health.Current =
- partProperties.Health.Current == 0
- ? partProperties.Health.Maximum * HealthConfig.HealthMultipliers.Blacked
- : partProperties.Health.Current;
-
- matchingProfilePart.Health.Maximum = partProperties.Health.Maximum;
-
- // Cursed player + limb was not lost, reset to 20%
- if (playerWasCursed && matchingProfilePart.Health.Current > 20)
+ if (!isDead)
{
- matchingProfilePart.Health.Current = 20;
+ // If the player isn't dead, restore blacked limbs with a penalty
+ matchingProfilePart.Health.Current =
+ partProperties.Health.Current == 0
+ ? matchingProfilePart.Health.Maximum * HealthConfig.HealthMultipliers.Blacked
+ : partProperties.Health.Current;
+ }
+ else
+ {
+ // If the player died, set all limbs with a penalty
+ matchingProfilePart.Health.Current = matchingProfilePart.Health.Maximum * HealthConfig.HealthMultipliers.Death;
+
+ // Cursed player, body part gets set to 1 on death
+ if (playerWasCursed)
+ {
+ matchingProfilePart.Health.Current = 1;
+ }
}
}
diff --git a/Libraries/SPTarkov.Server.Core/Models/Spt/Config/HealthConfig.cs b/Libraries/SPTarkov.Server.Core/Models/Spt/Config/HealthConfig.cs
index 069fd882..6d255115 100644
--- a/Libraries/SPTarkov.Server.Core/Models/Spt/Config/HealthConfig.cs
+++ b/Libraries/SPTarkov.Server.Core/Models/Spt/Config/HealthConfig.cs
@@ -18,6 +18,9 @@ public record HealthMultipliers
{
[JsonPropertyName("blacked")]
public double Blacked { get; set; }
+
+ [JsonPropertyName("death")]
+ public double Death { get; set; }
}
public record HealthSave
diff --git a/Libraries/SPTarkov.Server.Core/Services/LocationLifecycleService.cs b/Libraries/SPTarkov.Server.Core/Services/LocationLifecycleService.cs
index 2714f71f..ba94bcb1 100644
--- a/Libraries/SPTarkov.Server.Core/Services/LocationLifecycleService.cs
+++ b/Libraries/SPTarkov.Server.Core/Services/LocationLifecycleService.cs
@@ -792,11 +792,7 @@ public class LocationLifecycleService(
MergePmcAndScavEncyclopedias(serverPmcProfile, scavProfile);
// Handle temp, hydration, limb hp/effects
- healthHelper.ApplyHealthChangesToProfile(sessionId, serverPmcProfile, postRaidProfile.Health);
-
- // Required when player loses limb in-raid and fixes it, max now stuck at 50% or less if lost multiple times
- var profileTemplate = profileHelper.GetProfileTemplateForSide(fullServerProfile.ProfileInfo.Edition, serverPmcProfile.Info.Side);
- serverPmcProfile.ResetMaxLimbHp(profileTemplate);
+ healthHelper.ApplyHealthChangesToProfile(sessionId, serverPmcProfile, postRaidProfile.Health, isDead);
if (isTransfer)
{