Build 0.18.4.0
This commit is contained in:
@@ -34,14 +34,18 @@ namespace Barotrauma
|
||||
public float SoundRange
|
||||
{
|
||||
get { return soundRange; }
|
||||
set
|
||||
set
|
||||
{
|
||||
if (float.IsNaN(value))
|
||||
{
|
||||
DebugConsole.ThrowError("Attempted to set the SoundRange of an AITarget to NaN.\n" + Environment.StackTrace.CleanupStackTrace());
|
||||
return;
|
||||
}
|
||||
soundRange = MathHelper.Clamp(value, MinSoundRange, MaxSoundRange);
|
||||
soundRange = MathHelper.Clamp(value, MinSoundRange, MaxSoundRange);
|
||||
if (soundRange > 0.0f && !Static && FadeOutTime > 0.0f)
|
||||
{
|
||||
NeedsUpdate = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +59,11 @@ namespace Barotrauma
|
||||
DebugConsole.ThrowError("Attempted to set the SightRange of an AITarget to NaN.\n" + Environment.StackTrace.CleanupStackTrace());
|
||||
return;
|
||||
}
|
||||
sightRange = MathHelper.Clamp(value, MinSightRange, MaxSightRange);
|
||||
sightRange = MathHelper.Clamp(value, MinSightRange, MaxSightRange);
|
||||
if (sightRange > 0 && !Static && FadeOutTime > 0.0f)
|
||||
{
|
||||
NeedsUpdate = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,13 +107,33 @@ namespace Barotrauma
|
||||
/// </summary>
|
||||
public bool InDetectable
|
||||
{
|
||||
get => inDetectable || (SoundRange <= 0 && SightRange <= 0);
|
||||
set => inDetectable = value;
|
||||
get
|
||||
{
|
||||
return inDetectable || (SoundRange <= 0 && SightRange <= 0);
|
||||
}
|
||||
set
|
||||
{
|
||||
inDetectable = value;
|
||||
if (inDetectable)
|
||||
{
|
||||
NeedsUpdate = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public float MinSoundRange, MinSightRange;
|
||||
public float MaxSoundRange = 100000, MaxSightRange = 100000;
|
||||
|
||||
/// <summary>
|
||||
/// Does the AI target do something that requires Update() to be called (e.g. static targets don't need to be updated)
|
||||
/// </summary>
|
||||
public bool NeedsUpdate
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
} = true;
|
||||
|
||||
public TargetType Type { get; private set; }
|
||||
|
||||
public enum TargetType
|
||||
@@ -190,14 +218,22 @@ namespace Barotrauma
|
||||
if (!Static && FadeOutTime > 0)
|
||||
{
|
||||
// The aitarget goes silent/invisible if the components don't keep it active
|
||||
if (!StaticSight && SightRange > 0)
|
||||
if (!StaticSight && sightRange > 0)
|
||||
{
|
||||
DecreaseSightRange(deltaTime);
|
||||
}
|
||||
if (!StaticSound && SoundRange > 0)
|
||||
if (!StaticSound && soundRange > 0)
|
||||
{
|
||||
DecreaseSoundRange(deltaTime);
|
||||
}
|
||||
if (sightRange <= 0 && soundRange <= 0)
|
||||
{
|
||||
NeedsUpdate = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NeedsUpdate = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1440,14 +1440,33 @@ namespace Barotrauma
|
||||
}
|
||||
else if (selectedTargetingParams.AttackPattern == AttackPattern.Straight && distance < AttackLimb.attack.Range * 5)
|
||||
{
|
||||
reachTimer += deltaTime;
|
||||
if (reachTimer > reachTimeOut)
|
||||
Vector2 targetVelocity = Vector2.Zero;
|
||||
Submarine targetSub = SelectedAiTarget.Entity.Submarine;
|
||||
if (targetSub != null)
|
||||
{
|
||||
reachTimer = 0;
|
||||
IgnoreTarget(SelectedAiTarget);
|
||||
State = AIState.Idle;
|
||||
ResetAITarget();
|
||||
return;
|
||||
targetVelocity = targetSub.Velocity;
|
||||
}
|
||||
else if (targetCharacter != null)
|
||||
{
|
||||
targetVelocity = targetCharacter.AnimController.Collider.LinearVelocity;
|
||||
}
|
||||
else if (SelectedAiTarget.Entity is Item i && i.body != null)
|
||||
{
|
||||
targetVelocity = i.body.LinearVelocity;
|
||||
}
|
||||
float mySpeed = Character.AnimController.Collider.LinearVelocity.LengthSquared();
|
||||
float targetSpeed = targetVelocity.LengthSquared();
|
||||
if (mySpeed < 0.1f || mySpeed > targetSpeed)
|
||||
{
|
||||
reachTimer += deltaTime;
|
||||
if (reachTimer > reachTimeOut)
|
||||
{
|
||||
reachTimer = 0;
|
||||
IgnoreTarget(SelectedAiTarget);
|
||||
State = AIState.Idle;
|
||||
ResetAITarget();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -866,8 +866,8 @@ namespace Barotrauma
|
||||
var container = i.GetComponent<ItemContainer>();
|
||||
if (container == null) { return 0; }
|
||||
if (!container.Inventory.CanBePut(containableItem)) { return 0; }
|
||||
var rootContainer = container.Item.GetRootContainer();
|
||||
if (rootContainer?.GetComponent<Fabricator>() != null || rootContainer?.GetComponent<Deconstructor>() != null) { return 0; }
|
||||
var rootContainer = container.Item.GetRootContainer() ?? container.Item;
|
||||
if (rootContainer.GetComponent<Fabricator>() != null || rootContainer.GetComponent<Deconstructor>() != null) { return 0; }
|
||||
if (container.ShouldBeContained(containableItem, out bool isRestrictionsDefined))
|
||||
{
|
||||
if (isRestrictionsDefined)
|
||||
@@ -882,7 +882,12 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
return isPreferencesDefined ? 0 : 1;
|
||||
if (isPreferencesDefined)
|
||||
{
|
||||
// Use any valid locker as a fall back container.
|
||||
return container.Item.HasTag("locker") ? 0.5f : 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1950,11 +1955,10 @@ namespace Barotrauma
|
||||
enemyFactor = MathHelper.Lerp(1, 0, MathHelper.Clamp(enemyCount * 0.9f, 0, 1));
|
||||
}
|
||||
float dangerousItemsFactor = 1f;
|
||||
foreach (Item item in Item.ItemList)
|
||||
foreach (Item item in Item.DangerousItems)
|
||||
{
|
||||
if (item.CurrentHull != hull) { continue; }
|
||||
if (item.Prefab != null && item.Prefab.IsDangerous)
|
||||
{
|
||||
if (item.CurrentHull == hull)
|
||||
{
|
||||
dangerousItemsFactor = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -245,7 +245,7 @@ namespace Barotrauma
|
||||
{
|
||||
get
|
||||
{
|
||||
if (IgnoreAtOutpost && Level.IsLoadedOutpost && character.TeamID != CharacterTeamType.FriendlyNPC)
|
||||
if (IgnoreAtOutpost && Level.IsLoadedFriendlyOutpost && character.TeamID != CharacterTeamType.FriendlyNPC)
|
||||
{
|
||||
if (Submarine.MainSub != null && Submarine.MainSub.DockedTo.None(s => s.TeamID != CharacterTeamType.FriendlyNPC && s.TeamID != character.TeamID))
|
||||
{
|
||||
|
||||
+23
-10
@@ -48,16 +48,29 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
float xDist = Math.Abs(character.WorldPosition.X - Leak.WorldPosition.X);
|
||||
float yDist = Math.Abs(character.WorldPosition.Y - Leak.WorldPosition.Y);
|
||||
// Vertical distance matters more than horizontal (climbing up/down is harder than moving horizontally).
|
||||
// If the target is close, ignore the distance factor alltogether so that we keep fixing the leaks that are nearby.
|
||||
float distanceFactor = isPriority || xDist < 200 && yDist < 100 ? 1 : MathHelper.Lerp(1, 0.1f, MathUtils.InverseLerp(0, 3000, xDist + yDist * 3.0f));
|
||||
float severity = isPriority ? 1 : AIObjectiveFixLeaks.GetLeakSeverity(Leak) / 100;
|
||||
float reduction = isPriority ? 1 : 2;
|
||||
float max = AIObjectiveManager.LowestOrderPriority - reduction;
|
||||
float devotion = CumulatedDevotion / 100;
|
||||
Priority = MathHelper.Lerp(0, max, MathHelper.Clamp(devotion + (severity * distanceFactor * PriorityModifier), 0, 1));
|
||||
float maxPriority = AIObjectiveManager.LowestOrderPriority - reduction;
|
||||
if (operateObjective != null && objectiveManager.GetActiveObjective<AIObjectiveFixLeaks>() is AIObjectiveFixLeaks fixLeaks && fixLeaks.CurrentSubObjective == this)
|
||||
{
|
||||
// Prioritize leaks that we are already fixing
|
||||
Priority = maxPriority;
|
||||
}
|
||||
else
|
||||
{
|
||||
float xDist = Math.Abs(character.WorldPosition.X - Leak.WorldPosition.X);
|
||||
float yDist = Math.Abs(character.WorldPosition.Y - Leak.WorldPosition.Y);
|
||||
// Vertical distance matters more than horizontal (climbing up/down is harder than moving horizontally).
|
||||
// If the target is close, ignore the distance factor alltogether so that we keep fixing the leaks that are nearby.
|
||||
float distanceFactor = isPriority || xDist < 200 && yDist < 100 ? 1 : MathHelper.Lerp(1, 0.1f, MathUtils.InverseLerp(0, 3000, xDist + yDist * 3.0f));
|
||||
if (Leak.linkedTo.Any(e => e is Hull h && h == character.CurrentHull))
|
||||
{
|
||||
// Double the distance when the leak can be accessed from the current hull.
|
||||
distanceFactor *= 2;
|
||||
}
|
||||
float severity = isPriority ? 1 : AIObjectiveFixLeaks.GetLeakSeverity(Leak) / 100;
|
||||
float devotion = CumulatedDevotion / 100;
|
||||
Priority = MathHelper.Lerp(0, maxPriority, MathHelper.Clamp(devotion + (severity * distanceFactor * PriorityModifier), 0, 1));
|
||||
}
|
||||
}
|
||||
return Priority;
|
||||
}
|
||||
@@ -202,7 +215,7 @@ namespace Barotrauma
|
||||
// This is an approximation, because we don't know the exact reach until the pose is taken.
|
||||
// And even then the actual range depends on the direction we are aiming to.
|
||||
// Found out that without any multiplier the value (209) is often too short.
|
||||
return repairTool.Range + armLength * 1.3f;
|
||||
return repairTool.Range + armLength * 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+19
-1
@@ -185,6 +185,11 @@ namespace Barotrauma
|
||||
{
|
||||
PathSteering.SteeringSeek(character.GetRelativeSimPosition(currentTarget), weight: 1, nodeFilter: node => node.Waypoint.CurrentHull != null);
|
||||
}
|
||||
else
|
||||
{
|
||||
PathSteering.ResetPath();
|
||||
PathSteering.Reset();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -290,12 +295,25 @@ namespace Barotrauma
|
||||
{
|
||||
PathSteering.SteeringSeek(character.GetRelativeSimPosition(currentTarget), weight: 1, nodeFilter: node => node.Waypoint.CurrentHull != null);
|
||||
}
|
||||
else
|
||||
{
|
||||
PathSteering.ResetPath();
|
||||
PathSteering.Reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Wander(float deltaTime)
|
||||
{
|
||||
if (character.IsClimbing) { return; }
|
||||
if (character.IsClimbing)
|
||||
{
|
||||
if (character.AnimController.GetHeightFromFloor() < 0.1f)
|
||||
{
|
||||
character.AnimController.Anim = AnimController.Animation.None;
|
||||
character.SelectedConstruction = null;
|
||||
}
|
||||
return;
|
||||
}
|
||||
var currentHull = character.CurrentHull;
|
||||
if (!character.AnimController.InWater && currentHull != null)
|
||||
{
|
||||
|
||||
+1
-1
@@ -142,7 +142,7 @@ namespace Barotrauma
|
||||
}
|
||||
var order = new Order(orderPrefab, autonomousObjective.Option, item ?? character.CurrentHull as Entity, orderPrefab.GetTargetItemComponent(item), orderGiver: character);
|
||||
if (order == null) { continue; }
|
||||
if ((order.IgnoreAtOutpost || autonomousObjective.IgnoreAtOutpost) && Level.IsLoadedOutpost && character.TeamID != CharacterTeamType.FriendlyNPC)
|
||||
if ((order.IgnoreAtOutpost || autonomousObjective.IgnoreAtOutpost) && Level.IsLoadedFriendlyOutpost && character.TeamID != CharacterTeamType.FriendlyNPC)
|
||||
{
|
||||
if (Submarine.MainSub != null && Submarine.MainSub.DockedTo.None(s => s.TeamID != CharacterTeamType.FriendlyNPC && s.TeamID != character.TeamID))
|
||||
{
|
||||
|
||||
+1
-1
@@ -238,7 +238,7 @@ namespace Barotrauma
|
||||
};
|
||||
if (repairTool != null)
|
||||
{
|
||||
objective.CloseEnough = repairTool.Range * 0.75f;
|
||||
objective.CloseEnough = AIObjectiveFixLeak.CalculateReach(repairTool, character);
|
||||
}
|
||||
return objective;
|
||||
},
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
using FarseerPhysics.Dynamics;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using FarseerPhysics;
|
||||
using Barotrauma.Extensions;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -90,6 +88,10 @@ namespace Barotrauma
|
||||
{
|
||||
steering = Vector2.Normalize(steering) * Math.Abs(speed);
|
||||
}
|
||||
if (host is AIController aiController && aiController?.Character.CharacterHealth.GetAfflictionOfType("invertcontrols".ToIdentifier()) != null)
|
||||
{
|
||||
steering = -steering;
|
||||
}
|
||||
host.Steering = steering;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,8 +22,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (_ragdollParams == null)
|
||||
{
|
||||
#warning TODO: this is kinda janky, this should probably be done better
|
||||
_ragdollParams = FishRagdollParams.GetDefaultRagdollParams(character.VariantOf.IfEmpty(character.SpeciesName));
|
||||
_ragdollParams = FishRagdollParams.GetDefaultRagdollParams(character.SpeciesName);
|
||||
if (!character.VariantOf.IsEmpty)
|
||||
{
|
||||
_ragdollParams.ApplyVariantScale(character.Params.VariantFile);
|
||||
|
||||
@@ -74,7 +74,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasMultipleLimbsOfSameType => limbs == null ? false : Limbs.Length > limbDictionary.Count;
|
||||
public bool HasMultipleLimbsOfSameType => limbs != null && limbs.Length > limbDictionary.Count;
|
||||
|
||||
private bool frozen;
|
||||
public bool Frozen
|
||||
@@ -1850,36 +1850,30 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Note that if there are multiple limbs of the same type, only the first of them is found in the dictionary.
|
||||
/// Note that if there are multiple limbs of the same type, only the first (valid) limb is returned.
|
||||
/// </summary>
|
||||
public Limb GetLimb(LimbType limbType, bool excludeSevered = true)
|
||||
{
|
||||
Limb limb = null;
|
||||
if (HasMultipleLimbsOfSameType)
|
||||
if (limbDictionary.TryGetValue(limbType, out Limb limb))
|
||||
{
|
||||
for (int i = 0; i < 10; i++)
|
||||
if (excludeSevered && limb.IsSevered)
|
||||
{
|
||||
limbDictionary.TryGetValue(limbType, out limb);
|
||||
if (limb == null)
|
||||
limb = null;
|
||||
}
|
||||
}
|
||||
if (limb == null && HasMultipleLimbsOfSameType)
|
||||
{
|
||||
// Didn't find a (valid) limb of the matching type. If there's multiple limbs of the same type, check the other limbs.
|
||||
foreach (var l in limbs)
|
||||
{
|
||||
if (l.type != limbType) { continue; }
|
||||
if (!excludeSevered || !l.IsSevered)
|
||||
{
|
||||
// No limbs found
|
||||
break;
|
||||
}
|
||||
if (!excludeSevered || !limb.IsSevered)
|
||||
{
|
||||
// Found a valid limb
|
||||
limb = l;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
limbDictionary.TryGetValue(limbType, out limb);
|
||||
}
|
||||
if (excludeSevered && limb != null && limb.IsSevered)
|
||||
{
|
||||
limb = null;
|
||||
}
|
||||
return limb;
|
||||
}
|
||||
|
||||
|
||||
@@ -117,7 +117,29 @@ namespace Barotrauma
|
||||
|
||||
protected Key[] keys;
|
||||
|
||||
public HumanPrefab HumanPrefab;
|
||||
private HumanPrefab humanPrefab;
|
||||
public HumanPrefab HumanPrefab
|
||||
{
|
||||
get { return humanPrefab; }
|
||||
set
|
||||
{
|
||||
if (humanPrefab == value) { return; }
|
||||
humanPrefab = value;
|
||||
|
||||
if (humanPrefab != null)
|
||||
{
|
||||
HumanPrefabHealthMultiplier = humanPrefab.HealthMultiplier;
|
||||
if (GameMain.NetworkMember != null)
|
||||
{
|
||||
HumanPrefabHealthMultiplier *= humanPrefab.HealthMultiplierInMultiplayer;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
HumanPrefabHealthMultiplier = 1.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private CharacterTeamType teamID;
|
||||
public CharacterTeamType TeamID
|
||||
@@ -1192,7 +1214,7 @@ namespace Barotrauma
|
||||
CharacterHealth = new CharacterHealth(selectedHealthElement, this, limbHealthElement);
|
||||
}
|
||||
|
||||
if (Params.Husk && speciesName != "husk")
|
||||
if (Params.Husk && speciesName != "husk" && Prefab.VariantOf != "husk")
|
||||
{
|
||||
// Get the non husked name and find the ragdoll with it
|
||||
var matchingAffliction = AfflictionPrefab.List
|
||||
@@ -1392,7 +1414,7 @@ namespace Barotrauma
|
||||
if (inputType == InputType.Up || inputType == InputType.Down ||
|
||||
inputType == InputType.Left || inputType == InputType.Right)
|
||||
{
|
||||
var invertControls = CharacterHealth.GetAffliction("invertcontrols");
|
||||
var invertControls = CharacterHealth.GetAfflictionOfType("invertcontrols".ToIdentifier());
|
||||
if (invertControls != null)
|
||||
{
|
||||
switch (inputType)
|
||||
@@ -1652,14 +1674,9 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Can be used to modify a character's health for runtime session. Change with AddHealthMultiplier
|
||||
/// Health multiplier of the human prefab this character is an instance of (if any)
|
||||
/// </summary>
|
||||
public float StaticHealthMultiplier { get; private set; } = 1;
|
||||
|
||||
public void AddStaticHealthMultiplier(float newMultiplier)
|
||||
{
|
||||
StaticHealthMultiplier *= newMultiplier;
|
||||
}
|
||||
public float HumanPrefabHealthMultiplier { get; private set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Speed reduction from the current limb specific damage. Min 0, max 1.
|
||||
@@ -4824,21 +4841,21 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
private readonly List<AbilityFlags> abilityFlags = new List<AbilityFlags>();
|
||||
private AbilityFlags abilityFlags;
|
||||
|
||||
public void AddAbilityFlag(AbilityFlags abilityFlag)
|
||||
{
|
||||
abilityFlags.Add(abilityFlag);
|
||||
abilityFlags |= abilityFlag;
|
||||
}
|
||||
|
||||
public void RemoveAbilityFlag(AbilityFlags abilityFlag)
|
||||
{
|
||||
abilityFlags.Remove(abilityFlag);
|
||||
abilityFlags &= ~abilityFlag;
|
||||
}
|
||||
|
||||
public bool HasAbilityFlag(AbilityFlags abilityFlag)
|
||||
{
|
||||
return abilityFlags.Contains(abilityFlag) || CharacterHealth.HasFlag(abilityFlag);
|
||||
return abilityFlags.HasFlag(abilityFlag) || CharacterHealth.HasFlag(abilityFlag);
|
||||
}
|
||||
|
||||
private readonly Dictionary<Identifier, float> abilityResistances = new Dictionary<Identifier, float>();
|
||||
|
||||
+6
-2
@@ -35,6 +35,7 @@ namespace Barotrauma
|
||||
if (newValue > _strength)
|
||||
{
|
||||
PendingAdditionStrength = Prefab.GrainBurst;
|
||||
Duration = Prefab.Duration;
|
||||
}
|
||||
_strength = newValue;
|
||||
}
|
||||
@@ -60,6 +61,8 @@ namespace Barotrauma
|
||||
|
||||
public double AppliedAsSuccessfulTreatmentTime, AppliedAsFailedTreatmentTime;
|
||||
|
||||
public float Duration;
|
||||
|
||||
/// <summary>
|
||||
/// Which character gave this affliction
|
||||
/// </summary>
|
||||
@@ -75,6 +78,8 @@ namespace Barotrauma
|
||||
_strength = strength;
|
||||
Identifier = prefab.Identifier;
|
||||
|
||||
Duration = prefab.Duration;
|
||||
|
||||
foreach (var periodicEffect in prefab.PeriodicEffects)
|
||||
{
|
||||
PeriodicEffectTimers[periodicEffect] = Rand.Range(periodicEffect.MinInterval, periodicEffect.MaxInterval);
|
||||
@@ -315,8 +320,7 @@ namespace Barotrauma
|
||||
public bool HasFlag(AbilityFlags flagType)
|
||||
{
|
||||
if (!(GetViableEffect() is AfflictionPrefab.Effect currentEffect)) { return false; }
|
||||
|
||||
return currentEffect.AfflictionAbilityFlags.Contains(flagType);
|
||||
return currentEffect.AfflictionAbilityFlags.HasFlag(flagType);
|
||||
}
|
||||
|
||||
private AfflictionPrefab.Effect GetViableEffect()
|
||||
|
||||
+11
-4
@@ -235,7 +235,7 @@ namespace Barotrauma
|
||||
public Identifier[] BlockTransformation { get; private set; }
|
||||
|
||||
public readonly Dictionary<StatTypes, (float minValue, float maxValue)> AfflictionStatValues = new Dictionary<StatTypes, (float minValue, float maxValue)>();
|
||||
public readonly HashSet<AbilityFlags> AfflictionAbilityFlags = new HashSet<AbilityFlags>();
|
||||
public AbilityFlags AfflictionAbilityFlags;
|
||||
|
||||
//statuseffects applied on the character when the affliction is active
|
||||
public readonly List<StatusEffect> StatusEffects = new List<StatusEffect>();
|
||||
@@ -265,7 +265,7 @@ namespace Barotrauma
|
||||
break;
|
||||
case "abilityflag":
|
||||
var flagType = CharacterAbilityGroup.ParseFlagType(subElement.GetAttributeString("flagtype", ""), parentDebugName);
|
||||
AfflictionAbilityFlags.Add(flagType);
|
||||
AfflictionAbilityFlags |= flagType;
|
||||
break;
|
||||
case "affliction":
|
||||
DebugConsole.AddWarning($"Error in affliction \"{parentDebugName}\" - additional afflictions caused by the affliction should be configured inside status effects.");
|
||||
@@ -354,6 +354,11 @@ namespace Barotrauma
|
||||
//how strong the affliction needs to be before bots attempt to treat it
|
||||
public readonly float TreatmentThreshold = 5.0f;
|
||||
|
||||
/// <summary>
|
||||
/// The affliction is automatically removed after this time. 0 = unlimited
|
||||
/// </summary>
|
||||
public readonly float Duration;
|
||||
|
||||
//how much karma changes when a player applies this affliction to someone (per strength of the affliction)
|
||||
public float KarmaChangeOnApplied;
|
||||
|
||||
@@ -407,8 +412,10 @@ namespace Barotrauma
|
||||
!IsBuff &&
|
||||
AfflictionType != "geneticmaterialbuff" &&
|
||||
AfflictionType != "geneticmaterialdebuff");
|
||||
HealCostMultiplier = element.GetAttributeFloat(nameof(HealCostMultiplier).ToLowerInvariant(), 1f);
|
||||
BaseHealCost = element.GetAttributeInt(nameof(BaseHealCost).ToLowerInvariant(), 0);
|
||||
HealCostMultiplier = element.GetAttributeFloat(nameof(HealCostMultiplier), 1f);
|
||||
BaseHealCost = element.GetAttributeInt(nameof(BaseHealCost), 0);
|
||||
|
||||
Duration = element.GetAttributeFloat(nameof(Duration), 0.0f);
|
||||
|
||||
if (element.GetAttribute("nameidentifier") != null)
|
||||
{
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Barotrauma.Extensions;
|
||||
using Barotrauma.Networking;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Barotrauma.Networking;
|
||||
using Barotrauma.Extensions;
|
||||
using System.Globalization;
|
||||
using Barotrauma.Abilities;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -148,7 +147,7 @@ namespace Barotrauma
|
||||
{
|
||||
max += Character.Info.Job.Prefab.VitalityModifier;
|
||||
}
|
||||
max *= Character.StaticHealthMultiplier;
|
||||
max *= Character.HumanPrefabHealthMultiplier;
|
||||
max *= 1f + Character.GetStatValue(StatTypes.MaximumHealthMultiplier);
|
||||
return max * Character.HealthMultiplier;
|
||||
}
|
||||
@@ -700,6 +699,7 @@ namespace Barotrauma
|
||||
newStrength = Math.Min(existingAffliction.Prefab.MaxStrength, newStrength);
|
||||
if (existingAffliction == stunAffliction) { Character.SetStun(newStrength, true, true); }
|
||||
existingAffliction.Strength = newStrength;
|
||||
existingAffliction.Duration = existingAffliction.Prefab.Duration;
|
||||
if (newAffliction.Source != null) { existingAffliction.Source = newAffliction.Source; }
|
||||
CalculateVitality();
|
||||
if (Vitality <= MinVitality)
|
||||
@@ -759,6 +759,15 @@ namespace Barotrauma
|
||||
if (!irremovableAfflictions.Contains(affliction)) { afflictionsToRemove.Add(affliction); }
|
||||
continue;
|
||||
}
|
||||
if (affliction.Prefab.Duration > 0.0f)
|
||||
{
|
||||
affliction.Duration -= deltaTime;
|
||||
if (affliction.Duration <= 0.0f)
|
||||
{
|
||||
afflictionsToRemove.Add(affliction);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
afflictionsToUpdate.Add(kvp);
|
||||
}
|
||||
foreach (KeyValuePair<Affliction, LimbHealth> kvp in afflictionsToUpdate)
|
||||
|
||||
@@ -112,12 +112,6 @@ namespace Barotrauma
|
||||
|
||||
public void InitializeCharacter(Character npc, ISpatialEntity positionToStayIn = null)
|
||||
{
|
||||
npc.AddStaticHealthMultiplier(HealthMultiplier);
|
||||
if (GameMain.NetworkMember != null)
|
||||
{
|
||||
npc.AddStaticHealthMultiplier(HealthMultiplierInMultiplayer);
|
||||
}
|
||||
|
||||
var humanAI = npc.AIController as HumanAIController;
|
||||
if (humanAI != null)
|
||||
{
|
||||
|
||||
+33
-41
@@ -138,61 +138,53 @@ namespace Barotrauma
|
||||
ragdolls = new Dictionary<string, RagdollParams>();
|
||||
allRagdolls.Add(speciesName, ragdolls);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(fileName) && ragdolls.TryGetValue(fileName, out RagdollParams ragdoll))
|
||||
{
|
||||
return (T)ragdoll;
|
||||
}
|
||||
|
||||
string selectedFile = null;
|
||||
|
||||
void tryFolderForSpecies(Identifier species, out string err)
|
||||
Identifier ragdollSpecies = speciesName;
|
||||
if (CharacterPrefab.Prefabs.TryGet(speciesName, out var prefab))
|
||||
{
|
||||
err = null;
|
||||
string folder = GetFolder(species);
|
||||
if (!prefab.VariantOf.IsEmpty)
|
||||
{
|
||||
ragdollSpecies = prefab.VariantOf;
|
||||
}
|
||||
string error = null;
|
||||
string folder = GetFolder(ragdollSpecies);
|
||||
if (!Directory.Exists(folder))
|
||||
{
|
||||
err = $"[RagdollParams] Invalid directory: {folder}. Using the default ragdoll.";
|
||||
selectedFile = GetDefaultFile(species);
|
||||
return;
|
||||
}
|
||||
|
||||
string[] files = Directory.GetFiles(folder);
|
||||
if (files.None())
|
||||
{
|
||||
err = $"[RagdollParams] Could not find any ragdoll files from the folder: {folder}. Using the default ragdoll.";
|
||||
selectedFile = GetDefaultFile(species);
|
||||
}
|
||||
else if (string.IsNullOrEmpty(fileName))
|
||||
{
|
||||
// Files found, but none specified
|
||||
selectedFile = GetDefaultFile(species);
|
||||
error = $"[RagdollParams] Invalid directory: {folder}. Using the default ragdoll.";
|
||||
selectedFile = GetDefaultFile(ragdollSpecies);
|
||||
}
|
||||
else
|
||||
{
|
||||
selectedFile = files.FirstOrDefault(f => IO.Path.GetFileNameWithoutExtension(f).Equals(fileName, StringComparison.OrdinalIgnoreCase));
|
||||
if (selectedFile == null)
|
||||
string[] files = Directory.GetFiles(folder);
|
||||
if (files.None())
|
||||
{
|
||||
err = $"[RagdollParams] Could not find a ragdoll file that matches the name {fileName}. Using the default ragdoll.";
|
||||
selectedFile = GetDefaultFile(species);
|
||||
error = $"[RagdollParams] Could not find any ragdoll files from the folder: {folder}. Using the default ragdoll.";
|
||||
selectedFile = GetDefaultFile(ragdollSpecies);
|
||||
}
|
||||
else if (string.IsNullOrEmpty(fileName))
|
||||
{
|
||||
// Files found, but none specified
|
||||
selectedFile = GetDefaultFile(ragdollSpecies);
|
||||
}
|
||||
else
|
||||
{
|
||||
selectedFile = files.FirstOrDefault(f => IO.Path.GetFileNameWithoutExtension(f).Equals(fileName, StringComparison.OrdinalIgnoreCase));
|
||||
if (selectedFile == null)
|
||||
{
|
||||
error = $"[RagdollParams] Could not find a ragdoll file that matches the name {fileName}. Using the default ragdoll.";
|
||||
selectedFile = GetDefaultFile(ragdollSpecies);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (error != null)
|
||||
{
|
||||
DebugConsole.ThrowError(error);
|
||||
}
|
||||
}
|
||||
|
||||
tryFolderForSpecies(speciesName, out var error);
|
||||
Identifier parentSpeciesName = CharacterPrefab.Prefabs.TryGet(speciesName, out var prefab)
|
||||
? prefab.VariantOf
|
||||
: Identifier.Empty;
|
||||
if (!error.IsNullOrEmpty() && !parentSpeciesName.IsEmpty)
|
||||
{
|
||||
tryFolderForSpecies(parentSpeciesName, out error);
|
||||
}
|
||||
|
||||
if (!error.IsNullOrEmpty())
|
||||
{
|
||||
DebugConsole.ThrowError(error);
|
||||
}
|
||||
|
||||
if (selectedFile == null)
|
||||
{
|
||||
throw new Exception("[RagdollParams] Selected file null!");
|
||||
@@ -200,7 +192,7 @@ namespace Barotrauma
|
||||
DebugConsole.Log($"[RagdollParams] Loading ragdoll from {selectedFile}.");
|
||||
var characterPrefab = CharacterPrefab.Prefabs[speciesName];
|
||||
T r = new T();
|
||||
if (r.Load(ContentPath.FromRaw(characterPrefab.ContentPackage, selectedFile), speciesName))
|
||||
if (r.Load(ContentPath.FromRaw(characterPrefab.ContentPackage, selectedFile), ragdollSpecies))
|
||||
{
|
||||
if (!ragdolls.ContainsKey(r.Name))
|
||||
{
|
||||
|
||||
-1
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Abilities
|
||||
{
|
||||
|
||||
+1
-3
@@ -1,6 +1,4 @@
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Abilities
|
||||
namespace Barotrauma.Abilities
|
||||
{
|
||||
abstract class AbilityConditionDataless : AbilityCondition
|
||||
{
|
||||
|
||||
-3
@@ -1,8 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Abilities
|
||||
{
|
||||
|
||||
-1
@@ -1,5 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Abilities
|
||||
{
|
||||
|
||||
+2
-6
@@ -1,7 +1,4 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Abilities
|
||||
{
|
||||
@@ -19,10 +16,9 @@ namespace Barotrauma.Abilities
|
||||
|
||||
protected override void ApplyEffect()
|
||||
{
|
||||
IEnumerable<Character> chosenCharacters = Character.GetFriendlyCrew(Character).Where(c => allowSelf || c != Character);
|
||||
|
||||
foreach (Character character in chosenCharacters)
|
||||
foreach (Character character in Character.GetFriendlyCrew(Character))
|
||||
{
|
||||
if (!allowSelf && character == Character) { continue; }
|
||||
if (maxDistance < float.MaxValue)
|
||||
{
|
||||
if (Vector2.DistanceSquared(character.WorldPosition, Character.WorldPosition) > maxDistance * maxDistance) { continue; }
|
||||
|
||||
+1
-4
@@ -1,7 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Abilities
|
||||
namespace Barotrauma.Abilities
|
||||
{
|
||||
class CharacterAbilityApplyStatusEffectsToAttacker : CharacterAbilityApplyStatusEffects
|
||||
{
|
||||
|
||||
+1
-3
@@ -1,6 +1,4 @@
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Abilities
|
||||
namespace Barotrauma.Abilities
|
||||
{
|
||||
class CharacterAbilityApplyStatusEffectsToLastOrderedCharacter : CharacterAbilityApplyStatusEffects
|
||||
{
|
||||
|
||||
-1
@@ -1,6 +1,5 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Abilities
|
||||
{
|
||||
|
||||
-1
@@ -2,7 +2,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Abilities
|
||||
{
|
||||
|
||||
+9
-8
@@ -1,10 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Abilities
|
||||
namespace Barotrauma.Abilities
|
||||
{
|
||||
class CharacterAbilityGroupEffect : CharacterAbilityGroup
|
||||
{
|
||||
@@ -30,7 +24,14 @@ namespace Barotrauma.Abilities
|
||||
private bool IsApplicable(AbilityObject abilityObject)
|
||||
{
|
||||
if (timesTriggered >= maxTriggerCount) { return false; }
|
||||
return abilityConditions.All(c => c.MatchesCondition(abilityObject));
|
||||
foreach (var abilityCondition in abilityConditions)
|
||||
{
|
||||
if (!abilityCondition.MatchesCondition(abilityObject))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+9
-8
@@ -1,10 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Abilities
|
||||
namespace Barotrauma.Abilities
|
||||
{
|
||||
class CharacterAbilityGroupInterval : CharacterAbilityGroup
|
||||
{
|
||||
@@ -49,7 +43,14 @@ namespace Barotrauma.Abilities
|
||||
private bool IsApplicable()
|
||||
{
|
||||
if (timesTriggered >= maxTriggerCount) { return false; }
|
||||
return abilityConditions.All(c => c.MatchesCondition());
|
||||
foreach (var abilityCondition in abilityConditions)
|
||||
{
|
||||
if (!abilityCondition.MatchesCondition())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
using System;
|
||||
using Barotrauma.Abilities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Barotrauma.Abilities;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user