Release 1.11.4.1 (Winter Update)

This commit is contained in:
Markus Isberg
2025-12-08 14:56:47 +00:00
parent 21e34e5cd8
commit 598966f200
121 changed files with 1614 additions and 819 deletions
@@ -1223,6 +1223,7 @@ namespace Barotrauma
if (otherCharacter.SelectedCharacter == null ||
!otherCharacter.SelectedCharacter.IsDead ||
otherCharacter.SelectedCharacter.TeamID != Character.TeamID ||
otherCharacter.IsPet ||
otherCharacter.IsInstigator)
{
continue;
@@ -114,7 +114,7 @@ namespace Barotrauma
if (target.Submarine != character.Submarine) { return; }
Reset();
TargetCharacter = target;
targetBody = target.AnimController.Collider.FarseerBody;
targetBody = target.AnimController.MainLimb.body.FarseerBody;
attachSurfaceNormal = Vector2.Normalize(character.WorldPosition - target.WorldPosition);
}
@@ -769,7 +769,7 @@ namespace Barotrauma
Attack attack = GetAttackDefinition(weapon);
if (attack != null)
{
lethalDmg = attack.GetTotalDamage();
lethalDmg = attack.GetTotalCharacterDamage();
float max = lethalDmg + 1;
if (weapon.Item.HasTag(Tags.StunnerItem))
{
@@ -795,7 +795,7 @@ namespace Barotrauma
Attack attack = GetAttackDefinition(weapon);
if (attack != null)
{
lethalDmg = attack.GetTotalDamage();
lethalDmg = attack.GetTotalCharacterDamage();
float stunDmg = ApproximateStunDamage(weapon, attack);
float diff = stunDmg - lethalDmg;
if (diff < 0)
@@ -809,7 +809,7 @@ namespace Barotrauma
{
// Cannot do stun damage -> use the melee damage to determine the priority.
Attack attack = GetAttackDefinition(weapon);
priority = attack?.GetTotalDamage() ?? priority / 2;
priority = attack?.GetTotalCharacterDamage() ?? priority / 2;
}
// Reduce the priority of the weapon, if we don't have requires skills to use it.
float startPriority = priority;
@@ -960,7 +960,7 @@ namespace Barotrauma
Attack attack = GetAttackDefinition(weapon);
if (attack != null)
{
lethalDmg = attack.GetTotalDamage();
lethalDmg = attack.GetTotalCharacterDamage();
}
return lethalDmg;
}
@@ -1,4 +1,5 @@
using Barotrauma.Items.Components;
using Barotrauma.Extensions;
using Barotrauma.Items.Components;
using System.Linq;
namespace Barotrauma
@@ -94,6 +95,7 @@ namespace Barotrauma
if (potentialDeconstructor?.InputContainer == null) { continue; }
if (!potentialDeconstructor.InputContainer.Inventory.CanBePut(Item)) { continue; }
if (!potentialDeconstructor.Item.HasAccess(character)) { continue; }
if (Item.Prefab.DeconstructItems.None(it => it.IsValidDeconstructor(otherItem))) { continue; }
float distFactor = GetDistanceFactor(Item.WorldPosition, potentialDeconstructor.Item.WorldPosition, factorAtMaxDistance: 0.2f);
if (distFactor > bestDistFactor)
{
@@ -1,6 +1,7 @@
using Barotrauma.Extensions;
using Barotrauma.Items.Components;
using System.Collections.Generic;
using System.Linq;
namespace Barotrauma
{
@@ -30,6 +31,7 @@ namespace Barotrauma
if (character.Submarine == null ||
Item.ItemList.None(it =>
it.GetComponent<Deconstructor>() != null &&
!it.IgnoreByAI(character) &&
it.IsInteractable(character) &&
character.Submarine.IsEntityFoundOnThisSub(it, includingConnectedSubs: true, allowDifferentTeam: true, allowDifferentType: true)))
{
@@ -60,6 +62,9 @@ namespace Barotrauma
protected override bool IsValidTarget(Item target)
{
if (target == null || target.Removed) { return false; }
//bots can't handle deconstructing items that require another item to deconstruct, let's not try to do that
//in the vanilla game, this means unidentified genetic materials, which we don't want to "deconstruct" anyway
if (target.Prefab.DeconstructItems.All(d => d.RequiredOtherItem.Length > 0)) { return false; }
// If the target was selected as a valid target, we'll have to accept it so that the objective can be completed.
// The validity changes when a character picks the item up.
if (!IsValidTarget(target, character, checkInventory: true))
@@ -98,18 +98,11 @@ namespace Barotrauma
vitality -= affliction.GetVitalityDecrease(character.CharacterHealth, strength) / character.MaxVitality * 100;
if (affliction.Strength > affliction.Prefab.TreatmentThreshold)
{
if (affliction.Prefab.AfflictionType == AfflictionPrefab.ParalysisType)
//vitality loss is not required to treat this affliction -> evaluate the strength of the affliction too
if (!affliction.Prefab.VitalityLossRequiredForTreatment)
{
vitality -= affliction.Strength;
}
else if (affliction.Prefab.AfflictionType == AfflictionPrefab.PoisonType)
{
vitality -= affliction.Strength;
}
else if (affliction.Prefab == AfflictionPrefab.HuskInfection)
{
vitality -= affliction.Strength;
}
}
}
return Math.Clamp(vitality, 0, 100);
@@ -437,8 +437,25 @@ namespace Barotrauma
public bool TargetItemsMatchItem(Item item, Identifier option = default)
{
if (item == null) { return false; }
if (Identifier == Tags.DeconstructThis && item.AllowDeconstruct && !Item.DeconstructItems.Contains(item)) { return true; }
if (Identifier == Tags.DontDeconstructThis && Item.DeconstructItems.Contains(item)) { return true; }
if (Identifier == Tags.DeconstructThis && item.AllowDeconstruct)
{
if (item.AllowDeconstruct && !Item.DeconstructItems.Contains(item) &&
//only allow deconstructing if there are deconstruction recipes that
item.Prefab.DeconstructItems.Any(deconstructItem =>
//1. don't require any additional items (bots can't handle that)
deconstructItem.RequiredOtherItem.None() &&
//2. don't require a research station (bots don't know how to use those)
(deconstructItem.RequiredDeconstructor.Length == 0 || deconstructItem.RequiredDeconstructor.Any(d => d != Tags.GeneticResearchStation))))
{
return true;
}
}
else if (Identifier == Tags.DontDeconstructThis)
{
if (Item.DeconstructItems.Contains(item)) { return true; }
}
ImmutableArray<Identifier> targetItems = GetTargetItems(option);
return TargetItemsMatchItem(targetItems, item);
}
@@ -216,6 +216,7 @@ namespace Barotrauma
{
UpdateTemporaryAnimations();
UpdateAnim(deltaTime);
CheckRopeState();
}
protected abstract void UpdateAnim(float deltaTime);
@@ -1134,6 +1135,25 @@ namespace Barotrauma
character.TeleportTo(pos);
}
protected void CheckRopeState()
{
if (!shouldHangWithRope)
{
StopHangingWithRope();
}
if (!shouldHoldToRope)
{
StopHoldingToRope();
}
if (!shouldBeDraggedWithRope)
{
StopGettingDraggedWithRope();
}
shouldHoldToRope = false;
shouldHangWithRope = false;
shouldBeDraggedWithRope = false;
}
private void StartAnimation(Animation animation)
{
if (animation == Animation.UsingItem)
@@ -478,21 +478,6 @@ namespace Barotrauma
aiming = false;
wasAimingMelee = aimingMelee;
aimingMelee = false;
if (!shouldHangWithRope)
{
StopHangingWithRope();
}
if (!shouldHoldToRope)
{
StopHoldingToRope();
}
if (!shouldBeDraggedWithRope)
{
StopGettingDraggedWithRope();
}
shouldHoldToRope = false;
shouldHangWithRope = false;
shouldBeDraggedWithRope = false;
}
void UpdateStanding()
@@ -1256,34 +1241,25 @@ namespace Barotrauma
float prevVitality = target.Vitality;
bool wasCritical = prevVitality < 0.0f;
if (GameMain.NetworkMember == null || !GameMain.NetworkMember.IsClient) //Serverside code
float cprBoost = character.GetStatValue(StatTypes.CPRBoost);
float skill = character.GetSkillLevel(Tags.MedicalSkill);
bool oxygenAvailable = target.OxygenAvailable >= CharacterHealth.InsufficientOxygenThreshold;
//Serverside code
if (oxygenAvailable && GameMain.NetworkMember is not { IsClient: true })
{
target.Oxygen += deltaTime * 0.5f; //Stabilize them
}
float cprBoost = character.GetStatValue(StatTypes.CPRBoost);
int skill = (int)character.GetSkillLevel(Tags.MedicalSkill);
if (GameMain.NetworkMember is not { IsClient: true })
{
if (cprBoost >= 1f)
{
//prevent the patient from suffocating no matter how fast their oxygen level is dropping
target.Oxygen = Math.Max(target.Oxygen, -10.0f);
}
}
//Serverside code
if (GameMain.NetworkMember is not { IsClient: true })
{
if (target.Oxygen < -10.0f)
{
//stabilize the oxygen level but don't allow it to go positive and revive the character yet
float stabilizationAmount = skill * CPRSettings.Active.StabilizationPerSkill;
stabilizationAmount = MathHelper.Clamp(stabilizationAmount, CPRSettings.Active.StabilizationMin, CPRSettings.Active.StabilizationMax);
character.Oxygen -= 1.0f / stabilizationAmount * deltaTime; //Worse skill = more oxygen required
if (character.Oxygen > 0.0f) { target.Oxygen += stabilizationAmount * deltaTime; } //we didn't suffocate yet did we
target.Oxygen += stabilizationAmount * deltaTime;
}
}
@@ -1317,7 +1293,7 @@ namespace Barotrauma
}
//need to CPR for at least a couple of seconds before the target can be revived
//(reviving the target when the CPR has barely started looks strange)
if (cprAnimTimer > 2.0f && GameMain.NetworkMember is not { IsClient: true })
if (oxygenAvailable && cprAnimTimer > 2.0f && GameMain.NetworkMember is not { IsClient: true })
{
float reviveChance = skill * CPRSettings.Active.ReviveChancePerSkill;
reviveChance = (float)Math.Pow(reviveChance, CPRSettings.Active.ReviveChanceExponent);
@@ -1338,7 +1314,7 @@ namespace Barotrauma
//got the character back into a non-critical state, increase medical skill
//BUT only if it has been more than 10 seconds since the character revived someone
//otherwise it's easy to abuse the system by repeatedly reviving in a low-oxygen room
if (!target.IsDead)
if (!target.IsDead || !oxygenAvailable)
{
target.CharacterHealth.RecalculateVitality();
if (wasCritical && target.Vitality > 0.0f && Timing.TotalTime > lastReviveTime + 10.0f)
@@ -75,7 +75,7 @@ namespace Barotrauma
get { return frozen; }
set
{
if (frozen == value) return;
if (frozen == value) { return; }
frozen = value;
@@ -1055,7 +1055,8 @@ namespace Barotrauma
}
}
public void FindHull(Vector2? worldPosition = null, bool setSubmarine = true)
/// <param name="setInWater">Should the character be immediately considered "in water" if it's outside hulls (normally checked in Update)</param>
public void FindHull(Vector2? worldPosition = null, bool setSubmarine = true, bool setInWater = false)
{
Vector2 findPos = worldPosition == null ? this.WorldPosition : (Vector2)worldPosition;
if (!MathUtils.IsValid(findPos))
@@ -1068,6 +1069,10 @@ namespace Barotrauma
}
Hull newHull = Hull.FindHull(findPos, currentHull);
if (setInWater && newHull == null)
{
inWater = true;
}
if (newHull == currentHull) { return; }
@@ -403,14 +403,19 @@ namespace Barotrauma
return (Duration == 0.0f) ? dmg : dmg * deltaTime;
}
public float GetTotalDamage(bool includeStructureDamage = false)
/// <summary>
/// Returns the total damage (vitality decrease) this attack causes on characters.
/// </summary>
public float GetTotalCharacterDamage()
{
float totalDamage = includeStructureDamage ? StructureDamage : 0.0f;
float totalDamage = 0.0f;
foreach (Affliction affliction in Afflictions.Keys)
{
totalDamage += affliction.GetVitalityDecrease(null);
float afflictionVitalityDecrease = affliction.GetVitalityDecrease(null);
if (affliction.AffectedByAttackMultipliers) { afflictionVitalityDecrease *= DamageMultiplier; }
totalDamage += afflictionVitalityDecrease;
}
return totalDamage * DamageMultiplier;
return totalDamage;
}
public Attack(float damage, float bleedingDamage, float burnDamage, float structureDamage, float itemDamage, float range = 0.0f)
@@ -30,7 +30,7 @@ namespace Barotrauma
partial class Character : Entity, IDamageable, ISerializableEntity, IClientSerializable, IServerPositionSync
{
public readonly static List<Character> CharacterList = new List<Character>();
public static readonly List<Character> CharacterList = new List<Character>();
public const float MaxHighlightDistance = 150.0f;
public const float MaxDragDistance = 200.0f;
@@ -39,7 +39,13 @@ namespace Barotrauma
partial void UpdateLimbLightSource(Limb limb);
private bool enabled = true;
private bool initialized;
private bool enabled;
//characters start disabled in the multiplayer mode, and are enabled if/when
// - controlled by the player
// - client receives a position update from the server
// - server receives an input message from the client controlling the character
// - if an AICharacter, the server enables it when close enough to any of the players
public bool Enabled
{
get
@@ -48,7 +54,12 @@ namespace Barotrauma
}
set
{
if (value == enabled) { return; }
if (initialized && value == enabled)
{
// Ensure that we'll set the value and run the code below at least once, because otherwise the states might be out of sync.
return;
}
initialized = true;
if (Removed)
{
@@ -80,7 +91,6 @@ namespace Barotrauma
//we only want to enable the physics body if it's an actual holdable item, not e.g. a wearable item like handcuffs
item.body.Enabled = true;
}
}
AnimController.Collider.Enabled = value;
}
@@ -109,6 +119,13 @@ namespace Barotrauma
if (!CharacterList.Contains(this)) { CharacterList.Add(this); }
if (AiTarget != null && !AITarget.List.Contains(AiTarget)) { AITarget.List.Add(AiTarget); }
}
if (Inventory != null)
{
foreach (var item in Inventory.FindAllItems(recursive: true))
{
item.IsActive = !disabledByEvent;
}
}
}
}
@@ -1619,18 +1636,14 @@ namespace Barotrauma
PressureProtection = int.MaxValue;
}
AnimController.SetPosition(ConvertUnits.ToSimUnits(position));
CharacterHealth.CheckForErrors();
AnimController.FindHull(null);
AnimController.SetPosition(ConvertUnits.ToSimUnits(position));
AnimController.FindHull(setInWater: true);
if (AnimController.CurrentHull != null) { Submarine = AnimController.CurrentHull.Submarine; }
CharacterList.Add(this);
//characters start disabled in the multiplayer mode, and are enabled if/when
// - controlled by the player
// - client receives a position update from the server
// - server receives an input message from the client controlling the character
// - if an AICharacter, the server enables it when close enough to any of the players
Enabled = GameMain.NetworkMember == null;
if (info != null)
@@ -3304,17 +3317,22 @@ namespace Barotrauma
public static void UpdateAll(float deltaTime, Camera cam)
{
if (GameMain.NetworkMember == null || !GameMain.NetworkMember.IsClient)
if (GameMain.NetworkMember == null || !GameMain.NetworkMember.IsClient) // single player or server
{
foreach (Character c in CharacterList)
{
if (c is not AICharacter && !c.IsRemotePlayer) { continue; }
if (c.IsPlayer || (c.IsBot && !c.IsDead))
// TODO: The logic below seems to be overly complicated and quite confusing
if (c is not AICharacter && !c.IsRemotePlayer) { continue; } // confusing -> what this line is intended for? local player? But that's handled below...
if (c.IsRemotePlayer)
{
// Let the client tell when to enable the character. If we force it enabled here, it may e.g. get killed while still loading a round.
continue;
}
if (c.IsLocalPlayer || (c.IsBot && !c.IsDead))
{
c.Enabled = true;
}
else if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsServer)
else if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsServer) // mp server
{
//disable AI characters that are far away from all clients and the host's character and not controlled by anyone
float closestPlayerDist = c.GetDistanceToClosestPlayer();
@@ -3331,7 +3349,7 @@ namespace Barotrauma
c.Enabled = true;
}
}
else if (Submarine.MainSub != null)
else if (Submarine.MainSub != null) // sp only?
{
//disable AI characters that are far away from the sub and the controlled character
float distSqr = Vector2.DistanceSquared(Submarine.MainSub.WorldPosition, c.WorldPosition);
@@ -3360,10 +3378,9 @@ namespace Barotrauma
}
}
for (int i = 0; i < CharacterList.Count; i++)
foreach (Character character in CharacterList)
{
var character = CharacterList[i];
System.Diagnostics.Debug.Assert(character != null && !character.Removed);
Debug.Assert(character is { Removed: false });
character.Update(deltaTime, cam);
}
@@ -3425,8 +3442,7 @@ namespace Barotrauma
foreach (Item item in Inventory.GetAllItems(checkForDuplicates: false))
{
if (item.body == null || item.body.Enabled) { continue; }
item.SetTransform(SimPosition, 0.0f);
item.Submarine = Submarine;
item.SetTransform(SimPosition, 0.0f, forceSubmarine: Submarine);
}
}
@@ -4575,7 +4591,10 @@ namespace Barotrauma
SetStun(stun);
if (attacker != null && attacker != this && GameMain.NetworkMember != null && !GameMain.NetworkMember.ServerSettings.AllowFriendlyFire)
if (attacker != null && attacker != this &&
attacker.IsOnPlayerTeam &&
GameMain.NetworkMember != null &&
!GameMain.NetworkMember.ServerSettings.AllowFriendlyFire)
{
if (attacker.TeamID == TeamID)
{
@@ -85,6 +85,8 @@ namespace Barotrauma
public double AppliedAsSuccessfulTreatmentTime, AppliedAsFailedTreatmentTime;
public bool AffectedByAttackMultipliers => Prefab.AffectedByAttackMultipliers;
public float Duration;
/// <summary>
@@ -164,15 +164,18 @@ namespace Barotrauma
}
break;
case InfectionState.Transition:
if (character == Character.Controlled)
if (Prefab is AfflictionPrefabHusk { CauseSpeechImpediment: true })
{
if (character == Character.Controlled)
{
#if CLIENT
GUI.AddMessage(TextManager.Get("HuskCantSpeak"), GUIStyle.Red);
GUI.AddMessage(TextManager.Get("HuskCantSpeak"), GUIStyle.Red);
#endif
}
else if (character.IsBot)
{
character.Speak(TextManager.Get("dialoghuskcantspeak").Value, delay: Rand.Range(0.5f, 5.0f), identifier: "huskcantspeak".ToIdentifier());
}
else if (character.IsBot)
{
character.Speak(TextManager.Get("dialoghuskcantspeak").Value, delay: Rand.Range(0.5f, 5.0f), identifier: "huskcantspeak".ToIdentifier());
}
}
break;
case InfectionState.Active:
@@ -699,7 +699,13 @@ namespace Barotrauma
/// and the health UI will render the affected limb in green rather than red.
/// </summary>
public readonly bool IsBuff;
/// <summary>
/// Should the affliction be affected by damage multipliers on an attack (e.g. when the attacker has talents that boost damage).
/// By default, afflictions defined as buffs aren't affected.
/// </summary>
public readonly bool AffectedByAttackMultipliers;
/// <summary>
/// If set to true, this affliction can affect characters that are marked as
/// machines, such as the Fractal Guardian.
@@ -780,6 +786,14 @@ namespace Barotrauma
/// </summary>
public readonly float TreatmentSuggestionThreshold;
/// <summary>
/// Does the affliction need to have caused some amount of vitality loss for bots to consider treating it?
/// Normally bots use vitality loss as a way to determine what kind of injuries need treatment, but some afflictions (e.g. poisons, infections)
/// might require treatment regardless of the vitality loss. If disabled, the bots will use the strength of the affliction to evaluate the severity instead of the vitality loss.
/// Defaults to true for all afflictions that aren't of the type Paralysis, Poison or HuskInfection.
/// </summary>
public readonly bool VitalityLossRequiredForTreatment;
/// <summary>
/// Bots will not try to treat the affliction if the character has any of these afflictions
/// </summary>
@@ -838,14 +852,15 @@ namespace Barotrauma
public readonly bool DamageParticles;
/// <summary>
/// An arbitrary modifier that affects how much medical skill is increased when you apply the affliction on a target.
/// If the affliction causes damage or is of the 'poison' or 'paralysis' type, the skill is increased only when the target is hostile.
/// If the affliction is of the 'buff' type, the skill is increased only when the target is friendly.
/// A modifier that affects how much medical skill is increased when you apply this affliction on a target.
/// If the affliction causes damage or is of the 'poison' or 'paralysis' type, the skill is increased only when the target is hostile, and the modifier is multiplied by the amount of vitality the enemy lost.
/// If the affliction is of the 'buff' type, the skill is increased only when the target is friendly, and the modifier is multiplied by the strength of the affliction the target gained.
/// </summary>
public readonly float MedicalSkillGain;
/// <summary>
/// An arbitrary modifier that affects how much weapons skill is increased when you apply the affliction on a target.
/// A modifier that affects how much weapons skill is increased when you apply the affliction on a target.
/// Multiplied by the amount of vitality the enemy lost.
/// The skill is increased only when the target is hostile.
/// </summary>
public readonly float WeaponsSkillGain;
@@ -925,6 +940,7 @@ namespace Barotrauma
ShowDescriptionInTooltip = element.GetAttributeBool(nameof(ShowDescriptionInTooltip), true);
IsBuff = element.GetAttributeBool(nameof(IsBuff), false);
AffectedByAttackMultipliers = element.GetAttributeBool(nameof(AffectedByAttackMultipliers), def: !IsBuff);
AffectMachines = element.GetAttributeBool(nameof(AffectMachines), true);
ShowBarInHealthMenu = element.GetAttributeBool("showbarinhealthmenu", true);
@@ -977,6 +993,11 @@ namespace Barotrauma
TreatmentThreshold = element.GetAttributeFloat(nameof(TreatmentThreshold), Math.Max(ActivationThreshold, 10.0f));
TreatmentSuggestionThreshold = element.GetAttributeFloat(nameof(TreatmentSuggestionThreshold), TreatmentThreshold);
bool alwaysRequiresTreatment = AfflictionType == ParalysisType || AfflictionType == PoisonType || this is AfflictionPrefabHusk;
VitalityLossRequiredForTreatment = element.GetAttributeBool(nameof(VitalityLossRequiredForTreatment),
def: !alwaysRequiresTreatment);
DamageOverlayAlpha = element.GetAttributeFloat(nameof(DamageOverlayAlpha), 0.0f);
BurnOverlayAlpha = element.GetAttributeFloat(nameof(BurnOverlayAlpha), 0.0f);
@@ -304,6 +304,19 @@ namespace Barotrauma
InitProjSpecific(element, character);
}
public void CheckForErrors()
{
for (int i = 0; i < limbHealths.Count; i++)
{
if (Character.AnimController.Limbs.None(l => l.HealthIndex == i))
{
DebugConsole.AddWarning(
$"Potential error in character {Character.DisplayName}: none of the limbs have been set to use the LimbHealth #{i}, and it will do nothing. "
+ "Did you forget to set the HealthIndex values of the limbs?", contentPackage: Character.ContentPackage);
}
}
}
private void InitIrremovableAfflictions()
{
irremovableAfflictions.Add(bloodlossAffliction = new Affliction(AfflictionPrefab.Bloodloss, 0.0f));
@@ -1118,20 +1131,38 @@ namespace Barotrauma
// We need to use another list of the afflictions when we call the status effects triggered by afflictions,
// because those status effects may add or remove other afflictions while iterating the collection.
private readonly List<Affliction> afflictionsCopy = new List<Affliction>();
private readonly List<Affliction> afflictionsCopy = [];
private bool isApplyingAfflictionStatusEffects;
public void ApplyAfflictionStatusEffects(ActionType type)
{
afflictionsCopy.Clear();
afflictionsCopy.AddRange(afflictions.Keys);
foreach (Affliction affliction in afflictionsCopy)
if (isApplyingAfflictionStatusEffects)
{
affliction.ApplyStatusEffects(type, 1.0f, this, targetLimb: GetAfflictionLimb(affliction));
//pretty hacky: if we're already in the process of applying afflictions' status effects
//(i.e. calling this method caused some additional afflictions to appear and trigger status effects)
//let's instantiate a new list so we don't end up modifying afflictionsCopy while enumerating it
foreach (Affliction affliction in afflictions.Keys.ToList())
{
affliction.ApplyStatusEffects(type, 1.0f, this, targetLimb: GetAfflictionLimb(affliction));
}
}
else
{
isApplyingAfflictionStatusEffects = true;
afflictionsCopy.Clear();
afflictionsCopy.AddRange(afflictions.Keys);
isApplyingAfflictionStatusEffects = true;
foreach (Affliction affliction in afflictionsCopy)
{
affliction.ApplyStatusEffects(type, 1.0f, this, targetLimb: GetAfflictionLimb(affliction));
}
isApplyingAfflictionStatusEffects = false;
}
}
public (CauseOfDeathType type, Affliction affliction) GetCauseOfDeath()
{
List<Affliction> currentAfflictions = GetAllAfflictions(true);
IEnumerable<Affliction> currentAfflictions = GetAllAfflictions(true);
Affliction strongestAffliction = null;
float largestStrength = 0.0f;
@@ -1154,7 +1185,7 @@ namespace Barotrauma
}
private readonly List<Affliction> allAfflictions = new List<Affliction>();
private List<Affliction> GetAllAfflictions(bool mergeSameAfflictions, Func<Affliction, bool> predicate = null)
private IEnumerable<Affliction> GetAllAfflictions(bool mergeSameAfflictions, Func<Affliction, bool> predicate = null)
{
allAfflictions.Clear();
if (!mergeSameAfflictions)
@@ -843,7 +843,7 @@ namespace Barotrauma
}
}
if (!foundMatchingModifier && random > affliction.Probability) { continue; }
float finalDamageModifier = damageMultiplier;
float finalDamageModifier = affliction.AffectedByAttackMultipliers ? damageMultiplier : 1.0f;
if (character.EmpVulnerability > 0 && affliction.Prefab.AfflictionType == AfflictionPrefab.EMPType)
{
finalDamageModifier *= character.EmpVulnerability;