Unstable v0.19.1.0
This commit is contained in:
@@ -87,11 +87,11 @@ namespace Barotrauma
|
||||
if (_attackLimb != value)
|
||||
{
|
||||
_previousAttackLimb = _attackLimb;
|
||||
_previousAttackLimb?.AttachedRope?.Snap();
|
||||
if (_previousAttackLimb != null && _previousAttackLimb.attack.SnapRopeOnNewAttack) { _previousAttackLimb.AttachedRope?.Snap(); }
|
||||
}
|
||||
else if (_attackLimb != null && _attackLimb.attack.CoolDownTimer <= 0)
|
||||
{
|
||||
_attackLimb.AttachedRope?.Snap();
|
||||
if (_attackLimb != null && _attackLimb.attack.SnapRopeOnNewAttack) { _attackLimb.AttachedRope?.Snap(); }
|
||||
}
|
||||
_attackLimb = value;
|
||||
attackVector = null;
|
||||
@@ -3660,7 +3660,7 @@ namespace Barotrauma
|
||||
targetDir = Vector2.UnitY;
|
||||
}
|
||||
}
|
||||
float margin = 30000;
|
||||
float margin = Level.OutsideBoundsCurrentMargin;
|
||||
if (pos.X < -margin)
|
||||
{
|
||||
// Too far left
|
||||
|
||||
@@ -197,6 +197,10 @@ namespace Barotrauma
|
||||
return;
|
||||
}
|
||||
character.SelectedItem = null;
|
||||
if (character.SelectedSecondaryItem != null && !character.SelectedSecondaryItem.IsLadder)
|
||||
{
|
||||
character.SelectedSecondaryItem = null;
|
||||
}
|
||||
if (Target is Entity e)
|
||||
{
|
||||
if (e.Removed)
|
||||
|
||||
@@ -1234,7 +1234,7 @@ namespace Barotrauma
|
||||
{
|
||||
//find the room which the limb is in
|
||||
//the room where the ragdoll is in is used as the "guess", meaning that it's checked first
|
||||
Hull limbHull = currentHull == null ? null : Hull.FindHull(limb.WorldPosition, currentHull);
|
||||
Hull newHull = currentHull == null ? null : Hull.FindHull(limb.WorldPosition, currentHull);
|
||||
|
||||
bool prevInWater = limb.InWater;
|
||||
limb.InWater = false;
|
||||
@@ -1243,38 +1243,37 @@ namespace Barotrauma
|
||||
{
|
||||
limb.InWater = false;
|
||||
}
|
||||
else if (limbHull == null)
|
||||
else if (newHull == null)
|
||||
{
|
||||
//limb isn't in any room -> it's in the water
|
||||
limb.InWater = true;
|
||||
if (limb.type == LimbType.Head) headInWater = true;
|
||||
if (limb.type == LimbType.Head) { headInWater = true; }
|
||||
}
|
||||
else if (limbHull.WaterVolume > 0.0f && Submarine.RectContains(limbHull.Rect, limb.Position))
|
||||
else if (newHull.WaterVolume > 0.0f && Submarine.RectContains(newHull.Rect, limb.Position))
|
||||
{
|
||||
if (limb.Position.Y < limbHull.Surface)
|
||||
if (limb.Position.Y < newHull.Surface)
|
||||
{
|
||||
limb.InWater = true;
|
||||
surfaceY = limbHull.Surface;
|
||||
surfaceY = newHull.Surface;
|
||||
if (limb.type == LimbType.Head)
|
||||
{
|
||||
headInWater = true;
|
||||
}
|
||||
}
|
||||
//the limb has gone through the surface of the water
|
||||
if (Math.Abs(limb.LinearVelocity.Y) > 5.0f && limb.InWater != prevInWater)
|
||||
if (Math.Abs(limb.LinearVelocity.Y) > 5.0f && limb.InWater != prevInWater && newHull == limb.Hull)
|
||||
{
|
||||
Splash(limb, limbHull);
|
||||
|
||||
Splash(limb, newHull);
|
||||
//if the Character dropped into water, create a wave
|
||||
if (limb.LinearVelocity.Y < 0.0f)
|
||||
{
|
||||
Vector2 impulse = limb.LinearVelocity * limb.Mass;
|
||||
int n = (int)((limb.Position.X - limbHull.Rect.X) / Hull.WaveWidth);
|
||||
limbHull.WaveVel[n] += MathHelper.Clamp(impulse.Y, -5.0f, 5.0f);
|
||||
int n = (int)((limb.Position.X - newHull.Rect.X) / Hull.WaveWidth);
|
||||
newHull.WaveVel[n] += MathHelper.Clamp(impulse.Y, -5.0f, 5.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
limb.Hull = newHull;
|
||||
limb.Update(deltaTime);
|
||||
}
|
||||
|
||||
@@ -1492,12 +1491,12 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
if (flowForce.LengthSquared() > 0.001f)
|
||||
{
|
||||
Collider.ApplyForce(flowForce);
|
||||
{
|
||||
Collider.ApplyForce(flowForce * (Collider.Mass / Mass));
|
||||
foreach (Limb limb in limbs)
|
||||
{
|
||||
if (!limb.InWater) { continue; }
|
||||
limb.body.ApplyForce(flowForce);
|
||||
limb.body.ApplyForce(flowForce * (limb.Mass / Mass * limbs.Length));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,6 +100,9 @@ namespace Barotrauma
|
||||
[Serialize(false, IsPropertySaveable.Yes, description: "Should the AI try to turn around when aiming with this attack?"), Editable]
|
||||
public bool Reverse { get; private set; }
|
||||
|
||||
[Serialize(true, IsPropertySaveable.Yes, description: "Should the rope attached to this limb snap upon choosing a new attack?"), Editable]
|
||||
public bool SnapRopeOnNewAttack { get; private set; }
|
||||
|
||||
[Serialize(false, IsPropertySaveable.Yes, description: "Should the AI try to steer away from the target when aiming with this attack? Best combined with PassiveAggressive behavior."), Editable]
|
||||
public bool Retreat { get; private set; }
|
||||
|
||||
@@ -309,7 +312,7 @@ namespace Barotrauma
|
||||
List<Affliction> multipliedAfflictions = new List<Affliction>();
|
||||
foreach (Affliction affliction in Afflictions.Keys)
|
||||
{
|
||||
multipliedAfflictions.Add(affliction.CreateMultiplied(multiplier));
|
||||
multipliedAfflictions.Add(affliction.CreateMultiplied(multiplier, affliction.Probability));
|
||||
}
|
||||
return multipliedAfflictions;
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace Barotrauma
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value == enabled) return;
|
||||
if (value == enabled) { return; }
|
||||
|
||||
if (Removed)
|
||||
{
|
||||
@@ -63,6 +63,32 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private bool disabledByEvent;
|
||||
/// <summary>
|
||||
/// MonsterEvents disable monsters (which includes removing them from the character list, so they essentially "don't exist") until they're ready to spawn
|
||||
/// </summary>
|
||||
public bool DisabledByEvent
|
||||
{
|
||||
get { return disabledByEvent; }
|
||||
set
|
||||
{
|
||||
if (value == disabledByEvent) { return; }
|
||||
disabledByEvent = value;
|
||||
if (disabledByEvent)
|
||||
{
|
||||
Enabled = false;
|
||||
CharacterList.Remove(this);
|
||||
if (AiTarget != null) { AITarget.List.Remove(AiTarget); }
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!CharacterList.Contains(this)) { CharacterList.Add(this); }
|
||||
if (AiTarget != null && !AITarget.List.Contains(AiTarget)) { AITarget.List.Add(AiTarget); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Hull PreviousHull = null;
|
||||
public Hull CurrentHull = null;
|
||||
|
||||
@@ -1247,23 +1273,30 @@ namespace Barotrauma
|
||||
|
||||
if (Params.Husk && speciesName != "husk" && Prefab.VariantOf != "husk")
|
||||
{
|
||||
// Get the non husked name and find the ragdoll with it
|
||||
var matchingAffliction = AfflictionPrefab.List
|
||||
.Where(p => p is AfflictionPrefabHusk)
|
||||
.Select(p => p as AfflictionPrefabHusk)
|
||||
.FirstOrDefault(p => p.TargetSpecies.Any(t => t == AfflictionHusk.GetNonHuskedSpeciesName(speciesName, p)));
|
||||
Identifier nonHuskedSpeciesName = Identifier.Empty;
|
||||
if (matchingAffliction == null)
|
||||
AfflictionPrefabHusk matchingAffliction = null;
|
||||
foreach (var huskPrefab in AfflictionPrefab.Prefabs.OfType<AfflictionPrefabHusk>())
|
||||
{
|
||||
DebugConsole.ThrowError("Cannot find a husk infection that matches this species! Please add the speciesnames as 'targets' in the husk affliction prefab definition!");
|
||||
var nonHuskedName = AfflictionHusk.GetNonHuskedSpeciesName(speciesName, huskPrefab);
|
||||
if (huskPrefab.TargetSpecies.Contains(nonHuskedName))
|
||||
{
|
||||
var huskedSpeciesName = AfflictionHusk.GetHuskedSpeciesName(nonHuskedName, huskPrefab);
|
||||
if (huskedSpeciesName.Equals(speciesName))
|
||||
{
|
||||
nonHuskedSpeciesName = nonHuskedName;
|
||||
matchingAffliction = huskPrefab;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (matchingAffliction == null || nonHuskedSpeciesName.IsEmpty)
|
||||
{
|
||||
DebugConsole.ThrowError($"Cannot find a husk infection that matches {speciesName}! Please make sure that the speciesname is added as 'targets' in the husk affliction prefab definition!\n"
|
||||
+ "Note that all the infected speciesnames and files must stick the following pattern: [nonhuskedspeciesname][huskedspeciesname]. E.g. Humanhusk, Crawlerhusk, or Humancustomhusk, or Crawlerzombie. Not \"Customhumanhusk!\" or \"Zombiecrawler\"");
|
||||
// Crashes if we fail to create a ragdoll -> Let's just use some ragdoll so that the user sees the error msg.
|
||||
nonHuskedSpeciesName = IsHumanoid ? CharacterPrefab.HumanSpeciesName : "crawler".ToIdentifier();
|
||||
speciesName = nonHuskedSpeciesName;
|
||||
}
|
||||
else
|
||||
{
|
||||
nonHuskedSpeciesName = AfflictionHusk.GetNonHuskedSpeciesName(speciesName, matchingAffliction);
|
||||
}
|
||||
if (ragdollParams == null && prefab.VariantOf == null)
|
||||
{
|
||||
Identifier name = Params.UseHuskAppendage ? nonHuskedSpeciesName : speciesName;
|
||||
|
||||
@@ -1287,6 +1287,11 @@ namespace Barotrauma
|
||||
if (splitTag[0] != "name") { continue; }
|
||||
if (splitTag[1] != Name) { continue; }
|
||||
item.ReplaceTag(tag, $"name:{newName}");
|
||||
var idCard = item.GetComponent<IdCard>();
|
||||
if (idCard != null)
|
||||
{
|
||||
idCard.OwnerName = newName;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
+7
-2
@@ -50,6 +50,9 @@ namespace Barotrauma
|
||||
[Serialize(1.0f, IsPropertySaveable.Yes, description: "The probability for the affliction to be applied."), Editable(minValue: 0f, maxValue: 1f)]
|
||||
public float Probability { get; set; } = 1.0f;
|
||||
|
||||
[Serialize(true, IsPropertySaveable.Yes, description: "Explosion damage is applied per each affected limb. Should this affliction damage be divided by the count of affected limbs (1-15) or applied in full? Default: true. Only affects explosions."), Editable]
|
||||
public bool DivideByLimbCount { get; set; }
|
||||
|
||||
public float DamagePerSecond;
|
||||
public float DamagePerSecondTimer;
|
||||
public float PreviousVitalityDecrease;
|
||||
@@ -96,9 +99,11 @@ namespace Barotrauma
|
||||
SerializableProperties = SerializableProperty.DeserializeProperties(this, element);
|
||||
}
|
||||
|
||||
public Affliction CreateMultiplied(float multiplier)
|
||||
public Affliction CreateMultiplied(float multiplier, float probability)
|
||||
{
|
||||
return Prefab.Instantiate(NonClampedStrength * multiplier, Source);
|
||||
var instance = Prefab.Instantiate(NonClampedStrength * multiplier, Source);
|
||||
instance.Probability = probability;
|
||||
return instance;
|
||||
}
|
||||
|
||||
public override string ToString() => Prefab == null ? "Affliction (Invalid)" : $"Affliction ({Prefab.Name})";
|
||||
|
||||
+2
-3
@@ -450,13 +450,12 @@ namespace Barotrauma
|
||||
|
||||
public static Identifier GetHuskedSpeciesName(Identifier speciesName, AfflictionPrefabHusk prefab)
|
||||
{
|
||||
return prefab.HuskedSpeciesName.Replace(AfflictionPrefabHusk.Tag, speciesName);
|
||||
return new Identifier(speciesName.Value + prefab.HuskedSpeciesName.Value);
|
||||
}
|
||||
|
||||
public static Identifier GetNonHuskedSpeciesName(Identifier huskedSpeciesName, AfflictionPrefabHusk prefab)
|
||||
{
|
||||
Identifier nonTag = prefab.HuskedSpeciesName.Remove(AfflictionPrefabHusk.Tag);
|
||||
return huskedSpeciesName.Remove(nonTag);
|
||||
return huskedSpeciesName.Remove(prefab.HuskedSpeciesName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+15
-4
@@ -63,8 +63,10 @@ namespace Barotrauma
|
||||
if (HuskedSpeciesName.IsEmpty)
|
||||
{
|
||||
DebugConsole.NewMessage($"No 'huskedspeciesname' defined for the husk affliction ({Identifier}) in {element}", Color.Orange);
|
||||
HuskedSpeciesName = "[speciesname]husk".ToIdentifier();
|
||||
HuskedSpeciesName = "husk".ToIdentifier();
|
||||
}
|
||||
// Remove "[speciesname]" for backward support (we don't use it anymore)
|
||||
HuskedSpeciesName = HuskedSpeciesName.Remove("[speciesname]").ToIdentifier();
|
||||
TargetSpecies = element.GetAttributeIdentifierArray("targets", Array.Empty<Identifier>(), trim: true);
|
||||
if (TargetSpecies.Length == 0)
|
||||
{
|
||||
@@ -108,7 +110,6 @@ namespace Barotrauma
|
||||
|
||||
public readonly Identifier HuskedSpeciesName;
|
||||
public readonly Identifier[] TargetSpecies;
|
||||
public static readonly Identifier Tag = "[speciesname]".ToIdentifier();
|
||||
|
||||
public readonly bool TransferBuffs;
|
||||
public readonly bool SendMessages;
|
||||
@@ -404,8 +405,18 @@ namespace Barotrauma
|
||||
|
||||
AfflictionType = element.GetAttributeIdentifier("type", "");
|
||||
TranslationIdentifier = element.GetAttributeIdentifier("translationoverride", Identifier);
|
||||
Name = TextManager.Get($"AfflictionName.{TranslationIdentifier}").Fallback(element.GetAttributeString("name", ""));
|
||||
Description = TextManager.Get($"AfflictionDescription.{TranslationIdentifier}").Fallback(element.GetAttributeString("description", ""));
|
||||
Name = TextManager.Get($"AfflictionName.{TranslationIdentifier}");
|
||||
string fallbackName = element.GetAttributeString("name", "");
|
||||
if (!string.IsNullOrEmpty(fallbackName))
|
||||
{
|
||||
Name = Name.Fallback(fallbackName);
|
||||
}
|
||||
Description = TextManager.Get($"AfflictionDescription.{TranslationIdentifier}");
|
||||
string fallbackDescription = element.GetAttributeString("description", "");
|
||||
if (!string.IsNullOrEmpty(fallbackDescription))
|
||||
{
|
||||
Description = Description.Fallback(fallbackDescription);
|
||||
}
|
||||
IsBuff = element.GetAttributeBool("isbuff", false);
|
||||
|
||||
HealableInMedicalClinic = element.GetAttributeBool("healableinmedicalclinic",
|
||||
|
||||
@@ -909,19 +909,11 @@ namespace Barotrauma
|
||||
float vitalityDecrease = affliction.GetVitalityDecrease(this);
|
||||
if (limbHealth != null)
|
||||
{
|
||||
if (limbHealth.VitalityMultipliers.ContainsKey(affliction.Prefab.Identifier))
|
||||
{
|
||||
vitalityDecrease *= limbHealth.VitalityMultipliers[affliction.Prefab.Identifier];
|
||||
}
|
||||
if (limbHealth.VitalityTypeMultipliers.ContainsKey(affliction.Prefab.AfflictionType))
|
||||
{
|
||||
vitalityDecrease *= limbHealth.VitalityTypeMultipliers[affliction.Prefab.AfflictionType];
|
||||
}
|
||||
vitalityDecrease *= GetVitalityMultiplier(affliction, limbHealth);
|
||||
}
|
||||
Vitality -= vitalityDecrease;
|
||||
affliction.CalculateDamagePerSecond(vitalityDecrease);
|
||||
}
|
||||
|
||||
#if CLIENT
|
||||
if (IsUnconscious)
|
||||
{
|
||||
@@ -930,6 +922,33 @@ namespace Barotrauma
|
||||
#endif
|
||||
}
|
||||
|
||||
private float GetVitalityMultiplier(Affliction affliction, LimbHealth limbHealth)
|
||||
{
|
||||
float multiplier = 1.0f;
|
||||
if (limbHealth.VitalityMultipliers.TryGetValue(affliction.Prefab.Identifier, out float vitalityMultiplier))
|
||||
{
|
||||
multiplier *= vitalityMultiplier;
|
||||
}
|
||||
if (limbHealth.VitalityTypeMultipliers.TryGetValue(affliction.Prefab.AfflictionType, out float vitalityTypeMultiplier))
|
||||
{
|
||||
multiplier *= vitalityTypeMultiplier;
|
||||
}
|
||||
return multiplier;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// How much vitality the affliction reduces, taking into account the effects of vitality modifiers on the limb the affliction is on (if limb-based)
|
||||
/// </summary>
|
||||
private float GetVitalityDecreaseWithVitalityMultipliers(Affliction affliction)
|
||||
{
|
||||
float vitalityDecrease = affliction.GetVitalityDecrease(this);
|
||||
if (afflictions.TryGetValue(affliction, out LimbHealth limbHealth) && limbHealth != null)
|
||||
{
|
||||
vitalityDecrease *= GetVitalityMultiplier(affliction, limbHealth);
|
||||
}
|
||||
return vitalityDecrease;
|
||||
}
|
||||
|
||||
private void Kill()
|
||||
{
|
||||
if (Unkillable || Character.GodMode) { return; }
|
||||
|
||||
@@ -218,6 +218,8 @@ namespace Barotrauma
|
||||
|
||||
public Vector2 StepOffset => ConvertUnits.ToSimUnits(Params.StepOffset) * ragdoll.RagdollParams.JointScale;
|
||||
|
||||
public Hull Hull;
|
||||
|
||||
public bool InWater { get; set; }
|
||||
|
||||
private FixedMouseJoint pullJoint;
|
||||
@@ -720,11 +722,12 @@ namespace Barotrauma
|
||||
tempModifiers.Clear();
|
||||
var newAffliction = affliction;
|
||||
float random = Rand.Value(Rand.RandSync.Unsynced);
|
||||
if (random > affliction.Probability) { continue; }
|
||||
bool foundMatchingModifier = false;
|
||||
bool applyAffliction = true;
|
||||
foreach (DamageModifier damageModifier in DamageModifiers)
|
||||
{
|
||||
if (!damageModifier.MatchesAffliction(affliction)) { continue; }
|
||||
foundMatchingModifier = true;
|
||||
if (random > affliction.Probability * damageModifier.ProbabilityMultiplier)
|
||||
{
|
||||
applyAffliction = false;
|
||||
@@ -740,6 +743,7 @@ namespace Barotrauma
|
||||
foreach (DamageModifier damageModifier in wearable.WearableComponent.DamageModifiers)
|
||||
{
|
||||
if (!damageModifier.MatchesAffliction(affliction)) { continue; }
|
||||
foundMatchingModifier = true;
|
||||
if (random > affliction.Probability * damageModifier.ProbabilityMultiplier)
|
||||
{
|
||||
applyAffliction = false;
|
||||
@@ -751,6 +755,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!foundMatchingModifier && random > affliction.Probability) { continue; }
|
||||
float finalDamageModifier = damageMultiplier;
|
||||
foreach (DamageModifier damageModifier in tempModifiers)
|
||||
{
|
||||
@@ -763,7 +768,7 @@ namespace Barotrauma
|
||||
}
|
||||
if (!MathUtils.NearlyEqual(finalDamageModifier, 1.0f))
|
||||
{
|
||||
newAffliction = affliction.CreateMultiplied(finalDamageModifier);
|
||||
newAffliction = affliction.CreateMultiplied(finalDamageModifier, affliction.Probability);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user