v1.0.13.1 (first post-1.0 patch)
This commit is contained in:
+481
-111
@@ -6,6 +6,7 @@ using System.Reflection;
|
||||
using System.Xml.Linq;
|
||||
using Barotrauma.Extensions;
|
||||
using System.Collections.Immutable;
|
||||
using Barotrauma.Items.Components;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -56,8 +57,77 @@ namespace Barotrauma
|
||||
public override void Dispose() { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// AfflictionPrefabHusk is a special type of affliction that has added functionality for husk infection.
|
||||
/// </summary>
|
||||
class AfflictionPrefabHusk : AfflictionPrefab
|
||||
{
|
||||
// Use any of these to define which limb the appendage is attached to.
|
||||
// If multiple are defined, the order of preference is: id, name, type.
|
||||
public readonly int AttachLimbId;
|
||||
public readonly string AttachLimbName;
|
||||
public readonly LimbType AttachLimbType;
|
||||
|
||||
/// <summary>
|
||||
/// The minimum strength at which husk infection will be in the dormant stage.
|
||||
/// It must be less than or equal to ActiveThreshold.
|
||||
/// </summary>
|
||||
public readonly float DormantThreshold;
|
||||
|
||||
/// <summary>
|
||||
/// The minimum strength at which husk infection will be in the active stage.
|
||||
/// It must be greater than or equal to DormantThreshold and less than or equal to TransitionThreshold.
|
||||
/// </summary>
|
||||
public readonly float ActiveThreshold;
|
||||
|
||||
/// <summary>
|
||||
/// The minimum strength at which husk infection will be in its final stage.
|
||||
/// It must be greater than or equal to ActiveThreshold.
|
||||
/// </summary>
|
||||
public readonly float TransitionThreshold;
|
||||
|
||||
/// <summary>
|
||||
/// The minimum strength the affliction must have for the affected character
|
||||
/// to transform into a husk upon death.
|
||||
/// </summary>
|
||||
public readonly float TransformThresholdOnDeath;
|
||||
|
||||
/// <summary>
|
||||
/// The species of husk to convert the affected character to
|
||||
/// once husk infection reaches its final stage.
|
||||
/// </summary>
|
||||
public readonly Identifier HuskedSpeciesName;
|
||||
|
||||
/// <summary>
|
||||
/// If set to true, all buffs are transferred to the converted
|
||||
/// character after husk transformation is complete.
|
||||
/// </summary>
|
||||
public readonly bool TransferBuffs;
|
||||
|
||||
/// <summary>
|
||||
/// If set to true, the affected player will see on-screen messages describing husk infection symptoms
|
||||
/// and affected bots will speak about their current husk infection stage.
|
||||
/// </summary>
|
||||
public readonly bool SendMessages;
|
||||
|
||||
/// <summary>
|
||||
/// If set to true, affected characters will have their speech impeded once the affliction
|
||||
/// reaches the dormant stage.
|
||||
/// </summary>
|
||||
public readonly bool CauseSpeechImpediment;
|
||||
|
||||
/// <summary>
|
||||
/// If set to false, affected characters will no longer require air
|
||||
/// once the affliction reaches the active stage.
|
||||
/// </summary>
|
||||
public readonly bool NeedsAir;
|
||||
|
||||
/// <summary>
|
||||
/// If set to true, affected players will retain control of their character
|
||||
/// after transforming into a husk.
|
||||
/// </summary>
|
||||
public readonly bool ControlHusk;
|
||||
|
||||
public AfflictionPrefabHusk(ContentXElement element, AfflictionsFile file, Type type = null) : base(element, file, type)
|
||||
{
|
||||
HuskedSpeciesName = element.GetAttributeIdentifier("huskedspeciesname", Identifier.Empty);
|
||||
@@ -78,7 +148,7 @@ namespace Barotrauma
|
||||
{
|
||||
AttachLimbId = attachElement.GetAttributeInt("id", -1);
|
||||
AttachLimbName = attachElement.GetAttributeString("name", null);
|
||||
AttachLimbType = Enum.TryParse(attachElement.GetAttributeString("type", "none"), true, out LimbType limbType) ? limbType : LimbType.None;
|
||||
AttachLimbType = attachElement.GetAttributeEnum("type", LimbType.None);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -96,174 +166,282 @@ namespace Barotrauma
|
||||
DormantThreshold = element.GetAttributeFloat("dormantthreshold", MaxStrength * 0.5f);
|
||||
ActiveThreshold = element.GetAttributeFloat("activethreshold", MaxStrength * 0.75f);
|
||||
TransitionThreshold = element.GetAttributeFloat("transitionthreshold", MaxStrength);
|
||||
|
||||
if (DormantThreshold > ActiveThreshold)
|
||||
{
|
||||
DebugConsole.ThrowError($"Error in \"{Identifier}\": {nameof(DormantThreshold)} is greater than {nameof(ActiveThreshold)} ({DormantThreshold} > {ActiveThreshold})");
|
||||
}
|
||||
if (ActiveThreshold > TransitionThreshold)
|
||||
{
|
||||
DebugConsole.ThrowError($"Error in \"{Identifier}\": {nameof(ActiveThreshold)} is greater than {nameof(TransitionThreshold)} ({ActiveThreshold} > {TransitionThreshold})");
|
||||
}
|
||||
|
||||
TransformThresholdOnDeath = element.GetAttributeFloat("transformthresholdondeath", ActiveThreshold);
|
||||
}
|
||||
|
||||
// Use any of these to define which limb the appendage is attached to.
|
||||
// If multiple are defined, the order of preference is: id, name, type.
|
||||
public readonly int AttachLimbId;
|
||||
public readonly string AttachLimbName;
|
||||
public readonly LimbType AttachLimbType;
|
||||
|
||||
public float ActiveThreshold, DormantThreshold, TransitionThreshold;
|
||||
public float TransformThresholdOnDeath;
|
||||
|
||||
public readonly Identifier HuskedSpeciesName;
|
||||
|
||||
public readonly bool TransferBuffs;
|
||||
public readonly bool SendMessages;
|
||||
public readonly bool CauseSpeechImpediment;
|
||||
public readonly bool NeedsAir;
|
||||
public readonly bool ControlHusk;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// AfflictionPrefab is a prefab that defines a type of affliction that can be applied to a character.
|
||||
/// There are multiple sub-types of afflictions such as AfflictionPrefabHusk, AfflictionPsychosis and AfflictionBleeding that can be used for additional functionality.
|
||||
///
|
||||
/// When defining a new affliction, the type will be determined by the element name.
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// <code language="xml">
|
||||
/// <Afflictions>
|
||||
/// <!-- Defines a regular affliction. -->
|
||||
/// <Affliction identifier="mycoolaffliction1" />
|
||||
///
|
||||
/// <!-- Defines an AfflictionPrefabHusk affliction. -->
|
||||
/// <AfflictionPrefabHusk identifier="mycoolaffliction2"/>
|
||||
///
|
||||
/// <!-- Defines an AfflictionBleeding affliction. -->
|
||||
/// <AfflictionBleeding identifier="mycoolaffliction3"/>
|
||||
/// </Afflictions>
|
||||
/// </code>
|
||||
/// </example>
|
||||
class AfflictionPrefab : PrefabWithUintIdentifier
|
||||
{
|
||||
public class Effect
|
||||
/// <summary>
|
||||
/// Effects are the primary way to add functionality to afflictions.
|
||||
/// </summary>
|
||||
/// <doc>
|
||||
/// <Ignore type="SubElement" identifier="AbilityFlag" />
|
||||
/// <SubElement identifier="abilityflag" type="AppliedAbilityFlag">
|
||||
/// Enables the specified flag on the character as long as the effect is active.
|
||||
/// </SubElement>
|
||||
/// <Type identifier="AppliedAbilityFlag">
|
||||
/// <Summary>
|
||||
/// Flag that will be enabled for the character as long as the effect is active.
|
||||
/// <example>
|
||||
/// <code language="xml">
|
||||
/// <Effect minstrength="0" maxstrength="100">
|
||||
/// <!-- Grants pressure immunity to the character while the effect is active. -->
|
||||
/// <AbilityFlag flagtype="ImmuneToPressure" />
|
||||
/// </Effect>
|
||||
/// </code>
|
||||
/// </example>
|
||||
/// </Summary>
|
||||
/// <Field identifier="FlagType" type="AbilityFlags" defaultValue="None">
|
||||
/// Which ability flag to enable.
|
||||
/// </Field>
|
||||
/// </Type>
|
||||
/// </doc>
|
||||
public sealed class Effect
|
||||
{
|
||||
//this effect is applied when the strength is within this range
|
||||
[Serialize(0.0f, IsPropertySaveable.No)]
|
||||
[Serialize(0.0f, IsPropertySaveable.No, description: "Minimum affliction strength required for this effect to be active.")]
|
||||
public float MinStrength { get; private set; }
|
||||
|
||||
[Serialize(0.0f, IsPropertySaveable.No)]
|
||||
[Serialize(0.0f, IsPropertySaveable.No, description: "Maximum affliction strength for which this effect will be active.")]
|
||||
public float MaxStrength { get; private set; }
|
||||
|
||||
[Serialize(0.0f, IsPropertySaveable.No)]
|
||||
[Serialize(0.0f, IsPropertySaveable.No, description: "The amount of vitality that is lost at this effect's lowest strength.")]
|
||||
public float MinVitalityDecrease { get; private set; }
|
||||
|
||||
[Serialize(0.0f, IsPropertySaveable.No)]
|
||||
[Serialize(0.0f, IsPropertySaveable.No, description: "The amount of vitality that is lost at this effect's highest strength.")]
|
||||
public float MaxVitalityDecrease { get; private set; }
|
||||
|
||||
//how much the strength of the affliction changes per second
|
||||
[Serialize(0.0f, IsPropertySaveable.No)]
|
||||
[Serialize(0.0f, IsPropertySaveable.No, description: "How much the affliction's strength changes every second while this effect is active.")]
|
||||
public float StrengthChange { get; private set; }
|
||||
|
||||
[Serialize(false, IsPropertySaveable.No)]
|
||||
[Serialize(false, IsPropertySaveable.No, description:
|
||||
"If set to true, MinVitalityDecrease and MaxVitalityDecrease represent a fraction of the affected character's maximum " +
|
||||
"vitality, with 1 meaning 100%, instead of the same amount for all species.")]
|
||||
public bool MultiplyByMaxVitality { get; private set; }
|
||||
|
||||
[Serialize(0.0f, IsPropertySaveable.No)]
|
||||
[Serialize(0.0f, IsPropertySaveable.No, description: "Blur effect strength at this effect's lowest strength.")]
|
||||
public float MinScreenBlur { get; private set; }
|
||||
|
||||
[Serialize(0.0f, IsPropertySaveable.No)]
|
||||
[Serialize(0.0f, IsPropertySaveable.No, description: "Blur effect strength at this effect's highest strength.")]
|
||||
public float MaxScreenBlur { get; private set; }
|
||||
|
||||
[Serialize(0.0f, IsPropertySaveable.No)]
|
||||
[Serialize(0.0f, IsPropertySaveable.No, description: "Generic distortion effect strength at this effect's lowest strength.")]
|
||||
public float MinScreenDistort { get; private set; }
|
||||
|
||||
[Serialize(0.0f, IsPropertySaveable.No)]
|
||||
[Serialize(0.0f, IsPropertySaveable.No, description: "Generic distortion effect strength at this effect's highest strength.")]
|
||||
public float MaxScreenDistort { get; private set; }
|
||||
|
||||
[Serialize(0.0f, IsPropertySaveable.No)]
|
||||
[Serialize(0.0f, IsPropertySaveable.No, description: "Radial distortion effect strength at this effect's lowest strength.")]
|
||||
public float MinRadialDistort { get; private set; }
|
||||
|
||||
[Serialize(0.0f, IsPropertySaveable.No)]
|
||||
[Serialize(0.0f, IsPropertySaveable.No, description: "Radial distortion effect strength at this effect's highest strength.")]
|
||||
public float MaxRadialDistort { get; private set; }
|
||||
|
||||
[Serialize(0.0f, IsPropertySaveable.No)]
|
||||
[Serialize(0.0f, IsPropertySaveable.No, description: "Chromatic aberration effect strength at this effect's lowest strength.")]
|
||||
public float MinChromaticAberration { get; private set; }
|
||||
|
||||
[Serialize(0.0f, IsPropertySaveable.No)]
|
||||
[Serialize(0.0f, IsPropertySaveable.No, description: "Chromatic aberration effect strength at this effect's highest strength.")]
|
||||
public float MaxChromaticAberration { get; private set; }
|
||||
|
||||
[Serialize("255,255,255,255", IsPropertySaveable.No)]
|
||||
[Serialize("255,255,255,255", IsPropertySaveable.No, description: "Radiation grain effect color.")]
|
||||
public Color GrainColor { get; private set; }
|
||||
|
||||
[Serialize(0.0f, IsPropertySaveable.No)]
|
||||
[Serialize(0.0f, IsPropertySaveable.No, description: "Radiation grain effect strength at this effect's lowest strength.")]
|
||||
public float MinGrainStrength { get; private set; }
|
||||
|
||||
[Serialize(0.0f, IsPropertySaveable.No)]
|
||||
[Serialize(0.0f, IsPropertySaveable.No, description: "Radiation grain effect strength at this effect's highest strength.")]
|
||||
public float MaxGrainStrength { get; private set; }
|
||||
|
||||
[Serialize(0.0f, IsPropertySaveable.No)]
|
||||
[Serialize(0.0f, IsPropertySaveable.No, description:
|
||||
"The maximum rate of fluctuation to apply to visual effects caused by this affliction effect. " +
|
||||
"Effective fluctuation is proportional to the affliction's current strength.")]
|
||||
public float ScreenEffectFluctuationFrequency { get; private set; }
|
||||
|
||||
[Serialize(1.0f, IsPropertySaveable.No)]
|
||||
[Serialize(1.0f, IsPropertySaveable.No, description:
|
||||
"Multiplier for the affliction overlay's opacity at this effect's lowest strength. " +
|
||||
"See the list of elements for more details.")]
|
||||
public float MinAfflictionOverlayAlphaMultiplier { get; private set; }
|
||||
|
||||
[Serialize(1.0f, IsPropertySaveable.No)]
|
||||
[Serialize(1.0f, IsPropertySaveable.No, description:
|
||||
"Multiplier for the affliction overlay's opacity at this effect's highest strength. " +
|
||||
"See the list of elements for more details.")]
|
||||
public float MaxAfflictionOverlayAlphaMultiplier { get; private set; }
|
||||
|
||||
[Serialize(1.0f, IsPropertySaveable.No)]
|
||||
[Serialize(1.0f, IsPropertySaveable.No, description:
|
||||
"Multiplier for every buff's decay rate at this effect's lowest strength. " +
|
||||
"Only applies to afflictions of class BuffDurationIncrease.")]
|
||||
public float MinBuffMultiplier { get; private set; }
|
||||
|
||||
[Serialize(1.0f, IsPropertySaveable.No)]
|
||||
[Serialize(1.0f, IsPropertySaveable.No, description:
|
||||
"Multiplier for every buff's decay rate at this effect's highest strength. " +
|
||||
"Only applies to afflictions of class BuffDurationIncrease.")]
|
||||
public float MaxBuffMultiplier { get; private set; }
|
||||
|
||||
[Serialize(1.0f, IsPropertySaveable.No)]
|
||||
[Serialize(1.0f, IsPropertySaveable.No, description: "Multiplier to apply to the affected character's speed at this effect's lowest strength.")]
|
||||
public float MinSpeedMultiplier { get; private set; }
|
||||
|
||||
[Serialize(1.0f, IsPropertySaveable.No)]
|
||||
[Serialize(1.0f, IsPropertySaveable.No, description: "Multiplier to apply to the affected character's speed at this effect's highest strength.")]
|
||||
public float MaxSpeedMultiplier { get; private set; }
|
||||
|
||||
[Serialize(1.0f, IsPropertySaveable.No)]
|
||||
|
||||
[Serialize(1.0f, IsPropertySaveable.No, description: "Multiplier to apply to all of the affected character's skill levels at this effect's lowest strength.")]
|
||||
public float MinSkillMultiplier { get; private set; }
|
||||
|
||||
[Serialize(1.0f, IsPropertySaveable.No)]
|
||||
[Serialize(1.0f, IsPropertySaveable.No, description: "Multiplier to apply to all of the affected character's skill levels at this effect's highest strength.")]
|
||||
public float MaxSkillMultiplier { get; private set; }
|
||||
|
||||
private readonly Identifier[] resistanceFor;
|
||||
public IReadOnlyList<Identifier> ResistanceFor => resistanceFor;
|
||||
/// <summary>
|
||||
/// A list of identifiers of afflictions that the affected character will be
|
||||
/// resistant to when this effect is active.
|
||||
/// </summary>
|
||||
public readonly ImmutableArray<Identifier> ResistanceFor;
|
||||
|
||||
[Serialize(0.0f, IsPropertySaveable.No)]
|
||||
[Serialize(0.0f, IsPropertySaveable.No,
|
||||
description: "The amount of resistance to the afflictions specified by ResistanceFor to apply at this effect's lowest strength.")]
|
||||
public float MinResistance { get; private set; }
|
||||
|
||||
[Serialize(0.0f, IsPropertySaveable.No)]
|
||||
[Serialize(0.0f, IsPropertySaveable.No,
|
||||
description: "The amount of resistance to the afflictions specified by ResistanceFor to apply at this effect's highest strength.")]
|
||||
public float MaxResistance { get; private set; }
|
||||
|
||||
[Serialize("", IsPropertySaveable.No)]
|
||||
[Serialize("", IsPropertySaveable.No, description: "Identifier used by AI to determine conversation lines to say when this effect is active.")]
|
||||
public Identifier DialogFlag { get; private set; }
|
||||
|
||||
[Serialize("", IsPropertySaveable.No)]
|
||||
[Serialize("", IsPropertySaveable.No, description: "Tag that enemy AI may use to target the affected character when this effect is active.")]
|
||||
public Identifier Tag { get; private set; }
|
||||
|
||||
[Serialize("0,0,0,0", IsPropertySaveable.No)]
|
||||
[Serialize("0,0,0,0", IsPropertySaveable.No,
|
||||
description: "Color to tint the affected character's face with at this effect's lowest strength. The alpha channel is used to determine how much to tint the character's face.")]
|
||||
public Color MinFaceTint { get; private set; }
|
||||
|
||||
[Serialize("0,0,0,0", IsPropertySaveable.No)]
|
||||
[Serialize("0,0,0,0", IsPropertySaveable.No,
|
||||
description: "Color to tint the affected character's face with at this effect's highest strength. The alpha channel is used to determine how much to tint the character's face.")]
|
||||
public Color MaxFaceTint { get; private set; }
|
||||
|
||||
[Serialize("0,0,0,0", IsPropertySaveable.No)]
|
||||
[Serialize("0,0,0,0", IsPropertySaveable.No,
|
||||
description: "Color to tint the affected character's entire body with at this effect's lowest strength. The alpha channel is used to determine how much to tint the character.")]
|
||||
public Color MinBodyTint { get; private set; }
|
||||
|
||||
[Serialize("0,0,0,0", IsPropertySaveable.No)]
|
||||
[Serialize("0,0,0,0", IsPropertySaveable.No,
|
||||
description: "Color to tint the affected character's entire body with at this effect's highest strength. The alpha channel is used to determine how much to tint the character.")]
|
||||
public Color MaxBodyTint { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Prevents AfflictionHusks with the specified identifier(s) from transforming the character into an AI-controlled character
|
||||
/// StatType that will be applied to the affected character when the effect is active that is proportional to the effect's strength.
|
||||
/// </summary>
|
||||
public Identifier[] BlockTransformation { get; private set; }
|
||||
/// <example>
|
||||
/// <code language="xml">
|
||||
/// <Effect minstrength="0" maxstrength="100">
|
||||
/// <!-- Walking speed will be increased by 10% at strength 0, 20% at 50 and 30% at 100 -->
|
||||
/// <StatValue stattype="WalkingSpeed" minvalue="0.1" maxvalue="0.3" />
|
||||
/// <!-- Maximum health will be increased by 20% regardless of the effect strength -->
|
||||
/// <StatValue stattype="MaximumHealthMultiplier" value="0.2" />
|
||||
/// </Effect>
|
||||
/// </code>
|
||||
/// </example>
|
||||
public readonly struct AppliedStatValue
|
||||
{
|
||||
/// <summary>
|
||||
/// Which StatType to apply
|
||||
/// </summary>
|
||||
public readonly StatTypes StatType;
|
||||
|
||||
public readonly Dictionary<StatTypes, (float minValue, float maxValue)> AfflictionStatValues = new Dictionary<StatTypes, (float minValue, float maxValue)>();
|
||||
public AbilityFlags AfflictionAbilityFlags;
|
||||
/// <summary>
|
||||
/// Minimum value to apply
|
||||
/// </summary>
|
||||
public readonly float MinValue;
|
||||
|
||||
/// <summary>
|
||||
/// Minimum value to apply
|
||||
/// </summary>
|
||||
public readonly float MaxValue;
|
||||
|
||||
/// <summary>
|
||||
/// Constant value to apply, will be ignored if MinValue or MaxValue are set
|
||||
/// </summary>
|
||||
private readonly float Value;
|
||||
|
||||
public AppliedStatValue(ContentXElement element)
|
||||
{
|
||||
Value = element.GetAttributeFloat("value", 0.0f);
|
||||
StatType = element.GetAttributeEnum("stattype", StatTypes.None);
|
||||
MinValue = element.GetAttributeFloat("minvalue", Value);
|
||||
MaxValue = element.GetAttributeFloat("maxvalue", Value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Prevents AfflictionHusks with the specified identifier(s) from transforming the character into an AI-controlled character.
|
||||
/// </summary>
|
||||
public readonly ImmutableArray<Identifier> BlockTransformation;
|
||||
|
||||
/// <summary>
|
||||
/// StatType that will be applied to the affected character when the effect is active that is proportional to the effect's strength.
|
||||
/// </summary>
|
||||
public readonly ImmutableDictionary<StatTypes, AppliedStatValue> AfflictionStatValues;
|
||||
|
||||
public readonly AbilityFlags AfflictionAbilityFlags;
|
||||
|
||||
//statuseffects applied on the character when the affliction is active
|
||||
public readonly List<StatusEffect> StatusEffects = new List<StatusEffect>();
|
||||
public readonly ImmutableArray<StatusEffect> StatusEffects;
|
||||
|
||||
public Effect(ContentXElement element, string parentDebugName)
|
||||
{
|
||||
SerializableProperty.DeserializeProperties(this, element);
|
||||
|
||||
resistanceFor = element.GetAttributeIdentifierArray("resistancefor", Array.Empty<Identifier>());
|
||||
BlockTransformation = element.GetAttributeIdentifierArray("blocktransformation", Array.Empty<Identifier>());
|
||||
ResistanceFor = element.GetAttributeIdentifierArray("resistancefor", Array.Empty<Identifier>())!.ToImmutableArray();
|
||||
BlockTransformation = element.GetAttributeIdentifierArray("blocktransformation", Array.Empty<Identifier>())!.ToImmutableArray();
|
||||
|
||||
var afflictionStatValues = new Dictionary<StatTypes, AppliedStatValue>();
|
||||
var statusEffects = new List<StatusEffect>();
|
||||
foreach (var subElement in element.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
{
|
||||
case "statuseffect":
|
||||
StatusEffects.Add(StatusEffect.Load(subElement, parentDebugName));
|
||||
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));
|
||||
var newStatValue = new AppliedStatValue(subElement);
|
||||
afflictionStatValues.Add(newStatValue.StatType, newStatValue);
|
||||
break;
|
||||
case "abilityflag":
|
||||
var flagType = CharacterAbilityGroup.ParseFlagType(subElement.GetAttributeString("flagtype", ""), parentDebugName);
|
||||
AbilityFlags flagType = subElement.GetAttributeEnum("flagtype", AbilityFlags.None);
|
||||
if (flagType is AbilityFlags.None)
|
||||
{
|
||||
DebugConsole.ThrowError($"Error in affliction \"{parentDebugName}\" - invalid ability flag type \"{subElement.GetAttributeString("flagtype", "")}\".");
|
||||
continue;
|
||||
}
|
||||
AfflictionAbilityFlags |= flagType;
|
||||
break;
|
||||
case "affliction":
|
||||
@@ -271,21 +449,77 @@ namespace Barotrauma
|
||||
break;
|
||||
}
|
||||
}
|
||||
AfflictionStatValues = afflictionStatValues.ToImmutableDictionary();
|
||||
StatusEffects = statusEffects.ToImmutableArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns 0 if affliction.Strength is MinStrength,
|
||||
/// 1 if affliction.Strength is MaxStrength
|
||||
/// </summary>
|
||||
public float GetStrengthFactor(Affliction affliction) => GetStrengthFactor(affliction.Strength);
|
||||
|
||||
/// <summary>
|
||||
/// Returns 0 if affliction.Strength is MinStrength,
|
||||
/// 1 if affliction.Strength is MaxStrength
|
||||
/// </summary>
|
||||
public float GetStrengthFactor(float strength)
|
||||
=> MathUtils.InverseLerp(
|
||||
MinStrength,
|
||||
MaxStrength,
|
||||
strength);
|
||||
}
|
||||
|
||||
public class Description
|
||||
/// <summary>
|
||||
/// The description element can be used to define descriptions for the affliction which are shown under specific conditions;
|
||||
/// for example a description that only shows to other players or only at certain strength levels.
|
||||
/// </summary>
|
||||
/// <doc>
|
||||
/// <Field identifier="Text" type="string" defaultValue="""">
|
||||
/// Raw text for the description.
|
||||
/// </Field>
|
||||
/// </doc>
|
||||
public sealed class Description
|
||||
{
|
||||
public enum TargetType
|
||||
{
|
||||
/// <summary>
|
||||
/// Everyone can see the description.
|
||||
/// </summary>
|
||||
Any,
|
||||
/// <summary>
|
||||
/// Only the affected character can see the description.
|
||||
/// </summary>
|
||||
Self,
|
||||
/// <summary>
|
||||
/// The affected character cannot see the description but others can.
|
||||
/// </summary>
|
||||
OtherCharacter
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raw text for the description.
|
||||
/// </summary>
|
||||
public readonly LocalizedString Text;
|
||||
|
||||
/// <summary>
|
||||
/// Text tag used to set the text from the localization files.
|
||||
/// </summary>
|
||||
public readonly Identifier TextTag;
|
||||
public readonly float MinStrength, MaxStrength;
|
||||
|
||||
/// <summary>
|
||||
/// Minimum strength required for the description to be shown.
|
||||
/// </summary>
|
||||
public readonly float MinStrength;
|
||||
|
||||
/// <summary>
|
||||
/// Maximum strength required for the description to be shown.
|
||||
/// </summary>
|
||||
public readonly float MaxStrength;
|
||||
|
||||
/// <summary>
|
||||
/// Who can see the description.
|
||||
/// </summary>
|
||||
public readonly TargetType Target;
|
||||
|
||||
public Description(ContentXElement element, AfflictionPrefab affliction)
|
||||
@@ -315,7 +549,23 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public class PeriodicEffect
|
||||
/// <summary>
|
||||
/// PeriodicEffect applies StatusEffects to the character periodically.
|
||||
/// </summary>
|
||||
/// <doc>
|
||||
/// <SubElement identifier="StatusEffect" type="StatusEffect" />
|
||||
/// <Field identifier="Interval" type="float" defaultValue="1.0">
|
||||
/// How often the status effect is applied in seconds.
|
||||
/// Setting this attribute will set both the min and max interval to the specified value.
|
||||
/// </Field>
|
||||
/// <Field identifier="MinInterval" type="float" defaultValue="1.0">
|
||||
/// Minimum interval between applying the status effect in seconds.
|
||||
/// </Field>
|
||||
/// <Field identifier="MaxInterval" type="float" defaultValue="1.0">
|
||||
/// Maximum interval between applying the status effect in seconds.
|
||||
/// </Field>
|
||||
/// </doc>
|
||||
public sealed class PeriodicEffect
|
||||
{
|
||||
public readonly List<StatusEffect> StatusEffects = new List<StatusEffect>();
|
||||
public readonly float MinInterval, MaxInterval;
|
||||
@@ -368,52 +618,124 @@ namespace Barotrauma
|
||||
|
||||
public static readonly PrefabCollection<AfflictionPrefab> Prefabs = new PrefabCollection<AfflictionPrefab>();
|
||||
|
||||
public override void Dispose() { }
|
||||
|
||||
public static IEnumerable<AfflictionPrefab> List => Prefabs;
|
||||
|
||||
// Arbitrary string that is used to identify the type of the affliction.
|
||||
public readonly Identifier AfflictionType;
|
||||
public override void Dispose() { }
|
||||
|
||||
private readonly ContentXElement configElement;
|
||||
|
||||
//Does the affliction affect a specific limb or the whole character
|
||||
public readonly bool LimbSpecific;
|
||||
|
||||
//If not a limb-specific affliction, which limb is the indicator shown on in the health menu
|
||||
//(e.g. mental health problems on head, lack of oxygen on torso...)
|
||||
public readonly LimbType IndicatorLimb;
|
||||
|
||||
public readonly LocalizedString Name;
|
||||
public readonly Identifier TranslationIdentifier;
|
||||
public readonly bool IsBuff;
|
||||
public readonly bool AffectMachines;
|
||||
public readonly bool HealableInMedicalClinic;
|
||||
public readonly float HealCostMultiplier;
|
||||
public readonly int BaseHealCost;
|
||||
public readonly bool ShowBarInHealthMenu;
|
||||
|
||||
|
||||
public readonly LocalizedString CauseOfDeathDescription, SelfCauseOfDeathDescription;
|
||||
|
||||
private readonly LocalizedString defaultDescription;
|
||||
public readonly ImmutableList<Description> Descriptions;
|
||||
|
||||
/// <summary>
|
||||
/// Arbitrary string that is used to identify the type of the affliction.
|
||||
/// </summary>
|
||||
public readonly Identifier AfflictionType;
|
||||
|
||||
/// <summary>
|
||||
/// If set to true, the affliction affects individual limbs. Otherwise, it affects the whole character.
|
||||
/// </summary>
|
||||
public readonly bool LimbSpecific;
|
||||
|
||||
/// <summary>
|
||||
/// If the affliction doesn't affect individual limbs, this attribute determines
|
||||
/// where the game will render the affliction's indicator when viewed in the
|
||||
/// in-game health UI.
|
||||
///
|
||||
/// For example, the psychosis indicator is rendered on the head, and low oxygen
|
||||
/// is rendered on the torso.
|
||||
/// </summary>
|
||||
public readonly LimbType IndicatorLimb;
|
||||
|
||||
/// <summary>
|
||||
/// Can be set to the identifier of another affliction to make this affliction
|
||||
/// reuse the same name and description.
|
||||
/// </summary>
|
||||
public readonly Identifier TranslationIdentifier;
|
||||
|
||||
/// <summary>
|
||||
/// If set to true, the game will recognize this affliction as a buff.
|
||||
/// This means, among other things, that bots won't attempt to treat it,
|
||||
/// and the health UI will render the affected limb in green rather than red.
|
||||
/// </summary>
|
||||
public readonly bool IsBuff;
|
||||
|
||||
/// <summary>
|
||||
/// If set to true, this affliction can affect characters that are marked as
|
||||
/// machines, such as the Fractal Guardian.
|
||||
/// </summary>
|
||||
public readonly bool AffectMachines;
|
||||
|
||||
/// <summary>
|
||||
/// If set to true, this affliction can be healed at the medical clinic.
|
||||
/// </summary>
|
||||
/// <doc>
|
||||
/// <override type="DefaultValue">
|
||||
/// false if the affliction is a buff or has the type "geneticmaterialbuff" or "geneticmaterialdebuff", true otherwise.
|
||||
/// </override>
|
||||
/// </doc>
|
||||
public readonly bool HealableInMedicalClinic;
|
||||
|
||||
/// <summary>
|
||||
/// How much each unit of this affliction's strength will add
|
||||
/// to the cost of healing at the medical clinic.
|
||||
/// </summary>
|
||||
public readonly float HealCostMultiplier;
|
||||
|
||||
/// <summary>
|
||||
/// The minimum cost of healing this affliction at the medical clinic.
|
||||
/// </summary>
|
||||
public readonly int BaseHealCost;
|
||||
|
||||
/// <summary>
|
||||
/// If set to false, the health UI will not show the strength of the affliction
|
||||
/// as a bar under its indicator.
|
||||
/// </summary>
|
||||
public readonly bool ShowBarInHealthMenu;
|
||||
|
||||
/// <summary>
|
||||
/// If set to true, this affliction's icon will be hidden from the HUD after 5 seconds.
|
||||
/// </summary>
|
||||
public readonly bool HideIconAfterDelay;
|
||||
|
||||
//how high the strength has to be for the affliction to take affect
|
||||
/// <summary>
|
||||
/// How high the strength has to be for the affliction to take effect
|
||||
/// </summary>
|
||||
public readonly float ActivationThreshold = 0.0f;
|
||||
//how high the strength has to be for the affliction icon to be shown in the UI
|
||||
|
||||
/// <summary>
|
||||
/// How high the strength has to be for the affliction icon to be shown in the UI
|
||||
/// </summary>
|
||||
public readonly float ShowIconThreshold = 0.05f;
|
||||
//how high the strength has to be for the affliction icon to be shown to others with a health scanner or via the health interface
|
||||
|
||||
/// <summary>
|
||||
/// How high the strength has to be for the affliction icon to be shown to others with a health scanner or via the health interface
|
||||
/// </summary>
|
||||
public readonly float ShowIconToOthersThreshold = 0.05f;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum strength this affliction can have.
|
||||
/// </summary>
|
||||
public readonly float MaxStrength = 100.0f;
|
||||
|
||||
/// <summary>
|
||||
/// The strength of the radiation grain effect to apply when the strength of this affliction increases.
|
||||
/// </summary>
|
||||
public readonly float GrainBurst;
|
||||
|
||||
//how high the strength has to be for the affliction icon to be shown with a health scanner
|
||||
/// <summary>
|
||||
/// How high the strength has to be for the affliction icon to be shown with a health scanner
|
||||
/// </summary>
|
||||
public readonly float ShowInHealthScannerThreshold = 0.05f;
|
||||
|
||||
//how strong the affliction needs to be before bots attempt to treat it
|
||||
/// <summary>
|
||||
/// How strong the affliction needs to be before bots attempt to treat it.
|
||||
/// Also effects when the affliction is shown in the suitable treatments list.
|
||||
/// </summary>
|
||||
public readonly float TreatmentThreshold = 5.0f;
|
||||
|
||||
/// <summary>
|
||||
@@ -422,43 +744,84 @@ namespace Barotrauma
|
||||
public ImmutableHashSet<Identifier> IgnoreTreatmentIfAfflictedBy;
|
||||
|
||||
/// <summary>
|
||||
/// The affliction is automatically removed after this time. 0 = unlimited
|
||||
/// The duration of the affliction, in seconds. If set to 0, the affliction does not expire.
|
||||
/// </summary>
|
||||
public readonly float Duration;
|
||||
|
||||
//how much karma changes when a player applies this affliction to someone (per strength of the affliction)
|
||||
/// <summary>
|
||||
/// How much karma changes when a player applies this affliction to someone (per strength of the affliction)
|
||||
/// </summary>
|
||||
public float KarmaChangeOnApplied;
|
||||
|
||||
/// <summary>
|
||||
/// Opacity of the burn effect (darker tint) on limbs affected by this affliction. 1 = full strength.
|
||||
/// </summary>
|
||||
public readonly float BurnOverlayAlpha;
|
||||
|
||||
/// <summary>
|
||||
/// Opacity of the bloody damage overlay on limbs affected by this affliction. 1 = full strength.
|
||||
/// </summary>
|
||||
public readonly float DamageOverlayAlpha;
|
||||
|
||||
//steam achievement given when the controlled character receives the affliction
|
||||
/// Steam achievement given when the controlled character receives the affliction.
|
||||
/// </summary>
|
||||
public readonly Identifier AchievementOnReceived;
|
||||
|
||||
//steam achievement given when the affliction is removed from the controlled character
|
||||
/// <summary>
|
||||
/// Steam achievement given when the affliction is removed from the controlled character.
|
||||
/// </summary>
|
||||
public readonly Identifier AchievementOnRemoved;
|
||||
|
||||
public readonly Sprite Icon;
|
||||
/// <summary>
|
||||
/// A gradient that defines which color to render this affliction's icon
|
||||
/// with, based on the affliction's current strength.
|
||||
/// </summary>
|
||||
public readonly Color[] IconColors;
|
||||
|
||||
public readonly Sprite AfflictionOverlay;
|
||||
/// <summary>
|
||||
/// If set to true and the affliction has an AfflictionOverlay element, the overlay's opacity will be strictly proportional to its strength.
|
||||
/// Otherwise, the overlay's opacity will be determined based on its activation threshold and effects.
|
||||
/// </summary>
|
||||
public readonly bool AfflictionOverlayAlphaIsLinear;
|
||||
|
||||
/// <summary>
|
||||
/// If set to true, this affliction will not persist between rounds.
|
||||
/// </summary>
|
||||
public readonly bool ResetBetweenRounds;
|
||||
|
||||
/// <summary>
|
||||
/// Should damage particles be emitted when a character receives this affliction?
|
||||
/// Only relevant if the affliction is of the type "bleeding" or "damage".
|
||||
/// </summary>
|
||||
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 type poison or paralysis, the skill is increased only when the target is hostile.
|
||||
/// If the affliction is of type buff, the skill is increased only when the target is friendly.
|
||||
/// 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.
|
||||
/// </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.
|
||||
/// The skill is increased only when the target is hostile.
|
||||
/// </summary>
|
||||
public readonly float WeaponsSkillGain;
|
||||
|
||||
/// <summary>
|
||||
/// A list of species this affliction is allowed to affect.
|
||||
/// </summary>
|
||||
public Identifier[] TargetSpecies { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Effects to apply at various strength levels.
|
||||
/// Only one effect can be applied at any given moment, so their ranges should be defined with no overlap.
|
||||
/// </summary>
|
||||
private readonly List<Effect> effects = new List<Effect>();
|
||||
|
||||
/// <summary>
|
||||
/// PeriodicEffect applies StatusEffects to the character periodically.
|
||||
/// </summary>
|
||||
private readonly List<PeriodicEffect> periodicEffects = new List<PeriodicEffect>();
|
||||
|
||||
public IEnumerable<Effect> Effects => effects;
|
||||
@@ -467,9 +830,16 @@ namespace Barotrauma
|
||||
|
||||
private readonly ConstructorInfo constructor;
|
||||
|
||||
public Identifier[] TargetSpecies { get; protected set; }
|
||||
/// <summary>
|
||||
/// An icon that’s used in the UI to represent this affliction.
|
||||
/// </summary>
|
||||
public readonly Sprite Icon;
|
||||
|
||||
public readonly bool ResetBetweenRounds;
|
||||
/// <summary>
|
||||
/// A sprite that covers the affected player's entire screen when this affliction is active.
|
||||
/// Its opacity is controlled by the active effect's MinAfflictionOverlayAlphaMultiplier and MaxAfflictionOverlayAlphaMultiplier
|
||||
/// </summary>
|
||||
public readonly Sprite AfflictionOverlay;
|
||||
|
||||
public IEnumerable<KeyValuePair<Identifier, float>> TreatmentSuitability
|
||||
{
|
||||
@@ -497,7 +867,7 @@ namespace Barotrauma
|
||||
if (!string.IsNullOrEmpty(fallbackName))
|
||||
{
|
||||
Name = Name.Fallback(fallbackName);
|
||||
}
|
||||
}
|
||||
defaultDescription = TextManager.Get($"AfflictionDescription.{TranslationIdentifier}");
|
||||
string fallbackDescription = element.GetAttributeString("description", "");
|
||||
if (!string.IsNullOrEmpty(fallbackDescription))
|
||||
|
||||
Reference in New Issue
Block a user