Release v0.15.12.0

This commit is contained in:
Joonas Rikkonen
2021-10-27 18:50:57 +03:00
parent bf95e82d80
commit 234fb6bc06
450 changed files with 26042 additions and 10457 deletions
@@ -17,6 +17,8 @@ namespace Barotrauma
public float PendingAdditionStrength { get; set; }
public float AdditionStrength { get; set; }
private float fluctuationTimer;
protected float _strength;
[Serialize(0f, true), Editable]
@@ -56,6 +58,8 @@ namespace Barotrauma
public readonly Dictionary<AfflictionPrefab.PeriodicEffect, float> PeriodicEffectTimers = new Dictionary<AfflictionPrefab.PeriodicEffect, float>();
public double AppliedAsSuccessfulTreatmentTime, AppliedAsFailedTreatmentTime;
/// <summary>
/// Which character gave this affliction
/// </summary>
@@ -123,7 +127,7 @@ namespace Barotrauma
float amount = MathHelper.Lerp(
currentEffect.MinGrainStrength,
currentEffect.MaxGrainStrength,
(Strength - currentEffect.MinStrength) / (currentEffect.MaxStrength - currentEffect.MinStrength));
(Strength - currentEffect.MinStrength) / (currentEffect.MaxStrength - currentEffect.MinStrength)) * GetScreenEffectFluctuation(currentEffect);
if (Prefab.GrainBurst > 0 && AdditionStrength > amount)
{
@@ -138,12 +142,12 @@ namespace Barotrauma
if (Strength < Prefab.ActivationThreshold) { return 0.0f; }
AfflictionPrefab.Effect currentEffect = GetActiveEffect();
if (currentEffect == null) { return 0.0f; }
if (currentEffect.MaxScreenDistortStrength - currentEffect.MinScreenDistortStrength < 0.0f) { return 0.0f; }
if (currentEffect.MaxScreenDistort - currentEffect.MinScreenDistort < 0.0f) { return 0.0f; }
return MathHelper.Lerp(
currentEffect.MinScreenDistortStrength,
currentEffect.MaxScreenDistortStrength,
(Strength - currentEffect.MinStrength) / (currentEffect.MaxStrength - currentEffect.MinStrength));
currentEffect.MinScreenDistort,
currentEffect.MaxScreenDistort,
(Strength - currentEffect.MinStrength) / (currentEffect.MaxStrength - currentEffect.MinStrength)) * GetScreenEffectFluctuation(currentEffect);
}
public float GetRadialDistortStrength()
@@ -151,12 +155,12 @@ namespace Barotrauma
if (Strength < Prefab.ActivationThreshold) { return 0.0f; }
AfflictionPrefab.Effect currentEffect = GetActiveEffect();
if (currentEffect == null) { return 0.0f; }
if (currentEffect.MaxRadialDistortStrength - currentEffect.MinRadialDistortStrength < 0.0f) { return 0.0f; }
if (currentEffect.MaxRadialDistort - currentEffect.MinRadialDistort < 0.0f) { return 0.0f; }
return MathHelper.Lerp(
currentEffect.MinRadialDistortStrength,
currentEffect.MaxRadialDistortStrength,
(Strength - currentEffect.MinStrength) / (currentEffect.MaxStrength - currentEffect.MinStrength));
currentEffect.MinRadialDistort,
currentEffect.MaxRadialDistort,
(Strength - currentEffect.MinStrength) / (currentEffect.MaxStrength - currentEffect.MinStrength)) * GetScreenEffectFluctuation(currentEffect);
}
public float GetChromaticAberrationStrength()
@@ -164,11 +168,50 @@ namespace Barotrauma
if (Strength < Prefab.ActivationThreshold) { return 0.0f; }
AfflictionPrefab.Effect currentEffect = GetActiveEffect();
if (currentEffect == null) { return 0.0f; }
if (currentEffect.MaxChromaticAberrationStrength - currentEffect.MinChromaticAberrationStrength < 0.0f) { return 0.0f; }
if (currentEffect.MaxChromaticAberration - currentEffect.MinChromaticAberration < 0.0f) { return 0.0f; }
return MathHelper.Lerp(
currentEffect.MinChromaticAberrationStrength,
currentEffect.MaxChromaticAberrationStrength,
currentEffect.MinChromaticAberration,
currentEffect.MaxChromaticAberration,
(Strength - currentEffect.MinStrength) / (currentEffect.MaxStrength - currentEffect.MinStrength)) * GetScreenEffectFluctuation(currentEffect);
}
public float GetAfflictionOverlayMultiplier()
{
//If the overlay's alpha progresses linearly, then don't worry about affliction effects.
if (Prefab.AfflictionOverlayAlphaIsLinear) { return (Strength / Prefab.MaxStrength); }
if (Strength < Prefab.ActivationThreshold) { return 0.0f; }
AfflictionPrefab.Effect currentEffect = GetActiveEffect();
if (currentEffect == null) { return 0.0f; }
if (currentEffect.MaxAfflictionOverlayAlphaMultiplier - currentEffect.MinAfflictionOverlayAlphaMultiplier < 0.0f) { return 0.0f; }
return MathHelper.Lerp(
currentEffect.MinAfflictionOverlayAlphaMultiplier,
currentEffect.MaxAfflictionOverlayAlphaMultiplier,
(Strength - currentEffect.MinStrength) / (currentEffect.MaxStrength - currentEffect.MinStrength));
}
public Color GetFaceTint()
{
if (Strength < Prefab.ActivationThreshold) { return Color.TransparentBlack; }
AfflictionPrefab.Effect currentEffect = GetActiveEffect();
if (currentEffect == null) { return Color.TransparentBlack; }
return Color.Lerp(
currentEffect.MinFaceTint,
currentEffect.MaxFaceTint,
(Strength - currentEffect.MinStrength) / (currentEffect.MaxStrength - currentEffect.MinStrength));
}
public Color GetBodyTint()
{
if (Strength < Prefab.ActivationThreshold) { return Color.TransparentBlack; }
AfflictionPrefab.Effect currentEffect = GetActiveEffect();
if (currentEffect == null) { return Color.TransparentBlack; }
return Color.Lerp(
currentEffect.MinBodyTint,
currentEffect.MaxBodyTint,
(Strength - currentEffect.MinStrength) / (currentEffect.MaxStrength - currentEffect.MinStrength));
}
@@ -177,12 +220,18 @@ namespace Barotrauma
if (Strength < Prefab.ActivationThreshold) { return 0.0f; }
AfflictionPrefab.Effect currentEffect = GetActiveEffect();
if (currentEffect == null) { return 0.0f; }
if (currentEffect.MaxScreenBlurStrength - currentEffect.MinScreenBlurStrength < 0.0f) { return 0.0f; }
if (currentEffect.MaxScreenBlur - currentEffect.MinScreenBlur < 0.0f) { return 0.0f; }
return MathHelper.Lerp(
currentEffect.MinScreenBlurStrength,
currentEffect.MaxScreenBlurStrength,
(Strength - currentEffect.MinStrength) / (currentEffect.MaxStrength - currentEffect.MinStrength));
currentEffect.MinScreenBlur,
currentEffect.MaxScreenBlur,
(Strength - currentEffect.MinStrength) / (currentEffect.MaxStrength - currentEffect.MinStrength)) * GetScreenEffectFluctuation(currentEffect);
}
private float GetScreenEffectFluctuation(AfflictionPrefab.Effect currentEffect)
{
if (currentEffect == null || currentEffect.ScreenEffectFluctuationFrequency <= 0.0f) { return 1.0f; }
return ((float)Math.Sin(fluctuationTimer * MathHelper.TwoPi) + 1.0f) * 0.5f;
}
public float GetSkillMultiplier()
@@ -210,14 +259,17 @@ namespace Barotrauma
}
}
public float GetResistance(string afflictionId)
public float GetResistance(AfflictionPrefab affliction)
{
if (Strength < Prefab.ActivationThreshold) { return 0.0f; }
AfflictionPrefab.Effect currentEffect = GetActiveEffect();
if (currentEffect == null) { return 0.0f; }
if (currentEffect.MaxResistance - currentEffect.MinResistance <= 0.0f) { return 0.0f; }
if (afflictionId != null && afflictionId != currentEffect.ResistanceFor) { return 0.0f; }
if (!currentEffect.ResistanceFor.Any(r =>
r.Equals(affliction.Identifier, StringComparison.OrdinalIgnoreCase) ||
r.Equals(affliction.AfflictionType, StringComparison.OrdinalIgnoreCase)))
{
return 0.0f;
}
return MathHelper.Lerp(
currentEffect.MinResistance,
currentEffect.MaxResistance,
@@ -229,14 +281,39 @@ namespace Barotrauma
if (Strength < Prefab.ActivationThreshold) { return 1.0f; }
AfflictionPrefab.Effect currentEffect = GetActiveEffect();
if (currentEffect == null) { return 1.0f; }
if (currentEffect.MaxSpeedMultiplier - currentEffect.MinSpeedMultiplier <= 0.0f) { return 1.0f; }
return MathHelper.Lerp(
currentEffect.MinSpeedMultiplier,
currentEffect.MaxSpeedMultiplier,
(Strength - currentEffect.MinStrength) / (currentEffect.MaxStrength - currentEffect.MinStrength));
}
public float GetStatValue(StatTypes statType)
{
if (!(GetViableEffect() is AfflictionPrefab.Effect currentEffect)) { return 0.0f; }
if (currentEffect.AfflictionStatValues.TryGetValue(statType, out var value))
{
return MathHelper.Lerp(
value.minValue,
value.maxValue,
(Strength - currentEffect.MinStrength) / (currentEffect.MaxStrength - currentEffect.MinStrength));
}
return 0.0f;
}
public bool HasFlag(AbilityFlags flagType)
{
if (!(GetViableEffect() is AfflictionPrefab.Effect currentEffect)) { return false; }
return currentEffect.AfflictionAbilityFlags.Contains(flagType);
}
private AfflictionPrefab.Effect GetViableEffect()
{
if (Strength < Prefab.ActivationThreshold) { return null; }
return GetActiveEffect();
}
public virtual void Update(CharacterHealth characterHealth, Limb targetLimb, float deltaTime)
{
foreach (AfflictionPrefab.PeriodicEffect periodicEffect in Prefab.PeriodicEffects)
@@ -262,13 +339,20 @@ namespace Barotrauma
AfflictionPrefab.Effect currentEffect = GetActiveEffect();
if (currentEffect == null) { return; }
fluctuationTimer += deltaTime * currentEffect.ScreenEffectFluctuationFrequency;
fluctuationTimer %= 1.0f;
if (currentEffect.StrengthChange < 0) // Reduce diminishing of buffs if boosted
{
_strength += currentEffect.StrengthChange * deltaTime * StrengthDiminishMultiplier;
float durationMultiplier = 1 / (1 + (Prefab.IsBuff ? characterHealth.Character.GetStatValue(StatTypes.BuffDurationMultiplier)
: characterHealth.Character.GetStatValue(StatTypes.DebuffDurationMultiplier)));
_strength += currentEffect.StrengthChange * deltaTime * StrengthDiminishMultiplier * durationMultiplier;
}
else // Reduce strengthening of afflictions if resistant
else if (currentEffect.StrengthChange > 0) // Reduce strengthening of afflictions if resistant
{
_strength += currentEffect.StrengthChange * deltaTime * (1f - characterHealth.GetResistance(Prefab.Identifier));
_strength += currentEffect.StrengthChange * deltaTime * (1f - characterHealth.GetResistance(Prefab));
}
// 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);
@@ -306,6 +390,8 @@ namespace Barotrauma
private readonly List<ISerializableEntity> targets = new List<ISerializableEntity>();
public void ApplyStatusEffect(ActionType type, StatusEffect statusEffect, float deltaTime, CharacterHealth characterHealth, Limb targetLimb)
{
if (type == ActionType.OnDamaged && !statusEffect.HasRequiredAfflictions(characterHealth.Character.LastDamage)) { return; }
statusEffect.SetUser(Source);
if (statusEffect.HasTargetType(StatusEffect.TargetType.Character))
{
@@ -3,6 +3,7 @@ using System.Linq;
using System.Xml.Linq;
using System;
using Barotrauma.Extensions;
using Microsoft.Xna.Framework;
namespace Barotrauma
{
@@ -21,6 +22,8 @@ namespace Barotrauma
private Character character;
private bool stun = true;
private readonly List<Affliction> huskInfection = new List<Affliction>();
[Serialize(0f, true), Editable]
@@ -34,6 +37,11 @@ namespace Barotrauma
float threshold = _strength > ActiveThreshold ? ActiveThreshold + 1 : DormantThreshold - 1;
float max = Math.Max(threshold, previousValue);
_strength = Math.Clamp(value, 0, max);
stun = GameMain.GameSession?.IsRunning ?? true;
if (previousValue > 0.0f && value <= 0.0f)
{
DeactivateHusk();
}
}
}
@@ -51,8 +59,12 @@ namespace Barotrauma
}
}
private float DormantThreshold => Prefab.MaxStrength * 0.5f;
private float ActiveThreshold => Prefab.MaxStrength * 0.75f;
private float DormantThreshold => (Prefab as AfflictionPrefabHusk)?.DormantThreshold ?? Prefab.MaxStrength * 0.5f;
private float ActiveThreshold => (Prefab as AfflictionPrefabHusk)?.ActiveThreshold ?? Prefab.MaxStrength * 0.75f;
private float TransitionThreshold => (Prefab as AfflictionPrefabHusk)?.TransitionThreshold ?? Prefab.MaxStrength * 0.75f;
private float TransformThresholdOnDeath => (Prefab as AfflictionPrefabHusk)?.TransformThresholdOnDeath ?? ActiveThreshold;
public AfflictionHusk(AfflictionPrefab prefab, float strength) : base(prefab, strength) { }
@@ -83,9 +95,9 @@ namespace Barotrauma
}
State = InfectionState.Transition;
}
else if (Strength < Prefab.MaxStrength)
else if (Strength < TransitionThreshold)
{
if (State != InfectionState.Active)
if (State != InfectionState.Active && stun)
{
character.SetStun(Rand.Range(2, 4));
}
@@ -139,6 +151,7 @@ namespace Barotrauma
private void DeactivateHusk()
{
if (character?.AnimController == null || character.Removed) { return; }
if (Prefab is AfflictionPrefabHusk { NeedsAir: false })
{
character.NeedsAir = character.Params.MainElement.GetAttributeBool("needsair", false);
@@ -161,7 +174,7 @@ namespace Barotrauma
private void CharacterDead(Character character, CauseOfDeath causeOfDeath)
{
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) { return; }
if (Strength < ActiveThreshold || character.Removed)
if (Strength < TransformThresholdOnDeath || character.Removed)
{
UnsubscribeFromDeathEvent();
return;
@@ -205,6 +218,14 @@ namespace Barotrauma
XElement parentElement = new XElement("CharacterInfo");
XElement infoElement = character.Info?.Save(parentElement);
CharacterInfo huskCharacterInfo = infoElement == null ? null : new CharacterInfo(infoElement);
if (huskCharacterInfo != null)
{
var bodyTint = GetBodyTint();
huskCharacterInfo.SkinColor =
Color.Lerp(huskCharacterInfo.SkinColor, bodyTint.Opaque(), bodyTint.A / 255.0f);
}
var husk = Character.Create(huskedSpeciesName, character.WorldPosition, ToolBox.RandomSeed(8), huskCharacterInfo, isRemotePlayer: false, hasAi: true);
if (husk.Info != null)
{
@@ -212,6 +233,25 @@ namespace Barotrauma
husk.Info.TeamID = CharacterTeamType.None;
}
if (Prefab is AfflictionPrefabHusk huskPrefab)
{
if (huskPrefab.ControlHusk)
{
#if SERVER
var client = GameMain.Server?.ConnectedClients.FirstOrDefault(c => c.CharacterInfo.Character == character);
if (client != null)
{
GameMain.Server.SetClientCharacter(client, husk);
}
#else
if (!character.IsRemotelyControlled && character == Character.Controlled)
{
Character.Controlled = husk;
}
#endif
}
}
foreach (Limb limb in husk.AnimController.Limbs)
{
if (limb.type == LimbType.None)
@@ -229,15 +269,19 @@ namespace Barotrauma
}
}
if ((Prefab as AfflictionPrefabHusk)?.TransferBuffs ?? false)
{
foreach (Affliction affliction in character.CharacterHealth.Afflictions)
{
if (affliction.Prefab.IsBuff)
{
husk.CharacterHealth.ApplyAffliction(null, affliction.Prefab.Instantiate(affliction.Strength));
}
}
}
if (character.Inventory != null && husk.Inventory != null)
{
if (character.Inventory.Capacity != husk.Inventory.Capacity)
{
string errorMsg = "Failed to move items from the source character's inventory into a husk's inventory (inventory sizes don't match)";
DebugConsole.ThrowError(errorMsg);
GameAnalyticsManager.AddErrorEventOnce("AfflictionHusk.CreateAIHusk:InventoryMismatch", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
yield return CoroutineStatus.Success;
}
for (int i = 0; i < character.Inventory.Capacity && i < husk.Inventory.Capacity; i++)
{
character.Inventory.GetItemsAt(i).ForEachMod(item => husk.Inventory.TryPutItem(item, i, true, false, null));
@@ -1,10 +1,10 @@
using Microsoft.Xna.Framework;
using Barotrauma.Abilities;
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Xml.Linq;
using System.Linq;
using System.Security.Cryptography;
namespace Barotrauma
{
@@ -91,9 +91,16 @@ namespace Barotrauma
AttachLimbType = LimbType.None;
}
TransferBuffs = element.GetAttributeBool("transferbuffs", true);
SendMessages = element.GetAttributeBool("sendmessages", true);
CauseSpeechImpediment = element.GetAttributeBool("causespeechimpediment", true);
NeedsAir = element.GetAttributeBool("needsair", false);
ControlHusk = element.GetAttributeBool("controlhusk", false);
DormantThreshold = element.GetAttributeFloat("dormantthreshold", MaxStrength * 0.5f);
ActiveThreshold = element.GetAttributeFloat("activethreshold", MaxStrength * 0.75f);
TransitionThreshold = element.GetAttributeFloat("transitionthreshold", MaxStrength);
TransformThresholdOnDeath = element.GetAttributeFloat("transformthresholdondeath", ActiveThreshold);
}
// Use any of these to define which limb the appendage is attached to.
@@ -102,13 +109,18 @@ namespace Barotrauma
public readonly string AttachLimbName;
public readonly LimbType AttachLimbType;
public float ActiveThreshold, DormantThreshold, TransitionThreshold;
public float TransformThresholdOnDeath;
public readonly string HuskedSpeciesName;
public readonly string[] TargetSpecies;
public const string Tag = "[speciesname]";
public readonly bool TransferBuffs;
public readonly bool SendMessages;
public readonly bool CauseSpeechImpediment;
public readonly bool NeedsAir;
public readonly bool ControlHusk;
}
class AfflictionPrefab : IPrefab, IDisposable, IHasUintIdentifier
@@ -116,83 +128,123 @@ namespace Barotrauma
public class Effect
{
//this effect is applied when the strength is within this range
public float MinStrength, MaxStrength;
[Serialize(0.0f, false)]
public float MinStrength { get; private set; }
[Serialize(0.0f, false)]
public float MaxStrength { get; private set; }
[Serialize(0.0f, false)]
public float MinVitalityDecrease { get; private set; }
[Serialize(0.0f, false)]
public float MaxVitalityDecrease { get; private set; }
public readonly float MinVitalityDecrease = 0.0f;
public readonly float MaxVitalityDecrease = 0.0f;
//how much the strength of the affliction changes per second
public readonly float StrengthChange = 0.0f;
[Serialize(0.0f, false)]
public float StrengthChange { get; private set; }
public readonly bool MultiplyByMaxVitality;
[Serialize(false, false)]
public bool MultiplyByMaxVitality { get; private set; }
public float MinScreenBlurStrength, MaxScreenBlurStrength;
public float MinScreenDistortStrength, MaxScreenDistortStrength;
public float MinGrainStrength, MaxGrainStrength;
public float MinRadialDistortStrength, MaxRadialDistortStrength;
public float MinChromaticAberrationStrength, MaxChromaticAberrationStrength;
public float MinSpeedMultiplier, MaxSpeedMultiplier;
public float MinBuffMultiplier, MaxBuffMultiplier;
[Serialize(0.0f, false)]
public float MinScreenBlur { get; private set; }
public float MinSkillMultiplier, MaxSkillMultiplier;
[Serialize(0.0f, false)]
public float MaxScreenBlur { get; private set; }
public float MinResistance, MaxResistance;
public string ResistanceFor;
public string DialogFlag;
[Serialize(0.0f, false)]
public float MinScreenDistort { get; private set; }
[Serialize(0.0f, false)]
public float MaxScreenDistort { get; private set; }
[Serialize(0.0f, false)]
public float MinRadialDistort { get; private set; }
[Serialize(0.0f, false)]
public float MaxRadialDistort { get; private set; }
[Serialize(0.0f, false)]
public float MinChromaticAberration { get; private set; }
[Serialize(0.0f, false)]
public float MaxChromaticAberration { get; private set; }
[Serialize("255,255,255,255", false)]
public Color GrainColor { get; private set; }
[Serialize(0.0f, false)]
public float MinGrainStrength { get; private set; }
[Serialize(0.0f, false)]
public float MaxGrainStrength { get; private set; }
[Serialize(0.0f, false)]
public float ScreenEffectFluctuationFrequency { get; private set; }
[Serialize(1.0f, false)]
public float MinAfflictionOverlayAlphaMultiplier { get; private set; }
[Serialize(1.0f, false)]
public float MaxAfflictionOverlayAlphaMultiplier { get; private set; }
[Serialize(1.0f, false)]
public float MinBuffMultiplier { get; private set; }
[Serialize(1.0f, false)]
public float MaxBuffMultiplier { get; private set; }
[Serialize(1.0f, false)]
public float MinSpeedMultiplier { get; private set; }
[Serialize(1.0f, false)]
public float MaxSpeedMultiplier { get; private set; }
[Serialize(1.0f, false)]
public float MinSkillMultiplier { get; private set; }
[Serialize(1.0f, false)]
public float MaxSkillMultiplier { get; private set; }
private readonly string[] resistanceFor;
public IEnumerable<string> ResistanceFor
{
get { return resistanceFor; }
}
[Serialize(0.0f, false)]
public float MinResistance { get; private set; }
[Serialize(0.0f, false)]
public float MaxResistance { get; private set; }
[Serialize("", false)]
public string DialogFlag { get; private set; }
[Serialize("0,0,0,0", false)]
public Color MinFaceTint { get; private set; }
[Serialize("0,0,0,0", false)]
public Color MaxFaceTint { get; private set; }
[Serialize("0,0,0,0", false)]
public Color MinBodyTint { get; private set; }
[Serialize("0,0,0,0", false)]
public Color MaxBodyTint { get; private set; }
public readonly Dictionary<StatTypes, (float minValue, float maxValue)> AfflictionStatValues = new Dictionary<StatTypes, (float minValue, float maxValue)>();
public readonly HashSet<AbilityFlags> AfflictionAbilityFlags = new HashSet<AbilityFlags>();
//statuseffects applied on the character when the affliction is active
public readonly List<StatusEffect> StatusEffects = new List<StatusEffect>();
public Effect(XElement element, string parentDebugName)
{
MinStrength = element.GetAttributeFloat("minstrength", 0);
MaxStrength = element.GetAttributeFloat("maxstrength", 0);
SerializableProperty.DeserializeProperties(this, element);
MultiplyByMaxVitality = element.GetAttributeBool("multiplybymaxvitality", false);
MinVitalityDecrease = element.GetAttributeFloat("minvitalitydecrease", 0.0f);
MaxVitalityDecrease = element.GetAttributeFloat("maxvitalitydecrease", 0.0f);
MaxVitalityDecrease = Math.Max(MinVitalityDecrease, MaxVitalityDecrease);
MinScreenDistortStrength = element.GetAttributeFloat("minscreendistort", 0.0f);
MaxScreenDistortStrength = element.GetAttributeFloat("maxscreendistort", 0.0f);
MaxScreenDistortStrength = Math.Max(MinScreenDistortStrength, MaxScreenDistortStrength);
MinRadialDistortStrength = element.GetAttributeFloat("minradialdistort", 0.0f);
MaxRadialDistortStrength = element.GetAttributeFloat("maxradialdistort", 0.0f);
MaxRadialDistortStrength = Math.Max(MinRadialDistortStrength, MaxRadialDistortStrength);
MinChromaticAberrationStrength = element.GetAttributeFloat("minchromaticaberration", 0.0f);
MaxChromaticAberrationStrength = element.GetAttributeFloat("maxchromaticaberration", 0.0f);
MaxChromaticAberrationStrength = Math.Max(MinChromaticAberrationStrength, MaxChromaticAberrationStrength);
MinGrainStrength = element.GetAttributeFloat(nameof(MinGrainStrength).ToLower(), 0.0f);
MaxGrainStrength = element.GetAttributeFloat(nameof(MaxGrainStrength).ToLower(), 0.0f);
MaxGrainStrength = Math.Max(MinGrainStrength, MaxGrainStrength);
MinScreenBlurStrength = element.GetAttributeFloat("minscreenblur", 0.0f);
MaxScreenBlurStrength = element.GetAttributeFloat("maxscreenblur", 0.0f);
MaxScreenBlurStrength = Math.Max(MinScreenBlurStrength, MaxScreenBlurStrength);
MinSkillMultiplier = element.GetAttributeFloat("minskillmultiplier", 1.0f);
MaxSkillMultiplier = element.GetAttributeFloat("maxskillmultiplier", 1.0f);
ResistanceFor = element.GetAttributeString("resistancefor", "");
MinResistance = element.GetAttributeFloat("minresistance", 0.0f);
MaxResistance = element.GetAttributeFloat("maxresistance", 0.0f);
MaxResistance = Math.Max(MinResistance, MaxResistance);
MinSpeedMultiplier = element.GetAttributeFloat("minspeedmultiplier", 1.0f);
MaxSpeedMultiplier = element.GetAttributeFloat("maxspeedmultiplier", 1.0f);
MaxSpeedMultiplier = Math.Max(MinSpeedMultiplier, MaxSpeedMultiplier);
MinBuffMultiplier = element.GetAttributeFloat("minbuffmultiplier", 1.0f);
MaxBuffMultiplier = element.GetAttributeFloat("maxbuffmultiplier", 1.0f);
MaxBuffMultiplier = Math.Max(MinBuffMultiplier, MaxBuffMultiplier);
DialogFlag = element.GetAttributeString("dialogflag", "");
StrengthChange = element.GetAttributeFloat("strengthchange", 0.0f);
resistanceFor = element.GetAttributeStringArray("resistancefor", new string[0], convertToLowerInvariant: true);
foreach (XElement subElement in element.Elements())
{
@@ -201,6 +253,19 @@ namespace Barotrauma
case "statuseffect":
StatusEffects.Add(StatusEffect.Load(subElement, parentDebugName));
break;
case "statvalue":
var statType = CharacterAbilityGroup.ParseStatType(subElement.GetAttributeString("stattype", ""), parentDebugName);
float defaultValue = subElement.GetAttributeFloat("value", 0f);
float minValue = subElement.GetAttributeFloat("minvalue", defaultValue);
float maxValue = subElement.GetAttributeFloat("maxvalue", defaultValue);
AfflictionStatValues.TryAdd(statType, (minValue, maxValue));
break;
case "abilityflag":
var flagType = CharacterAbilityGroup.ParseFlagType(subElement.GetAttributeString("flagtype", ""), parentDebugName);
AfflictionAbilityFlags.Add(flagType);
break;
}
}
}
@@ -317,6 +382,9 @@ namespace Barotrauma
public readonly Sprite Icon;
public readonly Color[] IconColors;
public readonly Sprite AfflictionOverlay;
public readonly bool AfflictionOverlayAlphaIsLinear;
private readonly List<Effect> effects = new List<Effect>();
private readonly List<PeriodicEffect> periodicEffects = new List<PeriodicEffect>();
@@ -576,6 +644,11 @@ namespace Barotrauma
Description = TextManager.Get("AfflictionDescription." + translationId, true) ?? element.GetAttributeString("description", "");
IsBuff = element.GetAttributeBool("isbuff", false);
if (element.Attribute("nameidentifier") != null)
{
Name = TextManager.Get(element.GetAttributeString("nameidentifier", string.Empty), returnNull: true) ?? Name;
}
LimbSpecific = element.GetAttributeBool("limbspecific", false);
if (!LimbSpecific)
{
@@ -590,7 +663,7 @@ namespace Barotrauma
ShowIconThreshold = element.GetAttributeFloat("showiconthreshold", Math.Max(ActivationThreshold, 0.05f));
ShowIconToOthersThreshold = element.GetAttributeFloat("showicontoothersthreshold", ShowIconThreshold);
MaxStrength = element.GetAttributeFloat("maxstrength", 100.0f);
GrainBurst = element.GetAttributeFloat(nameof(GrainBurst).ToLower(), 0.0f);
GrainBurst = element.GetAttributeFloat(nameof(GrainBurst).ToLowerInvariant(), 0.0f);
ShowInHealthScannerThreshold = element.GetAttributeFloat("showinhealthscannerthreshold", Math.Max(ActivationThreshold, 0.05f));
TreatmentThreshold = element.GetAttributeFloat("treatmentthreshold", Math.Max(ActivationThreshold, 5.0f));
@@ -604,6 +677,7 @@ namespace Barotrauma
SelfCauseOfDeathDescription = TextManager.Get("AfflictionCauseOfDeathSelf." + translationId, true) ?? element.GetAttributeString("selfcauseofdeathdescription", "");
IconColors = element.GetAttributeColorArray("iconcolors", null);
AfflictionOverlayAlphaIsLinear = element.GetAttributeBool("afflictionoverlayalphaislinear", false);
AchievementOnRemoved = element.GetAttributeString("achievementonremoved", "");
foreach (XElement subElement in element.Elements())
@@ -613,6 +687,18 @@ namespace Barotrauma
case "icon":
Icon = new Sprite(subElement);
break;
case "afflictionoverlay":
AfflictionOverlay = new Sprite(subElement);
break;
case "statvalue":
DebugConsole.ThrowError($"Error in affliction \"{Identifier}\" - stat values should be configured inside the affliction's effects.");
break;
case "effect":
case "periodiceffect":
break;
default:
DebugConsole.AddWarning($"Unrecognized element in affliction \"{Identifier}\" ({subElement.Name})");
break;
}
}