v0.10.5.1
This commit is contained in:
+81
-28
@@ -15,13 +15,24 @@ namespace Barotrauma
|
||||
public Dictionary<string, SerializableProperty> SerializableProperties { get; set; }
|
||||
|
||||
protected float _strength;
|
||||
|
||||
[Serialize(0f, true), Editable]
|
||||
public virtual float Strength
|
||||
{
|
||||
get { return _strength; }
|
||||
set { _strength = MathHelper.Clamp(value, 0.0f, Prefab.MaxStrength); }
|
||||
set
|
||||
{
|
||||
if (_nonClampedStrength < 0 && value > 0)
|
||||
{
|
||||
_nonClampedStrength = value;
|
||||
}
|
||||
_strength = MathHelper.Clamp(value, 0.0f, Prefab.MaxStrength);
|
||||
}
|
||||
}
|
||||
|
||||
private float _nonClampedStrength = -1;
|
||||
public float NonClampedStrength => _nonClampedStrength > 0 ? _nonClampedStrength : _strength;
|
||||
|
||||
[Serialize("", true), Editable]
|
||||
public string Identifier { get; private set; }
|
||||
|
||||
@@ -35,6 +46,8 @@ namespace Barotrauma
|
||||
public float StrengthDiminishMultiplier = 1.0f;
|
||||
public Affliction MultiplierSource;
|
||||
|
||||
public readonly Dictionary<AfflictionPrefab.PeriodicEffect, float> PeriodicEffectTimers = new Dictionary<AfflictionPrefab.PeriodicEffect, float>();
|
||||
|
||||
/// <summary>
|
||||
/// Which character gave this affliction
|
||||
/// </summary>
|
||||
@@ -45,6 +58,11 @@ namespace Barotrauma
|
||||
Prefab = prefab;
|
||||
_strength = strength;
|
||||
Identifier = prefab?.Identifier;
|
||||
|
||||
foreach (var periodicEffect in prefab.PeriodicEffects)
|
||||
{
|
||||
PeriodicEffectTimers[periodicEffect] = Rand.Range(periodicEffect.MinInterval, periodicEffect.MaxInterval);
|
||||
}
|
||||
}
|
||||
|
||||
public void Serialize(XElement element)
|
||||
@@ -59,24 +77,27 @@ namespace Barotrauma
|
||||
|
||||
public Affliction CreateMultiplied(float multiplier)
|
||||
{
|
||||
return Prefab.Instantiate(Strength * multiplier, Source);
|
||||
return Prefab.Instantiate(NonClampedStrength * multiplier, Source);
|
||||
}
|
||||
|
||||
public override string ToString() => Prefab == null ? "Affliction (Invalid)" : $"Affliction ({Prefab.Name})";
|
||||
|
||||
public float GetVitalityDecrease(CharacterHealth characterHealth)
|
||||
{
|
||||
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.MaxStrength - currentEffect.MinStrength <= 0.0f) return 0.0f;
|
||||
if (currentEffect == null) { return 0.0f; }
|
||||
if (currentEffect.MaxStrength - currentEffect.MinStrength <= 0.0f) { return 0.0f; }
|
||||
|
||||
float currVitalityDecrease = MathHelper.Lerp(
|
||||
currentEffect.MinVitalityDecrease,
|
||||
currentEffect.MaxVitalityDecrease,
|
||||
(Strength - currentEffect.MinStrength) / (currentEffect.MaxStrength - currentEffect.MinStrength));
|
||||
|
||||
if (currentEffect.MultiplyByMaxVitality) currVitalityDecrease *= characterHealth == null ? 100.0f : characterHealth.MaxVitality;
|
||||
if (currentEffect.MultiplyByMaxVitality)
|
||||
{
|
||||
currVitalityDecrease *= characterHealth == null ? 100.0f : characterHealth.MaxVitality;
|
||||
}
|
||||
|
||||
return currVitalityDecrease;
|
||||
}
|
||||
@@ -173,8 +194,28 @@ namespace Barotrauma
|
||||
|
||||
public virtual void Update(CharacterHealth characterHealth, Limb targetLimb, float deltaTime)
|
||||
{
|
||||
foreach (AfflictionPrefab.PeriodicEffect periodicEffect in Prefab.PeriodicEffects)
|
||||
{
|
||||
PeriodicEffectTimers[periodicEffect] -= deltaTime;
|
||||
if (PeriodicEffectTimers[periodicEffect] <= 0.0f)
|
||||
{
|
||||
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient)
|
||||
{
|
||||
PeriodicEffectTimers[periodicEffect] = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (StatusEffect statusEffect in periodicEffect.StatusEffects)
|
||||
{
|
||||
ApplyStatusEffect(statusEffect, 1.0f, characterHealth, targetLimb);
|
||||
PeriodicEffectTimers[periodicEffect] = Rand.Range(periodicEffect.MinInterval, periodicEffect.MaxInterval);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AfflictionPrefab.Effect currentEffect = Prefab.GetActiveEffect(Strength);
|
||||
if (currentEffect == null) return;
|
||||
if (currentEffect == null) { return; }
|
||||
|
||||
if (currentEffect.StrengthChange < 0) // Reduce diminishing of buffs if boosted
|
||||
{
|
||||
@@ -184,32 +225,44 @@ namespace Barotrauma
|
||||
{
|
||||
_strength += currentEffect.StrengthChange * deltaTime * (1f - characterHealth.GetResistance(Prefab.Identifier));
|
||||
}
|
||||
// Don't use the property, because its virtual and some afflictions like husk overload it for external use.
|
||||
// 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);
|
||||
|
||||
foreach (StatusEffect statusEffect in currentEffect.StatusEffects)
|
||||
{
|
||||
statusEffect.SetUser(Source);
|
||||
if (statusEffect.HasTargetType(StatusEffect.TargetType.Character))
|
||||
{
|
||||
statusEffect.Apply(ActionType.OnActive, deltaTime, characterHealth.Character, characterHealth.Character);
|
||||
}
|
||||
if (targetLimb != null && statusEffect.HasTargetType(StatusEffect.TargetType.Limb))
|
||||
{
|
||||
statusEffect.Apply(ActionType.OnActive, deltaTime, characterHealth.Character, targetLimb);
|
||||
}
|
||||
if (targetLimb != null && statusEffect.HasTargetType(StatusEffect.TargetType.AllLimbs))
|
||||
{
|
||||
statusEffect.Apply(ActionType.OnActive, deltaTime, targetLimb.character, targetLimb.character.AnimController.Limbs.Cast<ISerializableEntity>().ToList());
|
||||
}
|
||||
if (statusEffect.HasTargetType(StatusEffect.TargetType.NearbyItems) ||
|
||||
statusEffect.HasTargetType(StatusEffect.TargetType.NearbyCharacters))
|
||||
{
|
||||
var targets = new List<ISerializableEntity>();
|
||||
statusEffect.GetNearbyTargets(characterHealth.Character.WorldPosition, targets);
|
||||
statusEffect.Apply(ActionType.OnActive, deltaTime, targetLimb.character, targets);
|
||||
}
|
||||
ApplyStatusEffect(statusEffect, deltaTime, characterHealth, targetLimb);
|
||||
}
|
||||
}
|
||||
|
||||
public void ApplyStatusEffect(StatusEffect statusEffect, float deltaTime, CharacterHealth characterHealth, Limb targetLimb)
|
||||
{
|
||||
statusEffect.SetUser(Source);
|
||||
if (statusEffect.HasTargetType(StatusEffect.TargetType.Character))
|
||||
{
|
||||
statusEffect.Apply(ActionType.OnActive, deltaTime, characterHealth.Character, characterHealth.Character);
|
||||
}
|
||||
if (targetLimb != null && statusEffect.HasTargetType(StatusEffect.TargetType.Limb))
|
||||
{
|
||||
statusEffect.Apply(ActionType.OnActive, deltaTime, characterHealth.Character, targetLimb);
|
||||
}
|
||||
if (targetLimb != null && statusEffect.HasTargetType(StatusEffect.TargetType.AllLimbs))
|
||||
{
|
||||
statusEffect.Apply(ActionType.OnActive, deltaTime, targetLimb.character, targetLimb.character.AnimController.Limbs.Cast<ISerializableEntity>().ToList());
|
||||
}
|
||||
if (statusEffect.HasTargetType(StatusEffect.TargetType.NearbyItems) ||
|
||||
statusEffect.HasTargetType(StatusEffect.TargetType.NearbyCharacters))
|
||||
{
|
||||
var targets = new List<ISerializableEntity>();
|
||||
statusEffect.GetNearbyTargets(characterHealth.Character.WorldPosition, targets);
|
||||
statusEffect.Apply(ActionType.OnActive, deltaTime, targetLimb.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;
|
||||
}
|
||||
}
|
||||
|
||||
+5
-4
@@ -29,8 +29,9 @@ namespace Barotrauma
|
||||
set
|
||||
{
|
||||
// Don't allow to set the strength too high (from outside) to avoid rapid transformation into husk when taking lots of damage from husks.
|
||||
// If the strength is more than the value, this will effectively reset the current strength to the max. That's why we use two steps.
|
||||
float max = _strength > ActiveThreshold ? ActiveThreshold + 1 : DormantThreshold - 1;
|
||||
float previousValue = _strength;
|
||||
float threshold = _strength > ActiveThreshold ? ActiveThreshold + 1 : DormantThreshold - 1;
|
||||
float max = Math.Max(threshold, previousValue);
|
||||
_strength = Math.Clamp(value, 0, max);
|
||||
}
|
||||
}
|
||||
@@ -79,7 +80,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (State != InfectionState.Active)
|
||||
{
|
||||
character.SetStun(Rand.Range(2, 4, Rand.RandSync.Server));
|
||||
character.SetStun(Rand.Range(2, 4));
|
||||
}
|
||||
State = InfectionState.Active;
|
||||
ActivateHusk();
|
||||
@@ -101,7 +102,7 @@ namespace Barotrauma
|
||||
foreach (Limb limb in character.AnimController.Limbs)
|
||||
{
|
||||
if (limb.IsSevered) { continue; }
|
||||
float random = Rand.Value(Rand.RandSync.Server);
|
||||
float random = Rand.Value();
|
||||
huskInfection.Clear();
|
||||
huskInfection.Add(AfflictionPrefab.InternalDamage.Instantiate(random * 10 * deltaTime / limbCount));
|
||||
character.LastDamageSource = null;
|
||||
|
||||
+35
-4
@@ -68,13 +68,13 @@ namespace Barotrauma
|
||||
HuskedSpeciesName = element.GetAttributeString("huskedspeciesname", null).ToLowerInvariant();
|
||||
if (HuskedSpeciesName == null)
|
||||
{
|
||||
DebugConsole.NewMessage($"No 'huskedspeciesname' defined for the husk affliction ({Identifier}) in {element.ToString()}", Color.Orange);
|
||||
DebugConsole.NewMessage($"No 'huskedspeciesname' defined for the husk affliction ({Identifier}) in {element}", Color.Orange);
|
||||
HuskedSpeciesName = "[speciesname]husk";
|
||||
}
|
||||
TargetSpecies = element.GetAttributeStringArray("targets", new string[0] { }, trim: true, convertToLowerInvariant: true);
|
||||
if (TargetSpecies.Length == 0)
|
||||
{
|
||||
DebugConsole.NewMessage($"No 'targets' defined for the husk affliction ({Identifier}) in {element.ToString()}", Color.Orange);
|
||||
DebugConsole.NewMessage($"No 'targets' defined for the husk affliction ({Identifier}) in {element}", Color.Orange);
|
||||
TargetSpecies = new string[] { "human" };
|
||||
}
|
||||
var attachElement = element.GetChildElement("attachlimb");
|
||||
@@ -188,6 +188,30 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public class PeriodicEffect
|
||||
{
|
||||
public readonly List<StatusEffect> StatusEffects = new List<StatusEffect>();
|
||||
public readonly float MinInterval, MaxInterval;
|
||||
|
||||
public PeriodicEffect(XElement element, string parentDebugName)
|
||||
{
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
StatusEffects.Add(StatusEffect.Load(subElement, parentDebugName));
|
||||
}
|
||||
|
||||
if (element.Attribute("interval") != null)
|
||||
{
|
||||
MinInterval = MaxInterval = Math.Max(element.GetAttributeFloat("interval", 1.0f), 1.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
MinInterval = Math.Max(element.GetAttributeFloat("mininterval", 1.0f), 1.0f);
|
||||
MaxInterval = Math.Max(element.GetAttributeFloat("maxinterval", 1.0f), MinInterval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static AfflictionPrefab InternalDamage;
|
||||
public static AfflictionPrefab ImpactDamage;
|
||||
public static AfflictionPrefab Bleeding;
|
||||
@@ -267,8 +291,12 @@ namespace Barotrauma
|
||||
public readonly Color[] IconColors;
|
||||
|
||||
private readonly List<Effect> effects = new List<Effect>();
|
||||
private readonly List<PeriodicEffect> periodicEffects = new List<PeriodicEffect>();
|
||||
|
||||
public IEnumerable<Effect> Effects => effects;
|
||||
|
||||
public IList<PeriodicEffect> PeriodicEffects => periodicEffects;
|
||||
|
||||
private readonly string typeName;
|
||||
|
||||
private readonly ConstructorInfo constructor;
|
||||
@@ -304,10 +332,10 @@ namespace Barotrauma
|
||||
CharacterHealth.DamageOverlay = null;
|
||||
CharacterHealth.DamageOverlayFile = string.Empty;
|
||||
#endif
|
||||
var prevPrefabs = Prefabs.ToList();
|
||||
var prevPrefabs = Prefabs.AllPrefabs.SelectMany(kvp => kvp.Value).ToList();
|
||||
foreach (var prefab in prevPrefabs)
|
||||
{
|
||||
prefab.Dispose();
|
||||
prefab?.Dispose();
|
||||
}
|
||||
System.Diagnostics.Debug.Assert(Prefabs.Count() == 0, "All previous AfflictionPrefabs were not removed in AfflictionPrefab.LoadAll");
|
||||
|
||||
@@ -552,6 +580,9 @@ namespace Barotrauma
|
||||
case "effect":
|
||||
effects.Add(new Effect(subElement, Name));
|
||||
break;
|
||||
case "periodiceffect":
|
||||
periodicEffects.Add(new PeriodicEffect(subElement, Name));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -170,12 +170,12 @@ namespace Barotrauma
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!Character.NeedsOxygen || Unkillable) { return 100.0f; }
|
||||
if (!Character.NeedsOxygen || Unkillable || Character.GodMode) { return 100.0f; }
|
||||
return -oxygenLowAffliction.Strength + 100;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (!Character.NeedsOxygen || Unkillable) { return; }
|
||||
if (!Character.NeedsOxygen || Unkillable || Character.GodMode) { return; }
|
||||
oxygenLowAffliction.Strength = MathHelper.Clamp(-value + 100, 0.0f, 200.0f);
|
||||
}
|
||||
}
|
||||
@@ -399,7 +399,7 @@ namespace Barotrauma
|
||||
|
||||
public void ApplyAffliction(Limb targetLimb, Affliction affliction)
|
||||
{
|
||||
if (Unkillable) { return; }
|
||||
if (Unkillable || Character.GodMode) { return; }
|
||||
if (affliction.Prefab.LimbSpecific)
|
||||
{
|
||||
if (targetLimb == null)
|
||||
@@ -481,7 +481,7 @@ namespace Barotrauma
|
||||
|
||||
public void ApplyDamage(Limb hitLimb, AttackResult attackResult)
|
||||
{
|
||||
if (Unkillable) { return; }
|
||||
if (Unkillable || Character.GodMode) { return; }
|
||||
if (hitLimb.HealthIndex < 0 || hitLimb.HealthIndex >= limbHealths.Count)
|
||||
{
|
||||
DebugConsole.ThrowError("Limb health index out of bounds. Character\"" + Character.Name +
|
||||
@@ -504,7 +504,7 @@ namespace Barotrauma
|
||||
|
||||
public void SetAllDamage(float damageAmount, float bleedingDamageAmount, float burnDamageAmount)
|
||||
{
|
||||
if (Unkillable) { return; }
|
||||
if (Unkillable || Character.GodMode) { return; }
|
||||
foreach (LimbHealth limbHealth in limbHealths)
|
||||
{
|
||||
limbHealth.Afflictions.RemoveAll(a =>
|
||||
@@ -741,7 +741,7 @@ namespace Barotrauma
|
||||
public void CalculateVitality()
|
||||
{
|
||||
Vitality = MaxVitality;
|
||||
if (Unkillable) { return; }
|
||||
if (Unkillable || Character.GodMode) { return; }
|
||||
|
||||
float damageResistanceMultiplier = 1f - GetResistance("damage");
|
||||
|
||||
@@ -777,7 +777,7 @@ namespace Barotrauma
|
||||
|
||||
private void Kill()
|
||||
{
|
||||
if (Unkillable) { return; }
|
||||
if (Unkillable || Character.GodMode) { return; }
|
||||
|
||||
var causeOfDeath = GetCauseOfDeath();
|
||||
Character.Kill(causeOfDeath.First, causeOfDeath.Second);
|
||||
@@ -913,6 +913,11 @@ namespace Barotrauma
|
||||
msg.WriteRangedSingle(
|
||||
MathHelper.Clamp(affliction.Strength, 0.0f, affliction.Prefab.MaxStrength),
|
||||
0.0f, affliction.Prefab.MaxStrength, 8);
|
||||
msg.Write((byte)affliction.Prefab.PeriodicEffects.Count());
|
||||
foreach (AfflictionPrefab.PeriodicEffect periodicEffect in affliction.Prefab.PeriodicEffects)
|
||||
{
|
||||
msg.WriteRangedSingle(affliction.PeriodicEffectTimers[periodicEffect], periodicEffect.MinInterval, periodicEffect.MaxInterval, 8);
|
||||
}
|
||||
}
|
||||
|
||||
limbAfflictions.Clear();
|
||||
@@ -933,6 +938,11 @@ namespace Barotrauma
|
||||
msg.WriteRangedSingle(
|
||||
MathHelper.Clamp(limbAffliction.Second.Strength, 0.0f, limbAffliction.Second.Prefab.MaxStrength),
|
||||
0.0f, limbAffliction.Second.Prefab.MaxStrength, 8);
|
||||
msg.Write((byte)limbAffliction.Second.Prefab.PeriodicEffects.Count());
|
||||
foreach (AfflictionPrefab.PeriodicEffect periodicEffect in limbAffliction.Second.Prefab.PeriodicEffects)
|
||||
{
|
||||
msg.WriteRangedSingle(limbAffliction.Second.PeriodicEffectTimers[periodicEffect], periodicEffect.MinInterval, periodicEffect.MaxInterval, 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user