Merge remote-tracking branch 'upstream/master' into develop
This commit is contained in:
+8
-3
@@ -68,7 +68,7 @@ namespace Barotrauma
|
||||
public bool DivideByLimbCount { get; set; }
|
||||
|
||||
[Serialize(false, IsPropertySaveable.Yes, description: "Is the damage relative to the max vitality (percentage) or absolute (normal)"), Editable]
|
||||
public bool MultiplyByMaxVitality { get; private set; }
|
||||
public bool MultiplyByMaxVitality { get; set; }
|
||||
|
||||
public float DamagePerSecond;
|
||||
public float DamagePerSecondTimer;
|
||||
@@ -130,11 +130,16 @@ namespace Barotrauma
|
||||
public void Deserialize(XElement element)
|
||||
{
|
||||
SerializableProperties = SerializableProperty.DeserializeProperties(this, element);
|
||||
//backwards compatibility
|
||||
if (element.GetAttribute("amount") != null && element.GetAttribute("strength") == null)
|
||||
{
|
||||
Strength = element.GetAttributeFloat("amount", 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
public Affliction CreateMultiplied(float multiplier, Affliction affliction)
|
||||
{
|
||||
var instance = Prefab.Instantiate(NonClampedStrength * multiplier, Source);
|
||||
Affliction instance = Prefab.Instantiate(NonClampedStrength * multiplier, Source);
|
||||
instance.CopyProperties(affliction);
|
||||
return instance;
|
||||
}
|
||||
@@ -183,7 +188,7 @@ namespace Barotrauma
|
||||
|
||||
if (currentEffect.MultiplyByMaxVitality)
|
||||
{
|
||||
currVitalityDecrease *= characterHealth == null ? 100.0f : characterHealth.MaxVitality;
|
||||
currVitalityDecrease *= characterHealth?.MaxVitality ?? 100.0f;
|
||||
}
|
||||
|
||||
return currVitalityDecrease;
|
||||
|
||||
+12
-6
@@ -141,6 +141,9 @@ namespace Barotrauma
|
||||
if (prevDisplayedMessage.HasValue && prevDisplayedMessage.Value == State) { return; }
|
||||
if (highestStrength > Strength) { return; }
|
||||
|
||||
// Show initial husk warning by default, and disable it only if campaign difficulty settings explicitly disable it
|
||||
bool showHuskWarning = GameMain.GameSession?.Campaign?.Settings.ShowHuskWarning ?? true;
|
||||
|
||||
switch (State)
|
||||
{
|
||||
case InfectionState.Dormant:
|
||||
@@ -148,15 +151,18 @@ namespace Barotrauma
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (character == Character.Controlled)
|
||||
if (showHuskWarning)
|
||||
{
|
||||
if (character == Character.Controlled)
|
||||
{
|
||||
#if CLIENT
|
||||
GUI.AddMessage(TextManager.Get("HuskDormant"), GUIStyle.Red);
|
||||
GUI.AddMessage(TextManager.Get("HuskDormant"), GUIStyle.Red);
|
||||
#endif
|
||||
}
|
||||
else if (character.IsBot)
|
||||
{
|
||||
character.Speak(TextManager.Get("dialoghuskdormant").Value, delay: Rand.Range(0.5f, 5.0f), identifier: "huskdormant".ToIdentifier());
|
||||
}
|
||||
else if (character.IsBot)
|
||||
{
|
||||
character.Speak(TextManager.Get("dialoghuskdormant").Value, delay: Rand.Range(0.5f, 5.0f), identifier: "huskdormant".ToIdentifier());
|
||||
}
|
||||
}
|
||||
break;
|
||||
case InfectionState.Transition:
|
||||
|
||||
@@ -178,6 +178,12 @@ namespace Barotrauma
|
||||
max += Character.Info.Job.Prefab.VitalityModifier;
|
||||
}
|
||||
max *= Character.HumanPrefabHealthMultiplier;
|
||||
if (GameMain.GameSession?.Campaign is CampaignMode campaign)
|
||||
{
|
||||
max *= Character.IsOnPlayerTeam
|
||||
? campaign.Settings.CrewVitalityMultiplier
|
||||
: campaign.Settings.NonCrewVitalityMultiplier;
|
||||
}
|
||||
max *= 1f + Character.GetStatValue(StatTypes.MaximumHealthMultiplier);
|
||||
return max * Character.HealthMultiplier;
|
||||
}
|
||||
@@ -275,9 +281,9 @@ namespace Barotrauma
|
||||
this.Character = character;
|
||||
InitIrremovableAfflictions();
|
||||
|
||||
vitality = UnmodifiedMaxVitality;
|
||||
vitality = UnmodifiedMaxVitality;
|
||||
|
||||
minVitality = character.IsHuman ? -100.0f : 0.0f;
|
||||
minVitality = element.GetAttributeFloat(nameof(MinVitality), character.IsHuman ? -100.0f : 0.0f);
|
||||
|
||||
limbHealths.Clear();
|
||||
limbHealthElement ??= element;
|
||||
@@ -374,7 +380,7 @@ namespace Barotrauma
|
||||
|
||||
public Limb GetAfflictionLimb(Affliction affliction)
|
||||
{
|
||||
if (afflictions.TryGetValue(affliction, out LimbHealth limbHealth))
|
||||
if (affliction != null && afflictions.TryGetValue(affliction, out LimbHealth limbHealth))
|
||||
{
|
||||
if (limbHealth == null) { return null; }
|
||||
int limbHealthIndex = limbHealths.IndexOf(limbHealth);
|
||||
@@ -472,13 +478,17 @@ namespace Barotrauma
|
||||
|
||||
public float GetResistance(AfflictionPrefab afflictionPrefab)
|
||||
{
|
||||
// This is a % resistance (0 to 1.0)
|
||||
float resistance = 0.0f;
|
||||
foreach (KeyValuePair<Affliction, LimbHealth> kvp in afflictions)
|
||||
{
|
||||
var affliction = kvp.Key;
|
||||
resistance += affliction.GetResistance(afflictionPrefab.Identifier);
|
||||
}
|
||||
return 1 - ((1 - resistance) * Character.GetAbilityResistance(afflictionPrefab));
|
||||
// This is a multiplier, ie. 0.0 = 100% resistance and 1.0 = 0% resistance
|
||||
float abilityResistanceMultiplier = Character.GetAbilityResistance(afflictionPrefab);
|
||||
// The returned value is calculated to be a % resistance again
|
||||
return 1 - ((1 - resistance) * abilityResistanceMultiplier);
|
||||
}
|
||||
|
||||
public float GetStatValue(StatTypes statType)
|
||||
@@ -512,7 +522,7 @@ namespace Barotrauma
|
||||
ReduceMatchingAfflictions(amount, treatmentAction);
|
||||
}
|
||||
|
||||
public void ReduceAfflictionOnAllLimbs(Identifier afflictionIdOrType, float amount, ActionType? treatmentAction = null)
|
||||
public void ReduceAfflictionOnAllLimbs(Identifier afflictionIdOrType, float amount, ActionType? treatmentAction = null, Character attacker = null)
|
||||
{
|
||||
if (afflictionIdOrType.IsEmpty) { throw new ArgumentException($"{nameof(afflictionIdOrType)} is empty"); }
|
||||
|
||||
@@ -525,7 +535,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
ReduceMatchingAfflictions(amount, treatmentAction);
|
||||
ReduceMatchingAfflictions(amount, treatmentAction, attacker);
|
||||
}
|
||||
|
||||
private IEnumerable<Affliction> GetAfflictionsForLimb(Limb targetLimb)
|
||||
@@ -537,11 +547,11 @@ namespace Barotrauma
|
||||
|
||||
matchingAfflictions.Clear();
|
||||
matchingAfflictions.AddRange(GetAfflictionsForLimb(targetLimb));
|
||||
|
||||
|
||||
ReduceMatchingAfflictions(amount, treatmentAction);
|
||||
}
|
||||
|
||||
public void ReduceAfflictionOnLimb(Limb targetLimb, Identifier afflictionIdOrType, float amount, ActionType? treatmentAction = null)
|
||||
|
||||
public void ReduceAfflictionOnLimb(Limb targetLimb, Identifier afflictionIdOrType, float amount, ActionType? treatmentAction = null, Character attacker = null)
|
||||
{
|
||||
if (afflictionIdOrType.IsEmpty) { throw new ArgumentException($"{nameof(afflictionIdOrType)} is empty"); }
|
||||
if (targetLimb is null) { throw new ArgumentNullException(nameof(targetLimb)); }
|
||||
@@ -556,14 +566,22 @@ namespace Barotrauma
|
||||
matchingAfflictions.Add(affliction.Key);
|
||||
}
|
||||
}
|
||||
ReduceMatchingAfflictions(amount, treatmentAction);
|
||||
ReduceMatchingAfflictions(amount, treatmentAction, attacker);
|
||||
}
|
||||
|
||||
private void ReduceMatchingAfflictions(float amount, ActionType? treatmentAction)
|
||||
private void ReduceMatchingAfflictions(float amount, ActionType? treatmentAction, Character attacker = null)
|
||||
{
|
||||
if (matchingAfflictions.Count == 0) { return; }
|
||||
|
||||
float reduceAmount = amount / matchingAfflictions.Count;
|
||||
|
||||
if (reduceAmount > 0f)
|
||||
{
|
||||
var abilityReduceAffliction = new AbilityReduceAffliction(Character, reduceAmount);
|
||||
attacker?.CheckTalents(AbilityEffectType.OnReduceAffliction, abilityReduceAffliction);
|
||||
reduceAmount = abilityReduceAffliction.Value;
|
||||
}
|
||||
|
||||
for (int i = matchingAfflictions.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var matchingAffliction = matchingAfflictions[i];
|
||||
@@ -748,10 +766,16 @@ namespace Barotrauma
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (Character.Params.Health.PoisonImmunity &&
|
||||
(newAffliction.Prefab.AfflictionType == AfflictionPrefab.PoisonType || newAffliction.Prefab.AfflictionType == AfflictionPrefab.ParalysisType)) { return; }
|
||||
if (Character.Params.Health.PoisonImmunity)
|
||||
{
|
||||
if (newAffliction.Prefab.AfflictionType == AfflictionPrefab.PoisonType || newAffliction.Prefab.AfflictionType == AfflictionPrefab.ParalysisType)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (Character.EmpVulnerability <= 0 && newAffliction.Prefab.AfflictionType == AfflictionPrefab.EMPType) { return; }
|
||||
if (newAffliction.Prefab.TargetSpecies.Any() && newAffliction.Prefab.TargetSpecies.None(s => s == Character.SpeciesName)) { return; }
|
||||
if (Character.Params.Health.ImmunityIdentifiers.Contains(newAffliction.Identifier)) { return; }
|
||||
|
||||
var should = GameMain.LuaCs.Hook.Call<bool?>("character.applyAffliction", this, limbHealth, newAffliction, allowStacking);
|
||||
|
||||
@@ -759,12 +783,11 @@ namespace Barotrauma
|
||||
return;
|
||||
|
||||
Affliction existingAffliction = null;
|
||||
foreach (KeyValuePair<Affliction, LimbHealth> kvp in afflictions)
|
||||
foreach ((Affliction affliction, LimbHealth value) in afflictions)
|
||||
{
|
||||
var affliction = kvp.Key;
|
||||
if (kvp.Value == limbHealth && kvp.Key.Prefab == newAffliction.Prefab)
|
||||
if (value == limbHealth && affliction.Prefab == newAffliction.Prefab)
|
||||
{
|
||||
existingAffliction = kvp.Key;
|
||||
existingAffliction = affliction;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -990,10 +1013,8 @@ namespace Barotrauma
|
||||
IsParalyzed = false;
|
||||
if (Unkillable || Character.GodMode) { return; }
|
||||
|
||||
foreach (KeyValuePair<Affliction, LimbHealth> kvp in afflictions)
|
||||
foreach (var (affliction, limbHealth) in afflictions)
|
||||
{
|
||||
var affliction = kvp.Key;
|
||||
var limbHealth = kvp.Value;
|
||||
float vitalityDecrease = affliction.GetVitalityDecrease(this);
|
||||
if (limbHealth != null)
|
||||
{
|
||||
@@ -1133,9 +1154,8 @@ namespace Barotrauma
|
||||
/// and negative treatment suitabilities (e.g. a medicine that causes oxygen loss may not be suitable if the character is already suffocating)
|
||||
/// </summary>
|
||||
/// <param name="treatmentSuitability">A dictionary where the key is the identifier of the item and the value the suitability</param>
|
||||
/// <param name="normalize">If true, the suitability values are normalized between 0 and 1. If not, they're arbitrary values defined in the medical item XML, where negative values are unsuitable, and positive ones suitable.</param>
|
||||
/// <param name="predictFutureDuration">If above 0, the method will take into account how much currently active status effects while affect the afflictions in the next x seconds.</param>
|
||||
public void GetSuitableTreatments(Dictionary<Identifier, float> treatmentSuitability, bool normalize, Character user, Limb limb = null, bool ignoreHiddenAfflictions = false, float predictFutureDuration = 0.0f)
|
||||
public void GetSuitableTreatments(Dictionary<Identifier, float> treatmentSuitability, Character user, Limb limb = null, bool ignoreHiddenAfflictions = false, float predictFutureDuration = 0.0f)
|
||||
{
|
||||
//key = item identifier
|
||||
//float = suitability
|
||||
@@ -1145,7 +1165,9 @@ namespace Barotrauma
|
||||
{
|
||||
var affliction = kvp.Key;
|
||||
var limbHealth = kvp.Value;
|
||||
if (limb != null && affliction.Prefab.IndicatorLimb != limb.type)
|
||||
if (limb != null &&
|
||||
affliction.Prefab.LimbSpecific &&
|
||||
GetMatchingLimbHealth(affliction) != GetMatchingLimbHealth(limb))
|
||||
{
|
||||
if (limbHealth == null) { continue; }
|
||||
int healthIndex = limbHealths.IndexOf(limbHealth);
|
||||
@@ -1161,8 +1183,7 @@ namespace Barotrauma
|
||||
//other afflictions of the same type increase the "treatability"
|
||||
// e.g. we might want to ignore burns below 5%, but not if the character has them on all limbs
|
||||
float totalAfflictionStrength = strength + GetTotalAdjustedAfflictionStrength(affliction, includeSameAffliction: false);
|
||||
if (totalAfflictionStrength < affliction.Prefab.TreatmentThreshold) { continue; }
|
||||
|
||||
|
||||
if (afflictions.Any(otherAffliction => affliction.Prefab.IgnoreTreatmentIfAfflictedBy.Contains(otherAffliction.Key.Identifier))) { continue; }
|
||||
|
||||
if (ignoreHiddenAfflictions)
|
||||
@@ -1180,6 +1201,13 @@ namespace Barotrauma
|
||||
foreach (KeyValuePair<Identifier, float> treatment in affliction.Prefab.TreatmentSuitabilities)
|
||||
{
|
||||
float suitability = treatment.Value * strength;
|
||||
if (suitability > 0)
|
||||
{
|
||||
//if this a suitable treatment, ignore it if the affliction isn't severe enough to treat
|
||||
//if the suitability is negative though, we need to take it into account!
|
||||
//otherwise we may end up e.g. giving too much opiates to someone already close to overdosing
|
||||
if (totalAfflictionStrength < affliction.Prefab.TreatmentThreshold) { continue; }
|
||||
}
|
||||
if (treatment.Value > strength)
|
||||
{
|
||||
//avoid using very effective meds on small injuries
|
||||
@@ -1198,14 +1226,6 @@ namespace Barotrauma
|
||||
maxSuitability = Math.Max(treatmentSuitability[treatment.Key], maxSuitability);
|
||||
}
|
||||
}
|
||||
//normalize the suitabilities to a range of 0 to 1
|
||||
if (normalize)
|
||||
{
|
||||
foreach (Identifier treatment in treatmentSuitability.Keys.ToList())
|
||||
{
|
||||
treatmentSuitability[treatment] = (treatmentSuitability[treatment] - minSuitability) / (maxSuitability - minSuitability);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user