From cb559fdf5c12ead5b4d11ba0a85edf187788a053 Mon Sep 17 00:00:00 2001 From: Chomp Date: Sun, 29 Jun 2025 15:48:23 +0100 Subject: [PATCH] Reduced complexity of post-raid health transfer Likely fixed issue with effects not transferring over correctly out of raid --- .../Extensions/FullProfileExtensions.cs | 12 - .../Helpers/HealthHelper.cs | 211 ++++-------------- 2 files changed, 45 insertions(+), 178 deletions(-) diff --git a/Libraries/SPTarkov.Server.Core/Extensions/FullProfileExtensions.cs b/Libraries/SPTarkov.Server.Core/Extensions/FullProfileExtensions.cs index 45db2338..7cf71219 100644 --- a/Libraries/SPTarkov.Server.Core/Extensions/FullProfileExtensions.cs +++ b/Libraries/SPTarkov.Server.Core/Extensions/FullProfileExtensions.cs @@ -6,18 +6,6 @@ namespace SPTarkov.Server.Core.Extensions { public static class FullProfileExtensions { - public static void StoreHydrationEnergyTempInProfile( - this SptProfile fullProfile, - double hydration, - double energy, - double temperature - ) - { - fullProfile.VitalityData.Hydration = hydration; - fullProfile.VitalityData.Energy = energy; - fullProfile.VitalityData.Temperature = temperature; - } - /// /// Add a list of suit ids to a profiles suit list, no duplicates /// diff --git a/Libraries/SPTarkov.Server.Core/Helpers/HealthHelper.cs b/Libraries/SPTarkov.Server.Core/Helpers/HealthHelper.cs index d186b641..aa68214e 100644 --- a/Libraries/SPTarkov.Server.Core/Helpers/HealthHelper.cs +++ b/Libraries/SPTarkov.Server.Core/Helpers/HealthHelper.cs @@ -1,8 +1,6 @@ using SPTarkov.DI.Annotations; -using SPTarkov.Server.Core.Extensions; using SPTarkov.Server.Core.Models.Eft.Common; using SPTarkov.Server.Core.Models.Eft.Common.Tables; -using SPTarkov.Server.Core.Models.Eft.Profile; using SPTarkov.Server.Core.Models.Spt.Config; using SPTarkov.Server.Core.Servers; using SPTarkov.Server.Core.Utils; @@ -20,20 +18,6 @@ public class HealthHelper( { protected readonly HealthConfig _healthConfig = _configServer.GetConfig(); - /// - /// Resets the profiles vitality/health and vitality/effects properties to their defaults - /// - /// Session Id - /// Updated profile - public SptProfile ResetVitality(string sessionID) - { - var profile = _saveServer.GetProfile(sessionID); - - profile.VitalityData.SetDefaults(); - - return profile; - } - /// /// Update player profile vitality values with changes from client request object /// @@ -58,50 +42,15 @@ public class HealthHelper( var defaultTemperature = matchingSide?.Character?.Health?.Temperature ?? new CurrentMinMax { Current = 36.6 }; - fullProfile.StoreHydrationEnergyTempInProfile( - healthChanges.Hydration.Current ?? 0, - healthChanges.Energy.Current ?? 0, - defaultTemperature.Current ?? 0 // Reset profile temp to the default to prevent very cold/hot temps persisting into next raid - ); - - // Store limb effects from post-raid in profile - foreach (var bodyPart in healthChanges.BodyParts) - { - // Effects - if (healthChanges.BodyParts[bodyPart.Key].Effects is not null) - { - fullProfile.VitalityData.Health[bodyPart.Key].Effects = healthChanges - .BodyParts[bodyPart.Key] - .Effects; - } - - // Limb hp - if (!isDead) - // Player alive, not is limb alive - { - fullProfile.VitalityData.Health[bodyPart.Key].Health.Current = - healthChanges.BodyParts[bodyPart.Key].Health.Current ?? 0; - } - else - { - fullProfile.VitalityData.Health[bodyPart.Key].Health.Current = - pmcProfileToUpdate.Health.BodyParts[bodyPart.Key].Health.Maximum - * _healthConfig.HealthMultipliers.Death - ?? 0; - } - } // Alter saved profiles Health with values from post-raid client data - ModifyProfileHeathProperties( - healthChanges.BodyParts, + ModifyProfileHealthProperties( pmcProfileToUpdate, + healthChanges.BodyParts, ["Dehydration", "Exhaustion"] ); - // Adjust hydration/energy/temp and limb hp using temp storage hydrated above - SaveHealth(pmcProfileToUpdate, sessionID); - - // Reset temp storage - ResetVitality(sessionID); + // Adjust hydration/energy/temperature + AdjustProfileHydrationEnergyTemperature(pmcProfileToUpdate, healthChanges); // Update last edited timestamp pmcProfileToUpdate.Health.UpdateTime = _timeUtil.GetTimeStamp(); @@ -110,22 +59,39 @@ public class HealthHelper( /// /// Apply Health values to profile /// - /// Changes to apply /// Player profile on server + /// Changes to apply /// - protected void ModifyProfileHeathProperties( - Dictionary bodyPartChanges, + protected void ModifyProfileHealthProperties( PmcData profileToAdjust, + Dictionary bodyPartChanges, HashSet? effectsToSkip = null ) { foreach (var (partName, partProperties) in bodyPartChanges) { + if ( + !profileToAdjust.Health.BodyParts.TryGetValue(partName, out var matchingProfilePart) + ) + { + continue; + } + + 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; + } + // Process each effect for each part foreach (var (key, effectDetails) in partProperties.Effects) { // Null guard - var matchingProfilePart = profileToAdjust.Health.BodyParts[partName]; matchingProfilePart.Effects ??= new Dictionary(); // Effect already exists on limb in server profile, skip @@ -157,117 +123,30 @@ public class HealthHelper( } /// - /// Adjust hydration/energy/temperate and body part hp values in player profile to values in `profile.vitality` + /// Adjust hydration/energy/temperate /// - /// Profile to update - /// Session id - protected void SaveHealth(PmcData pmcData, string sessionID) - { - if (!_healthConfig.Save.Health) - { - return; - } - - var profileHealth = _saveServer.GetProfile(sessionID).VitalityData; - - if (profileHealth.Hydration > pmcData.Health.Hydration.Maximum) - { - profileHealth.Hydration = pmcData.Health.Hydration.Maximum; - } - - if (profileHealth.Energy > pmcData.Health.Energy.Maximum) - { - profileHealth.Energy = pmcData.Health.Energy.Maximum; - } - - if (profileHealth.Temperature > pmcData.Health.Temperature.Maximum) - { - profileHealth.Temperature = pmcData.Health.Temperature.Maximum; - } - - pmcData.Health.Hydration.Current = Math.Round(profileHealth.Hydration ?? 0); - pmcData.Health.Energy.Current = Math.Round(profileHealth.Energy ?? 0); - pmcData.Health.Temperature.Current = Math.Round(profileHealth.Temperature ?? 0); - - foreach (var (partName, partProperties) in pmcData.Health.BodyParts) - { - var matchingProfilePart = profileHealth.Health[partName]; - if (matchingProfilePart.Health.Maximum > partProperties.Health.Maximum) - { - matchingProfilePart.Health.Maximum = partProperties.Health.Maximum; - } - - if (matchingProfilePart.Health.Current == 0) - { - matchingProfilePart.Health.Current = - partProperties.Health.Maximum * _healthConfig.HealthMultipliers.Blacked; - } - - partProperties.Health.Current = Math.Round(matchingProfilePart.Health.Current ?? 0); - } - } - - /// - /// Save effects to profile - /// Works by removing all effects and adding them back from profile - /// Removes empty 'Effects' objects if found - /// - /// Player profile - /// Session id - /// Dictionary of body parts with effects that should be added to profile - /// Should effects be added back to profile - protected void SaveEffects( - PmcData pmcData, - string sessionID, - Dictionary bodyPartsWithEffects, - bool deleteExistingEffects = true + /// Profile to update + /// + protected void AdjustProfileHydrationEnergyTemperature( + PmcData profileToUpdate, + BotBaseHealth healthChanges ) { - // TODO: this will need to change, typing is all fucked up - if (!_healthConfig.Save.Effects) - { - return; - } + // Ensure current hydration/energy/temp are copied over and don't exceed maximum + var profileHealth = profileToUpdate.Health; + profileHealth.Hydration.Current = + profileHealth.Hydration.Current > healthChanges.Hydration.Maximum + ? healthChanges.Hydration.Maximum + : Math.Round(healthChanges.Hydration.Current ?? 0); - foreach (var bodyPart in bodyPartsWithEffects) - { - // clear effects from profile bodyPart - if (deleteExistingEffects) - { - pmcData.Health.BodyParts[bodyPart.Key].Effects = - new Dictionary(); - } + profileHealth.Energy.Current = + profileHealth.Energy.Current > healthChanges.Energy.Maximum + ? healthChanges.Energy.Maximum + : Math.Round(healthChanges.Energy.Current ?? 0); - foreach (var effectType in bodyPartsWithEffects[bodyPart.Key].Effects) - { - var time = effectType.Value.Time; - if (time is not null && time > 0) - { - AddEffect(pmcData, effectType, time); - } - else - { - AddEffect(pmcData, effectType); - } - } - } - } - - /// - /// Add effect to body part in profile - /// - /// Player profile - /// Effect to add to body part - /// How long the effect has left in seconds (-1 by default, no duration). - protected void AddEffect( - PmcData pmcData, - KeyValuePair effectType, - double? duration = -1 - ) - { - var profileBodyPart = pmcData.Health.BodyParts[effectType.Key]; - profileBodyPart.Effects ??= new Dictionary(); - - profileBodyPart.Effects[effectType.Key] = new BodyPartEffectProperties { Time = duration }; + profileHealth.Temperature.Current = + profileHealth.Temperature.Current > healthChanges.Temperature.Maximum + ? healthChanges.Temperature.Maximum + : Math.Round(healthChanges.Temperature.Current ?? 0); } }