Merge branch 'master' of https://github.com/Regalis11/Barotrauma into develop

This commit is contained in:
EvilFactory
2023-03-13 13:32:14 -03:00
335 changed files with 11052 additions and 5179 deletions
@@ -19,6 +19,10 @@ namespace Barotrauma
private float fluctuationTimer;
private AfflictionPrefab.Effect activeEffect;
private float prevActiveEffectStrength;
protected bool activeEffectDirty = true;
protected float _strength;
[Serialize(0f, IsPropertySaveable.Yes), Editable]
@@ -46,6 +50,7 @@ namespace Barotrauma
Duration = Prefab.Duration;
}
_strength = newValue;
activeEffectDirty = true;
}
}
@@ -147,7 +152,16 @@ namespace Barotrauma
MathHelper.Clamp((int)Math.Floor(strength / maxStrength * strengthTexts.Length), 0, strengthTexts.Length - 1)];
}
public AfflictionPrefab.Effect GetActiveEffect() => Prefab.GetActiveEffect(Strength);
public AfflictionPrefab.Effect GetActiveEffect()
{
if (activeEffectDirty)
{
activeEffect = Prefab.GetActiveEffect(_strength);
prevActiveEffectStrength = _strength;
activeEffectDirty = false;
}
return activeEffect;
}
public float GetVitalityDecrease(CharacterHealth characterHealth)
{
@@ -158,7 +172,7 @@ namespace Barotrauma
{
if (strength < Prefab.ActivationThreshold) { return 0.0f; }
strength = MathHelper.Clamp(strength, 0.0f, Prefab.MaxStrength);
AfflictionPrefab.Effect currentEffect = Prefab.GetActiveEffect(strength);
AfflictionPrefab.Effect currentEffect = GetActiveEffect();
if (currentEffect == null) { return 0.0f; }
if (currentEffect.MaxStrength - currentEffect.MinStrength <= 0.0f) { return 0.0f; }
@@ -349,7 +363,7 @@ namespace Barotrauma
public float GetStatValue(StatTypes statType)
{
if (!(GetViableEffect() is AfflictionPrefab.Effect currentEffect)) { return 0.0f; }
if (GetViableEffect() is not AfflictionPrefab.Effect currentEffect) { return 0.0f; }
if (currentEffect.AfflictionStatValues.TryGetValue(statType, out var value))
{
@@ -363,7 +377,7 @@ namespace Barotrauma
public bool HasFlag(AbilityFlags flagType)
{
if (!(GetViableEffect() is AfflictionPrefab.Effect currentEffect)) { return false; }
if (GetViableEffect() is not AfflictionPrefab.Effect currentEffect) { return false; }
return currentEffect.AfflictionAbilityFlags.HasFlag(flagType);
}
@@ -415,6 +429,7 @@ namespace Barotrauma
}
// Don't use the property, because it's virtual and some afflictions like husk overload it for external use.
_strength = MathHelper.Clamp(_strength, 0.0f, Prefab.MaxStrength);
activeEffectDirty |= !MathUtils.NearlyEqual(prevActiveEffectStrength, _strength);
foreach (StatusEffect statusEffect in currentEffect.StatusEffects)
{
@@ -445,7 +460,10 @@ namespace Barotrauma
var currentEffect = GetActiveEffect();
if (currentEffect != null)
{
currentEffect.StatusEffects.ForEach(se => ApplyStatusEffect(type, se, deltaTime, characterHealth, targetLimb));
foreach (var statusEffect in currentEffect.StatusEffects)
{
ApplyStatusEffect(type, statusEffect, deltaTime, characterHealth, targetLimb);
}
}
}
@@ -484,6 +502,7 @@ namespace Barotrauma
{
_nonClampedStrength = strength;
_strength = _nonClampedStrength;
activeEffectDirty |= !MathUtils.NearlyEqual(_strength, prevActiveEffectStrength);
}
public bool ShouldShowIcon(Character afflictedCharacter)
@@ -22,7 +22,7 @@ namespace Barotrauma
private Character character;
private bool stun = true;
private bool stun = false;
private readonly List<Affliction> huskInfection = new List<Affliction>();
@@ -43,6 +43,7 @@ namespace Barotrauma
DeactivateHusk();
highestStrength = 0;
}
activeEffectDirty = true;
}
}
private float highestStrength;
@@ -216,7 +217,8 @@ namespace Barotrauma
private void DeactivateHusk()
{
if (character?.AnimController == null || character.Removed) { return; }
if (Prefab is AfflictionPrefabHusk { NeedsAir: false })
if (Prefab is AfflictionPrefabHusk { NeedsAir: false } &&
!character.CharacterHealth.GetAllAfflictions().Any(a => a != this && a.Prefab is AfflictionPrefabHusk { NeedsAir: false }))
{
character.NeedsAir = character.Params.MainElement.GetAttributeBool("needsair", false);
}
@@ -68,7 +68,6 @@ namespace Barotrauma
}
// Remove "[speciesname]" for backward support (we don't use it anymore)
HuskedSpeciesName = HuskedSpeciesName.Remove("[speciesname]").ToIdentifier();
TargetSpecies = element.GetAttributeIdentifierArray("targets", Array.Empty<Identifier>(), trim: true);
if (TargetSpecies.Length == 0)
{
DebugConsole.NewMessage($"No 'targets' defined for the husk affliction ({Identifier}) in {element}", Color.Orange);
@@ -110,7 +109,6 @@ namespace Barotrauma
public float TransformThresholdOnDeath;
public readonly Identifier HuskedSpeciesName;
public readonly Identifier[] TargetSpecies;
public readonly bool TransferBuffs;
public readonly bool SendMessages;
@@ -344,17 +342,30 @@ namespace Barotrauma
}
}
public static readonly Identifier DamageType = "damage".ToIdentifier();
public static readonly Identifier BurnType = "burn".ToIdentifier();
public static readonly Identifier BleedingType = "bleeding".ToIdentifier();
public static readonly Identifier ParalysisType = "paralysis".ToIdentifier();
public static readonly Identifier PoisonType = "poison".ToIdentifier();
public static readonly Identifier StunType = "stun".ToIdentifier();
public static readonly Identifier EMPType = "emp".ToIdentifier();
public static readonly Identifier SpaceHerpesType = "spaceherpes".ToIdentifier();
public static readonly Identifier AlienInfectedType = "alieninfected".ToIdentifier();
public static readonly Identifier InvertControlsType = "invertcontrols".ToIdentifier();
public static readonly Identifier HuskInfectionType = "huskinfection".ToIdentifier();
public static AfflictionPrefab InternalDamage => Prefabs["internaldamage"];
public static AfflictionPrefab BiteWounds => Prefabs["bitewounds"];
public static AfflictionPrefab ImpactDamage => Prefabs["blunttrauma"];
public static AfflictionPrefab Bleeding => Prefabs["bleeding"];
public static AfflictionPrefab Burn => Prefabs["burn"];
public static AfflictionPrefab Bleeding => Prefabs[BleedingType];
public static AfflictionPrefab Burn => Prefabs[BurnType];
public static AfflictionPrefab OxygenLow => Prefabs["oxygenlow"];
public static AfflictionPrefab Bloodloss => Prefabs["bloodloss"];
public static AfflictionPrefab Pressure => Prefabs["pressure"];
public static AfflictionPrefab Stun => Prefabs["stun"];
public static AfflictionPrefab Stun => Prefabs[StunType];
public static AfflictionPrefab RadiationSickness => Prefabs["radiationsickness"];
public static readonly PrefabCollection<AfflictionPrefab> Prefabs = new PrefabCollection<AfflictionPrefab>();
public override void Dispose() { }
@@ -421,6 +432,9 @@ namespace Barotrauma
public readonly float BurnOverlayAlpha;
public readonly float DamageOverlayAlpha;
//steam achievement given when the controlled character receives the affliction
public readonly Identifier AchievementOnReceived;
//steam achievement given when the affliction is removed from the controlled character
public readonly Identifier AchievementOnRemoved;
@@ -453,6 +467,8 @@ namespace Barotrauma
private readonly ConstructorInfo constructor;
public Identifier[] TargetSpecies { get; protected set; }
public readonly bool ResetBetweenRounds;
public IEnumerable<KeyValuePair<Identifier, float>> TreatmentSuitability
@@ -536,13 +552,22 @@ namespace Barotrauma
KarmaChangeOnApplied = element.GetAttributeFloat(nameof(KarmaChangeOnApplied), 0.0f);
CauseOfDeathDescription = TextManager.Get($"AfflictionCauseOfDeath.{TranslationIdentifier}").Fallback(element.GetAttributeString("causeofdeathdescription", ""));
SelfCauseOfDeathDescription = TextManager.Get($"AfflictionCauseOfDeathSelf.{TranslationIdentifier}").Fallback(element.GetAttributeString("selfcauseofdeathdescription", ""));
CauseOfDeathDescription =
TextManager.Get($"AfflictionCauseOfDeath.{TranslationIdentifier}")
.Fallback(TextManager.Get(element.GetAttributeString("causeofdeathdescription", "")))
.Fallback(element.GetAttributeString("causeofdeathdescription", ""));
SelfCauseOfDeathDescription =
TextManager.Get($"AfflictionCauseOfDeathSelf.{TranslationIdentifier}")
.Fallback(TextManager.Get(element.GetAttributeString("selfcauseofdeathdescription", "")))
.Fallback(element.GetAttributeString("selfcauseofdeathdescription", ""));
IconColors = element.GetAttributeColorArray(nameof(IconColors), null);
AfflictionOverlayAlphaIsLinear = element.GetAttributeBool(nameof(AfflictionOverlayAlphaIsLinear), false);
AchievementOnReceived = element.GetAttributeIdentifier(nameof(AchievementOnReceived), "");
AchievementOnRemoved = element.GetAttributeIdentifier(nameof(AchievementOnRemoved), "");
TargetSpecies = element.GetAttributeIdentifierArray("targets", Array.Empty<Identifier>(), trim: true);
ResetBetweenRounds = element.GetAttributeBool("resetbetweenrounds", false);
DamageParticles = element.GetAttributeBool(nameof(DamageParticles), true);
@@ -344,12 +344,12 @@ namespace Barotrauma
return null;
}
public T GetAffliction<T>(string identifier, bool allowLimbAfflictions = true) where T : Affliction
public T GetAffliction<T>(Identifier identifier, bool allowLimbAfflictions = true) where T : Affliction
{
return GetAffliction(identifier, allowLimbAfflictions) as T;
}
public Affliction GetAffliction(string identifier, Limb limb)
public Affliction GetAffliction(Identifier identifier, Limb limb)
{
if (limb.HealthIndex < 0 || limb.HealthIndex >= limbHealths.Count)
{
@@ -385,7 +385,7 @@ namespace Barotrauma
/// <param name="limb">The limb the affliction is attached to</param>
/// <param name="requireLimbSpecific">Does the affliction have to be attached to only the specific limb.
/// Most monsters for example don't have separate healths for different limbs, essentially meaning that every affliction is applied to every limb.</param>
public float GetAfflictionStrength(string afflictionType, Limb limb, bool requireLimbSpecific)
public float GetAfflictionStrength(Identifier afflictionType, Limb limb, bool requireLimbSpecific)
{
if (requireLimbSpecific && limbHealths.Count == 1) { return 0.0f; }
@@ -406,7 +406,7 @@ namespace Barotrauma
return strength;
}
public float GetAfflictionStrength(string afflictionType, bool allowLimbAfflictions = true)
public float GetAfflictionStrength(Identifier afflictionType, bool allowLimbAfflictions = true)
{
float strength = 0.0f;
foreach (KeyValuePair<Affliction, LimbHealth> kvp in afflictions)
@@ -489,16 +489,19 @@ namespace Barotrauma
ReduceMatchingAfflictions(amount, treatmentAction);
}
public void ReduceAfflictionOnAllLimbs(Identifier affliction, float amount, ActionType? treatmentAction = null)
public void ReduceAfflictionOnAllLimbs(Identifier afflictionIdOrType, float amount, ActionType? treatmentAction = null)
{
if (affliction.IsEmpty) { throw new ArgumentException($"{nameof(affliction)} is empty"); }
if (afflictionIdOrType.IsEmpty) { throw new ArgumentException($"{nameof(afflictionIdOrType)} is empty"); }
matchingAfflictions.Clear();
matchingAfflictions.AddRange(afflictions.Keys);
matchingAfflictions.RemoveAll(a =>
a.Prefab.Identifier != affliction &&
a.Prefab.AfflictionType != affliction);
foreach (var affliction in afflictions)
{
if (affliction.Key.Prefab.Identifier == afflictionIdOrType || affliction.Key.Prefab.AfflictionType == afflictionIdOrType)
{
matchingAfflictions.Add(affliction.Key);
}
}
ReduceMatchingAfflictions(amount, treatmentAction);
}
@@ -515,18 +518,21 @@ namespace Barotrauma
ReduceMatchingAfflictions(amount, treatmentAction);
}
public void ReduceAfflictionOnLimb(Limb targetLimb, Identifier affliction, float amount, ActionType? treatmentAction = null)
public void ReduceAfflictionOnLimb(Limb targetLimb, Identifier afflictionIdOrType, float amount, ActionType? treatmentAction = null)
{
if (affliction.IsEmpty) { throw new ArgumentException($"{nameof(affliction)} is empty"); }
if (afflictionIdOrType.IsEmpty) { throw new ArgumentException($"{nameof(afflictionIdOrType)} is empty"); }
if (targetLimb is null) { throw new ArgumentNullException(nameof(targetLimb)); }
matchingAfflictions.Clear();
matchingAfflictions.AddRange(GetAfflictionsForLimb(targetLimb));
matchingAfflictions.RemoveAll(a =>
a.Prefab.Identifier != affliction &&
a.Prefab.AfflictionType != affliction);
var targetLimbHealth = limbHealths[targetLimb.HealthIndex];
foreach (var affliction in afflictions)
{
if ((affliction.Key.Prefab.Identifier == afflictionIdOrType || affliction.Key.Prefab.AfflictionType == afflictionIdOrType) &&
affliction.Value == targetLimbHealth)
{
matchingAfflictions.Add(affliction.Key);
}
}
ReduceMatchingAfflictions(amount, treatmentAction);
}
@@ -633,7 +639,7 @@ namespace Barotrauma
KillIfOutOfVitality();
}
public float GetLimbDamage(Limb limb, string afflictionType = null)
public float GetLimbDamage(Limb limb, Identifier afflictionType)
{
float damageStrength;
if (limb.IsSevered)
@@ -646,16 +652,16 @@ namespace Barotrauma
// Therefore with e.g. 80 health, the max damage per limb would be 40.
// Having at least 40 damage on both legs would cause maximum limping.
float max = MaxVitality / 2;
if (string.IsNullOrEmpty(afflictionType))
if (afflictionType.IsEmpty)
{
float damage = GetAfflictionStrength("damage", limb, true);
float bleeding = GetAfflictionStrength("bleeding", limb, true);
float burn = GetAfflictionStrength("burn", limb, true);
float damage = GetAfflictionStrength(AfflictionPrefab.DamageType, limb, true);
float bleeding = GetAfflictionStrength(AfflictionPrefab.BleedingType, limb, true);
float burn = GetAfflictionStrength(AfflictionPrefab.BurnType, limb, true);
damageStrength = Math.Min(damage + bleeding + burn, max);
}
else
{
damageStrength = Math.Min(GetAfflictionStrength("damage", limb, true), max);
damageStrength = Math.Min(GetAfflictionStrength(afflictionType, limb, true), max);
}
return damageStrength / max;
}
@@ -712,22 +718,17 @@ namespace Barotrauma
if (Character.Params.IsMachine && !newAffliction.Prefab.AffectMachines) { return; }
if (!DoesBleed && newAffliction is AfflictionBleeding) { return; }
if (!Character.NeedsOxygen && newAffliction.Prefab == AfflictionPrefab.OxygenLow) { return; }
if (Character.Params.Health.StunImmunity && newAffliction.Prefab.AfflictionType == "stun")
if (Character.Params.Health.StunImmunity && newAffliction.Prefab.AfflictionType == AfflictionPrefab.StunType)
{
if (Character.EmpVulnerability <= 0 || GetAfflictionStrength("emp", allowLimbAfflictions: false) <= 0)
{
return;
}
}
if (Character.Params.Health.PoisonImmunity && (newAffliction.Prefab.AfflictionType == "poison" || newAffliction.Prefab.AfflictionType == "paralysis")) { return; }
if (Character.EmpVulnerability <= 0 && newAffliction.Prefab.AfflictionType == "emp") { return; }
if (newAffliction.Prefab is AfflictionPrefabHusk huskPrefab)
{
if (huskPrefab.TargetSpecies.None(s => s == Character.SpeciesName))
if (Character.EmpVulnerability <= 0 || GetAfflictionStrength(AfflictionPrefab.EMPType, allowLimbAfflictions: false) <= 0)
{
return;
}
}
if (Character.Params.Health.PoisonImmunity &&
(newAffliction.Prefab.AfflictionType == AfflictionPrefab.PoisonType || newAffliction.Prefab.AfflictionType == AfflictionPrefab.ParalysisType)) { return; }
if (Character.EmpVulnerability <= 0 && newAffliction.Prefab.AfflictionType == AfflictionPrefab.EMPType) { return; }
if (newAffliction.Prefab.TargetSpecies.Any() && newAffliction.Prefab.TargetSpecies.None(s => s == Character.SpeciesName)) { return; }
var should = GameMain.LuaCs.Hook.Call<bool?>("character.applyAffliction", this, limbHealth, newAffliction, allowStacking);
@@ -769,7 +770,9 @@ namespace Barotrauma
Math.Min(newAffliction.Prefab.MaxStrength, newAffliction.Strength * (100.0f / MaxVitality) * (1f - GetResistance(newAffliction.Prefab))),
newAffliction.Source);
afflictions.Add(copyAffliction, limbHealth);
SteamAchievementManager.OnAfflictionReceived(copyAffliction, Character);
MedicalClinic.OnAfflictionCountChanged(Character);
Character.HealthUpdateInterval = 0.0f;
CalculateVitality();
@@ -842,10 +845,16 @@ namespace Barotrauma
}
Character.StackSpeedMultiplier(affliction.GetSpeedMultiplier());
}
foreach (var affliction in afflictionsToRemove)
{
afflictions.Remove(affliction);
}
}
if (afflictionsToRemove.Count is not 0)
{
MedicalClinic.OnAfflictionCountChanged(Character);
}
}
Character.StackSpeedMultiplier(1f + Character.GetStatValue(StatTypes.MovementSpeed));
@@ -899,6 +908,11 @@ namespace Barotrauma
}
}
/// <summary>
/// 0-1.
/// </summary>
public float OxygenLowResistance => !Character.NeedsOxygen ? 1 : GetResistance(oxygenLowAffliction.Prefab);
private void UpdateOxygen(float deltaTime)
{
if (!Character.NeedsOxygen)