Unstable 1.8.4.0
This commit is contained in:
@@ -42,13 +42,13 @@ 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);
|
||||
}
|
||||
GUI.DrawString(spriteBatch, pos - Vector2.UnitY * 60.0f, $"{SelectedAiTarget.Entity}", GUIStyle.Red, Color.Black);
|
||||
GUI.DrawString(spriteBatch, pos - Vector2.UnitY * 40.0f, $"{targetValue.FormatZeroDecimal()} (M: {SelectedTargetMemory?.Priority.FormatZeroDecimal()}, P: {SelectedTargetingParams?.Priority.FormatZeroDecimal()})", GUIStyle.Red, Color.Black);
|
||||
GUI.DrawString(spriteBatch, pos - Vector2.UnitY * 40.0f, $"{targetValue.FormatZeroDecimal()} (M: {CurrentTargetMemory?.Priority.FormatZeroDecimal()}, P: {CurrentTargetingParams?.Priority.FormatZeroDecimal()})", GUIStyle.Red, Color.Black);
|
||||
}
|
||||
|
||||
/*GUIStyle.Font.DrawString(spriteBatch, targetValue.ToString(), pos - Vector2.UnitY * 80.0f, GUIStyle.Red);
|
||||
@@ -73,7 +73,7 @@ namespace Barotrauma
|
||||
}
|
||||
GUI.DrawString(spriteBatch, pos - Vector2.UnitY * 80.0f, State.ToString(), stateColor, Color.Black);
|
||||
|
||||
if (State == AIState.Attack && selectedTargetingParams != null && selectedTargetingParams.AttackPattern == AttackPattern.Circle)
|
||||
if (State == AIState.Attack && currentTargetingParams != null && currentTargetingParams.AttackPattern == AttackPattern.Circle)
|
||||
{
|
||||
GUI.DrawString(spriteBatch, pos - Vector2.UnitY * 100.0f, CirclePhase.ToString(), stateColor, Color.Black);
|
||||
}
|
||||
@@ -134,8 +134,8 @@ namespace Barotrauma
|
||||
//GUI.DrawLine(spriteBatch, pos, ConvertUnits.ToDisplayUnits(steeringManager.AvoidLookAheadPos.X, -steeringManager.AvoidLookAheadPos.Y), Color.Orange, width: 4);
|
||||
}
|
||||
}
|
||||
GUI.DrawLine(spriteBatch, pos, pos + ConvertUnits.ToDisplayUnits(new Vector2(Steering.X, -Steering.Y)), Color.Blue, width: 4);
|
||||
GUI.DrawLine(spriteBatch, pos, pos + ConvertUnits.ToDisplayUnits(new Vector2(Character.AnimController.TargetMovement.X, -Character.AnimController.TargetMovement.Y)), Color.SteelBlue, width: 2);
|
||||
GUI.DrawLine(spriteBatch, pos, pos + ConvertUnits.ToDisplayUnits(new Vector2(Steering.X, -Steering.Y)), Color.Blue, width: 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using FarseerPhysics;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
@@ -11,7 +12,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;
|
||||
@@ -63,6 +64,25 @@ namespace Barotrauma
|
||||
stringDrawPos += new Vector2(0, 20);
|
||||
GUI.DrawString(spriteBatch, stringDrawPos, $"ACTIVE OBJECTIVE: {activeObjective.DebugTag} ({activeObjective.Priority.FormatZeroDecimal()})", Color.White, Color.Black);
|
||||
}
|
||||
if (currentObjective is AIObjectiveCombat
|
||||
{
|
||||
Weapon: Item weapon,
|
||||
BlockedPositions: List<Vector2> blockedPositions
|
||||
})
|
||||
{
|
||||
Vector2 weaponPos = weapon.DrawPosition;
|
||||
weaponPos.Y = -weaponPos.Y;
|
||||
foreach (Vector2 blockedPosition in blockedPositions)
|
||||
{
|
||||
Vector2 blockedPos = blockedPosition;
|
||||
if (Character.Submarine != null)
|
||||
{
|
||||
blockedPos += Character.Submarine.DrawPosition;
|
||||
}
|
||||
blockedPos.Y = -blockedPos.Y;
|
||||
GUI.DrawLine(spriteBatch, weaponPos, blockedPos, Color.Red);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vector2 objectiveStringDrawPos = stringDrawPos + new Vector2(120, 40);
|
||||
|
||||
@@ -23,13 +23,13 @@ namespace Barotrauma
|
||||
|
||||
partial void UpdateNetPlayerPositionProjSpecific(float deltaTime, float lowestSubPos)
|
||||
{
|
||||
if (character != GameMain.Client.Character || !character.CanMove)
|
||||
if (character != GameMain.Client.Character)
|
||||
{
|
||||
//remove states without a timestamp (there may still be ID-based states
|
||||
//in the list when the controlled character switches to timestamp-based interpolation)
|
||||
character.MemState.RemoveAll(m => m.Timestamp == 0.0f);
|
||||
|
||||
//use simple interpolation for other players' characters and characters that can't move
|
||||
//use simple interpolation for other players' characters
|
||||
if (character.MemState.Count > 0)
|
||||
{
|
||||
CharacterStateInfo serverPos = character.MemState.Last();
|
||||
@@ -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,30 +130,35 @@ 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;
|
||||
float mainLimbDistSqrd = Vector2.DistanceSquared(MainLimb.PullJointWorldAnchorA, newPosition);
|
||||
float mainLimbErrorTolerance = character == GameMain.Client.Character ? 0.25f : 0.1f;
|
||||
MainLimb.body.LinearVelocity = newVelocity;
|
||||
//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 if (!ColliderControlsMovement)
|
||||
{
|
||||
//correct velocity regardless of the positional error
|
||||
MainLimb.body.LinearVelocity = newVelocity;
|
||||
}
|
||||
}
|
||||
character.MemLocalState.Clear();
|
||||
}
|
||||
@@ -179,12 +188,14 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
if (character.MemState.Count < 1) return;
|
||||
if (character.MemState.Count < 1) { return; }
|
||||
|
||||
overrideTargetMovement = Vector2.Zero;
|
||||
overrideTargetMovement = null;
|
||||
|
||||
CharacterStateInfo serverPos = character.MemState.Last();
|
||||
|
||||
Collider.LastServerState = serverPos;
|
||||
|
||||
if (!character.isSynced)
|
||||
{
|
||||
SetPosition(serverPos.Position, lerp: false);
|
||||
@@ -282,18 +293,65 @@ namespace Barotrauma
|
||||
}
|
||||
else if (errorMagnitude > 0.01f)
|
||||
{
|
||||
Collider.TargetPosition = Collider.SimPosition + positionError;
|
||||
Collider.TargetRotation = Collider.Rotation + rotationError;
|
||||
Collider.MoveToTargetPosition(lerp: true);
|
||||
if (ColliderControlsMovement)
|
||||
{
|
||||
Collider.TargetPosition = Collider.SimPosition + positionError;
|
||||
Collider.TargetRotation = Collider.Rotation + rotationError;
|
||||
Collider.MoveToTargetPosition(lerp: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
float mainLimbErrorTolerance = character == GameMain.Client.Character ? 0.25f : 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 (errorMagnitude > mainLimbErrorTolerance)
|
||||
{
|
||||
MainLimb.PullJointWorldAnchorB = MainLimb.SimPosition + positionError;
|
||||
MainLimb.PullJointEnabled = true;
|
||||
if (serverPos.LinearVelocity.LengthSquared() < 0.01f) { TryPlatformCorrection(MainLimb.SimPosition + positionError); }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (character.MemLocalState.Count > 120) character.MemLocalState.RemoveRange(0, character.MemLocalState.Count - 120);
|
||||
if (character.MemLocalState.Count > 120) { character.MemLocalState.RemoveRange(0, character.MemLocalState.Count - 120); }
|
||||
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)
|
||||
{
|
||||
@@ -563,15 +621,19 @@ namespace Barotrauma
|
||||
|
||||
void AdjustDepthOffset(Item item)
|
||||
{
|
||||
if (item?.GetComponent<Controller>() is { ControlCharacterPose: true, UserInCorrectPosition: true } controller && controller.User == character)
|
||||
if (item == null) { return; }
|
||||
foreach (var controller in item.GetComponents<Controller>())
|
||||
{
|
||||
if (controller.Item.SpriteDepth <= maxDepth || controller.DrawUserBehind)
|
||||
if (controller is { ControlCharacterPose: true, UserInCorrectPosition: true } && controller.User == character)
|
||||
{
|
||||
depthOffset = Math.Max(controller.Item.GetDrawDepth() + 0.0001f - minDepth, -minDepth);
|
||||
}
|
||||
else
|
||||
{
|
||||
depthOffset = Math.Max(controller.Item.GetDrawDepth() - 0.0001f - maxDepth, 0.0f);
|
||||
if (controller.Item.SpriteDepth <= maxDepth || controller.DrawUserBehind)
|
||||
{
|
||||
depthOffset = Math.Max(controller.Item.GetDrawDepth() + 0.0001f - minDepth, -minDepth);
|
||||
}
|
||||
else
|
||||
{
|
||||
depthOffset = Math.Max(controller.Item.GetDrawDepth() - 0.0001f - maxDepth, 0.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace Barotrauma
|
||||
|
||||
if (sound != null)
|
||||
{
|
||||
SoundPlayer.PlaySound(sound.Sound, worldPosition, sound.Volume, sound.Range, ignoreMuffling: sound.IgnoreMuffling, freqMult: sound.GetRandomFrequencyMultiplier());
|
||||
SoundPlayer.PlaySound(sound, worldPosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
@@ -27,7 +28,8 @@ namespace Barotrauma
|
||||
|
||||
protected float lastRecvPositionUpdateTime;
|
||||
|
||||
private float hudInfoHeight = 100.0f;
|
||||
private const float DefaultHudInfoHeight = 78.0f;
|
||||
private float hudInfoHeight = DefaultHudInfoHeight;
|
||||
|
||||
private List<CharacterSound> sounds;
|
||||
|
||||
@@ -249,7 +251,9 @@ namespace Barotrauma
|
||||
public Vector2 Position;
|
||||
public Vector2 DrawPosition;
|
||||
public float MoveUpAmount;
|
||||
public readonly string Text;
|
||||
public readonly RichString Text;
|
||||
public ImmutableArray<RichTextData>? RichTextData { get; private set; }
|
||||
|
||||
public readonly Character Character;
|
||||
public readonly Submarine Submarine;
|
||||
public readonly Vector2 TextSize;
|
||||
@@ -259,8 +263,10 @@ namespace Barotrauma
|
||||
|
||||
public SpeechBubble(Character character, float lifeTime, Color color, string text = "")
|
||||
{
|
||||
Text = ToolBox.WrapText(text, GUI.IntScale(300), GUIStyle.SmallFont.GetFontForStr(text));
|
||||
var richStr = RichString.Rich(text);
|
||||
Text = ToolBox.WrapText(richStr.SanitizedValue, GUI.IntScale(300), GUIStyle.SmallFont.GetFontForStr(text));
|
||||
TextSize = GUIStyle.SmallFont.MeasureString(Text);
|
||||
RichTextData = richStr.RichTextData;
|
||||
|
||||
Character = character;
|
||||
Position = GetDesiredPosition();
|
||||
@@ -321,7 +327,6 @@ namespace Barotrauma
|
||||
/// </summary>
|
||||
public void ControlLocalPlayer(float deltaTime, Camera cam, bool moveCam = true)
|
||||
{
|
||||
|
||||
if (DisableControls || GUI.InputBlockingMenuOpen)
|
||||
{
|
||||
foreach (Key key in keys)
|
||||
@@ -329,7 +334,7 @@ namespace Barotrauma
|
||||
if (key == null) { continue; }
|
||||
key.Reset();
|
||||
}
|
||||
if (GUI.InputBlockingMenuOpen)
|
||||
if (GUI.InputBlockingMenuOpen || ConversationAction.IsDialogOpen)
|
||||
{
|
||||
cursorPosition =
|
||||
Position + PlayerInput.MouseSpeed.ClampLength(10.0f); //apply a little bit of movement to the cursor pos to prevent AFK kicking
|
||||
@@ -416,6 +421,11 @@ namespace Barotrauma
|
||||
|
||||
UpdateLocalCursor(cam);
|
||||
|
||||
if (IsKeyHit(InputType.ToggleRun))
|
||||
{
|
||||
ToggleRun = !ToggleRun;
|
||||
}
|
||||
|
||||
Vector2 mouseSimPos = ConvertUnits.ToSimUnits(cursorPosition);
|
||||
if (GUI.PauseMenuOpen)
|
||||
{
|
||||
@@ -471,7 +481,7 @@ namespace Barotrauma
|
||||
if (!GUI.InputBlockingMenuOpen)
|
||||
{
|
||||
if (SelectedItem != null &&
|
||||
(SelectedItem.ActiveHUDs.Any(ic => ic.GuiFrame != null && HUD.CloseHUD(ic.GuiFrame.Rect)) ||
|
||||
(SelectedItem.ActiveHUDs.Any(ic => ic.GuiFrame != null && ic.CloseByClickingOutsideGUIFrame && HUD.CloseHUD(ic.GuiFrame.Rect)) ||
|
||||
((ViewTarget as Item)?.Prefab.FocusOnSelected ?? false) && PlayerInput.KeyHit(Microsoft.Xna.Framework.Input.Keys.Escape)))
|
||||
{
|
||||
if (GameMain.Client != null)
|
||||
@@ -543,7 +553,10 @@ namespace Barotrauma
|
||||
{
|
||||
if (attackResult.Damage <= 1.0f) { return; }
|
||||
}
|
||||
PlaySound(CharacterSound.SoundType.Damage, maxInterval: 2);
|
||||
if (AIState != AIState.PlayDead)
|
||||
{
|
||||
PlaySound(CharacterSound.SoundType.Damage, maxInterval: 2);
|
||||
}
|
||||
}
|
||||
|
||||
partial void KillProjSpecific(CauseOfDeathType causeOfDeath, Affliction causeOfDeathAffliction, bool log)
|
||||
@@ -588,7 +601,6 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
sounds.ForEach(s => s.Sound?.Dispose());
|
||||
sounds.Clear();
|
||||
|
||||
if (GameMain.GameSession?.CrewManager != null &&
|
||||
@@ -814,9 +826,12 @@ namespace Barotrauma
|
||||
PlaySound(CharacterSound.SoundType.Idle);
|
||||
}
|
||||
break;
|
||||
case AIState.PlayDead:
|
||||
case AIState.Freeze:
|
||||
case AIState.Hiding:
|
||||
break;
|
||||
default:
|
||||
var petBehavior = enemyAI.PetBehavior;
|
||||
if (petBehavior != null &&
|
||||
if (enemyAI.PetBehavior is PetBehavior petBehavior &&
|
||||
(petBehavior.Happiness < petBehavior.UnhappyThreshold || petBehavior.Hunger > petBehavior.HungryThreshold))
|
||||
{
|
||||
PlaySound(CharacterSound.SoundType.Unhappy);
|
||||
@@ -948,7 +963,9 @@ namespace Barotrauma
|
||||
Controlled != this &&
|
||||
Submarine != null &&
|
||||
Controlled.Submarine == Submarine &&
|
||||
GameSettings.CurrentConfig.Graphics.LosMode != LosMode.None)
|
||||
GameSettings.CurrentConfig.Graphics.LosMode != LosMode.None &&
|
||||
//less restrictions on name tag visibility in PvP mode (always show them if the character is visible)
|
||||
GameMain.GameSession?.GameMode is not PvPMode)
|
||||
{
|
||||
float yPos = Controlled.AnimController.FloorY - 1.5f;
|
||||
|
||||
@@ -965,15 +982,16 @@ namespace Barotrauma
|
||||
Vector2 pos = DrawPosition;
|
||||
pos.Y += hudInfoHeight;
|
||||
|
||||
if (CurrentHull != null && DrawPosition.Y > CurrentHull.WorldRect.Y - 130.0f)
|
||||
float paddingBelowCeiling = 30.0f;
|
||||
if (CurrentHull != null && DrawPosition.Y + DefaultHudInfoHeight > CurrentHull.WorldRect.Y - paddingBelowCeiling)
|
||||
{
|
||||
float lowerAmount = DrawPosition.Y - (CurrentHull.WorldRect.Y - 130.0f);
|
||||
hudInfoHeight = MathHelper.Lerp(hudInfoHeight, 100.0f - lowerAmount, 0.1f);
|
||||
float lowerAmount = (DrawPosition.Y + DefaultHudInfoHeight) - (CurrentHull.WorldRect.Y - paddingBelowCeiling);
|
||||
hudInfoHeight = MathHelper.Lerp(hudInfoHeight, DefaultHudInfoHeight - lowerAmount, 0.1f);
|
||||
hudInfoHeight = Math.Max(hudInfoHeight, 20.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
hudInfoHeight = MathHelper.Lerp(hudInfoHeight, 100.0f, 0.1f);
|
||||
hudInfoHeight = MathHelper.Lerp(hudInfoHeight, DefaultHudInfoHeight, 0.1f);
|
||||
}
|
||||
|
||||
pos.Y = -pos.Y;
|
||||
@@ -1013,6 +1031,8 @@ namespace Barotrauma
|
||||
CampaignInteractionType == CampaignMode.InteractionType.None ?
|
||||
MathHelper.Clamp(1.0f - (cursorDist - (hoverRange - fadeOutRange)) / fadeOutRange, 0.2f, 1.0f) :
|
||||
1.0f;
|
||||
//full name tag visibility in PvP mode to make it easier to tell who's an enemy
|
||||
float nameTextAlpha = GameMain.GameSession?.GameMode is PvPMode ? 1.0f : hudInfoAlpha;
|
||||
|
||||
if (!GUI.DisableCharacterNames && hudInfoVisible &&
|
||||
(controlled == null || this != controlled.FocusedCharacter || IsPet) && cam.Zoom > 0.4f)
|
||||
@@ -1030,7 +1050,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
Vector2 nameSize = GUIStyle.Font.MeasureString(name);
|
||||
Vector2 namePos = new Vector2(pos.X, pos.Y - 10.0f - (5.0f / cam.Zoom)) - nameSize * 0.5f / cam.Zoom;
|
||||
Vector2 namePos = new Vector2(pos.X, pos.Y - 5.0f - (5.0f / cam.Zoom)) - nameSize * 0.5f / cam.Zoom;
|
||||
Color nameColor = GetNameColor();
|
||||
|
||||
Vector2 screenSize = new Vector2(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
|
||||
@@ -1057,7 +1077,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
GUIStyle.Font.DrawString(spriteBatch, name, namePos + new Vector2(1.0f / cam.Zoom, 1.0f / cam.Zoom), Color.Black, 0.0f, Vector2.Zero, 1.0f / cam.Zoom, SpriteEffects.None, 0.001f);
|
||||
GUIStyle.Font.DrawString(spriteBatch, name, namePos, nameColor * hudInfoAlpha, 0.0f, Vector2.Zero, 1.0f / cam.Zoom, SpriteEffects.None, 0.0f);
|
||||
GUIStyle.Font.DrawString(spriteBatch, name, namePos, nameColor * nameTextAlpha, 0.0f, Vector2.Zero, 1.0f / cam.Zoom, SpriteEffects.None, 0.0f);
|
||||
if (GameMain.DebugDraw)
|
||||
{
|
||||
GUIStyle.Font.DrawString(spriteBatch, ID.ToString(), namePos - new Vector2(0.0f, 20.0f), Color.White);
|
||||
@@ -1068,15 +1088,18 @@ namespace Barotrauma
|
||||
if (petBehavior != null && !IsDead && !IsUnconscious)
|
||||
{
|
||||
var petStatus = petBehavior.GetCurrentStatusIndicatorType();
|
||||
var iconStyle = GUIStyle.GetComponentStyle("PetIcon." + petStatus);
|
||||
if (iconStyle != null)
|
||||
if (petStatus != PetBehavior.StatusIndicatorType.None)
|
||||
{
|
||||
Vector2 headPos = AnimController.GetLimb(LimbType.Head)?.body?.DrawPosition ?? DrawPosition + Vector2.UnitY * 100.0f;
|
||||
Vector2 iconPos = headPos;
|
||||
iconPos.Y = -iconPos.Y;
|
||||
var icon = iconStyle.Sprites[GUIComponent.ComponentState.None].First();
|
||||
float iconScale = 30.0f / icon.Sprite.size.X / cam.Zoom;
|
||||
icon.Sprite.Draw(spriteBatch, iconPos + new Vector2(-35.0f, -25.0f), iconStyle.Color * hudInfoAlpha, scale: iconScale);
|
||||
var iconStyle = GUIStyle.GetComponentStyle("PetIcon." + petStatus);
|
||||
if (iconStyle != null)
|
||||
{
|
||||
Vector2 headPos = AnimController.GetLimb(LimbType.Head)?.body?.DrawPosition ?? DrawPosition + Vector2.UnitY * 100.0f;
|
||||
Vector2 iconPos = headPos;
|
||||
iconPos.Y = -iconPos.Y;
|
||||
var icon = iconStyle.Sprites[GUIComponent.ComponentState.None].First();
|
||||
float iconScale = 30.0f / icon.Sprite.size.X / cam.Zoom;
|
||||
icon.Sprite.Draw(spriteBatch, iconPos + new Vector2(-35.0f, -25.0f), iconStyle.Color * hudInfoAlpha, scale: iconScale);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1100,7 +1123,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
if (Params.ShowHealthBar && CharacterHealth.DisplayedVitality < MaxVitality * 0.98f && hudInfoVisible)
|
||||
if (Params.ShowHealthBar && CharacterHealth.DisplayedVitality < MaxVitality * 0.98f && hudInfoVisible && AIState != AIState.PlayDead && AIState != AIState.Hiding)
|
||||
{
|
||||
hudInfoAlpha = Math.Max(hudInfoAlpha, Math.Min(CharacterHealth.DamageOverlayTimer, 1.0f));
|
||||
|
||||
@@ -1175,7 +1198,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.RichTextData, font: GUIStyle.SmallFont);
|
||||
}
|
||||
spriteBatch.End();
|
||||
}
|
||||
@@ -1233,7 +1256,7 @@ namespace Barotrauma
|
||||
public Color GetNameColor()
|
||||
{
|
||||
CharacterTeamType team = teamID;
|
||||
if (Info?.IsDisguisedAsAnother != null)
|
||||
if (Info is { IsDisguisedAsAnother: true })
|
||||
{
|
||||
var idCard = Inventory.GetItemInLimbSlot(InvSlotType.Card)?.GetComponent<IdCard>();
|
||||
if (idCard != null)
|
||||
@@ -1249,18 +1272,22 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
CharacterTeamType myTeam =
|
||||
Controlled?.TeamID ??
|
||||
GameMain.Client?.MyClient?.TeamID ??
|
||||
CharacterTeamType.Team1;
|
||||
|
||||
Color nameColor = GUIStyle.TextColorNormal;
|
||||
if (Controlled != null && team != Controlled.TeamID)
|
||||
if (TeamID == CharacterTeamType.FriendlyNPC)
|
||||
{
|
||||
if (TeamID == CharacterTeamType.FriendlyNPC)
|
||||
{
|
||||
nameColor = UniqueNameColor ?? Color.SkyBlue;
|
||||
}
|
||||
else
|
||||
{
|
||||
nameColor = GUIStyle.Red;
|
||||
}
|
||||
nameColor = UniqueNameColor ?? Color.SkyBlue;
|
||||
}
|
||||
else if (team != myTeam)
|
||||
{
|
||||
//opposing team is red when controlling a character
|
||||
nameColor = GUIStyle.Red;
|
||||
}
|
||||
|
||||
return nameColor;
|
||||
}
|
||||
|
||||
@@ -1417,7 +1444,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;
|
||||
@@ -394,6 +392,7 @@ namespace Barotrauma
|
||||
foreach (var target in mission.HudIconTargets)
|
||||
{
|
||||
if (target.Submarine != character.Submarine) { continue; }
|
||||
if (target.Removed) { continue; }
|
||||
float alpha = GetDistanceBasedIconAlpha(target, maxDistance: mission.Prefab.HudIconMaxDistance);
|
||||
if (alpha <= 0.0f) { continue; }
|
||||
GUI.DrawIndicator(spriteBatch, target.DrawPosition, cam, 100.0f, mission.Prefab.HudIcon, mission.Prefab.HudIconColor * alpha);
|
||||
@@ -564,7 +563,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 +591,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -752,7 +751,8 @@ namespace Barotrauma
|
||||
}
|
||||
textPos.X += 10.0f * GUI.Scale;
|
||||
|
||||
if (!character.FocusedCharacter.IsIncapacitated && character.FocusedCharacter.IsPet)
|
||||
if (!character.FocusedCharacter.IsIncapacitated && character.FocusedCharacter.IsPet &&
|
||||
character.FocusedCharacter.AIController is EnemyAIController enemyAI && enemyAI.PetBehavior.CanPlayWith(character))
|
||||
{
|
||||
GUI.DrawString(spriteBatch, textPos, GetCachedHudText("PlayHint", InputType.Use),
|
||||
GUIStyle.Green, Color.Black, 2, GUIStyle.SmallFont);
|
||||
@@ -773,7 +773,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 +784,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,26 +803,26 @@ 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)
|
||||
if (healthBarMode == EnemyHealthBarMode.HideAll && progressBar is not MissionProgressBar)
|
||||
{
|
||||
return;
|
||||
}
|
||||
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 +850,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 +862,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())
|
||||
{
|
||||
@@ -887,7 +887,7 @@ namespace Barotrauma
|
||||
for (int i = bossProgressBars.Count - 1; i >= 0 ; i--)
|
||||
{
|
||||
var bossHealthBar = bossProgressBars[i];
|
||||
if (bossHealthBar.FadeTimer <= 0 || healthBarMode == EnemyHealthBarMode.HideAll)
|
||||
if (bossHealthBar.FadeTimer <= 0 || (healthBarMode == EnemyHealthBarMode.HideAll && bossHealthBar is not MissionProgressBar))
|
||||
{
|
||||
bossHealthBar.SideContainer.Parent?.RemoveChild(bossHealthBar.SideContainer);
|
||||
bossHealthBar.TopContainer.Parent?.RemoveChild(bossHealthBar.TopContainer);
|
||||
|
||||
@@ -17,7 +17,8 @@ namespace Barotrauma
|
||||
private static Sprite infoAreaPortraitBG;
|
||||
|
||||
public bool LastControlled;
|
||||
public int CrewListIndex { get; set; } = -1;
|
||||
|
||||
public int CrewListIndex { get; set; } = int.MaxValue; //default to the bottom of the list
|
||||
|
||||
private Sprite disguisedPortrait;
|
||||
private List<WearableSprite> disguisedAttachmentSprites;
|
||||
@@ -32,6 +33,8 @@ namespace Barotrauma
|
||||
private float tintHighlightThreshold;
|
||||
private float tintHighlightMultiplier;
|
||||
|
||||
public bool ShowTalentResetPopupOnOpen = true;
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
infoAreaPortraitBG = GUIStyle.GetComponentStyle("InfoAreaPortraitBG")?.GetDefaultSprite();
|
||||
@@ -208,7 +211,7 @@ namespace Barotrauma
|
||||
return frame;
|
||||
}
|
||||
|
||||
partial void OnSkillChanged(Identifier skillIdentifier, float prevLevel, float newLevel)
|
||||
partial void OnSkillChanged(Identifier skillIdentifier, float prevLevel, float newLevel, bool forceNotification)
|
||||
{
|
||||
if (TeamID == CharacterTeamType.FriendlyNPC) { return; }
|
||||
if (Character.Controlled != null && Character.Controlled.TeamID != TeamID) { return; }
|
||||
@@ -226,6 +229,18 @@ namespace Barotrauma
|
||||
specialIncrease ? GUIStyle.Orange : GUIStyle.Green,
|
||||
playSound: Character == Character.Controlled, skillIdentifier, increase);
|
||||
}
|
||||
else if (forceNotification)
|
||||
{
|
||||
float change = newLevel - prevLevel;
|
||||
if (Math.Abs(change) > 0.01f)
|
||||
{
|
||||
string sign = change > 0 ? "+" : "-";
|
||||
Character?.AddMessage(
|
||||
$"{sign}{Math.Round(change, 2)} {TextManager.Get("SkillName." + skillIdentifier).Value}",
|
||||
specialIncrease ? GUIStyle.Orange : GUIStyle.Green,
|
||||
playSound: Character == Character.Controlled);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
partial void OnExperienceChanged(int prevAmount, int newAmount)
|
||||
@@ -511,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)
|
||||
@@ -526,6 +552,8 @@ namespace Barotrauma
|
||||
string newName = inc.ReadString();
|
||||
string originalName = inc.ReadString();
|
||||
bool renamingEnabled = inc.ReadBoolean();
|
||||
BotStatus botStatus = (BotStatus)inc.ReadByte();
|
||||
int salary = inc.ReadInt32();
|
||||
int tagCount = inc.ReadByte();
|
||||
HashSet<Identifier> tagSet = new HashSet<Identifier>();
|
||||
for (int i = 0; i < tagCount; i++)
|
||||
@@ -576,6 +604,8 @@ namespace Barotrauma
|
||||
MinReputationToHire = (factionId, minReputationToHire),
|
||||
RenamingEnabled = renamingEnabled
|
||||
};
|
||||
ch.BotStatus = botStatus;
|
||||
ch.Salary = salary;
|
||||
ch.RecreateHead(tagSet.ToImmutableHashSet(), hairIndex, beardIndex, moustacheIndex, faceAttachmentIndex);
|
||||
ch.Head.SkinColor = skinColor;
|
||||
ch.Head.HairColor = hairColor;
|
||||
@@ -586,6 +616,8 @@ namespace Barotrauma
|
||||
ch.ExperiencePoints = inc.ReadInt32();
|
||||
ch.AdditionalTalentPoints = inc.ReadRangedInteger(0, MaxAdditionalTalentPoints);
|
||||
ch.PermanentlyDead = inc.ReadBoolean();
|
||||
ch.TalentRefundPoints = inc.ReadInt32();
|
||||
ch.TalentResetCount = inc.ReadInt32();
|
||||
return ch;
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
@@ -154,6 +155,9 @@ namespace Barotrauma
|
||||
case TreatmentEventData _:
|
||||
msg.WriteBoolean(AnimController.Anim == AnimController.Animation.CPR);
|
||||
break;
|
||||
case ConfirmRefundEventData _:
|
||||
//do nothing
|
||||
break;
|
||||
case CharacterStatusEventData _:
|
||||
//do nothing
|
||||
break;
|
||||
@@ -202,12 +206,16 @@ namespace Barotrauma
|
||||
keys[(int)InputType.Use].Held = useInput;
|
||||
keys[(int)InputType.Use].SetState(false, useInput);
|
||||
|
||||
bool crouching = msg.ReadBoolean();
|
||||
if (AnimController is HumanoidAnimController)
|
||||
{
|
||||
bool crouching = msg.ReadBoolean();
|
||||
keys[(int)InputType.Crouch].Held = crouching;
|
||||
keys[(int)InputType.Crouch].SetState(false, crouching);
|
||||
}
|
||||
else if (AnimController is FishAnimController fishAnim)
|
||||
{
|
||||
fishAnim.Reverse = msg.ReadBoolean();
|
||||
}
|
||||
|
||||
bool attackInput = msg.ReadBoolean();
|
||||
keys[(int)InputType.Attack].Held = attackInput;
|
||||
@@ -255,17 +263,22 @@ 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;
|
||||
if (!fixedRotation)
|
||||
{
|
||||
rotation = msg.ReadSingle();
|
||||
float MaxAngularVel = NetConfig.MaxPhysicsBodyAngularVelocity;
|
||||
angularVelocity = msg.ReadRangedSingle(-MaxAngularVel, MaxAngularVel, 8);
|
||||
angularVelocity = NetConfig.Quantize(angularVelocity.Value, -MaxAngularVel, MaxAngularVel, 8);
|
||||
angularVelocity = msg.ReadSingle();
|
||||
}
|
||||
|
||||
bool ignorePlatforms = msg.ReadBoolean();
|
||||
|
||||
bool readStatus = msg.ReadBoolean();
|
||||
if (readStatus)
|
||||
{
|
||||
@@ -287,7 +300,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;
|
||||
@@ -303,13 +316,13 @@ namespace Barotrauma
|
||||
msg.ReadPadBits();
|
||||
|
||||
int index = 0;
|
||||
if (GameMain.Client.Character == this && CanMove)
|
||||
if (GameMain.Client.Character == this)
|
||||
{
|
||||
var posInfo = new CharacterStateInfo(
|
||||
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++;
|
||||
@@ -321,7 +334,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++;
|
||||
@@ -371,6 +384,9 @@ namespace Barotrauma
|
||||
GameMain.Client.HasSpawned = true;
|
||||
GameMain.Client.Character = this;
|
||||
GameMain.LightManager.LosEnabled = true;
|
||||
#if DEBUG
|
||||
GameMain.LightManager.LosEnabled = !GameMain.DevMode;
|
||||
#endif
|
||||
GameMain.LightManager.LosAlpha = 1f;
|
||||
GameMain.Client.WaitForNextRoundRespawn = null;
|
||||
}
|
||||
@@ -393,15 +409,16 @@ namespace Barotrauma
|
||||
break;
|
||||
case EventType.Status:
|
||||
ReadStatus(msg);
|
||||
GodMode = msg.ReadBoolean();
|
||||
break;
|
||||
case EventType.UpdateSkills:
|
||||
int skillCount = msg.ReadByte();
|
||||
for (int i = 0; i < skillCount; i++)
|
||||
Identifier skillIdentifier = msg.ReadIdentifier();
|
||||
if (!skillIdentifier.IsEmpty)
|
||||
{
|
||||
Identifier skillIdentifier = msg.ReadIdentifier();
|
||||
bool forceNotification = msg.ReadBoolean();
|
||||
float skillLevel = msg.ReadSingle();
|
||||
info?.SetSkillLevel(skillIdentifier, skillLevel);
|
||||
}
|
||||
info?.SetSkillLevel(skillIdentifier, skillLevel, forceNotification: forceNotification);
|
||||
}
|
||||
break;
|
||||
case EventType.SetAttackTarget:
|
||||
case EventType.ExecuteAttack:
|
||||
@@ -512,7 +529,12 @@ namespace Barotrauma
|
||||
break;
|
||||
case EventType.UpdateExperience:
|
||||
int experienceAmount = msg.ReadInt32();
|
||||
info?.SetExperience(experienceAmount);
|
||||
int additionalTalentPoints = msg.ReadInt32();
|
||||
if (info != null)
|
||||
{
|
||||
info.SetExperience(experienceAmount);
|
||||
info.AdditionalTalentPoints = additionalTalentPoints;
|
||||
}
|
||||
break;
|
||||
case EventType.UpdateTalents:
|
||||
ushort talentCount = msg.ReadUInt16();
|
||||
@@ -527,6 +549,20 @@ namespace Barotrauma
|
||||
int moneyAmount = msg.ReadInt32();
|
||||
SetMoney(moneyAmount);
|
||||
break;
|
||||
case EventType.UpdateTalentRefundPoints:
|
||||
int refundPoints = msg.ReadInt32();
|
||||
if (info != null)
|
||||
{
|
||||
if (refundPoints > info.TalentRefundPoints)
|
||||
{
|
||||
info.ShowTalentResetPopupOnOpen = true;
|
||||
}
|
||||
info.TalentRefundPoints = refundPoints;
|
||||
}
|
||||
break;
|
||||
case EventType.ConfirmTalentRefund:
|
||||
Info?.RefundTalents();
|
||||
break;
|
||||
case EventType.UpdatePermanentStats:
|
||||
byte savedStatValueCount = msg.ReadByte();
|
||||
StatTypes statType = (StatTypes)msg.ReadByte();
|
||||
@@ -730,7 +766,7 @@ namespace Barotrauma
|
||||
|
||||
if (character.IsHuman && character.TeamID != CharacterTeamType.FriendlyNPC && character.TeamID != CharacterTeamType.None)
|
||||
{
|
||||
CharacterInfo duplicateCharacterInfo = GameMain.GameSession.CrewManager.GetCharacterInfos().FirstOrDefault(c => c.ID == info.ID);
|
||||
CharacterInfo duplicateCharacterInfo = GameMain.GameSession.CrewManager.GetCharacterInfos(includeReserveBench: true).FirstOrDefault(c => c.ID == info.ID);
|
||||
GameMain.GameSession.CrewManager.RemoveCharacterInfo(duplicateCharacterInfo);
|
||||
if (character.isDead)
|
||||
{
|
||||
@@ -750,6 +786,9 @@ namespace Barotrauma
|
||||
if (!character.IsDead) { Controlled = character; }
|
||||
|
||||
GameMain.LightManager.LosEnabled = true;
|
||||
#if DEBUG
|
||||
GameMain.LightManager.LosEnabled = !GameMain.DevMode;
|
||||
#endif
|
||||
GameMain.LightManager.LosAlpha = 1f;
|
||||
|
||||
GameMain.NetLobbyScreen.CampaignCharacterDiscarded = false;
|
||||
@@ -817,6 +856,7 @@ namespace Barotrauma
|
||||
if (IsDead) { Revive(); }
|
||||
CharacterHealth.ClientRead(msg);
|
||||
}
|
||||
|
||||
byte severedLimbCount = msg.ReadByte();
|
||||
for (int i = 0; i < severedLimbCount; i++)
|
||||
{
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -31,8 +31,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
public static Sprite DamageOverlay => DamageOverlayPrefab.Prefabs.ActivePrefab.DamageOverlay;
|
||||
|
||||
|
||||
|
||||
private Point screenResolution;
|
||||
|
||||
private float uiScale, inventoryScale;
|
||||
@@ -105,6 +104,12 @@ namespace Barotrauma
|
||||
private GUILayoutGroup treatmentLayout;
|
||||
private GUIListBox recommendedTreatmentContainer;
|
||||
|
||||
/// <summary>
|
||||
/// Timer for updating visuals (limb tints and overlays) caused by the affliction
|
||||
/// </summary>
|
||||
private float updateVisualsTimer = Rand.Range(0.0f, UpdateVisualsInterval);
|
||||
const float UpdateVisualsInterval = 0.5f;
|
||||
|
||||
private float distortTimer;
|
||||
|
||||
// 0-1
|
||||
@@ -461,15 +466,17 @@ namespace Barotrauma
|
||||
private void OnAttacked(Character attacker, AttackResult attackResult)
|
||||
{
|
||||
if (Math.Abs(attackResult.Damage) < 0.01f) { return; }
|
||||
DamageOverlayTimer = MathHelper.Clamp(attackResult.Damage / MaxVitality, DamageOverlayTimer, 1.0f);
|
||||
if (healthShadowDelay <= 0.0f) { healthShadowDelay = 1.0f; }
|
||||
|
||||
if (ShowDamageOverlay)
|
||||
{
|
||||
DamageOverlayTimer = MathHelper.Clamp(attackResult.Damage / MaxVitality, DamageOverlayTimer, 1.0f);
|
||||
float additionalIntensity = MathHelper.Lerp(0, 1, MathUtils.InverseLerp(0, 0.1f, attackResult.Damage / MaxVitality));
|
||||
damageIntensity = MathHelper.Clamp(damageIntensity + additionalIntensity, 0, 1);
|
||||
}
|
||||
|
||||
if (healthShadowDelay <= 0.0f) { healthShadowDelay = 1.0f; }
|
||||
if (healthBarPulsateTimer <= 0.0f) { healthBarPulsatePhase = 0.0f; }
|
||||
healthBarPulsateTimer = 1.0f;
|
||||
|
||||
float additionalIntensity = MathHelper.Lerp(0, 1, MathUtils.InverseLerp(0, 0.1f, attackResult.Damage / MaxVitality));
|
||||
damageIntensity = MathHelper.Clamp(damageIntensity + additionalIntensity, 0, 1);
|
||||
|
||||
DisplayVitalityDelay = 0.5f;
|
||||
}
|
||||
|
||||
@@ -1036,6 +1043,12 @@ namespace Barotrauma
|
||||
var affliction = kvp.Key;
|
||||
affliction.Prefab.AfflictionOverlay?.Draw(spriteBatch, Vector2.Zero, Color.White * affliction.GetAfflictionOverlayMultiplier(), Vector2.Zero, 0.0f,
|
||||
new Vector2(GameMain.GraphicsWidth / DamageOverlay.size.X, GameMain.GraphicsHeight / DamageOverlay.size.Y));
|
||||
|
||||
var activeEffect = affliction.GetActiveEffect();
|
||||
if (activeEffect is { ThermalOverlayRange: > 0.0f })
|
||||
{
|
||||
StatusHUD.DrawThermalOverlay(spriteBatch, Character, Character, activeEffect.ThermalOverlayColor, activeEffect.ThermalOverlayRange, effectState: (float)Timing.TotalTimeUnpaused, showDeadCharacters: false);
|
||||
}
|
||||
}
|
||||
|
||||
float damageOverlayAlpha = DamageOverlayTimer;
|
||||
@@ -1130,6 +1143,8 @@ namespace Barotrauma
|
||||
if (!statusIconVisibleTime.ContainsKey(afflictionPrefab)) { statusIconVisibleTime.Add(afflictionPrefab, 0.0f); }
|
||||
statusIconVisibleTime[afflictionPrefab] += deltaTime;
|
||||
|
||||
Color color = GetAfflictionIconColor(afflictionPrefab, affliction);
|
||||
|
||||
var matchingIcon =
|
||||
afflictionIconContainer.GetChildByUserData(afflictionPrefab) ??
|
||||
hiddenAfflictionIconContainer.GetChildByUserData(afflictionPrefab);
|
||||
@@ -1138,9 +1153,13 @@ namespace Barotrauma
|
||||
matchingIcon = new GUIButton(new RectTransform(new Point(afflictionIconContainer.Rect.Height), afflictionIconContainer.RectTransform), style: null)
|
||||
{
|
||||
UserData = afflictionPrefab,
|
||||
ToolTip = affliction.Prefab.Name,
|
||||
ToolTip = $"‖color:{color.ToStringHex()}‖{affliction.Prefab.Name}‖color:end‖",
|
||||
CanBeSelected = false
|
||||
};
|
||||
if (affliction.Prefab.ShowDescriptionInTooltip)
|
||||
{
|
||||
matchingIcon.ToolTip = matchingIcon.ToolTip + "\n" + affliction.Prefab.GetDescription(affliction.Strength, AfflictionPrefab.Description.TargetType.Self);
|
||||
}
|
||||
if (affliction == pressureAffliction)
|
||||
{
|
||||
matchingIcon.ToolTip = TextManager.Get("PressureHUDWarning");
|
||||
@@ -1149,6 +1168,8 @@ namespace Barotrauma
|
||||
{
|
||||
matchingIcon.ToolTip = TextManager.Get("OxygenHUDWarning");
|
||||
}
|
||||
matchingIcon.ToolTip = RichString.Rich(matchingIcon.ToolTip);
|
||||
|
||||
new GUIImage(new RectTransform(Vector2.One, matchingIcon.RectTransform, Anchor.BottomCenter), afflictionPrefab.Icon, scaleToFit: true)
|
||||
{
|
||||
CanBeFocused = false
|
||||
@@ -1159,7 +1180,7 @@ namespace Barotrauma
|
||||
matchingIcon.RectTransform.Parent = hiddenAfflictionIconContainer.RectTransform;
|
||||
}
|
||||
var image = matchingIcon.GetChild<GUIImage>();
|
||||
image.Color = GetAfflictionIconColor(afflictionPrefab, affliction);
|
||||
image.Color = color;
|
||||
image.HoverColor = Color.Lerp(image.Color, Color.White, 0.5f);
|
||||
|
||||
if (affliction.DamagePerSecond > 1.0f && matchingIcon.FlashTimer <= 0.0f)
|
||||
@@ -1380,7 +1401,7 @@ namespace Barotrauma
|
||||
|
||||
recommendedTreatmentContainer.Content.ClearChildren();
|
||||
|
||||
float characterSkillLevel = Character.Controlled == null ? 0.0f : Character.Controlled.GetSkillLevel("medical");
|
||||
float characterSkillLevel = Character.Controlled == null ? 0.0f : Character.Controlled.GetSkillLevel(Tags.MedicalSkill);
|
||||
|
||||
//key = item identifier
|
||||
//float = suitability
|
||||
@@ -1388,7 +1409,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())
|
||||
{
|
||||
@@ -1949,7 +1972,6 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private bool ShouldDisplayAfflictionOnLimb(KeyValuePair<Affliction, LimbHealth> kvp, LimbHealth limbHealth)
|
||||
{
|
||||
if (!kvp.Key.ShouldShowIcon(Character)) { return false; }
|
||||
@@ -2058,23 +2080,23 @@ namespace Barotrauma
|
||||
newAfflictions.Add((limbHealths[limbIndex], afflictionPrefab, afflictionStrength));
|
||||
}
|
||||
|
||||
foreach (KeyValuePair<Affliction, LimbHealth> kvp in afflictions)
|
||||
foreach ((Affliction affliction, LimbHealth limbHealth) in afflictions)
|
||||
{
|
||||
//deactivate afflictions that weren't included in the network message
|
||||
if (!newAfflictions.Any(a => kvp.Key.Prefab == a.afflictionPrefab && kvp.Value == a.limb))
|
||||
if (newAfflictions.None(a => affliction.Prefab == a.afflictionPrefab && limbHealth == a.limb))
|
||||
{
|
||||
kvp.Key.Strength = 0.0f;
|
||||
affliction.Strength = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var (limb, afflictionPrefab, strength) in newAfflictions)
|
||||
{
|
||||
Affliction existingAffliction = null;
|
||||
foreach (KeyValuePair<Affliction, LimbHealth> kvp in afflictions)
|
||||
foreach ((Affliction affliction, LimbHealth limbHealth) in afflictions)
|
||||
{
|
||||
if (kvp.Key.Prefab == afflictionPrefab && kvp.Value == limb)
|
||||
if (affliction.Prefab == afflictionPrefab && limbHealth == limb)
|
||||
{
|
||||
existingAffliction = kvp.Key;
|
||||
existingAffliction = affliction;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -2123,9 +2145,8 @@ namespace Barotrauma
|
||||
|
||||
if (!Character.Params.Health.ApplyAfflictionColors) { return; }
|
||||
|
||||
foreach (KeyValuePair<Affliction, LimbHealth> kvp in afflictions)
|
||||
foreach ((Affliction affliction, LimbHealth _) in afflictions)
|
||||
{
|
||||
var affliction = kvp.Key;
|
||||
Color faceTint = affliction.GetFaceTint();
|
||||
if (faceTint.A > FaceTint.A) { FaceTint = faceTint; }
|
||||
Color bodyTint = affliction.GetBodyTint();
|
||||
@@ -2137,17 +2158,23 @@ namespace Barotrauma
|
||||
{
|
||||
foreach (Limb limb in Character.AnimController.Limbs)
|
||||
{
|
||||
if (limb.HealthIndex < 0 || limb.HealthIndex >= limbHealths.Count) { continue; }
|
||||
limb.BurnOverlayStrength = 0.0f;
|
||||
limb.DamageOverlayStrength = 0.0f;
|
||||
foreach (KeyValuePair<Affliction, LimbHealth> kvp in afflictions)
|
||||
}
|
||||
|
||||
foreach ((Affliction affliction, LimbHealth limbHealth) in afflictions)
|
||||
{
|
||||
if (affliction.Prefab.BurnOverlayAlpha <= 0.0f && affliction.Prefab.DamageOverlayAlpha <= 0.0f) { continue; }
|
||||
|
||||
float burnStrength = affliction.Strength / Math.Min(affliction.Prefab.MaxStrength, 100) * affliction.Prefab.BurnOverlayAlpha;
|
||||
float damageOverlayStrength = affliction.Strength / Math.Min(affliction.Prefab.MaxStrength, 100) * affliction.Prefab.DamageOverlayAlpha;
|
||||
foreach (Limb limb in Character.AnimController.Limbs)
|
||||
{
|
||||
var affliction = kvp.Key;
|
||||
float burnStrength = affliction.Strength / Math.Min(affliction.Prefab.MaxStrength, 100) * affliction.Prefab.BurnOverlayAlpha;
|
||||
if (kvp.Value == limbHealths[limb.HealthIndex] || !affliction.Prefab.LimbSpecific)
|
||||
if (limb.HealthIndex < 0 || limb.HealthIndex >= limbHealths.Count) { continue; }
|
||||
if (limbHealth == limbHealths[limb.HealthIndex] || !affliction.Prefab.LimbSpecific)
|
||||
{
|
||||
limb.BurnOverlayStrength += burnStrength;
|
||||
limb.DamageOverlayStrength += affliction.Strength / Math.Min(affliction.Prefab.MaxStrength, 100) * affliction.Prefab.DamageOverlayAlpha;
|
||||
limb.DamageOverlayStrength += damageOverlayStrength;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -17,13 +17,16 @@ public static class InteractionLabelManager
|
||||
|
||||
public RectangleF TextRect { get; set; }
|
||||
|
||||
public RichString Text;
|
||||
|
||||
public readonly Vector2 OriginalItemPosition;
|
||||
|
||||
public bool OverlapPreventionDone;
|
||||
|
||||
public LabelData(Item item, RectangleF textRect, Camera drawCamera)
|
||||
public LabelData(Item item, RectangleF textRect, RichString text, Camera drawCamera)
|
||||
{
|
||||
Item = item;
|
||||
Text = text;
|
||||
TextRect = textRect;
|
||||
OriginalItemPosition = item.Position;
|
||||
this.drawCamera = drawCamera;
|
||||
@@ -106,7 +109,7 @@ public static class InteractionLabelManager
|
||||
|
||||
if (labels.None(l => l.Item == interactableInRange))
|
||||
{
|
||||
var labelData = new LabelData(interactableInRange, textRect, cam);
|
||||
var labelData = new LabelData(interactableInRange, textRect, RichString.Rich(interactableInRange.Prefab.Name), cam);
|
||||
labels.Add(labelData);
|
||||
}
|
||||
}
|
||||
@@ -124,7 +127,7 @@ public static class InteractionLabelManager
|
||||
private static RectangleF GetLabelRect(Item item, Camera cam)
|
||||
{
|
||||
// create rectangle for overlap prevention
|
||||
Vector2 itemTextSizeScreen = GUIStyle.SubHeadingFont.MeasureString(item.Name) * LabelScale;
|
||||
Vector2 itemTextSizeScreen = GUIStyle.SubHeadingFont.MeasureString(RichString.Rich(item.Prefab.Name).SanitizedValue) * LabelScale;
|
||||
Vector2 interactablePosScreen = cam.WorldToScreen(item.Position);
|
||||
RectangleF textRect = new RectangleF(interactablePosScreen.X, interactablePosScreen.Y, itemTextSizeScreen.X, itemTextSizeScreen.Y);
|
||||
// center the rectangle on the item
|
||||
@@ -320,9 +323,11 @@ public static class InteractionLabelManager
|
||||
|
||||
GUIStyle.InteractionLabelBackground.Draw(spriteBatch, backgroundRect, color * 0.7f);
|
||||
|
||||
GUIStyle.SubHeadingFont.DrawString(spriteBatch,
|
||||
labelData.Item.Name,
|
||||
textDrawPosScreen, color, rotation: 0, origin: Vector2.Zero, scale, spriteEffects: SpriteEffects.None, layerDepth: 0.0f,
|
||||
GUIStyle.SubHeadingFont.DrawStringWithColors(spriteBatch,
|
||||
labelData.Text.SanitizedValue,
|
||||
textDrawPosScreen, color, rotation: 0, origin: Vector2.Zero, scale, spriteEffects: SpriteEffects.None,
|
||||
layerDepth: 0.0f,
|
||||
richTextData: labelData.Text.RichTextData,
|
||||
forceUpperCase: ForceUpperCase.No);
|
||||
}
|
||||
}
|
||||
@@ -1,85 +1,75 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using System.Linq;
|
||||
using System;
|
||||
using System.Xml.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
partial class JobPrefab : PrefabWithUintIdentifier
|
||||
{
|
||||
public GUIButton CreateInfoFrame(out GUIComponent buttonContainer)
|
||||
public GUIButton CreateInfoFrame(bool isPvP, out GUIComponent buttonContainer)
|
||||
{
|
||||
int width = 500, height = 400;
|
||||
|
||||
int windowPixelWidth = 500, windowPixelHeight = 400;
|
||||
Point absoluteWindowSize = new Point((int)(windowPixelWidth * GUI.xScale), (int)(windowPixelHeight * GUI.yScale));
|
||||
|
||||
GUIButton frameHolder = new GUIButton(new RectTransform(Vector2.One, GUI.Canvas, Anchor.Center), style: null);
|
||||
new GUIFrame(new RectTransform(GUI.Canvas.RelativeSize, frameHolder.RectTransform, Anchor.Center), style: "GUIBackgroundBlocker");
|
||||
|
||||
GUIFrame frame = new GUIFrame(new RectTransform(new Point(width, height), frameHolder.RectTransform, Anchor.Center));
|
||||
GUIFrame frame = new GUIFrame(new RectTransform(absoluteWindowSize, frameHolder.RectTransform, Anchor.Center));
|
||||
GUIFrame paddedFrame = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.9f), frame.RectTransform, Anchor.Center), style: null);
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.1f), paddedFrame.RectTransform), Name, font: GUIStyle.LargeFont)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
|
||||
var contentList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.75f), paddedFrame.RectTransform) { RelativeOffset = new Vector2(0.0f, 0.1f) })
|
||||
{
|
||||
ScrollBarVisible = true,
|
||||
AutoHideScrollBar = true,
|
||||
CurrentSelectMode = GUIListBox.SelectMode.None,
|
||||
Padding = new Vector4(0, GUI.Scale * 10, 0, 0),
|
||||
Spacing = (int)(GUI.Scale * 5)
|
||||
};
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.1f), paddedFrame.RectTransform), Name, font: GUIStyle.LargeFont);
|
||||
|
||||
var descriptionBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedFrame.RectTransform) { RelativeOffset = new Vector2(0.0f, 0.15f) },
|
||||
Description, font: GUIStyle.SmallFont, wrap: true);
|
||||
|
||||
var skillContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.45f, 0.5f), paddedFrame.RectTransform)
|
||||
{ RelativeOffset = new Vector2(0.0f, 0.2f + descriptionBlock.RectTransform.RelativeSize.Y) });
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), skillContainer.RectTransform),
|
||||
TextManager.Get("Skills"), font: GUIStyle.LargeFont);
|
||||
var descriptionBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), contentList.Content.RectTransform),
|
||||
Description, font: GUIStyle.SmallFont, wrap: true, textAlignment: Alignment.TopLeft)
|
||||
{
|
||||
CanBeFocused = false,
|
||||
};
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), contentList.Content.RectTransform),
|
||||
TextManager.Get("Skills"), font: GUIStyle.LargeFont)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
|
||||
foreach (SkillPrefab skill in Skills)
|
||||
{
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), skillContainer.RectTransform),
|
||||
" - " + TextManager.AddPunctuation(':', TextManager.Get("SkillName." + skill.Identifier), (int)skill.LevelRange.Start + " - " + (int)skill.LevelRange.End),
|
||||
font: GUIStyle.SmallFont);
|
||||
var levelRange = skill.GetLevelRange(isPvP);
|
||||
|
||||
string levelStr =
|
||||
levelRange.End > levelRange.Start ?
|
||||
(int)levelRange.Start + " - " + (int)levelRange.End :
|
||||
((int)levelRange.Start).ToString();
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), contentList.Content.RectTransform),
|
||||
" - " + TextManager.AddPunctuation(':', TextManager.Get("SkillName." + skill.Identifier), levelStr),
|
||||
font: GUIStyle.SmallFont, wrap: true)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
}
|
||||
|
||||
buttonContainer = paddedFrame;
|
||||
|
||||
/*if (!ItemIdentifiers.TryGetValue(variant, out var itemIdentifiers)) { return backFrame; }
|
||||
var itemContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.45f, 0.5f), paddedFrame.RectTransform, Anchor.TopRight)
|
||||
{ RelativeOffset = new Vector2(0.0f, 0.2f + descriptionBlock.RectTransform.RelativeSize.Y) })
|
||||
{
|
||||
Stretch = true
|
||||
};
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), itemContainer.RectTransform),
|
||||
TextManager.Get("Items", "mapentitycategory.equipment"), font: GUIStyle.LargeFont);
|
||||
foreach (string identifier in itemIdentifiers.Distinct())
|
||||
{
|
||||
if (!(MapEntityPrefab.Find(name: null, identifier: identifier) is ItemPrefab itemPrefab)) { continue; }
|
||||
int count = itemIdentifiers.Count(i => i == identifier);
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), itemContainer.RectTransform),
|
||||
" - " + (count == 1 ? itemPrefab.Name : itemPrefab.Name + " x" + count),
|
||||
font: GUIStyle.SmallFont);
|
||||
}*/
|
||||
|
||||
|
||||
return frameHolder;
|
||||
}
|
||||
|
||||
public class OutfitPreview
|
||||
|
||||
public IEnumerable<Sprite> GetJobOutfitSprites(CharacterTeamType team, bool isPvPMode)
|
||||
{
|
||||
public readonly List<(Sprite sprite, Vector2 drawOffset)> Sprites;
|
||||
|
||||
public Vector2 Dimensions;
|
||||
|
||||
public OutfitPreview()
|
||||
{
|
||||
Sprites = new List<(Sprite sprite, Vector2 drawOffset)>();
|
||||
Dimensions = Vector2.One;
|
||||
}
|
||||
|
||||
public void AddSprite(Sprite sprite, Vector2 drawOffset)
|
||||
{
|
||||
Sprites.Add((sprite, drawOffset));
|
||||
}
|
||||
}
|
||||
|
||||
public List<OutfitPreview> GetJobOutfitSprites(CharacterInfoPrefab charInfoPrefab, bool useInventoryIcon, out Vector2 maxDimensions)
|
||||
{
|
||||
List<OutfitPreview> outfitPreviews = new List<OutfitPreview>();
|
||||
maxDimensions = Vector2.One;
|
||||
|
||||
var equipIdentifiers = Element.GetChildElements("ItemSet").Elements().Where(e => e.GetAttributeBool("outfit", false)).Select(e => e.GetAttributeIdentifier("identifier", ""));
|
||||
var equipIdentifiers = JobItems
|
||||
.SelectMany(kvp => kvp.Value)
|
||||
.Where(j => j.Outfit)
|
||||
.Select(j => j.GetItemIdentifier(team, isPvPMode));
|
||||
|
||||
List<ItemPrefab> outfitPrefabs = new List<ItemPrefab>();
|
||||
foreach (var equipIdentifier in equipIdentifiers)
|
||||
@@ -88,45 +78,9 @@ namespace Barotrauma
|
||||
if (itemPrefab != null) { outfitPrefabs.Add(itemPrefab); }
|
||||
}
|
||||
|
||||
if (!outfitPrefabs.Any()) { return null; }
|
||||
if (!outfitPrefabs.Any()) { return Enumerable.Empty<Sprite>(); }
|
||||
|
||||
for (int i = 0; i < outfitPrefabs.Count; i++)
|
||||
{
|
||||
var outfitPreview = new OutfitPreview();
|
||||
|
||||
if (!ItemSets.TryGetValue(i, out var itemSetElement)) { continue; }
|
||||
var previewElement = itemSetElement.GetChildElement("PreviewSprites");
|
||||
if (previewElement == null || useInventoryIcon)
|
||||
{
|
||||
if (outfitPrefabs[i] is ItemPrefab prefab && prefab.InventoryIcon != null)
|
||||
{
|
||||
outfitPreview.AddSprite(prefab.InventoryIcon, Vector2.Zero);
|
||||
outfitPreview.Dimensions = prefab.InventoryIcon.SourceRect.Size.ToVector2();
|
||||
maxDimensions.X = MathHelper.Max(maxDimensions.X, outfitPreview.Dimensions.X);
|
||||
maxDimensions.Y = MathHelper.Max(maxDimensions.Y, outfitPreview.Dimensions.Y);
|
||||
}
|
||||
outfitPreviews.Add(outfitPreview);
|
||||
continue;
|
||||
}
|
||||
|
||||
var children = previewElement.Elements().ToList();
|
||||
for (int n = 0; n < children.Count; n++)
|
||||
{
|
||||
var spriteElement = children[n];
|
||||
string spriteTexture = charInfoPrefab.ReplaceVars(spriteElement.GetAttributeString("texture", ""), charInfoPrefab.Heads.First());
|
||||
var sprite = new Sprite(spriteElement, file: spriteTexture);
|
||||
sprite.size = new Vector2(sprite.SourceRect.Width, sprite.SourceRect.Height);
|
||||
outfitPreview.AddSprite(sprite, children[n].GetAttributeVector2("offset", Vector2.Zero));
|
||||
}
|
||||
|
||||
outfitPreview.Dimensions = previewElement.GetAttributeVector2("dims", Vector2.One);
|
||||
maxDimensions.X = MathHelper.Max(maxDimensions.X, outfitPreview.Dimensions.X);
|
||||
maxDimensions.Y = MathHelper.Max(maxDimensions.Y, outfitPreview.Dimensions.Y);
|
||||
|
||||
outfitPreviews.Add(outfitPreview);
|
||||
}
|
||||
|
||||
return outfitPreviews;
|
||||
return outfitPrefabs.Select(p => p.InventoryIcon ?? p.Sprite);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -184,12 +202,6 @@ namespace Barotrauma
|
||||
|
||||
public Sprite DamagedSprite { get; private set; }
|
||||
|
||||
public bool Hide
|
||||
{
|
||||
get => Params.Hide;
|
||||
set => Params.Hide = value;
|
||||
}
|
||||
|
||||
public List<ConditionalSprite> ConditionalSprites { get; private set; } = new List<ConditionalSprite>();
|
||||
private Dictionary<DecorativeSprite, SpriteState> spriteAnimState = new Dictionary<DecorativeSprite, SpriteState>();
|
||||
private Dictionary<int, List<DecorativeSprite>> DecorativeSpriteGroups = new Dictionary<int, List<DecorativeSprite>>();
|
||||
@@ -198,6 +210,7 @@ namespace Barotrauma
|
||||
{
|
||||
public float RotationState;
|
||||
public float OffsetState;
|
||||
public float ScaleState;
|
||||
public Vector2 RandomOffsetMultiplier = new Vector2(Rand.Range(-1.0f, 1.0f), Rand.Range(-1.0f, 1.0f));
|
||||
public float RandomRotationFactor = Rand.Range(0.0f, 1.0f);
|
||||
public float RandomScaleFactor = Rand.Range(0.0f, 1.0f);
|
||||
@@ -301,7 +314,16 @@ namespace Barotrauma
|
||||
DamagedSprite = new Sprite(subElement, file: GetSpritePath(subElement, Params.damagedSpriteParams, ref _damagedTexturePath), sourceRectScale: sourceRectScale);
|
||||
break;
|
||||
case "conditionalsprite":
|
||||
var conditionalSprite = new ConditionalSprite(subElement, GetConditionalTarget(), file: GetSpritePath(subElement, null, ref _texturePath), sourceRectScale: sourceRectScale);
|
||||
string conditionalSpritePath = string.Empty;
|
||||
GetSpritePath(subElement.GetChildElement("sprite") ?? subElement.GetChildElement("deformablesprite") ?? subElement, null, ref conditionalSpritePath);
|
||||
if (conditionalSpritePath.IsNullOrEmpty())
|
||||
{
|
||||
DebugConsole.ThrowError($"Failed to find a sprite path in the conditional sprite defined in {character.SpeciesName}, limb {type}.",
|
||||
contentPackage: subElement.ContentPackage);
|
||||
}
|
||||
var conditionalSprite = new ConditionalSprite(subElement, GetConditionalTarget(),
|
||||
file: conditionalSpritePath,
|
||||
sourceRectScale: sourceRectScale);
|
||||
ConditionalSprites.Add(conditionalSprite);
|
||||
if (conditionalSprite.DeformableSprite != null)
|
||||
{
|
||||
@@ -475,13 +497,24 @@ namespace Barotrauma
|
||||
private string _damagedTexturePath;
|
||||
private string GetSpritePath(ContentXElement element, SpriteParams spriteParams, ref string path)
|
||||
{
|
||||
if (path == null)
|
||||
if (path.IsNullOrEmpty())
|
||||
{
|
||||
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?.GetRootExcludingOverride()?.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();
|
||||
@@ -491,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);
|
||||
}
|
||||
@@ -749,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);
|
||||
|
||||
@@ -771,11 +824,13 @@ namespace Barotrauma
|
||||
{
|
||||
if (ActiveDeformations.Any())
|
||||
{
|
||||
var deformation = SpriteDeformation.GetDeformation(ActiveDeformations, deformSprite.Size);
|
||||
var deformation = SpriteDeformation.GetDeformation(ActiveDeformations, deformSprite.Size, flippedHorizontally: IsFlipped, false);
|
||||
deformSprite.Deform(deformation);
|
||||
if (LightSource != null && LightSource.DeformableLightSprite != null)
|
||||
{
|
||||
deformation = SpriteDeformation.GetDeformation(ActiveDeformations, deformSprite.Size, dir == Direction.Left);
|
||||
//apparently inversing on the y-axis is only necessary for light sprites (see 345a65ca6)
|
||||
//it's a mystery why this is the case, something to do with sprite flipping being handled differently in light rendering?
|
||||
deformation = SpriteDeformation.GetDeformation(ActiveDeformations, deformSprite.Size, flippedHorizontally: IsFlipped, inverseY: dir == Direction.Left);
|
||||
LightSource.DeformableLightSprite.Deform(deformation);
|
||||
}
|
||||
}
|
||||
@@ -826,7 +881,7 @@ namespace Barotrauma
|
||||
var defSprite = conditionalSprite.DeformableSprite;
|
||||
if (ActiveDeformations.Any())
|
||||
{
|
||||
var deformation = SpriteDeformation.GetDeformation(ActiveDeformations, defSprite.Size);
|
||||
var deformation = SpriteDeformation.GetDeformation(ActiveDeformations, defSprite.Size, flippedHorizontally: IsFlipped);
|
||||
defSprite.Deform(deformation);
|
||||
}
|
||||
else
|
||||
@@ -883,28 +938,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)
|
||||
@@ -952,8 +1007,8 @@ namespace Barotrauma
|
||||
var ca = (float)Math.Cos(-body.Rotation);
|
||||
var sa = (float)Math.Sin(-body.Rotation);
|
||||
Vector2 transformedOffset = new Vector2(ca * offset.X + sa * offset.Y, -sa * offset.X + ca * offset.Y);
|
||||
decorativeSprite.Sprite.Draw(spriteBatch, new Vector2(body.DrawPosition.X + transformedOffset.X, -(body.DrawPosition.Y + transformedOffset.Y)), c,
|
||||
-body.Rotation + rotation, decorativeSprite.GetScale(spriteAnimState[decorativeSprite].RandomScaleFactor) * Scale, spriteEffect,
|
||||
decorativeSprite.Sprite.Draw(spriteBatch, new Vector2(body.DrawPosition.X + transformedOffset.X, -(body.DrawPosition.Y + transformedOffset.Y)), c, decorativeSprite.Sprite.Origin,
|
||||
-body.Rotation + rotation, decorativeSprite.GetScale(ref spriteAnimState[decorativeSprite].ScaleState, spriteAnimState[decorativeSprite].RandomScaleFactor) * Scale, spriteEffect,
|
||||
depth: activeSprite.Depth - depthStep);
|
||||
depthStep += step;
|
||||
}
|
||||
@@ -963,7 +1018,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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user