v0.13.0.11
This commit is contained in:
+77
-16
@@ -14,6 +14,9 @@ namespace Barotrauma
|
||||
|
||||
public Dictionary<string, SerializableProperty> SerializableProperties { get; set; }
|
||||
|
||||
public float PendingAdditionStrenght { get; set; }
|
||||
public float AdditionStrength { get; set; }
|
||||
|
||||
protected float _strength;
|
||||
|
||||
[Serialize(0f, true), Editable]
|
||||
@@ -26,7 +29,12 @@ namespace Barotrauma
|
||||
{
|
||||
_nonClampedStrength = value;
|
||||
}
|
||||
_strength = MathHelper.Clamp(value, 0.0f, Prefab.MaxStrength);
|
||||
float newValue = MathHelper.Clamp(value, 0.0f, Prefab.MaxStrength);
|
||||
if (newValue > _strength)
|
||||
{
|
||||
PendingAdditionStrenght = Prefab.GrainBurst;
|
||||
}
|
||||
_strength = newValue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,6 +64,7 @@ namespace Barotrauma
|
||||
public Affliction(AfflictionPrefab prefab, float strength)
|
||||
{
|
||||
Prefab = prefab;
|
||||
PendingAdditionStrenght = Prefab.GrainBurst;
|
||||
_strength = strength;
|
||||
Identifier = prefab?.Identifier;
|
||||
|
||||
@@ -101,13 +110,33 @@ namespace Barotrauma
|
||||
|
||||
return currVitalityDecrease;
|
||||
}
|
||||
|
||||
public float GetScreenGrainStrength()
|
||||
{
|
||||
if (Strength < Prefab.ActivationThreshold) { return 0.0f; }
|
||||
AfflictionPrefab.Effect currentEffect = Prefab.GetActiveEffect(Strength);
|
||||
if (currentEffect == null) { return 0.0f; }
|
||||
if (MathUtils.NearlyEqual(currentEffect.MaxGrainStrength, 0f)) { return 0.0f; }
|
||||
|
||||
float amount = MathHelper.Lerp(
|
||||
currentEffect.MinGrainStrength,
|
||||
currentEffect.MaxGrainStrength,
|
||||
(Strength - currentEffect.MinStrength) / (currentEffect.MaxStrength - currentEffect.MinStrength));
|
||||
|
||||
if (Prefab.GrainBurst > 0 && AdditionStrength > amount)
|
||||
{
|
||||
return AdditionStrength;
|
||||
}
|
||||
|
||||
return amount;
|
||||
}
|
||||
|
||||
public float GetScreenDistortStrength()
|
||||
{
|
||||
if (Strength < Prefab.ActivationThreshold) return 0.0f;
|
||||
if (Strength < Prefab.ActivationThreshold) { return 0.0f; }
|
||||
AfflictionPrefab.Effect currentEffect = Prefab.GetActiveEffect(Strength);
|
||||
if (currentEffect == null) return 0.0f;
|
||||
if (currentEffect.MaxScreenDistortStrength - currentEffect.MinScreenDistortStrength <= 0.0f) return 0.0f;
|
||||
if (currentEffect == null) { return 0.0f; }
|
||||
if (currentEffect.MaxScreenDistortStrength - currentEffect.MinScreenDistortStrength < 0.0f) { return 0.0f; }
|
||||
|
||||
return MathHelper.Lerp(
|
||||
currentEffect.MinScreenDistortStrength,
|
||||
@@ -117,10 +146,10 @@ namespace Barotrauma
|
||||
|
||||
public float GetRadialDistortStrength()
|
||||
{
|
||||
if (Strength < Prefab.ActivationThreshold) return 0.0f;
|
||||
if (Strength < Prefab.ActivationThreshold) { return 0.0f; }
|
||||
AfflictionPrefab.Effect currentEffect = Prefab.GetActiveEffect(Strength);
|
||||
if (currentEffect == null) return 0.0f;
|
||||
if (currentEffect.MaxRadialDistortStrength - currentEffect.MinRadialDistortStrength <= 0.0f) return 0.0f;
|
||||
if (currentEffect == null) { return 0.0f; }
|
||||
if (currentEffect.MaxRadialDistortStrength - currentEffect.MinRadialDistortStrength < 0.0f) { return 0.0f; }
|
||||
|
||||
return MathHelper.Lerp(
|
||||
currentEffect.MinRadialDistortStrength,
|
||||
@@ -130,10 +159,10 @@ namespace Barotrauma
|
||||
|
||||
public float GetChromaticAberrationStrength()
|
||||
{
|
||||
if (Strength < Prefab.ActivationThreshold) return 0.0f;
|
||||
if (Strength < Prefab.ActivationThreshold) { return 0.0f; }
|
||||
AfflictionPrefab.Effect currentEffect = Prefab.GetActiveEffect(Strength);
|
||||
if (currentEffect == null) return 0.0f;
|
||||
if (currentEffect.MaxChromaticAberrationStrength - currentEffect.MinChromaticAberrationStrength <= 0.0f) return 0.0f;
|
||||
if (currentEffect == null) { return 0.0f; }
|
||||
if (currentEffect.MaxChromaticAberrationStrength - currentEffect.MinChromaticAberrationStrength < 0.0f) { return 0.0f; }
|
||||
|
||||
return MathHelper.Lerp(
|
||||
currentEffect.MinChromaticAberrationStrength,
|
||||
@@ -143,10 +172,10 @@ namespace Barotrauma
|
||||
|
||||
public float GetScreenBlurStrength()
|
||||
{
|
||||
if (Strength < Prefab.ActivationThreshold) return 0.0f;
|
||||
if (Strength < Prefab.ActivationThreshold) { return 0.0f; }
|
||||
AfflictionPrefab.Effect currentEffect = Prefab.GetActiveEffect(Strength);
|
||||
if (currentEffect == null) return 0.0f;
|
||||
if (currentEffect.MaxScreenBlurStrength - currentEffect.MinScreenBlurStrength <= 0.0f) return 0.0f;
|
||||
if (currentEffect == null) { return 0.0f; }
|
||||
if (currentEffect.MaxScreenBlurStrength - currentEffect.MinScreenBlurStrength < 0.0f) { return 0.0f; }
|
||||
|
||||
return MathHelper.Lerp(
|
||||
currentEffect.MinScreenBlurStrength,
|
||||
@@ -154,6 +183,20 @@ namespace Barotrauma
|
||||
(Strength - currentEffect.MinStrength) / (currentEffect.MaxStrength - currentEffect.MinStrength));
|
||||
}
|
||||
|
||||
public float GetSkillMultiplier()
|
||||
{
|
||||
if (Strength < Prefab.ActivationThreshold) { return 1.0f; }
|
||||
AfflictionPrefab.Effect currentEffect = Prefab.GetActiveEffect(Strength);
|
||||
if (currentEffect == null) { return 1.0f; }
|
||||
|
||||
float amount = MathHelper.Lerp(
|
||||
currentEffect.MinSkillMultiplier,
|
||||
currentEffect.MaxSkillMultiplier,
|
||||
(Strength - currentEffect.MinStrength) / (currentEffect.MaxStrength - currentEffect.MinStrength));
|
||||
|
||||
return amount;
|
||||
}
|
||||
|
||||
public void CalculateDamagePerSecond(float currentVitalityDecrease)
|
||||
{
|
||||
DamagePerSecond = Math.Max(DamagePerSecond, currentVitalityDecrease - PreviousVitalityDecrease);
|
||||
@@ -232,6 +275,21 @@ namespace Barotrauma
|
||||
{
|
||||
ApplyStatusEffect(statusEffect, deltaTime, characterHealth, targetLimb);
|
||||
}
|
||||
|
||||
float amount = deltaTime;
|
||||
if (Prefab.GrainBurst > 0)
|
||||
{
|
||||
amount /= Prefab.GrainBurst;
|
||||
}
|
||||
if (PendingAdditionStrenght >= 0)
|
||||
{
|
||||
AdditionStrength += amount;
|
||||
PendingAdditionStrenght -= deltaTime;
|
||||
}
|
||||
else if (AdditionStrength > 0)
|
||||
{
|
||||
AdditionStrength -= amount;
|
||||
}
|
||||
}
|
||||
|
||||
public void ApplyStatusEffect(StatusEffect statusEffect, float deltaTime, CharacterHealth characterHealth, Limb targetLimb)
|
||||
@@ -254,16 +312,19 @@ namespace Barotrauma
|
||||
{
|
||||
var targets = new List<ISerializableEntity>();
|
||||
statusEffect.GetNearbyTargets(characterHealth.Character.WorldPosition, targets);
|
||||
statusEffect.Apply(ActionType.OnActive, deltaTime, targetLimb.character, targets);
|
||||
statusEffect.Apply(ActionType.OnActive, deltaTime, characterHealth.Character, targets);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use this method to skip clamping and additional logic of the setters.
|
||||
/// Intended only to be used when the value is already clamped! (networking code)
|
||||
/// Ideally we would keep this private, but doing so would require too much refactoring.
|
||||
/// </summary>
|
||||
public void SetStrength(float strength) => _strength = strength;
|
||||
public void SetStrength(float strength)
|
||||
{
|
||||
_nonClampedStrength = strength;
|
||||
_strength = _nonClampedStrength;
|
||||
}
|
||||
|
||||
public bool ShouldShowIcon(Character afflictedCharacter)
|
||||
{
|
||||
|
||||
+16
-9
@@ -102,7 +102,7 @@ namespace Barotrauma
|
||||
|
||||
private void ApplyDamage(float deltaTime, bool applyForce)
|
||||
{
|
||||
int limbCount = character.AnimController.Limbs.Count(l => !l.IgnoreCollisions && !l.IsSevered);
|
||||
int limbCount = character.AnimController.Limbs.Count(l => !l.IgnoreCollisions && !l.IsSevered && !l.Hidden);
|
||||
foreach (Limb limb in character.AnimController.Limbs)
|
||||
{
|
||||
if (limb.IsSevered) { continue; }
|
||||
@@ -148,10 +148,9 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public void Remove()
|
||||
public void UnsubscribeFromDeathEvent()
|
||||
{
|
||||
if (character == null) { return; }
|
||||
DeactivateHusk();
|
||||
if (character == null || !subscribedToDeathEvent) { return; }
|
||||
character.OnDeath -= CharacterDead;
|
||||
subscribedToDeathEvent = false;
|
||||
}
|
||||
@@ -159,7 +158,11 @@ namespace Barotrauma
|
||||
private void CharacterDead(Character character, CauseOfDeath causeOfDeath)
|
||||
{
|
||||
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) { return; }
|
||||
if (Strength < ActiveThreshold || character.Removed) { return; }
|
||||
if (Strength < ActiveThreshold || character.Removed)
|
||||
{
|
||||
UnsubscribeFromDeathEvent();
|
||||
return;
|
||||
}
|
||||
|
||||
//don't turn the character into a husk if any of its limbs are severed
|
||||
if (character.AnimController?.LimbJoints != null)
|
||||
@@ -170,18 +173,22 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
//character already in remove queue (being removed by something else, for example a modded affliction that uses AfflictionHusk as the base)
|
||||
// -> don't spawn the AI husk
|
||||
if (Entity.Spawner.IsInRemoveQueue(character)) { return; }
|
||||
|
||||
//create the AI husk in a coroutine to ensure that we don't modify the character list while enumerating it
|
||||
CoroutineManager.StartCoroutine(CreateAIHusk());
|
||||
}
|
||||
|
||||
private IEnumerable<object> CreateAIHusk()
|
||||
{
|
||||
//character already in remove queue (being removed by something else, for example a modded affliction that uses AfflictionHusk as the base)
|
||||
// -> don't spawn the AI husk
|
||||
if (Entity.Spawner.IsInRemoveQueue(character))
|
||||
{
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
character.Enabled = false;
|
||||
Entity.Spawner.AddToRemoveQueue(character);
|
||||
UnsubscribeFromDeathEvent();
|
||||
|
||||
string huskedSpeciesName = GetHuskedSpeciesName(character.SpeciesName, Prefab as AfflictionPrefabHusk);
|
||||
CharacterPrefab prefab = CharacterPrefab.FindBySpeciesName(huskedSpeciesName);
|
||||
|
||||
+58
-23
@@ -111,7 +111,7 @@ namespace Barotrauma
|
||||
public readonly bool NeedsAir;
|
||||
}
|
||||
|
||||
class AfflictionPrefab : IPrefab, IDisposable
|
||||
class AfflictionPrefab : IPrefab, IDisposable, IHasUintIdentifier
|
||||
{
|
||||
public class Effect
|
||||
{
|
||||
@@ -128,11 +128,14 @@ namespace Barotrauma
|
||||
|
||||
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;
|
||||
|
||||
public float MinSkillMultiplier, MaxSkillMultiplier;
|
||||
|
||||
public float MinResistance, MaxResistance;
|
||||
public string ResistanceFor;
|
||||
public string DialogFlag;
|
||||
@@ -163,10 +166,17 @@ namespace Barotrauma
|
||||
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);
|
||||
@@ -228,6 +238,7 @@ namespace Barotrauma
|
||||
public static AfflictionPrefab Bloodloss;
|
||||
public static AfflictionPrefab Pressure;
|
||||
public static AfflictionPrefab Stun;
|
||||
public static AfflictionPrefab RadiationSickness;
|
||||
|
||||
public static readonly PrefabCollection<AfflictionPrefab> Prefabs = new PrefabCollection<AfflictionPrefab>();
|
||||
|
||||
@@ -256,7 +267,7 @@ namespace Barotrauma
|
||||
/// Unique identifier that's generated by hashing the prefab's string identifier.
|
||||
/// Used to reduce the amount of bytes needed to write affliction data into network messages in multiplayer.
|
||||
/// </summary>
|
||||
public uint UIntIdentifier;
|
||||
public uint UIntIdentifier { get; set; }
|
||||
|
||||
// Arbitrary string that is used to identify the type of the affliction.
|
||||
public readonly string AfflictionType;
|
||||
@@ -273,6 +284,7 @@ namespace Barotrauma
|
||||
public ContentPackage ContentPackage { get; private set; }
|
||||
|
||||
public readonly string Name, Description;
|
||||
public readonly string TranslationOverride;
|
||||
public readonly bool IsBuff;
|
||||
|
||||
public readonly string CauseOfDeathDescription, SelfCauseOfDeathDescription;
|
||||
@@ -285,9 +297,14 @@ namespace Barotrauma
|
||||
public readonly float ShowIconToOthersThreshold = 0.05f;
|
||||
public readonly float MaxStrength = 100.0f;
|
||||
|
||||
public readonly float GrainBurst;
|
||||
|
||||
//how high the strength has to be for the affliction icon to be shown with a health scanner
|
||||
public readonly float ShowInHealthScannerThreshold = 0.05f;
|
||||
|
||||
//how strong the affliction needs to be before bots attempt to treat it
|
||||
public readonly float TreatmentThreshold = 5.0f;
|
||||
|
||||
//how much karma changes when a player applies this affliction to someone (per strength of the affliction)
|
||||
public float KarmaChangeOnApplied;
|
||||
|
||||
@@ -337,6 +354,7 @@ namespace Barotrauma
|
||||
Bloodloss = null;
|
||||
Pressure = null;
|
||||
Stun = null;
|
||||
RadiationSickness = null;
|
||||
#if CLIENT
|
||||
CharacterHealth.DamageOverlay?.Remove();
|
||||
CharacterHealth.DamageOverlay = null;
|
||||
@@ -361,6 +379,7 @@ namespace Barotrauma
|
||||
if (Bloodloss == null) { DebugConsole.ThrowError("Affliction \"Bloodloss\" not defined in the affliction prefabs."); }
|
||||
if (Pressure == null) { DebugConsole.ThrowError("Affliction \"Pressure\" not defined in the affliction prefabs."); }
|
||||
if (Stun == null) { DebugConsole.ThrowError("Affliction \"Stun\" not defined in the affliction prefabs."); }
|
||||
if (RadiationSickness == null) { DebugConsole.ThrowError("Affliction \"RadiationSickness\" not defined in the affliction prefabs."); }
|
||||
}
|
||||
|
||||
public static void LoadFromFile(ContentFile file)
|
||||
@@ -372,6 +391,9 @@ namespace Barotrauma
|
||||
{
|
||||
DebugConsole.ThrowError("Cannot override all afflictions, because many of them are required by the main game! Please try overriding them one by one.");
|
||||
}
|
||||
|
||||
List<(AfflictionPrefab prefab, XElement element)> loadedAfflictions = new List<(AfflictionPrefab prefab, XElement element)>();
|
||||
|
||||
foreach (XElement element in mainElement.Elements())
|
||||
{
|
||||
bool isOverride = element.IsOverride();
|
||||
@@ -436,6 +458,7 @@ namespace Barotrauma
|
||||
prefab = new AfflictionPrefab(sourceElement, file.Path, typeof(AfflictionBleeding));
|
||||
break;
|
||||
case "huskinfection":
|
||||
case "alieninfection":
|
||||
prefab = new AfflictionPrefabHusk(sourceElement, file.Path, typeof(AfflictionHusk));
|
||||
break;
|
||||
case "cprsettings":
|
||||
@@ -498,27 +521,25 @@ namespace Barotrauma
|
||||
case "stun":
|
||||
Stun = prefab;
|
||||
break;
|
||||
case "radiationsickness":
|
||||
RadiationSickness = prefab;
|
||||
break;
|
||||
}
|
||||
if (ImpactDamage == null) { ImpactDamage = InternalDamage; }
|
||||
|
||||
if (prefab != null)
|
||||
{
|
||||
loadedAfflictions.Add((prefab, sourceElement));
|
||||
Prefabs.Add(prefab, isOverride);
|
||||
prefab.CalculatePrefabUIntIdentifier(Prefabs);
|
||||
}
|
||||
}
|
||||
|
||||
using MD5 md5 = MD5.Create();
|
||||
foreach (AfflictionPrefab prefab in Prefabs)
|
||||
//load the effects after all the afflictions in the file have been instantiated
|
||||
//otherwise afflictions can't inflict other afflictions that are defined at a later point in the file
|
||||
foreach ((AfflictionPrefab prefab, XElement element) in loadedAfflictions)
|
||||
{
|
||||
prefab.UIntIdentifier = ToolBox.StringToUInt32Hash(prefab.Identifier, md5);
|
||||
|
||||
//it's theoretically possible for two different values to generate the same hash, but the probability is astronomically small
|
||||
var collision = Prefabs.Find(p => p != prefab && p.UIntIdentifier == prefab.UIntIdentifier);
|
||||
if (collision != null)
|
||||
{
|
||||
DebugConsole.ThrowError("Hashing collision when generating uint identifiers for Afflictions: " + prefab.Identifier + " has the same identifier as " + collision.Identifier + " (" + prefab.UIntIdentifier + ")");
|
||||
collision.UIntIdentifier++;
|
||||
}
|
||||
prefab.LoadEffects(element);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -549,8 +570,10 @@ namespace Barotrauma
|
||||
Identifier = element.GetAttributeString("identifier", "");
|
||||
|
||||
AfflictionType = element.GetAttributeString("type", "");
|
||||
Name = TextManager.Get("AfflictionName." + Identifier, true) ?? element.GetAttributeString("name", "");
|
||||
Description = TextManager.Get("AfflictionDescription." + Identifier, true) ?? element.GetAttributeString("description", "");
|
||||
TranslationOverride = element.GetAttributeString("translationoverride", null);
|
||||
string translationId = TranslationOverride ?? Identifier;
|
||||
Name = TextManager.Get("AfflictionName." + translationId, true) ?? element.GetAttributeString("name", "");
|
||||
Description = TextManager.Get("AfflictionDescription." + translationId, true) ?? element.GetAttributeString("description", "");
|
||||
IsBuff = element.GetAttributeBool("isbuff", false);
|
||||
|
||||
LimbSpecific = element.GetAttributeBool("limbspecific", false);
|
||||
@@ -567,16 +590,18 @@ 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);
|
||||
|
||||
ShowInHealthScannerThreshold = element.GetAttributeFloat("showinhealthscannerthreshold", Math.Max(ActivationThreshold, 0.05f));
|
||||
TreatmentThreshold = element.GetAttributeFloat("treatmentthreshold", Math.Max(ActivationThreshold, 5.0f));
|
||||
|
||||
DamageOverlayAlpha = element.GetAttributeFloat("damageoverlayalpha", 0.0f);
|
||||
BurnOverlayAlpha = element.GetAttributeFloat("burnoverlayalpha", 0.0f);
|
||||
|
||||
KarmaChangeOnApplied = element.GetAttributeFloat("karmachangeonapplied", 0.0f);
|
||||
|
||||
CauseOfDeathDescription = TextManager.Get("AfflictionCauseOfDeath." + Identifier, true) ?? element.GetAttributeString("causeofdeathdescription", "");
|
||||
SelfCauseOfDeathDescription = TextManager.Get("AfflictionCauseOfDeathSelf." + Identifier, true) ?? element.GetAttributeString("selfcauseofdeathdescription", "");
|
||||
CauseOfDeathDescription = TextManager.Get("AfflictionCauseOfDeath." + translationId, true) ?? element.GetAttributeString("causeofdeathdescription", "");
|
||||
SelfCauseOfDeathDescription = TextManager.Get("AfflictionCauseOfDeathSelf." + translationId, true) ?? element.GetAttributeString("selfcauseofdeathdescription", "");
|
||||
|
||||
IconColors = element.GetAttributeColorArray("iconcolors", null);
|
||||
AchievementOnRemoved = element.GetAttributeString("achievementonremoved", "");
|
||||
@@ -588,12 +613,6 @@ namespace Barotrauma
|
||||
case "icon":
|
||||
Icon = new Sprite(subElement);
|
||||
break;
|
||||
case "effect":
|
||||
effects.Add(new Effect(subElement, Name));
|
||||
break;
|
||||
case "periodiceffect":
|
||||
periodicEffects.Add(new PeriodicEffect(subElement, Name));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -618,6 +637,22 @@ namespace Barotrauma
|
||||
constructor = type.GetConstructor(new[] { typeof(AfflictionPrefab), typeof(float) });
|
||||
}
|
||||
|
||||
private void LoadEffects(XElement element)
|
||||
{
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
{
|
||||
case "effect":
|
||||
effects.Add(new Effect(subElement, Name));
|
||||
break;
|
||||
case "periodiceffect":
|
||||
periodicEffects.Add(new PeriodicEffect(subElement, Name));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "AfflictionPrefab (" + Name + ")";
|
||||
|
||||
@@ -36,7 +36,11 @@ namespace Barotrauma
|
||||
|
||||
public LimbHealth(XElement element, CharacterHealth characterHealth)
|
||||
{
|
||||
Name = TextManager.Get("HealthLimbName." + element.GetAttributeString("name", ""));
|
||||
string limbName = element.GetAttributeString("name", null) ?? "generic";
|
||||
if (limbName != "generic")
|
||||
{
|
||||
Name = TextManager.Get("HealthLimbName." + limbName);
|
||||
}
|
||||
this.characterHealth = characterHealth;
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
@@ -186,12 +190,14 @@ namespace Barotrauma
|
||||
set { bloodlossAffliction.Strength = MathHelper.Clamp(value, 0.0f, 100.0f); }
|
||||
}
|
||||
|
||||
public float StunTimer
|
||||
public float Stun
|
||||
{
|
||||
get { return stunAffliction.Strength; }
|
||||
set { stunAffliction.Strength = MathHelper.Clamp(value, 0.0f, stunAffliction.Prefab.MaxStrength); }
|
||||
}
|
||||
|
||||
public float StunTimer { get; private set; }
|
||||
|
||||
public Affliction PressureAffliction
|
||||
{
|
||||
get { return pressureAffliction; }
|
||||
@@ -484,7 +490,7 @@ namespace Barotrauma
|
||||
CalculateVitality();
|
||||
}
|
||||
|
||||
public void ApplyDamage(Limb hitLimb, AttackResult attackResult)
|
||||
public void ApplyDamage(Limb hitLimb, AttackResult attackResult, bool allowStacking = true)
|
||||
{
|
||||
if (Unkillable || Character.GodMode) { return; }
|
||||
if (hitLimb.HealthIndex < 0 || hitLimb.HealthIndex >= limbHealths.Count)
|
||||
@@ -498,11 +504,11 @@ namespace Barotrauma
|
||||
{
|
||||
if (newAffliction.Prefab.LimbSpecific)
|
||||
{
|
||||
AddLimbAffliction(hitLimb, newAffliction);
|
||||
AddLimbAffliction(hitLimb, newAffliction, allowStacking);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddAffliction(newAffliction);
|
||||
AddAffliction(newAffliction, allowStacking);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -569,7 +575,7 @@ namespace Barotrauma
|
||||
CalculateVitality();
|
||||
}
|
||||
|
||||
private void AddLimbAffliction(Limb limb, Affliction newAffliction)
|
||||
private void AddLimbAffliction(Limb limb, Affliction newAffliction, bool allowStacking = true)
|
||||
{
|
||||
if (!newAffliction.Prefab.LimbSpecific || limb == null) { return; }
|
||||
if (limb.HealthIndex < 0 || limb.HealthIndex >= limbHealths.Count)
|
||||
@@ -578,10 +584,10 @@ namespace Barotrauma
|
||||
"\" only has health configured for" + limbHealths.Count + " limbs but the limb " + limb.type + " is targeting index " + limb.HealthIndex);
|
||||
return;
|
||||
}
|
||||
AddLimbAffliction(limbHealths[limb.HealthIndex], newAffliction);
|
||||
AddLimbAffliction(limbHealths[limb.HealthIndex], newAffliction, allowStacking);
|
||||
}
|
||||
|
||||
private void AddLimbAffliction(LimbHealth limbHealth, Affliction newAffliction)
|
||||
private void AddLimbAffliction(LimbHealth limbHealth, Affliction newAffliction, bool allowStacking = true)
|
||||
{
|
||||
if (!DoesBleed && newAffliction is AfflictionBleeding) { return; }
|
||||
if (!Character.NeedsOxygen && newAffliction.Prefab == AfflictionPrefab.OxygenLow) { return; }
|
||||
@@ -590,7 +596,15 @@ namespace Barotrauma
|
||||
{
|
||||
if (newAffliction.Prefab == affliction.Prefab)
|
||||
{
|
||||
affliction.Strength = Math.Min(affliction.Prefab.MaxStrength, affliction.Strength + (newAffliction.Strength * (100.0f / MaxVitality) * (1f - GetResistance(affliction.Prefab.Identifier))));
|
||||
float newStrength = newAffliction.Strength * (100.0f / MaxVitality) * (1f - GetResistance(affliction.Prefab.Identifier));
|
||||
if (allowStacking)
|
||||
{
|
||||
// Add the existing strength
|
||||
newStrength += affliction.Strength;
|
||||
}
|
||||
newStrength = Math.Min(affliction.Prefab.MaxStrength, newStrength);
|
||||
if (affliction == stunAffliction) { Character.SetStun(newStrength, true, true); }
|
||||
affliction.Strength = newStrength;
|
||||
affliction.Source = newAffliction.Source;
|
||||
CalculateVitality();
|
||||
if (Vitality <= MinVitality)
|
||||
@@ -620,13 +634,12 @@ namespace Barotrauma
|
||||
#endif
|
||||
}
|
||||
|
||||
private void AddAffliction(Affliction newAffliction)
|
||||
private void AddAffliction(Affliction newAffliction, bool allowStacking = true)
|
||||
{
|
||||
if (!DoesBleed && newAffliction is AfflictionBleeding) { return; }
|
||||
if (!Character.NeedsOxygen && newAffliction.Prefab == AfflictionPrefab.OxygenLow) { return; }
|
||||
if (newAffliction.Prefab.AfflictionType == "huskinfection")
|
||||
if (newAffliction.Prefab is AfflictionPrefabHusk huskPrefab)
|
||||
{
|
||||
var huskPrefab = newAffliction.Prefab as AfflictionPrefabHusk;
|
||||
if (huskPrefab.TargetSpecies.None(s => s.Equals(Character.SpeciesName, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
return;
|
||||
@@ -636,7 +649,13 @@ namespace Barotrauma
|
||||
{
|
||||
if (newAffliction.Prefab == affliction.Prefab)
|
||||
{
|
||||
float newStrength = Math.Min(affliction.Prefab.MaxStrength, affliction.Strength + (newAffliction.Strength * (100.0f / MaxVitality) * (1f - GetResistance(affliction.Prefab.Identifier))));
|
||||
float newStrength = newAffliction.Strength * (100.0f / MaxVitality) * (1f - GetResistance(affliction.Prefab.Identifier));
|
||||
if (allowStacking)
|
||||
{
|
||||
// Add the existing strength
|
||||
newStrength += affliction.Strength;
|
||||
}
|
||||
newStrength = Math.Min(affliction.Prefab.MaxStrength, newStrength);
|
||||
if (affliction == stunAffliction) { Character.SetStun(newStrength, true, true); }
|
||||
affliction.Strength = newStrength;
|
||||
affliction.Source = newAffliction.Source;
|
||||
@@ -664,7 +683,6 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
partial void UpdateProjSpecific(float deltaTime);
|
||||
|
||||
partial void UpdateLimbAfflictionOverlays();
|
||||
@@ -673,6 +691,8 @@ namespace Barotrauma
|
||||
{
|
||||
UpdateOxygen(deltaTime);
|
||||
|
||||
StunTimer = Stun > 0 ? StunTimer + deltaTime : 0;
|
||||
|
||||
for (int i = 0; i < limbHealths.Count; i++)
|
||||
{
|
||||
for (int j = limbHealths[i].Afflictions.Count - 1; j >= 0; j--)
|
||||
@@ -686,12 +706,16 @@ namespace Barotrauma
|
||||
for (int j = limbHealths[i].Afflictions.Count - 1; j >= 0; j--)
|
||||
{
|
||||
var affliction = limbHealths[i].Afflictions[j];
|
||||
Limb targetLimb = Character.AnimController.Limbs.FirstOrDefault(l => l.HealthIndex == i);
|
||||
Limb targetLimb = Character.AnimController.Limbs.LastOrDefault(l => !l.IsSevered && !l.Hidden && l.HealthIndex == i);
|
||||
if (targetLimb == null)
|
||||
{
|
||||
targetLimb = Character.AnimController.MainLimb;
|
||||
}
|
||||
affliction.Update(this, targetLimb, deltaTime);
|
||||
affliction.DamagePerSecondTimer += deltaTime;
|
||||
if (affliction is AfflictionBleeding)
|
||||
if (affliction is AfflictionBleeding bleeding)
|
||||
{
|
||||
UpdateBleedingProjSpecific((AfflictionBleeding)affliction, targetLimb, deltaTime);
|
||||
UpdateBleedingProjSpecific(bleeding, targetLimb, deltaTime);
|
||||
}
|
||||
Character.StackSpeedMultiplier(affliction.GetSpeedMultiplier());
|
||||
}
|
||||
@@ -788,6 +812,13 @@ namespace Barotrauma
|
||||
Vitality -= vitalityDecrease;
|
||||
affliction.CalculateDamagePerSecond(vitalityDecrease);
|
||||
}
|
||||
|
||||
#if CLIENT
|
||||
if (IsUnconscious)
|
||||
{
|
||||
HintManager.OnCharacterUnconscious(Character);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
private void Kill()
|
||||
@@ -877,6 +908,7 @@ namespace Barotrauma
|
||||
float minSuitability = -10, maxSuitability = 10;
|
||||
foreach (Affliction affliction in GetAllAfflictions())
|
||||
{
|
||||
if (affliction.Strength < affliction.Prefab.TreatmentThreshold) { continue; }
|
||||
foreach (KeyValuePair<string, float> treatment in affliction.Prefab.TreatmentSuitability)
|
||||
{
|
||||
if (!treatmentSuitability.ContainsKey(treatment.Key))
|
||||
|
||||
Reference in New Issue
Block a user