Merge branch 'dev' of https://github.com/Regalis11/Barotrauma into unstable

This commit is contained in:
EvilFactory
2022-09-29 12:13:55 -03:00
602 changed files with 19759 additions and 16312 deletions
@@ -50,6 +50,9 @@ namespace Barotrauma
[Serialize(1.0f, IsPropertySaveable.Yes, description: "The probability for the affliction to be applied."), Editable(minValue: 0f, maxValue: 1f)]
public float Probability { get; set; } = 1.0f;
[Serialize(true, IsPropertySaveable.Yes, description: "Explosion damage is applied per each affected limb. Should this affliction damage be divided by the count of affected limbs (1-15) or applied in full? Default: true. Only affects explosions."), Editable]
public bool DivideByLimbCount { get; set; }
public float DamagePerSecond;
public float DamagePerSecondTimer;
public float PreviousVitalityDecrease;
@@ -96,9 +99,11 @@ namespace Barotrauma
SerializableProperties = SerializableProperty.DeserializeProperties(this, element);
}
public Affliction CreateMultiplied(float multiplier)
public Affliction CreateMultiplied(float multiplier, float probability)
{
return Prefab.Instantiate(NonClampedStrength * multiplier, Source);
var instance = Prefab.Instantiate(NonClampedStrength * multiplier, Source);
instance.Probability = probability;
return instance;
}
public override string ToString() => Prefab == null ? "Affliction (Invalid)" : $"Affliction ({Prefab.Name})";
@@ -451,13 +451,12 @@ namespace Barotrauma
public static Identifier GetHuskedSpeciesName(Identifier speciesName, AfflictionPrefabHusk prefab)
{
return prefab.HuskedSpeciesName.Replace(AfflictionPrefabHusk.Tag, speciesName);
return new Identifier(speciesName.Value + prefab.HuskedSpeciesName.Value);
}
public static Identifier GetNonHuskedSpeciesName(Identifier huskedSpeciesName, AfflictionPrefabHusk prefab)
{
Identifier nonTag = prefab.HuskedSpeciesName.Remove(AfflictionPrefabHusk.Tag);
return huskedSpeciesName.Remove(nonTag);
return huskedSpeciesName.Remove(prefab.HuskedSpeciesName);
}
}
}
@@ -63,8 +63,10 @@ namespace Barotrauma
if (HuskedSpeciesName.IsEmpty)
{
DebugConsole.NewMessage($"No 'huskedspeciesname' defined for the husk affliction ({Identifier}) in {element}", Color.Orange);
HuskedSpeciesName = "[speciesname]husk".ToIdentifier();
HuskedSpeciesName = "husk".ToIdentifier();
}
// 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)
{
@@ -108,7 +110,6 @@ namespace Barotrauma
public readonly Identifier HuskedSpeciesName;
public readonly Identifier[] TargetSpecies;
public static readonly Identifier Tag = "[speciesname]".ToIdentifier();
public readonly bool TransferBuffs;
public readonly bool SendMessages;
@@ -404,8 +405,18 @@ namespace Barotrauma
AfflictionType = element.GetAttributeIdentifier("type", "");
TranslationIdentifier = element.GetAttributeIdentifier("translationoverride", Identifier);
Name = TextManager.Get($"AfflictionName.{TranslationIdentifier}").Fallback(element.GetAttributeString("name", ""));
Description = TextManager.Get($"AfflictionDescription.{TranslationIdentifier}").Fallback(element.GetAttributeString("description", ""));
Name = TextManager.Get($"AfflictionName.{TranslationIdentifier}");
string fallbackName = element.GetAttributeString("name", "");
if (!string.IsNullOrEmpty(fallbackName))
{
Name = Name.Fallback(fallbackName);
}
Description = TextManager.Get($"AfflictionDescription.{TranslationIdentifier}");
string fallbackDescription = element.GetAttributeString("description", "");
if (!string.IsNullOrEmpty(fallbackDescription))
{
Description = Description.Fallback(fallbackDescription);
}
IsBuff = element.GetAttributeBool("isbuff", false);
HealableInMedicalClinic = element.GetAttributeBool("healableinmedicalclinic",
@@ -60,13 +60,27 @@ namespace Barotrauma
if (vitalityMultipliers != null)
{
float multiplier = subElement.GetAttributeFloat("multiplier", 1.0f);
vitalityMultipliers.ForEach(i => VitalityMultipliers.Add(i, multiplier));
foreach (var vitalityMultiplier in vitalityMultipliers)
{
VitalityMultipliers.Add(vitalityMultiplier, multiplier);
if (AfflictionPrefab.Prefabs.None(p => p.Identifier == vitalityMultiplier))
{
DebugConsole.AddWarning($"Potentially incorrectly defined vitality multiplier in \"{characterHealth.Character.Name}\". Could not find any afflictions with the identifier \"{vitalityMultiplier}\". Did you mean to define the afflictions by type instead?");
}
}
}
var vitalityTypeMultipliers = subElement.GetAttributeIdentifierArray("type", null) ?? subElement.GetAttributeIdentifierArray("types", null);
if (vitalityTypeMultipliers != null)
{
float multiplier = subElement.GetAttributeFloat("multiplier", 1.0f);
vitalityTypeMultipliers.ForEach(i => VitalityTypeMultipliers.Add(i, multiplier));
foreach (var vitalityTypeMultiplier in vitalityTypeMultipliers)
{
VitalityTypeMultipliers.Add(vitalityTypeMultiplier, multiplier);
if (AfflictionPrefab.Prefabs.None(p => p.AfflictionType == vitalityTypeMultiplier))
{
DebugConsole.AddWarning($"Potentially incorrectly defined vitality multiplier in \"{characterHealth.Character.Name}\". Could not find any afflictions of the type \"{vitalityTypeMultiplier}\". Did you mean to define the afflictions by identifier instead?");
}
}
}
if (vitalityMultipliers == null && VitalityTypeMultipliers == null)
{
@@ -911,19 +925,11 @@ namespace Barotrauma
float vitalityDecrease = affliction.GetVitalityDecrease(this);
if (limbHealth != null)
{
if (limbHealth.VitalityMultipliers.ContainsKey(affliction.Prefab.Identifier))
{
vitalityDecrease *= limbHealth.VitalityMultipliers[affliction.Prefab.Identifier];
}
if (limbHealth.VitalityTypeMultipliers.ContainsKey(affliction.Prefab.AfflictionType))
{
vitalityDecrease *= limbHealth.VitalityTypeMultipliers[affliction.Prefab.AfflictionType];
}
vitalityDecrease *= GetVitalityMultiplier(affliction, limbHealth);
}
Vitality -= vitalityDecrease;
affliction.CalculateDamagePerSecond(vitalityDecrease);
}
#if CLIENT
if (IsUnconscious)
{
@@ -932,6 +938,33 @@ namespace Barotrauma
#endif
}
private float GetVitalityMultiplier(Affliction affliction, LimbHealth limbHealth)
{
float multiplier = 1.0f;
if (limbHealth.VitalityMultipliers.TryGetValue(affliction.Prefab.Identifier, out float vitalityMultiplier))
{
multiplier *= vitalityMultiplier;
}
if (limbHealth.VitalityTypeMultipliers.TryGetValue(affliction.Prefab.AfflictionType, out float vitalityTypeMultiplier))
{
multiplier *= vitalityTypeMultiplier;
}
return multiplier;
}
/// <summary>
/// How much vitality the affliction reduces, taking into account the effects of vitality modifiers on the limb the affliction is on (if limb-based)
/// </summary>
private float GetVitalityDecreaseWithVitalityMultipliers(Affliction affliction)
{
float vitalityDecrease = affliction.GetVitalityDecrease(this);
if (afflictions.TryGetValue(affliction, out LimbHealth limbHealth) && limbHealth != null)
{
vitalityDecrease *= GetVitalityMultiplier(affliction, limbHealth);
}
return vitalityDecrease;
}
private void Kill()
{
if (Unkillable || Character.GodMode) { return; }
@@ -1021,7 +1054,7 @@ namespace Barotrauma
/// <param name="treatmentSuitability">A dictionary where the key is the identifier of the item and the value the suitability</param>
/// <param name="normalize">If true, the suitability values are normalized between 0 and 1. If not, they're arbitrary values defined in the medical item XML, where negative values are unsuitable, and positive ones suitable.</param>
/// <param name="predictFutureDuration">If above 0, the method will take into account how much currently active status effects while affect the afflictions in the next x seconds.</param>
public void GetSuitableTreatments(Dictionary<Identifier, float> treatmentSuitability, bool normalize, Limb limb = null, bool ignoreHiddenAfflictions = false, float predictFutureDuration = 0.0f)
public void GetSuitableTreatments(Dictionary<Identifier, float> treatmentSuitability, bool normalize, Character user, Limb limb = null, bool ignoreHiddenAfflictions = false, float predictFutureDuration = 0.0f)
{
//key = item identifier
//float = suitability
@@ -1045,7 +1078,18 @@ namespace Barotrauma
}
if (strength <= affliction.Prefab.TreatmentThreshold) { continue; }
if (ignoreHiddenAfflictions && strength < affliction.Prefab.ShowIconThreshold) { continue; }
if (ignoreHiddenAfflictions)
{
if (user == Character)
{
if (strength < affliction.Prefab.ShowIconThreshold) { continue; }
}
else
{
if (strength < affliction.Prefab.ShowIconToOthersThreshold) { continue; }
}
}
foreach (KeyValuePair<Identifier, float> treatment in affliction.Prefab.TreatmentSuitability)
{
@@ -1129,17 +1173,17 @@ namespace Barotrauma
activeAfflictions.Add(affliction);
}
}
msg.Write((byte)activeAfflictions.Count);
msg.WriteByte((byte)activeAfflictions.Count);
foreach (Affliction affliction in activeAfflictions)
{
msg.Write(affliction.Prefab.UintIdentifier);
msg.WriteUInt32(affliction.Prefab.UintIdentifier);
msg.WriteRangedSingle(
MathHelper.Clamp(affliction.Strength, 0.0f, affliction.Prefab.MaxStrength),
0.0f, affliction.Prefab.MaxStrength, 8);
msg.Write((byte)affliction.Prefab.PeriodicEffects.Count());
msg.WriteByte((byte)affliction.Prefab.PeriodicEffects.Count);
foreach (AfflictionPrefab.PeriodicEffect periodicEffect in affliction.Prefab.PeriodicEffects)
{
msg.WriteRangedSingle(affliction.PeriodicEffectTimers[periodicEffect], periodicEffect.MinInterval, periodicEffect.MaxInterval, 8);
msg.WriteRangedSingle(affliction.PeriodicEffectTimers[periodicEffect], 0, periodicEffect.MaxInterval, 8);
}
}
@@ -1153,15 +1197,15 @@ namespace Barotrauma
limbAfflictions.Add((limbHealth, limbAffliction));
}
msg.Write((byte)limbAfflictions.Count);
msg.WriteByte((byte)limbAfflictions.Count);
foreach (var (limbHealth, affliction) in limbAfflictions)
{
msg.WriteRangedInteger(limbHealths.IndexOf(limbHealth), 0, limbHealths.Count - 1);
msg.Write(affliction.Prefab.UintIdentifier);
msg.WriteUInt32(affliction.Prefab.UintIdentifier);
msg.WriteRangedSingle(
MathHelper.Clamp(affliction.Strength, 0.0f, affliction.Prefab.MaxStrength),
0.0f, affliction.Prefab.MaxStrength, 8);
msg.Write((byte)affliction.Prefab.PeriodicEffects.Count());
msg.WriteByte((byte)affliction.Prefab.PeriodicEffects.Count);
foreach (AfflictionPrefab.PeriodicEffect periodicEffect in affliction.Prefab.PeriodicEffects)
{
msg.WriteRangedSingle(affliction.PeriodicEffectTimers[periodicEffect], periodicEffect.MinInterval, periodicEffect.MaxInterval, 8);
@@ -1210,7 +1254,7 @@ namespace Barotrauma
}
}
public void Load(XElement element)
public void Load(XElement element, Func<AfflictionPrefab, bool> afflictionPredicate = null)
{
foreach (var subElement in element.Elements())
{
@@ -1243,6 +1287,7 @@ namespace Barotrauma
DebugConsole.ThrowError($"Error while loading character health: affliction \"{id}\" not found.");
return;
}
if (afflictionPredicate != null && !afflictionPredicate.Invoke(afflictionPrefab)) { return; }
float strength = afflictionElement.GetAttributeFloat("strength", 0.0f);
var irremovableAffliction = irremovableAfflictions.FirstOrDefault(a => a.Prefab == afflictionPrefab);
if (irremovableAffliction != null)
@@ -86,6 +86,28 @@ namespace Barotrauma
{
DebugConsole.ThrowError("Error in DamageModifier config (" + parentDebugName + ") - define afflictions using identifiers or types instead of names.");
}
foreach (var afflictionType in parsedAfflictionTypes)
{
if (!AfflictionPrefab.Prefabs.Any(p => p.AfflictionType == afflictionType))
{
createWarningOrError($"Potentially invalid damage modifier in \"{parentDebugName}\". Could not find any afflictions of the type \"{afflictionType}\". Did you mean to use an affliction identifier instead?");
}
}
foreach (var afflictionIdentifier in parsedAfflictionIdentifiers)
{
if (!AfflictionPrefab.Prefabs.ContainsKey(afflictionIdentifier))
{
createWarningOrError($"Potentially invalid damage modifier in \"{parentDebugName}\". Could not find any afflictions with the identifier \"{afflictionIdentifier}\". Did you mean to use an affliction type instead?");
}
}
static void createWarningOrError(string msg)
{
#if DEBUG
DebugConsole.ThrowError(msg);
#else
DebugConsole.AddWarning(msg);
#endif
}
}
private void ParseAfflictionTypes()