v1.7.7.0 (Winter Update 2024)

This commit is contained in:
Regalis11
2024-12-11 13:26:13 +02:00
parent 7d5b7a310a
commit f6349b2175
256 changed files with 4794 additions and 1653 deletions
@@ -42,7 +42,7 @@ namespace Barotrauma
if (wallTarget != null && !IsCoolDownRunning)
{
Vector2 wallTargetPos = wallTarget.Position;
if (wallTarget.Structure.Submarine != null) { wallTargetPos += wallTarget.Structure.Submarine.Position; }
if (wallTarget.Structure.Submarine != null) { wallTargetPos += wallTarget.Structure.Submarine.DrawPosition; }
wallTargetPos.Y = -wallTargetPos.Y;
GUI.DrawRectangle(spriteBatch, wallTargetPos - new Vector2(10.0f, 10.0f), new Vector2(20.0f, 20.0f), Color.Orange, false);
GUI.DrawLine(spriteBatch, pos, wallTargetPos, Color.Orange * 0.5f, 0, 5);
@@ -11,7 +11,7 @@ namespace Barotrauma
{
if (Character == Character.Controlled) { return; }
if (!DebugAI) { return; }
Vector2 pos = Character.WorldPosition;
Vector2 pos = Character.DrawPosition;
pos.Y = -pos.Y;
Vector2 textOffset = new Vector2(-40, -160);
textOffset.Y -= Math.Max(ObjectiveManager.CurrentOrders.Count - 1, 0) * 20;
@@ -93,6 +93,9 @@ namespace Barotrauma
character.AnimController.Anim = AnimController.Animation.None;
}
character.AnimController.IgnorePlatforms = character.MemState[0].IgnorePlatforms;
character.AnimController.overrideTargetMovement = character.MemState[0].TargetMovement;
Vector2 newVelocity = Collider.LinearVelocity;
Vector2 newPosition = Collider.SimPosition;
float newRotation = Collider.Rotation;
@@ -103,16 +106,17 @@ namespace Barotrauma
{
newVelocity = newVelocity.ClampLength(100.0f);
if (!MathUtils.IsValid(newVelocity)) { newVelocity = Vector2.Zero; }
overrideTargetMovement = newVelocity.LengthSquared() > 0.01f ? newVelocity : Vector2.Zero;
Collider.LinearVelocity = newVelocity;
Collider.AngularVelocity = newAngularVelocity;
}
float distSqrd = Vector2.DistanceSquared(newPosition, Collider.SimPosition);
float errorTolerance = character.CanMove && (!character.IsRagdolled || character.AnimController.IsHangingWithRope) ? 0.01f : 0.2f;
float errorTolerance =
ColliderControlsMovement && (!character.IsRagdolled || character.AnimController.IsHangingWithRope) ? 0.01f : 0.2f;
if (distSqrd > errorTolerance)
{
if (distSqrd > 10.0f || !character.CanMove)
character.AnimController.BodyInRest = false;
if (distSqrd > 10.0f)
{
Collider.TargetRotation = newRotation;
if (distSqrd > 10.0f)
@@ -126,28 +130,31 @@ namespace Barotrauma
}
}
SetPosition(newPosition, lerp: distSqrd < 5.0f, ignorePlatforms: false);
//make sure ragdoll isn't stuck at the wrong side of a platform if the movement is controlled by the ragdoll, and the ragdoll has come to rest server-side
if (!ColliderControlsMovement && newVelocity.LengthSquared() < 0.01f) { TryPlatformCorrection(newPosition); }
}
else
else if (ColliderControlsMovement)
{
Collider.TargetRotation = newRotation;
Collider.TargetPosition = newPosition;
Collider.MoveToTargetPosition(true);
}
}
//immobilized characters can't correct their position using AnimController movement
// -> we need to correct it manually
if (!character.CanMove)
{
float mainLimbDistSqrd = Vector2.DistanceSquared(MainLimb.PullJointWorldAnchorA, Collider.SimPosition);
float mainLimbErrorTolerance = 0.1f;
//if the main limb is roughly at the correct position and the collider isn't moving (much at least),
//don't attempt to correct the position.
if (mainLimbDistSqrd > mainLimbErrorTolerance || Collider.LinearVelocity.LengthSquared() > 0.05f)
else
{
MainLimb.PullJointWorldAnchorB = Collider.SimPosition;
MainLimb.PullJointEnabled = true;
MainLimb.body.LinearVelocity = newVelocity;
float mainLimbDistSqrd = Vector2.DistanceSquared(MainLimb.PullJointWorldAnchorA, newPosition);
float mainLimbErrorTolerance = 0.1f;
//if the main limb is roughly at the correct position and the collider isn't moving (much at least),
//don't attempt to correct the position.
if (mainLimbDistSqrd > mainLimbErrorTolerance)
{
MainLimb.PullJointWorldAnchorB = newPosition;
MainLimb.PullJointEnabled = true;
if (!ColliderControlsMovement && newVelocity.LengthSquared() < 0.01f) { TryPlatformCorrection(newPosition); }
}
else
{
MainLimb.body.LinearVelocity = newVelocity;
}
}
}
}
@@ -179,9 +186,9 @@ namespace Barotrauma
}
}
if (character.MemState.Count < 1) return;
if (character.MemState.Count < 1) { return; }
overrideTargetMovement = Vector2.Zero;
overrideTargetMovement = null;
CharacterStateInfo serverPos = character.MemState.Last();
@@ -294,6 +301,38 @@ namespace Barotrauma
character.MemState.Clear();
}
}
/// <summary>
/// Attempts to correct the ragdoll to the correct side of a platform if the server position is above the platform and some of the ragdoll's limbs below it client-side, or vice versa.
/// </summary>
private void TryPlatformCorrection(Vector2 serverPos)
{
float highestPos = limbs.Where(static l => !l.IsSevered).Max(static l => l.SimPosition.Y);
highestPos = Math.Max(serverPos.Y, highestPos);
float lowestPos = limbs.Where(static l => !l.IsSevered).Min(static l => l.SimPosition.Y);
lowestPos = Math.Min(serverPos.Y, lowestPos);
var platform = Submarine.PickBody(new Vector2(serverPos.X, highestPos), new Vector2(serverPos.X, lowestPos), collisionCategory: Physics.CollisionPlatform, allowInsideFixture: true);
if (platform == null) { return; }
int serverDir = Math.Sign(serverPos.Y - platform.Position.Y);
foreach (var limb in limbs)
{
if (limb.IsSevered) { continue; }
int limbDir = Math.Sign(limb.SimPosition.Y - platform.Position.Y);
const float Margin = 0.01f;
if (limbDir != serverDir)
{
limb.body.SetTransformIgnoreContacts(
new Vector2(
limb.SimPosition.X,
serverDir > 0 ? Math.Max(serverPos.Y + Margin + limb.body.GetMaxExtent(), limb.SimPosition.Y) : Math.Min(serverPos.Y - Margin - limb.body.GetMaxExtent(), limb.SimPosition.Y)),
limb.Rotation);
}
}
}
partial void ImpactProjSpecific(float impact, Body body)
{
@@ -250,7 +250,7 @@ namespace Barotrauma
public Vector2 Position;
public Vector2 DrawPosition;
public float MoveUpAmount;
public readonly string Text;
public readonly RichString Text;
public readonly Character Character;
public readonly Submarine Submarine;
public readonly Vector2 TextSize;
@@ -260,7 +260,7 @@ namespace Barotrauma
public SpeechBubble(Character character, float lifeTime, Color color, string text = "")
{
Text = ToolBox.WrapText(text, GUI.IntScale(300), GUIStyle.SmallFont.GetFontForStr(text));
Text = RichString.Rich(ToolBox.WrapText(text, GUI.IntScale(300), GUIStyle.SmallFont.GetFontForStr(text)));
TextSize = GUIStyle.SmallFont.MeasureString(Text);
Character = character;
@@ -322,7 +322,6 @@ namespace Barotrauma
/// </summary>
public void ControlLocalPlayer(float deltaTime, Camera cam, bool moveCam = true)
{
if (DisableControls || GUI.InputBlockingMenuOpen)
{
foreach (Key key in keys)
@@ -417,6 +416,11 @@ namespace Barotrauma
UpdateLocalCursor(cam);
if (IsKeyHit(InputType.ToggleRun))
{
ToggleRun = !ToggleRun;
}
Vector2 mouseSimPos = ConvertUnits.ToSimUnits(cursorPosition);
if (GUI.PauseMenuOpen)
{
@@ -1189,7 +1193,7 @@ namespace Barotrauma
Vector2 bubbleSize = bubble.TextSize + Vector2.One * GUI.IntScale(15);
speechBubbleIconSliced.Draw(spriteBatch, new RectangleF(iconPos - bubbleSize / 2, bubbleSize), bubble.Color * Math.Min(bubble.LifeTime, 1.0f) * alpha);
}
GUI.DrawString(spriteBatch, iconPos - bubble.TextSize / 2, bubble.Text, bubble.Color * Math.Min(bubble.LifeTime, 1.0f) * alpha, font: GUIStyle.SmallFont);
GUI.DrawStringWithColors(spriteBatch, iconPos - bubble.TextSize / 2, bubble.Text.SanitizedValue, bubble.Color * Math.Min(bubble.LifeTime, 1.0f) * alpha, bubble.Text.RichTextData, font: GUIStyle.SmallFont);
}
spriteBatch.End();
}
@@ -1435,7 +1439,10 @@ namespace Barotrauma
partial void OnTalentGiven(TalentPrefab talentPrefab)
{
AddMessage(TextManager.Get("talentname." + talentPrefab.Identifier).Value, GUIStyle.Yellow, playSound: this == Controlled);
if (!talentPrefab.IsHiddenExtraTalent)
{
AddMessage(TextManager.Get("talentname." + talentPrefab.Identifier).Value, GUIStyle.Yellow, playSound: this == Controlled);
}
}
}
}
@@ -11,17 +11,15 @@ namespace Barotrauma
{
partial class CharacterHUD
{
const float BossHealthBarDuration = 120.0f;
abstract class BossProgressBar
abstract class ProgressBar
{
public float FadeTimer;
public readonly GUIComponent TopContainer;
public readonly GUIComponent SideContainer;
public readonly GUIProgressBar TopHealthBar;
public readonly GUIProgressBar SideHealthBar;
public readonly GUIProgressBar TopBar;
public readonly GUIProgressBar SideBar;
public abstract bool Completed { get; }
@@ -33,9 +31,9 @@ namespace Barotrauma
public abstract Color Color { get; }
public BossProgressBar(LocalizedString label)
public ProgressBar(LocalizedString label, float fadeTimer = 120.0f)
{
FadeTimer = BossHealthBarDuration;
FadeTimer = fadeTimer;
TopContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.18f, 0.03f), HUDFrame.RectTransform, Anchor.TopCenter)
{
@@ -43,25 +41,25 @@ namespace Barotrauma
RelativeOffset = new Vector2(0.0f, 0.01f)
}, isHorizontal: false, childAnchor: Anchor.TopCenter);
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.4f), TopContainer.RectTransform), label, textAlignment: Alignment.Center, textColor: GUIStyle.Red);
TopHealthBar = new GUIProgressBar(new RectTransform(new Vector2(1.0f, 0.6f), TopContainer.RectTransform)
TopBar = new GUIProgressBar(new RectTransform(new Vector2(1.0f, 0.6f), TopContainer.RectTransform)
{
MinSize = new Point(100, HUDLayoutSettings.HealthBarArea.Size.Y)
}, barSize: 0.0f, style: "CharacterHealthBarCentered")
{
Color = GUIStyle.Red
};
CreateNumberText(TopHealthBar);
CreateNumberText(TopBar);
SideContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), bossHealthContainer.RectTransform)
{
MinSize = new Point(80, 60)
}, isHorizontal: false, childAnchor: Anchor.TopRight);
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.3f), SideContainer.RectTransform), label, textAlignment: Alignment.CenterRight, textColor: GUIStyle.Red);
SideHealthBar = new GUIProgressBar(new RectTransform(new Vector2(1.0f, 0.7f), SideContainer.RectTransform), barSize: 0.0f, style: "CharacterHealthBar")
SideBar = new GUIProgressBar(new RectTransform(new Vector2(1.0f, 0.7f), SideContainer.RectTransform), barSize: 0.0f, style: "CharacterHealthBar")
{
Color = GUIStyle.Red
};
CreateNumberText(SideHealthBar);
CreateNumberText(SideBar);
TopContainer.Visible = SideContainer.Visible = false;
TopContainer.CanBeFocused = false;
@@ -88,7 +86,7 @@ namespace Barotrauma
public abstract bool IsDuplicate(object targetObject);
}
class BossHealthBar : BossProgressBar
class HealthBar : ProgressBar
{
public readonly Character Character;
@@ -104,7 +102,7 @@ namespace Barotrauma
public override string NumberToDisplay => string.Empty;
public BossHealthBar(Character character) : base(character.DisplayName)
public HealthBar(Character character) : base(character.DisplayName)
{
Character = character;
}
@@ -115,7 +113,7 @@ namespace Barotrauma
}
}
class MissionProgressBar : BossProgressBar
class MissionProgressBar : ProgressBar
{
public readonly Mission Mission;
@@ -125,13 +123,13 @@ namespace Barotrauma
public override bool Interrupted => Mission.Failed || GameMain.GameSession?.Missions == null || !GameMain.GameSession.Missions.Contains(Mission);
public override Color Color => GUIStyle.Red;
public override Color Color => Mission.Prefab.ProgressBarColor;
public override string NumberToDisplay => Mission.Prefab.ShowProgressInNumbers ?
$"{Mission.State}/{Mission.Prefab.MaxProgressState}" :
string.Empty;
public MissionProgressBar(Mission mission) : base(mission.Prefab.ProgressBarLabel)
public MissionProgressBar(Mission mission) : base(mission.Prefab.ProgressBarLabel, fadeTimer: float.PositiveInfinity)
{
Mission = mission;
}
@@ -150,7 +148,7 @@ namespace Barotrauma
private static readonly List<Item> brokenItems = new List<Item>();
private static float brokenItemsCheckTimer;
private static readonly List<BossProgressBar> bossProgressBars = new List<BossProgressBar>();
private static readonly List<ProgressBar> bossProgressBars = new List<ProgressBar>();
private static readonly Dictionary<Identifier, LocalizedString> cachedHudTexts = new Dictionary<Identifier, LocalizedString>();
private static LanguageIdentifier cachedHudTextLanguage = LanguageIdentifier.None;
@@ -564,7 +562,7 @@ namespace Barotrauma
float alpha = MathHelper.Lerp(0.3f, 1.0f, distFactor);
GUI.DrawIndicator(
spriteBatch,
entity.WorldPosition,
entity.DrawPosition,
cam,
visibleRange,
style.GetDefaultSprite(),
@@ -592,7 +590,7 @@ namespace Barotrauma
if (Vector2.DistanceSquared(character.Position, item.Position) > 500f * 500f) { continue; }
var body = Submarine.CheckVisibility(character.SimPosition, item.SimPosition, ignoreLevel: true);
if (body != null && body.UserData as Item != item) { continue; }
GUI.DrawIndicator(spriteBatch, item.WorldPosition + new Vector2(0f, item.RectHeight * 0.65f), cam, new Range<float>(-100f, 500.0f), item.IconStyle.GetDefaultSprite(), item.IconStyle.Color, createOffset: false);
GUI.DrawIndicator(spriteBatch, item.DrawPosition + new Vector2(0f, item.RectHeight * 0.65f), cam, new Range<float>(-100f, 500.0f), item.IconStyle.GetDefaultSprite(), item.IconStyle.Color, createOffset: false);
}
}
@@ -773,7 +771,7 @@ namespace Barotrauma
GUIStyle.Green, Color.Black, 2, GUIStyle.SmallFont);
textPos.Y += textSize.Y;
}
if (!character.FocusedCharacter.CustomInteractHUDText.IsNullOrEmpty() && character.FocusedCharacter.AllowCustomInteract)
if (character.FocusedCharacter.ShouldShowCustomInteractText)
{
GUI.DrawString(spriteBatch, textPos, character.FocusedCharacter.CustomInteractHUDText, GUIStyle.Green, Color.Black, 2, GUIStyle.SmallFont);
textPos.Y += textSize.Y;
@@ -784,7 +782,7 @@ namespace Barotrauma
{
if (character == null || character.IsDead || character.Removed) { return; }
if (bossProgressBars.Any(b => b.IsDuplicate(character))) { return; }
AddBossProgressBar(new BossHealthBar(character));
AddBossProgressBar(new HealthBar(character));
}
public static void ShowMissionProgressBar(Mission mission)
@@ -803,14 +801,14 @@ namespace Barotrauma
bossProgressBars.Clear();
}
private static void RemoveBossProgressBar(BossProgressBar progressBar)
private static void RemoveBossProgressBar(ProgressBar progressBar)
{
progressBar.SideContainer.Parent?.RemoveChild(progressBar.SideContainer);
progressBar.TopContainer.Parent?.RemoveChild(progressBar.TopContainer);
bossProgressBars.Remove(progressBar);
}
private static void AddBossProgressBar(BossProgressBar progressBar)
private static void AddBossProgressBar(ProgressBar progressBar)
{
var healthBarMode = GameMain.NetworkMember?.ServerSettings.ShowEnemyHealthBars ?? GameSettings.CurrentConfig.ShowEnemyHealthBars;
if (healthBarMode == EnemyHealthBarMode.HideAll)
@@ -819,10 +817,10 @@ namespace Barotrauma
}
if (bossProgressBars.Count > 5)
{
BossProgressBar oldestHealthBar = bossProgressBars.First();
ProgressBar oldestHealthBar = bossProgressBars.First();
foreach (var bar in bossProgressBars)
{
if (bar.TopHealthBar.BarSize < oldestHealthBar.TopHealthBar.BarSize)
if (bar.TopBar.BarSize < oldestHealthBar.TopBar.BarSize)
{
oldestHealthBar = bar;
}
@@ -850,7 +848,7 @@ namespace Barotrauma
bossHealthBar.TopContainer.Visible = showTopBar;
bossHealthBar.SideContainer.Visible = !bossHealthBar.TopContainer.Visible;
bossHealthBar.TopHealthBar.BarSize = bossHealthBar.SideHealthBar.BarSize = bossHealthBar.State;
bossHealthBar.TopBar.BarSize = bossHealthBar.SideBar.BarSize = bossHealthBar.State;
float alpha = Math.Min(bossHealthBar.FadeTimer, 1.0f);
if (bossHealthBar.TopContainer.Visible)
@@ -862,7 +860,7 @@ namespace Barotrauma
SetColor(bossHealthBar, bossHealthBar.SideContainer, alpha);
}
static void SetColor(BossProgressBar bossHealthBar, GUIComponent container, float alpha)
static void SetColor(ProgressBar bossHealthBar, GUIComponent container, float alpha)
{
foreach (var component in container.GetAllChildren())
{
@@ -526,6 +526,17 @@ namespace Barotrauma
else
{
origin = attachment.Sprite.Origin;
if (spriteEffects.HasFlag(SpriteEffects.FlipHorizontally))
{
origin.X = attachment.Sprite.size.X - origin.X;
}
if (spriteEffects.HasFlag(SpriteEffects.FlipVertically))
{
origin.Y = attachment.Sprite.size.Y - origin.Y;
}
//the portrait's origin is forced to 0,0 (presumably for easier drawing on the UI?), see LoadHeadElement
//we need to take that into account here and draw the attachment at where the origin of the "actual" head sprite would be
drawPos += HeadSprite.Origin * scale;
}
float depth = attachment.Sprite.Depth;
if (attachment.InheritLimbDepth)
@@ -47,6 +47,7 @@ namespace Barotrauma
SelectedCharacter,
SelectedItem,
SelectedSecondaryItem,
AnimController.TargetMovement,
AnimController.Anim);
memLocalState.Add(posInfo);
@@ -56,7 +57,7 @@ namespace Barotrauma
if (IsKeyDown(InputType.Right)) newInput |= InputNetFlags.Right;
if (IsKeyDown(InputType.Up)) newInput |= InputNetFlags.Up;
if (IsKeyDown(InputType.Down)) newInput |= InputNetFlags.Down;
if (IsKeyDown(InputType.Run)) newInput |= InputNetFlags.Run;
if (IsKeyDown(InputType.Run) || ToggleRun) newInput |= InputNetFlags.Run;
if (IsKeyDown(InputType.Crouch)) newInput |= InputNetFlags.Crouch;
if (IsKeyHit(InputType.Select)) newInput |= InputNetFlags.Select; //TODO: clean up the way this input is registered
if (IsKeyHit(InputType.Deselect)) newInput |= InputNetFlags.Deselect;
@@ -68,7 +69,7 @@ namespace Barotrauma
if (IsKeyDown(InputType.Attack)) newInput |= InputNetFlags.Attack;
if (IsKeyDown(InputType.Ragdoll)) newInput |= InputNetFlags.Ragdoll;
if (AnimController.TargetDir == Direction.Left) newInput |= InputNetFlags.FacingLeft;
if (AnimController.Dir < 0) newInput |= InputNetFlags.FacingLeft;
Vector2 relativeCursorPos = cursorPosition - AimRefPosition;
relativeCursorPos.Normalize();
@@ -262,6 +263,11 @@ namespace Barotrauma
msg.ReadRangedSingle(-MaxVel, MaxVel, 12));
linearVelocity = NetConfig.Quantize(linearVelocity, -MaxVel, MaxVel, 12);
Vector2 targetMovement = new Vector2(
msg.ReadRangedSingle(-Ragdoll.MAX_SPEED, Ragdoll.MAX_SPEED, 12),
msg.ReadRangedSingle(-Ragdoll.MAX_SPEED, Ragdoll.MAX_SPEED, 12));
targetMovement = NetConfig.Quantize(targetMovement, -Ragdoll.MAX_SPEED, Ragdoll.MAX_SPEED, 12);
bool fixedRotation = msg.ReadBoolean();
float? rotation = null;
float? angularVelocity = null;
@@ -273,6 +279,8 @@ namespace Barotrauma
angularVelocity = NetConfig.Quantize(angularVelocity.Value, -MaxAngularVel, MaxAngularVel, 8);
}
bool ignorePlatforms = msg.ReadBoolean();
bool readStatus = msg.ReadBoolean();
if (readStatus)
{
@@ -294,7 +302,7 @@ namespace Barotrauma
{
byte happiness = msg.ReadByte();
byte hunger = msg.ReadByte();
if ((AIController as EnemyAIController)?.PetBehavior is PetBehavior petBehavior)
if (AIController is EnemyAIController { PetBehavior: PetBehavior petBehavior })
{
petBehavior.Happiness = (float)happiness / byte.MaxValue * petBehavior.MaxHappiness;
petBehavior.Hunger = (float)hunger / byte.MaxValue * petBehavior.MaxHunger;
@@ -316,7 +324,7 @@ namespace Barotrauma
pos, rotation,
networkUpdateID,
facingRight ? Direction.Right : Direction.Left,
selectedCharacter, selectedItem, selectedSecondaryItem, animation);
selectedCharacter, selectedItem, selectedSecondaryItem, targetMovement, animation, ignorePlatforms);
while (index < memState.Count && NetIdUtils.IdMoreRecent(posInfo.ID, memState[index].ID))
index++;
@@ -328,7 +336,7 @@ namespace Barotrauma
pos, rotation,
linearVelocity, angularVelocity,
sendingTime, facingRight ? Direction.Right : Direction.Left,
selectedCharacter, selectedItem, selectedSecondaryItem, animation);
selectedCharacter, selectedItem, selectedSecondaryItem, targetMovement, animation, ignorePlatforms);
while (index < memState.Count && posInfo.Timestamp > memState[index].Timestamp)
index++;
@@ -180,7 +180,7 @@ namespace Barotrauma
fakeBrokenTimer -= deltaTime;
if (fakeBrokenTimer > 0.0f) { return; }
foreach (Item item in Item.ItemList)
foreach (Item item in Item.RepairableItems)
{
var repairable = item.GetComponent<Repairable>();
if (repairable == null) { continue; }
@@ -1401,7 +1401,9 @@ namespace Barotrauma
GetSuitableTreatments(treatmentSuitability,
user: Character.Controlled,
ignoreHiddenAfflictions: true,
limb: selectedLimbIndex == -1 ? null : Character.AnimController.Limbs.Find(l => l.HealthIndex == selectedLimbIndex));
limb: selectedLimbIndex == -1 ? null : Character.AnimController.Limbs.Find(l => l.HealthIndex == selectedLimbIndex),
checkTreatmentSuggestionThreshold: true,
checkTreatmentThreshold: false);
foreach (Identifier treatment in treatmentSuitability.Keys.ToList())
{
@@ -137,7 +137,16 @@ namespace Barotrauma
{
get
{
var conditionalSprite = ConditionalSprites.FirstOrDefault(c => c.Exclusive && c.IsActive && c.DeformableSprite != null);
// Performance-sensitive, hence implemented without Linq.
ConditionalSprite conditionalSprite = null;
foreach (ConditionalSprite cs in ConditionalSprites)
{
if (cs.Exclusive && cs.IsActive && cs.DeformableSprite != null)
{
conditionalSprite = cs;
break;
}
}
if (conditionalSprite != null)
{
return conditionalSprite.DeformableSprite;
@@ -155,7 +164,16 @@ namespace Barotrauma
{
get
{
var conditionalSprite = ConditionalSprites.FirstOrDefault(c => c.Exclusive && c.IsActive && c.ActiveSprite != null);
// Performance-sensitive, hence implemented without Linq.
ConditionalSprite conditionalSprite = null;
foreach (ConditionalSprite cs in ConditionalSprites)
{
if (cs.Exclusive && cs.IsActive && cs.ActiveSprite != null)
{
conditionalSprite = cs;
break;
}
}
if (conditionalSprite != null)
{
return conditionalSprite.ActiveSprite;
@@ -483,9 +501,20 @@ namespace Barotrauma
{
if (spriteParams != null)
{
//1. check if the variant file redefines the texture
ContentPath texturePath = character.Params.VariantFile?.Root?.GetAttributeContentPath("texture", character.Prefab.ContentPackage);
//2. check if the base prefab defines the texture
ContentPath texturePath;
//1. check if the limb defines the texture directly
var definedTexturePath = element?.GetAttributeContentPath("texture");
if (!definedTexturePath.IsNullOrEmpty())
{
texturePath = definedTexturePath;
}
else
{
//2. check if the character file defines the texture directly
texturePath = character.Params.VariantFile?.Root?.GetAttributeContentPath("texture", character.Prefab.ContentPackage);
}
//3. check if the base prefab defines the texture
if (texturePath.IsNullOrEmpty() && !character.Prefab.VariantOf.IsEmpty)
{
Identifier speciesName = character.GetBaseCharacterSpeciesName();
@@ -495,7 +524,7 @@ namespace Barotrauma
texturePath = parentRagdollParams.OriginalElement?.GetAttributeContentPath("texture");
}
//3. "default case", get the texture from this character's XML
//4. "default case", get the texture from this character's XML
texturePath ??= ContentPath.FromRaw(spriteParams.Element.ContentPackage ?? character.Prefab.ContentPackage, spriteParams.GetTexturePath());
path = GetSpritePath(texturePath);
}
@@ -753,9 +782,29 @@ namespace Barotrauma
float herpesStrength = character.CharacterHealth.GetAfflictionStrengthByType(AfflictionPrefab.SpaceHerpesType);
bool hideLimb = Hide ||
OtherWearables.Any(w => w.HideLimb) ||
WearingItems.Any(w => w.HideLimb);
bool hideLimb = ShouldHideLimb(this);
if (!hideLimb && Params.InheritHiding != LimbType.None)
{
if (character.AnimController.GetLimb(Params.InheritHiding) is Limb otherLimb)
{
hideLimb = ShouldHideLimb(otherLimb);
}
}
static bool ShouldHideLimb(Limb limb)
{
if (limb.Hide) { return true; }
// Performance-sensitive code -> implemented without Linq
foreach (var wearable in limb.OtherWearables)
{
if (wearable.HideLimb) { return true; }
}
foreach (var wearable in limb.WearingItems)
{
if (wearable.HideLimb) { return true; }
}
return false;
}
bool drawHuskSprite = HuskSprite != null && !wearableTypesToHide.Contains(WearableType.Husk);
@@ -887,28 +936,28 @@ namespace Barotrauma
}
depthStep += step;
}
foreach (WearableSprite wearable in OtherWearables)
if (!hideLimb)
{
if (wearable.Type == WearableType.Husk) { continue; }
if (wearableTypesToHide.Contains(wearable.Type))
foreach (WearableSprite wearable in OtherWearables)
{
if (wearable.Type == WearableType.Hair)
if (wearable.Type == WearableType.Husk) { continue; }
if (wearableTypesToHide.Contains(wearable.Type))
{
if (HairWithHatSprite != null && !hideLimb)
// Draws the short hair
if (wearable.Type == WearableType.Hair)
{
DrawWearable(HairWithHatSprite, depthStep, spriteBatch, blankColor, alpha: color.A / 255f, spriteEffect);
depthStep += step;
continue;
if (HairWithHatSprite != null)
{
DrawWearable(HairWithHatSprite, depthStep, spriteBatch, blankColor, alpha: color.A / 255f, spriteEffect);
depthStep += step;
}
}
}
else
{
continue;
}
DrawWearable(wearable, depthStep, spriteBatch, blankColor, alpha: color.A / 255f, spriteEffect);
//if there are multiple sprites on this limb, make the successive ones be drawn in front
depthStep += step;
}
DrawWearable(wearable, depthStep, spriteBatch, blankColor, alpha: color.A / 255f, spriteEffect);
//if there are multiple sprites on this limb, make the successive ones be drawn in front
depthStep += step;
}
}
foreach (WearableSprite wearable in WearingItems)
@@ -967,7 +1016,7 @@ namespace Barotrauma
new Vector2(body.DrawPosition.X, -body.DrawPosition.Y),
colorWithoutTint * damageOverlayStrength, activeSprite.Origin,
-body.DrawRotation,
Scale, spriteEffect, activeSprite.Depth - depthStep * Math.Max(1, WearingItems.Count * 2)); // Multiply by 2 to get rid of z-fighting with some clothing combos
Scale * TextureScale, spriteEffect, activeSprite.Depth - depthStep * Math.Max(1, WearingItems.Count * 2)); // Multiply by 2 to get rid of z-fighting with some clothing combos
}
}