Unstable 1.8.4.0

This commit is contained in:
Markus Isberg
2025-03-12 12:56:27 +00:00
parent a4c3e868e4
commit a4a3427e4e
627 changed files with 29860 additions and 10018 deletions
@@ -20,7 +20,7 @@ namespace Barotrauma
private List<LevelObject> updateableObjects;
private List<LevelObject>[,] objectGrid;
const float ParallaxStrength = 0.0001f;
public const float ParallaxStrength = 0.0001f;
public float GlobalForceDecreaseTimer
{
@@ -178,12 +178,21 @@ namespace Barotrauma
{
float minDistance = level.Size.X * 0.2f;
bool allowAtStart = prefab.AllowAtStart;
bool allowAtEnd = prefab.AllowAtEnd;
if (GameMain.GameSession?.GameMode is PvPMode)
{
//in PvP mode, the object must be allowed at both the start and end to be placed at either end
//since the 2nd team starts at the end of the level, it'd be unfair to allow e.g. ballast flora to spawn at the end of the level but not the start
allowAtEnd = allowAtStart = allowAtEnd && allowAtStart;
}
suitableSpawnPositions.Add(prefab,
availableSpawnPositions.Where(sp =>
sp.SpawnPosTypes.Any(type => prefab.SpawnPos.HasFlag(type)) &&
sp.Length >= prefab.MinSurfaceWidth &&
(prefab.AllowAtStart || !level.IsCloseToStart(sp.GraphEdge.Center, minDistance)) &&
(prefab.AllowAtEnd || !level.IsCloseToEnd(sp.GraphEdge.Center, minDistance)) &&
(allowAtStart || !level.IsCloseToStart(sp.GraphEdge.Center, minDistance)) &&
(allowAtEnd || !level.IsCloseToEnd(sp.GraphEdge.Center, minDistance)) &&
(sp.Alignment == Alignment.Any || prefab.Alignment.HasFlag(sp.Alignment))).ToList());
spawnPositionWeights.Add(prefab,
@@ -407,11 +416,11 @@ namespace Barotrauma
}
}
float minX = spriteCorners.Min(c => c.X) - newObject.Position.Z * ParallaxStrength;
float maxX = spriteCorners.Max(c => c.X) + newObject.Position.Z * ParallaxStrength;
float minX = spriteCorners.Min(c => c.X) - newObject.Position.Z;
float maxX = spriteCorners.Max(c => c.X) + newObject.Position.Z;
float minY = spriteCorners.Min(c => c.Y) - newObject.Position.Z * ParallaxStrength - level.BottomPos;
float maxY = spriteCorners.Max(c => c.Y) + newObject.Position.Z * ParallaxStrength - level.BottomPos;
float minY = spriteCorners.Min(c => c.Y) - newObject.Position.Z - level.BottomPos;
float maxY = spriteCorners.Max(c => c.Y) + newObject.Position.Z - level.BottomPos;
if (newObject.Triggers != null)
{
@@ -446,6 +455,8 @@ namespace Barotrauma
#endif
objects.Add(newObject);
if (newObject.NeedsUpdate) { updateableObjects.Add(newObject); }
//add some variance to the Z position to prevent z-fighting
//(based on the x and y position of the object, scaled to be visually insignificant)
newObject.Position.Z += (minX + minY) % 100.0f * 0.00001f;
int xStart = (int)Math.Floor(minX / GridSize);
@@ -557,7 +568,7 @@ namespace Barotrauma
return availableSpawnPositions;
}
public void Update(float deltaTime)
public void Update(float deltaTime, Camera cam)
{
GlobalForceDecreaseTimer += deltaTime;
if (GlobalForceDecreaseTimer > 1000000.0f)
@@ -603,10 +614,10 @@ namespace Barotrauma
}
}
UpdateProjSpecific(deltaTime);
UpdateProjSpecific(deltaTime, cam);
}
partial void UpdateProjSpecific(float deltaTime);
partial void UpdateProjSpecific(float deltaTime, Camera cam);
private void OnObjectTriggered(LevelObject triggeredObject, LevelTrigger trigger, Entity triggerer)
{
@@ -1,7 +1,6 @@
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Xml.Linq;
@@ -136,6 +135,14 @@ namespace Barotrauma
private set;
}
[Serialize(3000.0f, IsPropertySaveable.Yes, description: "Objects fade out to the background color of the level the further they are from the camera. This value is the depth at which the object becomes \"maximally\" faded out."), Editable]
public float FadeOutDepth
{
get;
private set;
}
[Editable(MinValueFloat = 0.0f, MaxValueFloat = 10.0f),
Serialize(0.0f, IsPropertySaveable.Yes, description: "The tendency for the prefab to form clusters. Used as an exponent for perlin noise values that are used to determine the probability for an object to spawn at a specific position.")]
/// <summary>
@@ -339,11 +346,11 @@ namespace Barotrauma
InitProjSpecific(element);
}
//use the maximum width of the sprite as the minimum surface width if no value is given
if (element != null && !element.Attributes("minsurfacewidth").Any())
//use (a bit less than) the maximum width of the sprite as the minimum surface width if no value is given
if (element != null && element.GetAttribute("minsurfacewidth") == null)
{
if (Sprites.Any()) MinSurfaceWidth = Sprites[0].size.X * MaxSize;
if (DeformableSprite != null) MinSurfaceWidth = Math.Max(MinSurfaceWidth, DeformableSprite.Size.X * MaxSize);
if (Sprites.Any()) { MinSurfaceWidth = Sprites[0].size.X * MaxSize * 0.8f; }
if (DeformableSprite != null) { MinSurfaceWidth = Math.Max(MinSurfaceWidth, DeformableSprite.Size.X * MaxSize * 0.8f); }
}
}
@@ -6,7 +6,9 @@ using FarseerPhysics.Dynamics.Contacts;
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Barotrauma.Items.Components;
namespace Barotrauma
{
@@ -55,6 +57,8 @@ namespace Barotrauma
private readonly HashSet<Entity> triggerers = new HashSet<Entity>();
private readonly TriggererType triggeredBy;
private readonly Identifier triggerSpeciesOrGroup;
private readonly PropertyConditional.LogicalComparison conditionals;
private readonly float randomTriggerInterval;
private readonly float randomTriggerProbability;
@@ -255,7 +259,16 @@ namespace Barotrauma
string triggeredByStr = element.GetAttributeString("triggeredby", "Character");
if (!Enum.TryParse(triggeredByStr, out triggeredBy))
{
DebugConsole.ThrowError("Error in LevelTrigger config: \"" + triggeredByStr + "\" is not a valid triggerer type.");
Identifier speciesOrGroup = triggeredByStr.ToIdentifier();
if (CharacterPrefab.Prefabs.Any(p => p.MatchesSpeciesNameOrGroup(speciesOrGroup)))
{
triggerSpeciesOrGroup = speciesOrGroup;
triggeredBy = TriggererType.Character;
}
else
{
DebugConsole.ThrowError("Error in LevelTrigger config: \"" + triggeredByStr + "\" is not a valid triggerer type.");
}
}
if (PhysicsBody != null)
{
@@ -293,6 +306,8 @@ namespace Barotrauma
break;
}
}
conditionals = PropertyConditional.LoadConditionals(element);
forceFluctuationTimer = Rand.Range(0.0f, ForceFluctuationInterval);
randomTriggerTimer = Rand.Range(0.0f, randomTriggerInterval);
@@ -341,7 +356,7 @@ namespace Barotrauma
{
Entity entity = GetEntity(fixtureB);
if (entity == null) { return false; }
if (!IsTriggeredByEntity(entity, triggeredBy, mustBeOutside: true)) { return false; }
if (!IsTriggeredByEntity(entity, triggeredBy, triggerSpeciesOrGroup: triggerSpeciesOrGroup, conditionals: conditionals, mustBeOutside: true)) { return false; }
if (!triggerers.Contains(entity))
{
if (!IsTriggered)
@@ -354,12 +369,22 @@ namespace Barotrauma
return true;
}
public static bool IsTriggeredByEntity(Entity entity, TriggererType triggeredBy, bool mustBeOutside = false, (bool mustBe, Submarine sub) mustBeOnSpecificSub = default)
public static bool IsTriggeredByEntity(
Entity entity,
TriggererType triggeredBy,
Identifier triggerSpeciesOrGroup,
PropertyConditional.LogicalComparison conditionals,
(bool mustBe, Submarine sub) mustBeOnSpecificSub = default,
bool mustBeOutside = false)
{
if (entity is Character character)
{
if (mustBeOutside && character.CurrentHull != null) { return false; }
if (mustBeOnSpecificSub.mustBe && character.Submarine != mustBeOnSpecificSub.sub) { return false; }
if (!triggerSpeciesOrGroup.IsEmpty)
{
if (character.SpeciesName != triggerSpeciesOrGroup && character.Group != triggerSpeciesOrGroup) { return false; }
}
if (character.IsHuman)
{
if (!triggeredBy.HasFlag(TriggererType.Human)) { return false; }
@@ -379,6 +404,10 @@ namespace Barotrauma
{
if (!triggeredBy.HasFlag(TriggererType.Submarine)) { return false; }
}
if (conditionals != null && entity is ISerializableEntity serializableEntity)
{
if (!PropertyConditional.CheckConditionals(serializableEntity, conditionals.Conditionals, conditionals.LogicalOperator)) { return false; }
}
return true;
}
@@ -497,7 +526,7 @@ namespace Barotrauma
triggeredTimer = stayTriggeredDelay;
if (!wasAlreadyTriggered)
{
if (!IsTriggeredByEntity(triggerer, triggeredBy, mustBeOutside: true)) { return; }
if (!IsTriggeredByEntity(triggerer, triggeredBy, triggerSpeciesOrGroup, conditionals, mustBeOutside: true)) { return; }
if (!triggerers.Contains(triggerer))
{
if (!IsTriggered)
@@ -580,6 +609,21 @@ namespace Barotrauma
return;
}
if (PhysicsBody != null)
{
if (currentForceFluctuation <= 0.0f && statusEffects.None() && attacks.None())
{
//no force atm, and no status effects or attacks the trigger could apply
// -> we can disable the collider and get a minor physics performance improvement
PhysicsBody.Enabled = false;
return;
}
else
{
PhysicsBody.Enabled = true;
}
}
foreach (Entity triggerer in triggerers)
{
if (triggerer.Removed) { continue; }
@@ -652,13 +696,20 @@ namespace Barotrauma
}
}
public static void ApplyStatusEffects(List<StatusEffect> statusEffects, Vector2 worldPosition, Entity triggerer, float deltaTime, List<ISerializableEntity> targets)
public static void ApplyStatusEffects(List<StatusEffect> statusEffects, Vector2 worldPosition, Entity triggerer, float deltaTime, List<ISerializableEntity> targets, Item targetItem = null)
{
foreach (StatusEffect effect in statusEffects)
{
if (effect.type == ActionType.OnBroken) { return; }
Vector2? position = null;
if (effect.HasTargetType(StatusEffect.TargetType.This)) { position = worldPosition; }
if (effect.HasTargetType(StatusEffect.TargetType.This))
{
position = worldPosition;
if (targetItem != null)
{
effect.Apply(effect.type, deltaTime, triggerer, targetItem.AllPropertyObjects, position);
}
}
if (triggerer is Character character)
{
effect.Apply(effect.type, deltaTime, triggerer, character, position);
@@ -728,6 +779,8 @@ namespace Barotrauma
if (distFactor < 0.0f) return;
}
if (MathUtils.NearlyEqual(currentForceFluctuation, 0.0f)) { return; }
switch (ForceMode)
{
case TriggerForceMode.Force: