diff --git a/Barotrauma/BarotraumaClient/ClientCode.projitems b/Barotrauma/BarotraumaClient/ClientCode.projitems
index ab5b8970a..a5cc964a4 100644
--- a/Barotrauma/BarotraumaClient/ClientCode.projitems
+++ b/Barotrauma/BarotraumaClient/ClientCode.projitems
@@ -18,13 +18,14 @@
-
+
+
diff --git a/Barotrauma/BarotraumaClient/Content/Effects/deformshader.xnb b/Barotrauma/BarotraumaClient/Content/Effects/deformshader.xnb
index 35b0ae81b..d40fbb220 100644
Binary files a/Barotrauma/BarotraumaClient/Content/Effects/deformshader.xnb and b/Barotrauma/BarotraumaClient/Content/Effects/deformshader.xnb differ
diff --git a/Barotrauma/BarotraumaClient/Content/Effects/deformshader_opengl.xnb b/Barotrauma/BarotraumaClient/Content/Effects/deformshader_opengl.xnb
index 15bed2a78..8d926c6ea 100644
Binary files a/Barotrauma/BarotraumaClient/Content/Effects/deformshader_opengl.xnb and b/Barotrauma/BarotraumaClient/Content/Effects/deformshader_opengl.xnb differ
diff --git a/Barotrauma/BarotraumaClient/LinuxClient.csproj b/Barotrauma/BarotraumaClient/LinuxClient.csproj
index 9f61fb02c..2a79e12b8 100644
--- a/Barotrauma/BarotraumaClient/LinuxClient.csproj
+++ b/Barotrauma/BarotraumaClient/LinuxClient.csproj
@@ -31,7 +31,6 @@
true
- ..\BarotraumaShared\IconBmp.bmp
..\BarotraumaShared\Icon.ico
@@ -192,11 +191,6 @@
-
-
- Icon.bmp
-
-
diff --git a/Barotrauma/BarotraumaClient/Properties/AssemblyInfo.cs b/Barotrauma/BarotraumaClient/Properties/AssemblyInfo.cs
index bd0597493..def51c503 100644
--- a/Barotrauma/BarotraumaClient/Properties/AssemblyInfo.cs
+++ b/Barotrauma/BarotraumaClient/Properties/AssemblyInfo.cs
@@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("0.8.9.7")]
-[assembly: AssemblyFileVersion("0.8.9.7")]
+[assembly: AssemblyVersion("0.8.9.6")]
+[assembly: AssemblyFileVersion("0.8.9.6")]
diff --git a/Barotrauma/BarotraumaClient/Shaders/deformshader.fx b/Barotrauma/BarotraumaClient/Shaders/deformshader.fx
index dcf54addd..bf621efe0 100644
--- a/Barotrauma/BarotraumaClient/Shaders/deformshader.fx
+++ b/Barotrauma/BarotraumaClient/Shaders/deformshader.fx
@@ -14,7 +14,6 @@ float2 uvTopLeft;
float2 uvBottomRight;
float4 tintColor;
-float4 solidColor;
struct VertexShaderInput
{
@@ -75,11 +74,6 @@ float4 mainPS(VertexShaderOutput input) : COLOR
return xTexture.Sample(TextureSampler, input.TexCoords) * input.Color;
}
-float4 solidColorPS(VertexShaderOutput input) : COLOR
-{
- return solidColor * xTexture.Sample(TextureSampler, input.TexCoords).a;
-}
-
technique DeformShader
{
pass Pass1
@@ -87,13 +81,4 @@ technique DeformShader
VertexShader = compile vs_4_0_level_9_1 mainVS();
PixelShader = compile ps_4_0_level_9_1 mainPS();
}
-}
-
-technique DeformShaderSolidColor
-{
- pass Pass1
- {
- VertexShader = compile vs_4_0_level_9_1 mainVS();
- PixelShader = compile ps_4_0_level_9_1 solidColorPS();
- }
}
\ No newline at end of file
diff --git a/Barotrauma/BarotraumaClient/Shaders/deformshader_opengl.fx b/Barotrauma/BarotraumaClient/Shaders/deformshader_opengl.fx
index c77904ffe..fbf640ede 100644
--- a/Barotrauma/BarotraumaClient/Shaders/deformshader_opengl.fx
+++ b/Barotrauma/BarotraumaClient/Shaders/deformshader_opengl.fx
@@ -14,7 +14,6 @@ float2 uvTopLeft;
float2 uvBottomRight;
float4 tintColor;
-float4 solidColor;
struct VertexShaderInput
{
@@ -75,11 +74,6 @@ float4 mainPS(VertexShaderOutput input) : COLOR
return xTexture.Sample(TextureSampler, input.TexCoords) * input.Color;
}
-float4 solidColorPS(VertexShaderOutput input) : COLOR
-{
- return solidColor * xTexture.Sample(TextureSampler, input.TexCoords).a;
-}
-
technique DeformShader
{
pass Pass1
@@ -87,13 +81,4 @@ technique DeformShader
VertexShader = compile vs_3_0 mainVS();
PixelShader = compile ps_3_0 mainPS();
}
-}
-
-technique DeformShaderSolidColor
-{
- pass Pass1
- {
- VertexShader = compile vs_3_0 mainVS();
- PixelShader = compile ps_3_0 solidColorPS();
- }
}
\ No newline at end of file
diff --git a/Barotrauma/BarotraumaClient/Source/Characters/AI/AITarget.cs b/Barotrauma/BarotraumaClient/Source/Characters/AI/AITarget.cs
index 318d1d048..6a7d9ec27 100644
--- a/Barotrauma/BarotraumaClient/Source/Characters/AI/AITarget.cs
+++ b/Barotrauma/BarotraumaClient/Source/Characters/AI/AITarget.cs
@@ -13,39 +13,13 @@ namespace Barotrauma
var pos = new Vector2(WorldPosition.X, -WorldPosition.Y);
if (soundRange > 0.0f)
{
- Color color;
- if (Entity is Character)
- {
- color = Color.Yellow;
- }
- else if (Entity is Item)
- {
- color = Color.Orange;
- }
- else
- {
- color = Color.OrangeRed;
- }
+ Color color = Entity is Character ? Color.Yellow : Color.Orange;
ShapeExtensions.DrawCircle(spriteBatch, pos, SoundRange, 100, color, thickness: 1 / Screen.Selected.Cam.Zoom);
- ShapeExtensions.DrawCircle(spriteBatch, pos, 3, 8, color, thickness: 2 / Screen.Selected.Cam.Zoom);
}
if (sightRange > 0.0f)
{
- Color color;
- if (Entity is Character)
- {
- color = Color.CornflowerBlue;
- }
- else if (Entity is Item)
- {
- color = Color.CadetBlue;
- }
- else
- {
- color = Color.WhiteSmoke;
- }
+ Color color = Entity is Character ? Color.CornflowerBlue : Color.CadetBlue;
ShapeExtensions.DrawCircle(spriteBatch, pos, SightRange, 100, color, thickness: 1 / Screen.Selected.Cam.Zoom);
- ShapeExtensions.DrawCircle(spriteBatch, pos, 6, 8, color, thickness: 2 / Screen.Selected.Cam.Zoom);
}
}
}
diff --git a/Barotrauma/BarotraumaClient/Source/Characters/AI/EnemyAIController.cs b/Barotrauma/BarotraumaClient/Source/Characters/AI/EnemyAIController.cs
index e112d338c..e5ddec5c8 100644
--- a/Barotrauma/BarotraumaClient/Source/Characters/AI/EnemyAIController.cs
+++ b/Barotrauma/BarotraumaClient/Source/Characters/AI/EnemyAIController.cs
@@ -16,17 +16,18 @@ namespace Barotrauma
if (SelectedAiTarget?.Entity != null)
{
- GUI.DrawLine(spriteBatch, pos, new Vector2(SelectedAiTarget.WorldPosition.X, -SelectedAiTarget.WorldPosition.Y), Color.Red * 0.5f, 0, 4);
+ GUI.DrawLine(spriteBatch, pos, new Vector2(SelectedAiTarget.WorldPosition.X, -SelectedAiTarget.WorldPosition.Y), Color.Red * 0.3f, 0, 5);
if (wallTarget != null)
{
Vector2 wallTargetPos = wallTarget.Position;
- if (wallTarget.Structure.Submarine != null) { wallTargetPos += wallTarget.Structure.Submarine.Position; }
+ if (wallTarget.Structure.Submarine != null) wallTargetPos += wallTarget.Structure.Submarine.Position;
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.DrawRectangle(spriteBatch, wallTargetPos - new Vector2(10.0f, 10.0f), new Vector2(20.0f, 20.0f), Color.Red, false);
+ GUI.DrawLine(spriteBatch, pos, wallTargetPos, Color.Orange * 0.5f, 0, 5);
}
- GUI.DrawString(spriteBatch, pos - Vector2.UnitY * 60.0f, $"{SelectedAiTarget.Entity.ToString()} ({targetValue.FormatZeroDecimal()})", Color.Red, Color.Black);
+
+ GUI.Font.DrawString(spriteBatch, $"{SelectedAiTarget.Entity.ToString()} ({targetValue.ToString()})", pos - Vector2.UnitY * 20.0f, Color.Red);
}
/*GUI.Font.DrawString(spriteBatch, targetValue.ToString(), pos - Vector2.UnitY * 80.0f, Color.Red);
@@ -57,9 +58,18 @@ namespace Barotrauma
{
GUI.DrawLine(spriteBatch,
ConvertUnits.ToDisplayUnits(new Vector2(attachJoint.WorldAnchorA.X, -attachJoint.WorldAnchorA.Y)),
- ConvertUnits.ToDisplayUnits(new Vector2(attachJoint.WorldAnchorB.X, -attachJoint.WorldAnchorB.Y)), Color.Green, 0, 4);
+ ConvertUnits.ToDisplayUnits(new Vector2(attachJoint.WorldAnchorB.X, -attachJoint.WorldAnchorB.Y)), Color.Orange * 0.6f, 0, 5);
}
+ if (latchOntoAI.WallAttachPos.HasValue)
+ {
+ GUI.DrawLine(spriteBatch, pos,
+ ConvertUnits.ToDisplayUnits(new Vector2(latchOntoAI.WallAttachPos.Value.X, -latchOntoAI.WallAttachPos.Value.Y)), Color.Orange * 0.6f, 0, 3);
+ }
+ }
+
+ GUI.DrawLine(spriteBatch, pos, pos + ConvertUnits.ToDisplayUnits(new Vector2(Steering.X, -Steering.Y)), Color.Blue, width: 3);
+
if (latchOntoAI.WallAttachPos.HasValue)
{
GUI.DrawLine(spriteBatch, pos,
@@ -67,34 +77,22 @@ namespace Barotrauma
}
}
- if (steeringManager is IndoorsSteeringManager pathSteering)
+ GUI.DrawLine(spriteBatch,
+ new Vector2(Character.DrawPosition.X, -Character.DrawPosition.Y),
+ new Vector2(pathSteering.CurrentPath.CurrentNode.DrawPosition.X, -pathSteering.CurrentPath.CurrentNode.DrawPosition.Y),
+ Color.Orange * 0.6f, 0, 3);
+
+ for (int i = 1; i < pathSteering.CurrentPath.Nodes.Count; i++)
{
- var path = pathSteering.CurrentPath;
- if (path != null)
- {
- if (path.CurrentNode != null)
- {
- GUI.DrawLine(spriteBatch, pos,
- new Vector2(path.CurrentNode.DrawPosition.X, -path.CurrentNode.DrawPosition.Y),
- Color.DarkViolet, 0, 3);
+ GUI.DrawLine(spriteBatch,
+ new Vector2(pathSteering.CurrentPath.Nodes[i].DrawPosition.X, -pathSteering.CurrentPath.Nodes[i].DrawPosition.Y),
+ new Vector2(pathSteering.CurrentPath.Nodes[i - 1].DrawPosition.X, -pathSteering.CurrentPath.Nodes[i - 1].DrawPosition.Y),
+ Color.Orange * 0.6f, 0, 3);
- GUI.DrawString(spriteBatch, pos - new Vector2(0, 100), "Path cost: " + path.Cost.FormatZeroDecimal(), Color.White, Color.Black * 0.5f);
- }
- for (int i = 1; i < path.Nodes.Count; i++)
- {
- var previousNode = path.Nodes[i - 1];
- var currentNode = path.Nodes[i];
- GUI.DrawLine(spriteBatch,
- new Vector2(currentNode.DrawPosition.X, -currentNode.DrawPosition.Y),
- new Vector2(previousNode.DrawPosition.X, -previousNode.DrawPosition.Y),
- Color.Red * 0.5f, 0, 3);
-
- GUI.SmallFont.DrawString(spriteBatch,
- currentNode.ID.ToString(),
- new Vector2(currentNode.DrawPosition.X + 20, -currentNode.DrawPosition.Y - 20),
- Color.Red);
- }
- }
+ GUI.SmallFont.DrawString(spriteBatch,
+ pathSteering.CurrentPath.Nodes[i].ID.ToString(),
+ new Vector2(pathSteering.CurrentPath.Nodes[i].DrawPosition.X, -pathSteering.CurrentPath.Nodes[i].DrawPosition.Y - 10),
+ Color.LightGreen);
}
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);
diff --git a/Barotrauma/BarotraumaClient/Source/Characters/AI/HumanAIController.cs b/Barotrauma/BarotraumaClient/Source/Characters/AI/HumanAIController.cs
index 28686501e..b588b93a4 100644
--- a/Barotrauma/BarotraumaClient/Source/Characters/AI/HumanAIController.cs
+++ b/Barotrauma/BarotraumaClient/Source/Characters/AI/HumanAIController.cs
@@ -75,12 +75,11 @@ namespace Barotrauma
GUI.SmallFont.DrawString(spriteBatch,
currentNode.ID.ToString(),
- new Vector2(currentNode.DrawPosition.X + 20, -currentNode.DrawPosition.Y - 20),
- Color.SkyBlue);
+ new Vector2(currentNode.DrawPosition.X, -currentNode.DrawPosition.Y - 10),
+ Color.LightGreen);
}
}
}
- 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);
//if (Character.IsKeyDown(InputType.Aim))
diff --git a/Barotrauma/BarotraumaClient/Source/Characters/Animation/Ragdoll.cs b/Barotrauma/BarotraumaClient/Source/Characters/Animation/Ragdoll.cs
index c6f95eda7..5c3dd9749 100644
--- a/Barotrauma/BarotraumaClient/Source/Characters/Animation/Ragdoll.cs
+++ b/Barotrauma/BarotraumaClient/Source/Characters/Animation/Ragdoll.cs
@@ -210,9 +210,7 @@ namespace Barotrauma
else
{
Vector2 positionError = serverPos.Position - localPos.Position;
- float rotationError = serverPos.Rotation.HasValue && localPos.Rotation.HasValue ?
- serverPos.Rotation.Value - localPos.Rotation.Value :
- 0.0f;
+ float rotationError = serverPos.Rotation - localPos.Rotation;
for (int i = localPosIndex; i < character.MemLocalState.Count; i++)
{
diff --git a/Barotrauma/BarotraumaClient/Source/Characters/CharacterHealth.cs b/Barotrauma/BarotraumaClient/Source/Characters/CharacterHealth.cs
index 75ea85fb8..4fb00dc00 100644
--- a/Barotrauma/BarotraumaClient/Source/Characters/CharacterHealth.cs
+++ b/Barotrauma/BarotraumaClient/Source/Characters/CharacterHealth.cs
@@ -544,10 +544,7 @@ namespace Barotrauma
{
healthBar.Color = healthWindowHealthBar.Color = ToolBox.GradientLerp(Vitality / MaxVitality, Color.Red, Color.Orange, Color.Green);
healthBar.HoverColor = healthWindowHealthBar.HoverColor = healthBar.Color * 2.0f;
- healthBar.BarSize = healthWindowHealthBar.BarSize =
- (Vitality > 0.0f) ?
- (MaxVitality > 0.0f ? Vitality / MaxVitality : 0.0f) :
- (Math.Abs(MinVitality) > 0.0f ? 1.0f - Vitality / MinVitality : 0.0f);
+ healthBar.BarSize = healthWindowHealthBar.BarSize = (Vitality > 0.0f) ? Vitality / MaxVitality : 1.0f - Vitality / MinVitality;
if (healthBarPulsateTimer > 0.0f)
{
diff --git a/Barotrauma/BarotraumaClient/Source/Characters/CharacterNetworking.cs b/Barotrauma/BarotraumaClient/Source/Characters/CharacterNetworking.cs
index c53b261fa..54acd801e 100644
--- a/Barotrauma/BarotraumaClient/Source/Characters/CharacterNetworking.cs
+++ b/Barotrauma/BarotraumaClient/Source/Characters/CharacterNetworking.cs
@@ -214,8 +214,8 @@ namespace Barotrauma
msg.ReadRangedSingle(-MaxVel, MaxVel, 12));
bool fixedRotation = msg.ReadBoolean();
- float? rotation = null;
- float? angularVelocity = null;
+ float rotation = AnimController.Collider.Rotation;
+ float angularVelocity = AnimController.Collider.AngularVelocity;
if (!fixedRotation)
{
rotation = msg.ReadFloat();
diff --git a/Barotrauma/BarotraumaClient/Source/Characters/Health/CharacterHealth.cs b/Barotrauma/BarotraumaClient/Source/Characters/Health/CharacterHealth.cs
index 04cb8c620..a43ee6069 100644
--- a/Barotrauma/BarotraumaClient/Source/Characters/Health/CharacterHealth.cs
+++ b/Barotrauma/BarotraumaClient/Source/Characters/Health/CharacterHealth.cs
@@ -1,1400 +1,7 @@
-using Barotrauma.Items.Components;
-using Barotrauma.Networking;
-using Lidgren.Network;
-using Microsoft.Xna.Framework;
-using Microsoft.Xna.Framework.Graphics;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Xml.Linq;
-
-namespace Barotrauma
+namespace Barotrauma
{
partial class CharacterHealth
{
- private static bool toggledThisFrame;
-
- private static Sprite damageOverlay;
-
- private static string[] strengthTexts;
-
- private GUIButton cprButton;
-
- private Point screenResolution;
-
- private float uiScale, inventoryScale;
-
- private Alignment alignment = Alignment.Left;
- public Alignment Alignment
- {
- get { return alignment; }
- set
- {
- if (alignment == value) return;
- alignment = value;
- UpdateAlignment();
- }
- }
-
- private GUIButton suicideButton;
-
- // healthbars
- private GUIProgressBar healthBar;
- private GUIProgressBar healthBarShadow;
- private GUIProgressBar healthWindowHealthBar;
- private GUIProgressBar healthWindowHealthBarShadow;
- private float healthShadowSize;
- private float healthShadowDelay;
- private float healthBarPulsateTimer;
- private float healthBarPulsatePhase;
-
- private GUITextBlock characterName;
- private GUIFrame afflictionInfoFrame;
- private GUIListBox afflictionInfoContainer;
- private GUIListBox recommendedTreatmentContainer;
-
- private float bloodParticleTimer;
-
- private GUIFrame healthWindow;
-
- private GUIComponent deadIndicator;
-
- private GUIComponent lowSkillIndicator;
-
- private SpriteSheet limbIndicatorOverlay;
- private float limbIndicatorOverlayAnimState;
-
- private GUIFrame dropItemArea;
-
- private float dropItemAnimDuration = 0.5f;
- private float dropItemAnimTimer;
- private Item droppedItem;
-
- private GUIComponent draggingMed;
-
- private int highlightedLimbIndex = -1;
- private int selectedLimbIndex = -1;
- private LimbHealth currentDisplayedLimb;
-
- private float distortTimer;
-
- // 0-1
- private float damageIntensity;
- private float damageIntensityDropdownRate = 0.1f;
-
- public float DamageOverlayTimer { get; private set; }
-
- private float updateDisplayedAfflictionsTimer;
- private const float UpdateDisplayedAfflictionsInterval = 0.5f;
- private List currentDisplayedAfflictions = new List();
-
- private static CharacterHealth openHealthWindow;
- public static CharacterHealth OpenHealthWindow
- {
- get
- {
- return openHealthWindow;
- }
- set
- {
- if (openHealthWindow == value) return;
- if (value != null && !value.UseHealthWindow) return;
-
- openHealthWindow = value;
- toggledThisFrame = true;
- if (Character.Controlled == null) { return; }
-
- if (value == null &&
- Character.Controlled?.SelectedCharacter?.CharacterHealth != null &&
- Character.Controlled.SelectedCharacter.CharacterHealth == openHealthWindow &&
- !Character.Controlled.SelectedCharacter.CanInventoryBeAccessed)
- {
- Character.Controlled.DeselectCharacter();
- }
-
- Character.Controlled.ResetInteract = true;
- if (openHealthWindow != null)
- {
- openHealthWindow.characterName.Text = value.Character.Name;
- Character.Controlled.SelectedConstruction = null;
- }
- }
- }
-
- static CharacterHealth()
- {
- damageOverlay = new Sprite("Content/UI/damageOverlay.png", Vector2.Zero);
- }
-
- partial void InitProjSpecific(XElement element, Character character)
- {
- if (strengthTexts == null)
- {
- strengthTexts = new string[]
- {
- TextManager.Get("AfflictionStrengthLow"),
- TextManager.Get("AfflictionStrengthMedium"),
- TextManager.Get("AfflictionStrengthHigh")
- };
- }
-
- character.OnAttacked += OnAttacked;
-
- bool horizontal = HUDLayoutSettings.HealthBarAreaLeft.Width > HUDLayoutSettings.HealthBarAreaLeft.Height;
- healthBar = new GUIProgressBar(HUDLayoutSettings.ToRectTransform(HUDLayoutSettings.HealthBarAreaLeft, GUI.Canvas),
- barSize: 1.0f, color: Color.Green, style: horizontal ? "GUIProgressBar" : "GUIProgressBarVertical")
- {
- IsHorizontal = horizontal
- };
- healthBarShadow = new GUIProgressBar(HUDLayoutSettings.ToRectTransform(HUDLayoutSettings.HealthBarAreaLeft, GUI.Canvas),
- barSize: 1.0f, color: Color.Green, style: horizontal ? "GUIProgressBar" : "GUIProgressBarVertical")
- {
- IsHorizontal = horizontal
- };
- healthShadowSize = 1.0f;
-
- afflictionInfoFrame = new GUIFrame(new RectTransform(new Point(HUDLayoutSettings.HealthWindowAreaLeft.Width / 2, 200), GUI.Canvas));
- var paddedInfoFrame = new GUIFrame(new RectTransform(new Vector2(0.95f, 0.9f), afflictionInfoFrame.RectTransform, Anchor.Center), style: null);
- new GUITextBlock(new RectTransform(new Vector2(0.8f, 0.08f), paddedInfoFrame.RectTransform), "", font: GUI.LargeFont)
- {
- UserData = "selectedlimbname"
- };
-
- afflictionInfoContainer = new GUIListBox(new RectTransform(new Vector2(0.7f, 0.85f), paddedInfoFrame.RectTransform, Anchor.BottomLeft));
-
- new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.08f), paddedInfoFrame.RectTransform), TextManager.Get("SuitableTreatments"), textAlignment: Alignment.TopRight);
- lowSkillIndicator = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.07f), paddedInfoFrame.RectTransform, Anchor.TopRight) { RelativeOffset = new Vector2(0.0f, 0.08f) },
- TextManager.Get("LowMedicalSkillWarning"), Color.Orange, textAlignment: Alignment.Center, font: GUI.SmallFont, wrap: true)
- {
- Visible = false
- };
- recommendedTreatmentContainer = new GUIListBox(new RectTransform(new Vector2(0.28f, 0.5f), paddedInfoFrame.RectTransform, Anchor.TopRight) { RelativeOffset = new Vector2(0.0f, 0.15f) })
- {
- Spacing = 10
- };
- dropItemArea = new GUIFrame(new RectTransform(new Vector2(0.28f, 0.3f), paddedInfoFrame.RectTransform, Anchor.BottomRight)
- { RelativeOffset = new Vector2(0.0f, 0.0f) }, style: null)
- {
- ToolTip = TextManager.Get("HealthItemUseTip")
- };
- dropItemArea.RectTransform.NonScaledSize = new Point(dropItemArea.Rect.Width);
-
- string[] healthCircleStyles = new string[] { "HealthCircleInner", "HealthCircleMid", "HealthCircleOuter" };
- foreach (string healthCircleStyle in healthCircleStyles)
- {
- for (int i = 1; i < 4; i++)
- {
- var style = GUI.Style.GetComponentStyle(healthCircleStyle + i);
- if (style != null)
- {
- new GUIImage(new RectTransform(Vector2.One, dropItemArea.RectTransform), healthCircleStyle + i)
- {
- CanBeFocused = false
- };
- }
- }
- }
-
- new GUIImage(new RectTransform(Vector2.One * 0.2f, dropItemArea.RectTransform, Anchor.Center), "HealthCross")
- {
- CanBeFocused = false
- };
-
- healthWindow = new GUIFrame(new RectTransform(new Point(100, 200), GUI.Canvas));
- var paddedHealthWindow = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.9f), healthWindow.RectTransform, Anchor.Center))
- {
- Stretch = true,
- RelativeSpacing = 0.03f
- };
-
- var nameContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.1f), paddedHealthWindow.RectTransform) { MinSize = new Point(0, 20) }, isHorizontal: true)
- {
- Stretch = true
- };
-
- characterName = new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), nameContainer.RectTransform), "", textAlignment: Alignment.CenterLeft, font: GUI.LargeFont)
- {
- AutoScale = true
- };
- new GUICustomComponent(new RectTransform(new Vector2(0.4f, 1.0f), nameContainer.RectTransform),
- onDraw: (spriteBatch, component) =>
- {
- character.Info.DrawPortrait(spriteBatch, new Vector2(component.Rect.X, component.Rect.Center.Y - component.Rect.Width / 2), component.Rect.Width);
- });
-
- new GUICustomComponent(new RectTransform(new Vector2(1.0f, 0.9f), paddedHealthWindow.RectTransform),
- (spriteBatch, component) =>
- {
- DrawHealthWindow(spriteBatch, component.RectTransform.Rect, true, false);
- },
- (deltaTime, component) =>
- {
- UpdateLimbIndicators(deltaTime, component.RectTransform.Rect);
- }
- );
- deadIndicator = new GUITextBlock(new RectTransform(new Vector2(0.9f, 0.1f), healthWindow.RectTransform, Anchor.Center),
- text: TextManager.Get("Deceased"), font: GUI.LargeFont, textAlignment: Alignment.Center, wrap: true, style: "GUIToolTip")
- {
- Visible = false,
- CanBeFocused = false
- };
-
- healthWindowHealthBar = new GUIProgressBar(HUDLayoutSettings.ToRectTransform(HUDLayoutSettings.HealthBarAreaLeft, GUI.Canvas),
- barSize: 1.0f, color: Color.Green, style: "GUIProgressBarVertical")
- {
- IsHorizontal = false
- };
- healthWindowHealthBarShadow = new GUIProgressBar(HUDLayoutSettings.ToRectTransform(HUDLayoutSettings.HealthBarAreaLeft, GUI.Canvas),
- barSize: 1.0f, color: Color.Green, style: "GUIProgressBarVertical")
- {
- IsHorizontal = false
- };
- cprButton = new GUIButton(new RectTransform(new Point(80, 80), GUI.Canvas), text: "", style: "CPRButton")
- {
- OnClicked = (button, userData) =>
- {
- Character selectedCharacter = Character.Controlled?.SelectedCharacter;
- if (selectedCharacter == null || (!selectedCharacter.IsUnconscious && selectedCharacter.Stun <= 0.0f)) return false;
-
- Character.Controlled.AnimController.Anim = (Character.Controlled.AnimController.Anim == AnimController.Animation.CPR) ?
- AnimController.Animation.None : AnimController.Animation.CPR;
-
- selectedCharacter.AnimController.ResetPullJoints();
-
- if (GameMain.Client != null)
- {
- GameMain.Client.CreateEntityEvent(Character.Controlled, new object[] { NetEntityEvent.Type.Treatment });
- }
-
- return true;
- },
- Visible = false
- };
-
- UpdateAlignment();
-
- suicideButton = new GUIButton(new RectTransform(new Vector2(0.06f, 0.02f), GUI.Canvas, Anchor.TopCenter)
- { MinSize = new Point(120, 20), RelativeOffset = new Vector2(0.0f, 0.01f) },
- TextManager.Get("GiveInButton"))
- {
- ToolTip = TextManager.Get(GameMain.NetworkMember == null ? "GiveInHelpSingleplayer" : "GiveInHelpMultiplayer"),
- OnClicked = (button, userData) =>
- {
- GUI.ForceMouseOn(null);
- if (Character.Controlled != null)
- {
- if (GameMain.Client != null)
- {
- GameMain.Client.CreateEntityEvent(Character.Controlled, new object[] { NetEntityEvent.Type.Status });
- }
- else
- {
- var causeOfDeath = GetCauseOfDeath();
- Character.Controlled.Kill(causeOfDeath.First, causeOfDeath.Second);
- Character.Controlled = null;
- }
- }
- return true;
- }
- };
-
- if (element != null)
- {
- foreach (XElement subElement in element.Elements())
- {
- switch (subElement.Name.ToString().ToLowerInvariant())
- {
- case "sprite":
- limbIndicatorOverlay = new SpriteSheet(subElement);
- break;
- }
- }
- }
- }
-
- private void OnAttacked(Character attacker, AttackResult attackResult)
- {
- if (Math.Abs(attackResult.Damage) < 0.01f && attackResult.Afflictions.Count == 0) return;
- DamageOverlayTimer = MathHelper.Clamp(attackResult.Damage / MaxVitality, DamageOverlayTimer, 1.0f);
- 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);
- }
-
- private void UpdateAlignment()
- {
- healthBar.RectTransform.RelativeOffset = healthBarShadow.RectTransform.RelativeOffset = Vector2.Zero;
- healthWindowHealthBar.RectTransform.RelativeOffset = healthWindowHealthBarShadow.RectTransform.RelativeOffset = Vector2.Zero;
-
- int healthWindowHealthBarWidth = (int)(40 * GUI.Scale);
-
- if (alignment == Alignment.Left)
- {
- healthBar.RectTransform.SetPosition(Anchor.BottomLeft);
- healthBarShadow.RectTransform.SetPosition(Anchor.BottomLeft);
- healthBar.RectTransform.AbsoluteOffset = healthBarShadow.RectTransform.AbsoluteOffset =
- new Point(HUDLayoutSettings.HealthBarAreaLeft.X, GameMain.GraphicsHeight - HUDLayoutSettings.HealthBarAreaLeft.Bottom);
- healthBar.RectTransform.NonScaledSize = healthBarShadow.RectTransform.NonScaledSize = HUDLayoutSettings.HealthBarAreaLeft.Size;
-
- healthWindow.RectTransform.AbsoluteOffset = HUDLayoutSettings.HealthWindowAreaLeft.Location + new Point(healthWindowHealthBarWidth, 0);
- healthWindow.RectTransform.NonScaledSize = new Point(
- HUDLayoutSettings.HealthWindowAreaLeft.Width / 3 - healthWindowHealthBarWidth,
- HUDLayoutSettings.HealthWindowAreaLeft.Height);
-
- afflictionInfoFrame.RectTransform.AbsoluteOffset = new Point(
- healthWindow.Rect.Right,
- HUDLayoutSettings.HealthWindowAreaLeft.Y);
- afflictionInfoFrame.RectTransform.NonScaledSize = new Point(
- (int)(HUDLayoutSettings.HealthWindowAreaLeft.Width * 0.66f),
- (int)(HUDLayoutSettings.HealthWindowAreaLeft.Height));
-
- healthWindowHealthBar.RectTransform.NonScaledSize = healthWindowHealthBarShadow.RectTransform.NonScaledSize =
- new Point(healthWindowHealthBarWidth, healthWindow.Rect.Height);
- healthWindowHealthBar.RectTransform.AbsoluteOffset = healthWindowHealthBarShadow.RectTransform.AbsoluteOffset =
- HUDLayoutSettings.HealthWindowAreaLeft.Location;
-
- int cprButtonSize = (int)(100 * GUI.Scale);
- cprButton.RectTransform.AbsoluteOffset = new Point(HUDLayoutSettings.HealthWindowAreaLeft.Right, dropItemArea.Rect.Center.Y - cprButtonSize / 2);
- cprButton.RectTransform.NonScaledSize = new Point(cprButtonSize);
- }
- else
- {
- healthBar.RectTransform.SetPosition(Anchor.TopLeft);
- healthBarShadow.RectTransform.SetPosition(Anchor.TopLeft);
- healthBar.RectTransform.AbsoluteOffset = healthBarShadow.RectTransform.AbsoluteOffset =
- HUDLayoutSettings.HealthBarAreaRight.Location;
- healthBar.RectTransform.NonScaledSize = healthBarShadow.RectTransform.NonScaledSize = HUDLayoutSettings.HealthBarAreaRight.Size;
-
- healthWindow.RectTransform.AbsoluteOffset = new Point(
- HUDLayoutSettings.HealthWindowAreaRight.X + HUDLayoutSettings.HealthWindowAreaRight.Width / 3 * 2,
- HUDLayoutSettings.HealthWindowAreaRight.Y);
- healthWindow.RectTransform.NonScaledSize = new Point(
- HUDLayoutSettings.HealthWindowAreaRight.Width / 3 - healthWindowHealthBarWidth,
- HUDLayoutSettings.HealthWindowAreaRight.Height);
-
- afflictionInfoFrame.RectTransform.AbsoluteOffset = new Point(
- HUDLayoutSettings.HealthWindowAreaRight.X,
- HUDLayoutSettings.HealthWindowAreaLeft.Y);
- afflictionInfoFrame.RectTransform.NonScaledSize = new Point(
- (int)(HUDLayoutSettings.HealthWindowAreaLeft.Width * 0.66f),
- (int)(HUDLayoutSettings.HealthWindowAreaLeft.Height));
-
- healthWindowHealthBar.RectTransform.NonScaledSize = healthWindowHealthBarShadow.RectTransform.NonScaledSize =
- new Point(healthWindowHealthBarWidth, healthWindow.Rect.Height);
- healthWindowHealthBar.RectTransform.AbsoluteOffset = healthWindowHealthBarShadow.RectTransform.AbsoluteOffset =
- new Point(HUDLayoutSettings.HealthWindowAreaRight.Right - healthWindowHealthBarWidth, HUDLayoutSettings.HealthWindowAreaRight.Y);
-
- int cprButtonSize = (int)(100 * GUI.Scale);
- cprButton.RectTransform.AbsoluteOffset = new Point(HUDLayoutSettings.HealthWindowAreaRight.X - cprButtonSize, dropItemArea.Rect.Center.Y - cprButtonSize / 2);
- cprButton.RectTransform.NonScaledSize = new Point(cprButtonSize);
- }
-
- dropItemArea.RectTransform.NonScaledSize = new Point(dropItemArea.Rect.Width);
-
- screenResolution = new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
- inventoryScale = Inventory.UIScale;
- uiScale = GUI.Scale;
- }
-
- partial void UpdateOxygenProjSpecific(float prevOxygen)
- {
- if (prevOxygen > 0.0f && OxygenAmount <= 0.0f &&
- Character.Controlled == Character)
- {
- SoundPlayer.PlaySound(Character.Info != null && Character.Info.Gender == Gender.Female ? "drownfemale" : "drownmale");
- }
- }
-
- partial void UpdateBleedingProjSpecific(AfflictionBleeding affliction, Limb targetLimb, float deltaTime)
- {
- bloodParticleTimer -= deltaTime * (affliction.Strength / 10.0f);
- if (bloodParticleTimer <= 0.0f)
- {
- float bloodParticleSize = MathHelper.Lerp(0.5f, 1.0f, affliction.Strength / 100.0f);
- if (!Character.AnimController.InWater) bloodParticleSize *= 2.0f;
- var blood = GameMain.ParticleManager.CreateParticle(
- Character.AnimController.InWater ? "waterblood" : "blooddrop",
- targetLimb.WorldPosition, Rand.Vector(affliction.Strength), 0.0f, Character.AnimController.CurrentHull);
-
- if (blood != null)
- {
- blood.Size *= bloodParticleSize;
- }
- bloodParticleTimer = 1.0f;
- }
- }
-
- public void UpdateHUD(float deltaTime)
- {
- if (GUI.DisableHUD) return;
- if (openHealthWindow != null)
- {
- if (openHealthWindow != Character.Controlled?.CharacterHealth && openHealthWindow != Character.Controlled?.SelectedCharacter?.CharacterHealth)
- {
- openHealthWindow = null;
- return;
- }
- }
-
- bool forceAfflictionContainerUpdate = false;
- if (updateDisplayedAfflictionsTimer > 0.0f)
- {
- updateDisplayedAfflictionsTimer -= deltaTime;
- }
- else
- {
- forceAfflictionContainerUpdate = true;
- currentDisplayedAfflictions = GetAllAfflictions(mergeSameAfflictions: true)
- .FindAll(a => a.Strength >= a.Prefab.ShowIconThreshold && a.Prefab.Icon != null);
- currentDisplayedAfflictions.Sort((a1, a2) =>
- {
- int dmgPerSecond = Math.Sign(a2.DamagePerSecond - a1.DamagePerSecond);
- return dmgPerSecond != 0 ? dmgPerSecond : Math.Sign(a1.Strength - a1.Strength);
- });
- updateDisplayedAfflictionsTimer = UpdateDisplayedAfflictionsInterval;
- }
-
- if (DamageOverlayTimer > 0.0f)
- {
- DamageOverlayTimer -= deltaTime;
- }
- if (damageIntensity > 0)
- {
- damageIntensity -= deltaTime * damageIntensityDropdownRate;
- if (damageIntensity < 0)
- {
- damageIntensity = 0;
- }
- }
-
- if (healthShadowDelay > 0.0f)
- {
- healthShadowDelay -= deltaTime;
- }
- else
- {
- healthShadowSize = healthBar.BarSize > healthShadowSize ?
- Math.Min(healthShadowSize + deltaTime, healthBar.BarSize) :
- Math.Max(healthShadowSize - deltaTime, healthBar.BarSize);
- }
-
- dropItemArea.Visible = !Character.IsDead;
-
- float blurStrength = 0.0f;
- float distortStrength = 0.0f;
- float distortSpeed = 0.0f;
- float radialDistortStrength = 0.0f;
- float chromaticAberrationStrength = 0.0f;
-
- if (Character.IsUnconscious)
- {
- blurStrength = 1.0f;
- distortSpeed = 1.0f;
- }
- else if (OxygenAmount < 100.0f)
- {
- blurStrength = MathHelper.Lerp(0.5f, 1.0f, 1.0f - Vitality / MaxVitality);
- distortStrength = blurStrength;
- distortSpeed = (blurStrength + 1.0f);
- distortSpeed *= distortSpeed * distortSpeed * distortSpeed;
- }
-
- foreach (Affliction affliction in afflictions)
- {
- distortStrength = Math.Max(distortStrength, affliction.GetScreenDistortStrength());
- blurStrength = Math.Max(blurStrength, affliction.GetScreenBlurStrength());
- radialDistortStrength = Math.Max(radialDistortStrength, affliction.GetRadialDistortStrength());
- chromaticAberrationStrength = Math.Max(chromaticAberrationStrength, affliction.GetChromaticAberrationStrength());
- }
- foreach (LimbHealth limbHealth in limbHealths)
- {
- foreach (Affliction affliction in limbHealth.Afflictions)
- {
- distortStrength = Math.Max(distortStrength, affliction.GetScreenDistortStrength());
- blurStrength = Math.Max(blurStrength, affliction.GetScreenBlurStrength());
- radialDistortStrength = Math.Max(radialDistortStrength, affliction.GetRadialDistortStrength());
- chromaticAberrationStrength = Math.Max(chromaticAberrationStrength, affliction.GetChromaticAberrationStrength());
- }
- }
-
- Character.RadialDistortStrength = radialDistortStrength;
- Character.ChromaticAberrationStrength = chromaticAberrationStrength;
- if (blurStrength > 0.0f)
- {
- distortTimer = (distortTimer + deltaTime * distortSpeed) % MathHelper.TwoPi;
- Character.BlurStrength = (float)(Math.Sin(distortTimer) + 1.5f) * 0.25f * blurStrength;
- Character.DistortStrength = (float)(Math.Sin(distortTimer) + 1.0f) * 0.1f * distortStrength;
- }
- else
- {
- Character.BlurStrength = 0.0f;
- Character.DistortStrength = 0.0f;
- distortTimer = 0.0f;
- }
-
- if (PlayerInput.KeyHit(InputType.Health) && GUI.KeyboardDispatcher.Subscriber == null &&
- Character.AllowInput && Character.FocusedCharacter == null && !toggledThisFrame)
- {
- if (openHealthWindow != null)
- OpenHealthWindow = null;
- else
- {
- OpenHealthWindow = this;
- forceAfflictionContainerUpdate = true;
- }
- }
- else if (openHealthWindow == this)
- {
- if (Alignment == Alignment.Right ?
- HUD.CloseHUD(HUDLayoutSettings.HealthWindowAreaRight) :
- HUD.CloseHUD(HUDLayoutSettings.HealthWindowAreaLeft))
- {
- //emulate a Health input to get the character to deselect the item server-side
- Character.Keys[(int)InputType.Health].Hit = true;
- OpenHealthWindow = null;
- }
- }
- toggledThisFrame = false;
-
- if (OpenHealthWindow == this)
- {
- var highlightedLimb = highlightedLimbIndex < 0 ? null : limbHealths[highlightedLimbIndex];
- if (highlightedLimbIndex < 0 && selectedLimbIndex < 0)
- {
- // If no limb is selected or highlighted, select the one with the most critical afflictions.
- var affliction = GetAllAfflictions(a => a.Prefab.IndicatorLimb != LimbType.None)
- .OrderByDescending(a => a.DamagePerSecond)
- .ThenByDescending(a => a.Strength).FirstOrDefault();
- var limbHealth = GetMathingLimbHealth(affliction);
- if (limbHealth != null)
- {
- selectedLimbIndex = limbHealths.IndexOf(limbHealth);
- }
- }
- LimbHealth selectedLimb = selectedLimbIndex < 0 ? highlightedLimb : limbHealths[selectedLimbIndex];
- if (selectedLimb != currentDisplayedLimb || forceAfflictionContainerUpdate)
- {
- UpdateAfflictionContainer(selectedLimb);
- currentDisplayedLimb = selectedLimb;
- }
- }
-
- if (Character.IsDead)
- {
- healthBar.Color = healthWindowHealthBar.Color = Color.Black;
- healthBar.BarSize = healthWindowHealthBar.BarSize = 1.0f;
- }
- else
- {
- healthBar.Color = healthWindowHealthBar.Color = ToolBox.GradientLerp(Vitality / MaxVitality, Color.Red, Color.Orange, Color.Green);
- healthBar.HoverColor = healthWindowHealthBar.HoverColor = healthBar.Color * 2.0f;
- healthBar.BarSize = healthWindowHealthBar.BarSize =
- (Vitality > 0.0f) ?
- (MaxVitality > 0.0f ? Vitality / MaxVitality : 0.0f) :
- (Math.Abs(MinVitality) > 0.0f ? 1.0f - Vitality / MinVitality : 0.0f);
-
- if (healthBarPulsateTimer > 0.0f)
- {
- //0-1
- float pulsateAmount = (float)(Math.Sin(healthBarPulsatePhase) + 1.0f) / 2.0f;
-
- healthBar.RectTransform.LocalScale = healthBarShadow.RectTransform.LocalScale = new Vector2(1.0f, (1.0f + pulsateAmount * healthBarPulsateTimer * 0.5f));
- healthBarPulsatePhase += deltaTime * 5.0f;
- healthBarPulsateTimer -= deltaTime;
- }
- else
- {
- healthBar.RectTransform.LocalScale = Vector2.One;
- }
- }
-
- if (OpenHealthWindow == this)
- {
- if (Character == Character.Controlled && !Character.AllowInput)
- {
- openHealthWindow = null;
- }
-
- lowSkillIndicator.Visible = Timing.TotalTime % 1.0f < 0.8f && Character.Controlled != null && Character.Controlled.GetSkillLevel("medical") < 50.0f;
-
- float rotationSpeed = 0.25f;
- int i = 0;
- foreach (GUIComponent dropItemIndicator in dropItemArea.Children)
- {
- GUIImage img = dropItemIndicator as GUIImage;
- if (img == null) continue;
-
- img.State = GUI.MouseOn == dropItemArea ? GUIComponent.ComponentState.Hover : GUIComponent.ComponentState.None;
-
- byte alpha = img.Color.A;
- byte hoverAlpha = img.HoverColor.A;
- img.Color = ToolBox.GradientLerp(Vitality / MaxVitality, Color.Red, Color.Orange, Color.Green);
- img.Color = new Color(img.Color.R, img.Color.G, img.Color.B, alpha);
- img.HoverColor = new Color(img.Color.R, img.Color.G, img.Color.B, hoverAlpha);
- img.HoverColor = Color.Lerp(img.HoverColor, Color.White, 0.5f);
-
- if (img.State == GUIComponent.ComponentState.Hover && droppedItem == null)
- {
- dropItemAnimTimer = Math.Min(0.3f, dropItemAnimTimer + deltaTime * 0.5f);
- }
-
- if (i < 4)
- {
- img.Scale = 1.0f - (float)Math.Sin(dropItemAnimTimer / dropItemAnimDuration * MathHelper.TwoPi) * 0.3f;
- }
-
- if (dropItemIndicator == dropItemArea.Children.Last()) break;
- img.Rotation = (img.Rotation + (rotationSpeed + dropItemAnimTimer * 10.0f) * deltaTime) % MathHelper.TwoPi;
- rotationSpeed = (rotationSpeed + 0.3f) % 1.0f;
-
- i++;
- }
-
- if (Inventory.draggingItem != null)
- {
- if (highlightedLimbIndex > -1)
- {
- selectedLimbIndex = highlightedLimbIndex;
- }
- }
-
- if (draggingMed != null)
- {
- if (!PlayerInput.LeftButtonHeld())
- {
- OnItemDropped(draggingMed.UserData as Item, ignoreMousePos: false);
- draggingMed = null;
- }
- }
-
- /*if (GUI.MouseOn?.UserData is Affliction affliction)
- {
- ShowAfflictionInfo(affliction, afflictionInfoContainer);
- }*/
-
- if (dropItemAnimTimer > 0.0f)
- {
- dropItemAnimTimer -= deltaTime;
- if (dropItemAnimTimer <= 0.0f) droppedItem = null;
- }
- }
- else
- {
- if (openHealthWindow != null && Character != Character.Controlled && Character != Character.Controlled?.SelectedCharacter)
- {
- openHealthWindow = null;
- }
- highlightedLimbIndex = -1;
- }
-
- Rectangle hoverArea = alignment == Alignment.Left ?
- Rectangle.Union(HUDLayoutSettings.AfflictionAreaLeft, HUDLayoutSettings.HealthBarAreaLeft) :
- Rectangle.Union(HUDLayoutSettings.AfflictionAreaRight, HUDLayoutSettings.HealthBarAreaRight);
-
- if (Character.AllowInput && UseHealthWindow && hoverArea.Contains(PlayerInput.MousePosition) && Inventory.SelectedSlot == null)
- {
- healthBar.State = GUIComponent.ComponentState.Hover;
- if (PlayerInput.LeftButtonClicked())
- {
- OpenHealthWindow = openHealthWindow == this ? null : this;
- }
- }
- else
- {
- healthBar.State = GUIComponent.ComponentState.None;
- }
-
- suicideButton.Visible = Character == Character.Controlled && Character.IsUnconscious && !Character.IsDead;
-
- cprButton.Visible =
- Character == Character.Controlled?.SelectedCharacter
- && (Character.IsUnconscious || Character.Stun > 0.0f)
- && !Character.IsDead
- && openHealthWindow == this;
-
- deadIndicator.Visible = Character.IsDead;
- }
-
- public void AddToGUIUpdateList()
- {
- if (GUI.DisableHUD) return;
- if (OpenHealthWindow == this)
- {
- //afflictionContainer.AddToGUIUpdateList();
- afflictionInfoFrame.AddToGUIUpdateList();
- healthWindow.AddToGUIUpdateList();
- healthWindowHealthBarShadow.AddToGUIUpdateList();
- healthWindowHealthBar.AddToGUIUpdateList();
- }
- else if (Character.Controlled == Character)
- {
- healthBarShadow.AddToGUIUpdateList();
- healthBar.AddToGUIUpdateList();
- }
- if (suicideButton.Visible && Character == Character.Controlled) suicideButton.AddToGUIUpdateList();
- if (cprButton != null && cprButton.Visible) cprButton.AddToGUIUpdateList();
- }
-
- public void DrawHUD(SpriteBatch spriteBatch)
- {
- if (GUI.DisableHUD) return;
- if (GameMain.GraphicsWidth != screenResolution.X ||
- GameMain.GraphicsHeight != screenResolution.Y ||
- Math.Abs(inventoryScale - Inventory.UIScale) > 0.01f ||
- Math.Abs(uiScale - GUI.Scale) > 0.01f)
- {
- UpdateAlignment();
- }
-
- float damageOverlayAlpha = DamageOverlayTimer;
- if (Vitality < MaxVitality * 0.1f)
- {
- damageOverlayAlpha = Math.Max(1.0f - (Vitality / maxVitality * 10.0f), damageOverlayAlpha);
- }
- else
- {
- float pulsateAmount = (float)(Math.Sin(healthBarPulsatePhase) + 1.0f) / 2.0f;
- damageOverlayAlpha = pulsateAmount * healthBarPulsateTimer * damageIntensity;
- }
-
- if (damageOverlayAlpha > 0.0f)
- {
- damageOverlay.Draw(spriteBatch, Vector2.Zero, Color.White * damageOverlayAlpha, Vector2.Zero, 0.0f,
- new Vector2(GameMain.GraphicsWidth / damageOverlay.size.X, GameMain.GraphicsHeight / damageOverlay.size.Y));
- }
-
- if (Character.Inventory != null)
- {
- if (Character.Inventory.CurrentLayout == CharacterInventory.Layout.Right)
- {
- //move the healthbar on top of the inventory slots
- healthBar.RectTransform.ScreenSpaceOffset = new Point(
- (GameMain.GraphicsWidth - HUDLayoutSettings.Padding) - HUDLayoutSettings.HealthBarAreaRight.Right,
- HUDLayoutSettings.HealthBarAreaRight.Y - (int)(Character.Inventory.SlotPositions.Max(s => s.Y) + Inventory.EquipIndicator.size.Y * Inventory.UIScale * 2) - HUDLayoutSettings.HealthBarAreaRight.Height);
- healthBarShadow.RectTransform.ScreenSpaceOffset = healthBar.RectTransform.ScreenSpaceOffset;
- }
- else
- {
- healthBar.RectTransform.ScreenSpaceOffset = healthBarShadow.RectTransform.ScreenSpaceOffset = Point.Zero;
- }
- }
-
- DrawStatusHUD(spriteBatch);
- }
-
- public void DrawStatusHUD(SpriteBatch spriteBatch)
- {
- //Rectangle interactArea = healthBar.Rect;
- if (openHealthWindow != this)
- {
- List> statusIcons = new List>();
- if (Character.CurrentHull == null || Character.CurrentHull.LethalPressure > 5.0f)
- statusIcons.Add(new Pair(pressureAffliction, TextManager.Get("PressureHUDWarning")));
- if (Character.CurrentHull != null && Character.OxygenAvailable < LowOxygenThreshold && oxygenLowAffliction.Strength < oxygenLowAffliction.Prefab.ShowIconThreshold)
- statusIcons.Add(new Pair(oxygenLowAffliction, TextManager.Get("OxygenHUDWarning")));
-
- foreach (Affliction affliction in currentDisplayedAfflictions)
- {
- statusIcons.Add(new Pair(affliction, affliction.Prefab.Name));
- }
-
- Pair highlightedIcon = null;
- Vector2 highlightedIconPos = Vector2.Zero;
- Rectangle afflictionArea = alignment == Alignment.Left ? HUDLayoutSettings.AfflictionAreaLeft : HUDLayoutSettings.AfflictionAreaRight;
- Point pos = afflictionArea.Location + healthBar.RectTransform.ScreenSpaceOffset;
-
- bool horizontal = afflictionArea.Width > afflictionArea.Height;
- int iconSize = horizontal ? afflictionArea.Height : afflictionArea.Width;
-
- foreach (Pair statusIcon in statusIcons)
- {
- Rectangle afflictionIconRect = new Rectangle(pos, new Point(iconSize));
- if (afflictionIconRect.Contains(PlayerInput.MousePosition))
- {
- highlightedIcon = statusIcon;
- highlightedIconPos = afflictionIconRect.Center.ToVector2();
- }
-
- if (statusIcon.First.DamagePerSecond > 1.0f)
- {
- Rectangle glowRect = afflictionIconRect;
- glowRect.Inflate((int)(25 * GUI.Scale), (int)(25 * GUI.Scale));
- var glow = GUI.Style.GetComponentStyle("OuterGlow");
- glow.Sprites[GUIComponent.ComponentState.None][0].Draw(
- spriteBatch, glowRect,
- Color.Red * (float)((Math.Sin(statusIcon.First.DamagePerSecondTimer * MathHelper.TwoPi - MathHelper.PiOver2) + 1.0f) * 0.5f));
- }
-
- var slot = GUI.Style.GetComponentStyle("AfflictionIconSlot");
- slot.Sprites[highlightedIcon == statusIcon ? GUIComponent.ComponentState.Hover : GUIComponent.ComponentState.None][0].Draw(
- spriteBatch, afflictionIconRect,
- highlightedIcon == statusIcon ? slot.HoverColor : slot.Color);
-
-
- statusIcon.First.Prefab.Icon?.Draw(spriteBatch,
- pos.ToVector2(),
- highlightedIcon == statusIcon ? statusIcon.First.Prefab.IconColor : statusIcon.First.Prefab.IconColor * 0.8f,
- rotate: 0,
- scale: iconSize / statusIcon.First.Prefab.Icon.size.X);
-
- if (horizontal)
- pos.X += iconSize + (int)(5 * GUI.Scale);
- else
- pos.Y += iconSize + (int)(5 * GUI.Scale);
- }
-
- if (highlightedIcon != null)
- {
- GUI.DrawString(spriteBatch,
- alignment == Alignment.Left ? highlightedIconPos + new Vector2(60 * GUI.Scale, 5) : highlightedIconPos + new Vector2(-10.0f - GUI.Font.MeasureString(highlightedIcon.Second).X, 5),
- highlightedIcon.Second,
- Color.White * 0.8f, Color.Black * 0.5f);
- }
-
- if (Vitality > 0.0f)
- {
- float currHealth = healthBar.BarSize;
- Color prevColor = healthBar.Color;
- healthBarShadow.BarSize = healthShadowSize;
- healthBarShadow.Color = Color.Red;
- healthBarShadow.Visible = true;
- healthBar.BarSize = currHealth;
- healthBar.Color = prevColor;
- }
- else
- {
- healthBarShadow.Visible = false;
- }
- }
- else
- {
- if (Vitality > 0.0f)
- {
- float currHealth = healthWindowHealthBar.BarSize;
- Color prevColor = healthWindowHealthBar.Color;
- healthWindowHealthBarShadow.BarSize = healthShadowSize;
- healthWindowHealthBarShadow.Color = Color.Red;
- healthWindowHealthBarShadow.Visible = true;
- healthWindowHealthBar.BarSize = currHealth;
- healthWindowHealthBar.Color = prevColor;
- }
- else
- {
- healthWindowHealthBarShadow.Visible = false;
- }
- }
- }
-
- private void UpdateAfflictionContainer(LimbHealth selectedLimb)
- {
- ((GUITextBlock)afflictionInfoContainer.Parent.GetChildByUserData("selectedlimbname")).Text = selectedLimb == null ? "" : selectedLimb.Name;
-
- if (selectedLimb == null)
- {
- afflictionInfoContainer.Content.ClearChildren();
- return;
- }
- var currentAfflictions = GetMatchingAfflictions(selectedLimb, a => a.Strength >= a.Prefab.ShowIconThreshold);
- var displayedAfflictions = afflictionInfoContainer.Content.Children.Select(c => c.UserData as Affliction);
- if (currentAfflictions.Any(a => !displayedAfflictions.Contains(a)) ||
- displayedAfflictions.Any(a => !currentAfflictions.Contains(a)))
- {
- CreateAfflictionInfos(currentAfflictions);
- }
-
- UpdateAfflictionInfos(displayedAfflictions);
- }
-
- private void CreateAfflictionInfos(IEnumerable afflictions)
- {
- afflictionInfoContainer.Content.ClearChildren();
- recommendedTreatmentContainer.Content.ClearChildren();
-
- float characterSkillLevel = Character.Controlled == null ? 0.0f : Character.Controlled.GetSkillLevel("medical");
-
- //random variance is 200% when the skill is 0
- //no random variance if the skill is 50 or more
- float randomVariance = MathHelper.Lerp(2.0f, 0.0f, characterSkillLevel / 50.0f);
-
- //key = item identifier
- //float = suitability
- Dictionary treatmentSuitability = new Dictionary();
- float minSuitability = -10, maxSuitability = 10;
- foreach (Affliction affliction in afflictions)
- {
- foreach (KeyValuePair treatment in affliction.Prefab.TreatmentSuitability)
- {
- if (!treatmentSuitability.ContainsKey(treatment.Key))
- {
- treatmentSuitability[treatment.Key] = treatment.Value * affliction.Strength;
- }
- else
- {
- treatmentSuitability[treatment.Key] += treatment.Value * affliction.Strength;
- }
- minSuitability = Math.Min(treatmentSuitability[treatment.Key], minSuitability);
- maxSuitability = Math.Max(treatmentSuitability[treatment.Key], maxSuitability);
- }
- }
- //normalize the suitabilities to a range of 0 to 1
- foreach (string treatment in treatmentSuitability.Keys.ToList())
- {
- treatmentSuitability[treatment] = (treatmentSuitability[treatment] - minSuitability) / (maxSuitability - minSuitability);
- //lerp towards a random value if the medical skill is low
- treatmentSuitability[treatment] = MathHelper.Lerp(treatmentSuitability[treatment], Rand.Range(0.0f, 1.0f), randomVariance);
- }
-
- foreach (Affliction affliction in afflictions)
- {
- var child = new GUILayoutGroup(new RectTransform(Vector2.One * 0.95f, afflictionInfoContainer.Content.RectTransform, Anchor.TopCenter))
- {
- Stretch = true,
- RelativeSpacing = 0.02f,
- UserData = affliction
- };
-
- var headerContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.15f), child.RectTransform), isHorizontal: true)
- {
- Stretch = true,
- UserData = "header"
- };
-
- new GUIImage(new RectTransform(new Vector2(0.15f, 1.0f), headerContainer.RectTransform), affliction.Prefab.Icon, scaleToFit: true)
- {
- Color = affliction.Prefab.IconColor
- };
-
- var labelContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.8f, 1.0f), headerContainer.RectTransform), isHorizontal: true)
- {
- Stretch = true,
- AbsoluteSpacing = 10,
- UserData = "label"
- };
- var afflictionName = new GUITextBlock(new RectTransform(new Vector2(0.65f, 1.0f), labelContainer.RectTransform), affliction.Prefab.Name, textAlignment: Alignment.CenterLeft, font: GUI.LargeFont);
- var afflictionStrength = new GUITextBlock(new RectTransform(new Vector2(0.35f, 0.6f), labelContainer.RectTransform), "", textAlignment: Alignment.TopRight, font: GUI.LargeFont)
- {
- Padding = Vector4.Zero,
- UserData = "strength"
- };
- var vitality = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.4f), labelContainer.RectTransform, Anchor.BottomRight), "", textAlignment: Alignment.BottomRight)
- {
- IgnoreLayoutGroups = true,
- UserData = "vitality"
- };
-
- var description = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.3f), child.RectTransform),
- affliction.Prefab.Description, textAlignment: Alignment.TopLeft, wrap: true);
- if (description.Font.MeasureString(description.WrappedText).Y > description.Rect.Height)
- {
- description.Font = GUI.SmallFont;
- }
- description.RectTransform.Resize(new Point(description.Rect.Width, (int)(description.TextSize.Y + 10)));
- child.RectTransform.Resize(new Point(child.Rect.Width, child.Children.Sum(c => c.Rect.Height)));
- child.Recalculate();
- headerContainer.Recalculate();
- labelContainer.Recalculate();
- afflictionStrength.AutoScale = true;
- afflictionName.AutoScale = true;
- vitality.AutoDraw = true;
- }
-
- List> treatmentSuitabilities = treatmentSuitability.OrderByDescending(t => t.Value).ToList();
-
- foreach (KeyValuePair treatment in treatmentSuitabilities)
- {
- ItemPrefab item = MapEntityPrefab.Find(name: null, identifier: treatment.Key, showErrorMessages: false) as ItemPrefab;
- if (item == null) continue;
- int slotSize = (int)(recommendedTreatmentContainer.Content.Rect.Width * 0.8f);
-
- var itemSlot = new GUIButton(new RectTransform(new Point(slotSize), recommendedTreatmentContainer.Content.RectTransform, Anchor.TopCenter),
- text: "", style: "InventorySlotSmall")
- {
- UserData = item
- };
- itemSlot.Color = ToolBox.GradientLerp(treatment.Value, Color.Red, Color.White, Color.LightGreen);
-
- Sprite itemSprite = item.InventoryIcon ?? item.sprite;
- Color itemColor = itemSprite == item.sprite ? item.SpriteColor : item.InventoryIconColor;
- var itemIcon = new GUIImage(new RectTransform(new Vector2(0.8f, 0.8f), itemSlot.RectTransform, Anchor.Center),
- itemSprite, scaleToFit: true)
- {
- CanBeFocused = false,
- Color = itemColor,
- HoverColor = itemColor,
- SelectedColor = itemColor
- };
- itemSlot.ToolTip = item.Name + "\n" + item.Description;
- }
-
- afflictionInfoContainer.Content.RectTransform.SortChildren((r1, r2) =>
- {
- var first = r1.GUIComponent.UserData as Affliction;
- var second = r2.GUIComponent.UserData as Affliction;
- int dmgPerSecond = Math.Sign(second.DamagePerSecond - first.DamagePerSecond);
- return dmgPerSecond != 0 ? dmgPerSecond : Math.Sign(second.Strength - first.Strength);
- });
-
- //afflictionInfoContainer.Content.RectTransform.SortChildren((r1, r2) =>
- //{
- // return Math.Sign(((Affliction)r2.GUIComponent.UserData).GetVitalityDecrease(this) - ((Affliction)r1.GUIComponent.UserData).GetVitalityDecrease(this));
- //});
- }
-
- private void UpdateAfflictionInfos(IEnumerable afflictions)
- {
- foreach (Affliction affliction in afflictions)
- {
- var child = afflictionInfoContainer.Content.FindChild(affliction);
- var headerContainer = child.GetChildByUserData("header");
- var labelContainer = headerContainer.GetChildByUserData("label");
- var strengthText = labelContainer.GetChildByUserData("strength") as GUITextBlock;
-
- strengthText.Text = strengthTexts[
- MathHelper.Clamp((int)Math.Floor((affliction.Strength / affliction.Prefab.MaxStrength) * strengthTexts.Length), 0, strengthTexts.Length - 1)];
-
- strengthText.TextColor = ToolBox.GradientLerp(
- affliction.Strength / affliction.Prefab.MaxStrength,
- Color.Yellow, Color.Orange, Color.Red);
-
- var vitalityText = labelContainer.GetChildByUserData("vitality") as GUITextBlock;
- int vitalityDecrease = (int)affliction.GetVitalityDecrease(this);
- if (vitalityDecrease == 0)
- {
- vitalityText.Visible = false;
- }
- else
- {
- vitalityText.Visible = true;
- vitalityText.Text = TextManager.Get("Vitality") + " -" + vitalityDecrease;
- vitalityText.TextColor = vitalityDecrease <= 0 ? Color.LightGreen :
- Color.Lerp(Color.Orange, Color.Red, affliction.Strength / affliction.Prefab.MaxStrength);
- }
- }
- }
-
- public bool OnItemDropped(Item item, bool ignoreMousePos)
- {
- //items can be dropped outside the health window
- if (!ignoreMousePos &&
- !healthWindow.Rect.Contains(PlayerInput.MousePosition) &&
- !afflictionInfoFrame.Rect.Contains(PlayerInput.MousePosition))
- {
- return false;
- }
-
- //can't apply treatment to dead characters
- if (Character.IsDead) return true;
- if (item == null || !item.UseInHealthInterface) return true;
- if (!ignoreMousePos)
- {
- if (highlightedLimbIndex > -1)
- {
- selectedLimbIndex = highlightedLimbIndex;
- }
- else if (!dropItemArea.Rect.Contains(PlayerInput.MousePosition))
- {
- return true;
- }
- }
-
- Limb targetLimb = Character.AnimController.Limbs.FirstOrDefault(l => l.HealthIndex == selectedLimbIndex);
-
- item.ApplyTreatment(Character.Controlled, Character, targetLimb);
-
- dropItemAnimTimer = dropItemAnimDuration;
- droppedItem = item;
- return true;
- }
-
- private List- GetAvailableMedicalItems()
- {
- List
- allInventoryItems = new List
- ();
- allInventoryItems.AddRange(Character.Inventory.Items);
- if (Character.SelectedCharacter?.Inventory != null && Character.CanAccessInventory(Character.SelectedCharacter.Inventory))
- {
- allInventoryItems.AddRange(Character.SelectedCharacter.Inventory.Items);
- }
- if (Character.SelectedBy?.Inventory != null)
- {
- allInventoryItems.AddRange(Character.SelectedBy.Inventory.Items);
- }
-
- List
- medicalItems = new List
- ();
- foreach (Item item in allInventoryItems)
- {
- if (item == null) continue;
-
- var containedItems = item.ContainedItems;
- if (containedItems != null)
- {
- foreach (Item containedItem in containedItems)
- {
- if (containedItem == null) continue;
- if (!containedItem.HasTag("medical") && !containedItem.HasTag("chem")) continue;
- medicalItems.Add(containedItem);
- }
- }
-
- if (!item.HasTag("medical") && !item.HasTag("chem")) continue;
- medicalItems.Add(item);
- }
-
- return medicalItems.Distinct().ToList();
- }
-
- private void UpdateLimbIndicators(float deltaTime, Rectangle drawArea)
- {
- limbIndicatorOverlayAnimState += deltaTime * 8.0f;
-
- highlightedLimbIndex = -1;
- int i = 0;
- foreach (LimbHealth limbHealth in limbHealths)
- {
- if (limbHealth.IndicatorSprite == null) continue;
-
- float scale = Math.Min(drawArea.Width / (float)limbHealth.IndicatorSprite.SourceRect.Width, drawArea.Height / (float)limbHealth.IndicatorSprite.SourceRect.Height);
-
- Rectangle highlightArea = GetLimbHighlightArea(limbHealth, drawArea);
-
- if (highlightArea.Contains(PlayerInput.MousePosition))
- {
- highlightedLimbIndex = i;
- }
- i++;
- }
-
- if (PlayerInput.LeftButtonClicked() && highlightedLimbIndex > -1)
- {
- selectedLimbIndex = highlightedLimbIndex;
- //afflictionContainer.ClearChildren();
- afflictionInfoContainer.ClearChildren();
- }
- }
-
- private void DrawHealthWindow(SpriteBatch spriteBatch, Rectangle drawArea, bool allowHighlight, bool highlightAll)
- {
- if (Character.Removed) { return; }
-
- int i = 0;
- foreach (LimbHealth limbHealth in limbHealths)
- {
- if (limbHealth.IndicatorSprite == null) continue;
-
- float damageLerp = limbHealth.TotalDamage > 0.0f ? MathHelper.Lerp(0.2f, 1.0f, limbHealth.TotalDamage / 100.0f) : 0.0f;
- Color color = Character.IsDead ?
- Color.Lerp(Color.Black, new Color(150, 100, 100), damageLerp) :
- ToolBox.GradientLerp(damageLerp, Color.Green, Color.Orange, Color.Red);
- float scale = Math.Min(drawArea.Width / (float)limbHealth.IndicatorSprite.SourceRect.Width, drawArea.Height / (float)limbHealth.IndicatorSprite.SourceRect.Height);
-
- if (((i == highlightedLimbIndex || i == selectedLimbIndex) && allowHighlight) || highlightAll)
- {
- color = Color.Lerp(color, Color.White, 0.5f);
- }
-
- limbHealth.IndicatorSprite.Draw(spriteBatch,
- drawArea.Center.ToVector2(), color,
- limbHealth.IndicatorSprite.Origin,
- 0, scale);
- i++;
- }
-
- spriteBatch.End();
- spriteBatch.Begin(SpriteSortMode.Deferred, Lights.CustomBlendStates.Multiplicative);
-
- float overlayScale = Math.Min(
- drawArea.Width / (float)limbIndicatorOverlay.FrameSize.X,
- drawArea.Height / (float)limbIndicatorOverlay.FrameSize.Y);
-
- int frame = 0;
- int frameCount = 17;
- if (limbIndicatorOverlayAnimState >= frameCount * 2) limbIndicatorOverlayAnimState = 0.0f;
- if (limbIndicatorOverlayAnimState < frameCount)
- {
- frame = (int)limbIndicatorOverlayAnimState;
- }
- else
- {
- frame = frameCount - (int)(limbIndicatorOverlayAnimState - (frameCount - 1));
- }
-
- limbIndicatorOverlay.Draw(spriteBatch, frame, drawArea.Center.ToVector2(), Color.Gray, origin: limbIndicatorOverlay.FrameSize.ToVector2() / 2, rotate: 0.0f,
- scale: Vector2.One * overlayScale);
-
- spriteBatch.End();
- spriteBatch.Begin(SpriteSortMode.Deferred, blendState: BlendState.AlphaBlend, rasterizerState: GameMain.ScissorTestEnable);
-
- i = 0;
- foreach (LimbHealth limbHealth in limbHealths)
- {
- if (limbHealth.IndicatorSprite == null) continue;
- float scale = Math.Min(drawArea.Width / (float)limbHealth.IndicatorSprite.SourceRect.Width, drawArea.Height / (float)limbHealth.IndicatorSprite.SourceRect.Height);
-
- Rectangle highlightArea = new Rectangle(
- (int)(drawArea.Center.X - (limbHealth.IndicatorSprite.Texture.Width / 2 - limbHealth.HighlightArea.X) * scale),
- (int)(drawArea.Center.Y - (limbHealth.IndicatorSprite.Texture.Height / 2 - limbHealth.HighlightArea.Y) * scale),
- (int)(limbHealth.HighlightArea.Width * scale),
- (int)(limbHealth.HighlightArea.Height * scale));
-
- if (selectedLimbIndex == i)
- {
- if (alignment == Alignment.Left)
- {
- GUI.DrawLine(spriteBatch,
- highlightArea.Center.ToVector2(),
- afflictionInfoContainer.Parent.Rect.Location.ToVector2() + Vector2.UnitY * 20,
- Color.LightBlue * 0.3f, 0, 4);
- }
- else
- {
- GUI.DrawLine(spriteBatch,
- highlightArea.Center.ToVector2(),
- new Vector2(afflictionInfoContainer.Parent.Rect.Right, afflictionInfoContainer.Parent.Rect.Y + 20),
- Color.LightBlue * 0.3f, 0, 4);
- }
- }
-
- var slot = GUI.Style.GetComponentStyle("AfflictionIconSlot");
-
- float iconScale = 0.3f * scale;
- Vector2 iconPos = highlightArea.Center.ToVector2();
- foreach (Affliction affliction in limbHealth.Afflictions)
- {
- DrawLimbAfflictionIcon(spriteBatch, affliction, slot, iconScale, ref iconPos);
- }
-
- foreach (Affliction affliction in afflictions)
- {
- Limb indicatorLimb = Character.AnimController.GetLimb(affliction.Prefab.IndicatorLimb);
- if (indicatorLimb != null && indicatorLimb.HealthIndex == i)
- {
- DrawLimbAfflictionIcon(spriteBatch, affliction, slot, iconScale, ref iconPos);
- }
- }
- i++;
- }
-
- if (draggingMed != null)
- {
- GUIImage itemImage = draggingMed.GetChild();
- float scale = Math.Min(40.0f / itemImage.Sprite.size.X, 40.0f / itemImage.Sprite.size.Y);
- itemImage.Sprite.Draw(spriteBatch, PlayerInput.MousePosition, itemImage.Color, 0, scale);
- }
-
- if (dropItemAnimTimer > 0.0f && droppedItem?.Prefab.InventoryIcon != null)
- {
- var droppedItemSprite = droppedItem.Prefab.InventoryIcon ?? droppedItem.Sprite;
- droppedItemSprite.Draw(spriteBatch, dropItemArea.Rect.Center.ToVector2(),
- droppedItemSprite == droppedItem.Sprite ? droppedItem.GetSpriteColor() : droppedItem.GetInventoryIconColor(),
- origin: droppedItemSprite.size / 2,
- scale: MathHelper.SmoothStep(0.0f, 100.0f / droppedItemSprite.size.Length(), dropItemAnimTimer / dropItemAnimDuration));
- }
- }
-
- private void DrawLimbAfflictionIcon(SpriteBatch spriteBatch, Affliction affliction, GUIComponentStyle slotStyle, float iconScale, ref Vector2 iconPos)
- {
- if (affliction.Strength < affliction.Prefab.ShowIconThreshold) return;
- Vector2 iconSize = (affliction.Prefab.Icon.size * iconScale);
-
- //afflictions that have a strength of less than 10 are faded out slightly
- float alpha = MathHelper.Lerp(0.3f, 1.0f,
- (affliction.Strength - affliction.Prefab.ShowIconThreshold) / Math.Min(affliction.Prefab.MaxStrength - affliction.Prefab.ShowIconThreshold, 10.0f));
-
- slotStyle.Sprites[GUIComponent.ComponentState.None][0].Draw(
- spriteBatch,
- new Rectangle((iconPos - iconSize / 2.0f).ToPoint(), iconSize.ToPoint()),
- slotStyle.Color * alpha);
- affliction.Prefab.Icon.Draw(spriteBatch, iconPos - iconSize / 2.0f, affliction.Prefab.IconColor * alpha, 0, iconScale);
- iconPos += new Vector2(10.0f, 20.0f) * iconScale;
- }
-
- private Rectangle GetLimbHighlightArea(LimbHealth limbHealth, Rectangle drawArea)
- {
- float scale = Math.Min(drawArea.Width / (float)limbHealth.IndicatorSprite.SourceRect.Width, drawArea.Height / (float)limbHealth.IndicatorSprite.SourceRect.Height);
- return new Rectangle(
- (int)(drawArea.Center.X - (limbHealth.IndicatorSprite.Texture.Width / 2 - limbHealth.HighlightArea.X) * scale),
- (int)(drawArea.Center.Y - (limbHealth.IndicatorSprite.Texture.Height / 2 - limbHealth.HighlightArea.Y) * scale),
- (int)(limbHealth.HighlightArea.Width * scale),
- (int)(limbHealth.HighlightArea.Height * scale));
- }
-
- public void ClientRead(NetBuffer inc)
- {
- List> newAfflictions = new List>();
-
- byte afflictionCount = inc.ReadByte();
- for (int i = 0; i < afflictionCount; i++)
- {
- AfflictionPrefab afflictionPrefab = AfflictionPrefab.List[inc.ReadRangedInteger(0, AfflictionPrefab.List.Count - 1)];
- float afflictionStrength = inc.ReadRangedSingle(0.0f, afflictionPrefab.MaxStrength, 8);
-
- newAfflictions.Add(new Pair(afflictionPrefab, afflictionStrength));
- }
-
- foreach (Affliction affliction in afflictions)
- {
- //deactivate afflictions that weren't included in the network message
- if (!newAfflictions.Any(a => a.First == affliction.Prefab))
- {
- affliction.Strength = 0.0f;
- }
- }
-
- foreach (Pair newAffliction in newAfflictions)
- {
- Affliction existingAffliction = afflictions.Find(a => a.Prefab == newAffliction.First);
- if (existingAffliction == null)
- {
- afflictions.Add(newAffliction.First.Instantiate(newAffliction.Second));
- }
- else
- {
- existingAffliction.Strength = newAffliction.Second;
- if (existingAffliction == stunAffliction) Character.SetStun(existingAffliction.Strength, true, true);
- }
- }
-
- List> newLimbAfflictions = new List>();
- byte limbAfflictionCount = inc.ReadByte();
- for (int i = 0; i < limbAfflictionCount; i++)
- {
- int limbIndex = inc.ReadRangedInteger(0, limbHealths.Count - 1);
- AfflictionPrefab afflictionPrefab = AfflictionPrefab.List[inc.ReadRangedInteger(0, AfflictionPrefab.List.Count - 1)];
- float afflictionStrength = inc.ReadRangedSingle(0.0f, afflictionPrefab.MaxStrength, 8);
-
- newLimbAfflictions.Add(new Triplet(limbHealths[limbIndex], afflictionPrefab, afflictionStrength));
- }
-
- foreach (LimbHealth limbHealth in limbHealths)
- {
- foreach (Affliction affliction in limbHealth.Afflictions)
- {
- //deactivate afflictions that weren't included in the network message
- if (!newLimbAfflictions.Any(a => a.First == limbHealth && a.Second == affliction.Prefab))
- {
- affliction.Strength = 0.0f;
- }
- }
-
- foreach (Triplet newAffliction in newLimbAfflictions)
- {
- if (newAffliction.First != limbHealth) continue;
- Affliction existingAffliction = limbHealth.Afflictions.Find(a => a.Prefab == newAffliction.Second);
- if (existingAffliction == null)
- {
- limbHealth.Afflictions.Add(newAffliction.Second.Instantiate(newAffliction.Third));
- }
- else
- {
- existingAffliction.Strength = newAffliction.Third;
- }
- }
- }
- }
-
partial void UpdateLimbAfflictionOverlays()
{
foreach (Limb limb in Character.AnimController.Limbs)
@@ -1411,20 +18,5 @@ namespace Barotrauma
limb.DamageOverlayStrength /= limbHealths[limb.HealthIndex].Afflictions.Count;
}
}
-
- partial void RemoveProjSpecific()
- {
- foreach (LimbHealth limbHealth in limbHealths)
- {
- if (limbHealth.IndicatorSprite != null)
- {
- limbHealth.IndicatorSprite.Remove();
- limbHealth.IndicatorSprite = null;
- }
- }
-
- limbIndicatorOverlay?.Remove();
- limbIndicatorOverlay = null;
- }
}
}
diff --git a/Barotrauma/BarotraumaClient/Source/DebugConsole.cs b/Barotrauma/BarotraumaClient/Source/DebugConsole.cs
index b8c7f8fee..60e369ebf 100644
--- a/Barotrauma/BarotraumaClient/Source/DebugConsole.cs
+++ b/Barotrauma/BarotraumaClient/Source/DebugConsole.cs
@@ -403,11 +403,6 @@ namespace Barotrauma
AssignRelayToServer("help", false);
AssignRelayToServer("verboselogging", false);
AssignRelayToServer("freecam", false);
-#if DEBUG
- AssignRelayToServer("simulatedlatency", false);
- AssignRelayToServer("simulatedloss", false);
- AssignRelayToServer("simulatedduplicateschance", false);
-#endif
commands.Add(new Command("clientlist", "", (string[] args) => { }));
AssignRelayToServer("clientlist", true);
@@ -444,7 +439,7 @@ namespace Barotrauma
AssignOnExecute("ambientlight", (string[] args) =>
{
- Color color = XMLExtensions.ParseColor(string.Join(",", args));
+ Color color = XMLExtensions.ParseColor(string.Join("", args));
if (Level.Loaded != null)
{
Level.Loaded.GenerationParams.AmbientLightColor = color;
@@ -533,27 +528,44 @@ namespace Barotrauma
}
}, isCheat: true));
- commands.Add(new Command("resetall", "Reset all items and structures to prefabs. Only applicable in the subeditor.", args =>
+ commands.Add(new Command("alpha", "Change the alpha (as bytes from 0 to 255) of the selected item/structure instances. Applied only in the subeditor.", (string[] args) =>
{
if (Screen.Selected == GameMain.SubEditorScreen)
{
- Item.ItemList.ForEach(i => i.Reset());
- Structure.WallList.ForEach(s => s.Reset());
- foreach (MapEntity entity in MapEntity.SelectedList)
+ if (!MapEntity.SelectedAny)
{
- if (entity is Item item)
+ ThrowError("You have to select item(s)/structure(s) first!");
+ }
+ else
+ {
+ if (args.Length > 0)
{
- item.CreateEditingHUD();
- break;
+ if (!byte.TryParse(args[0], out byte a))
+ {
+ ThrowError($"Failed to parse value for ALPHA from {args[0]}");
+ }
+ else
+ {
+ foreach (var mapEntity in MapEntity.SelectedList)
+ {
+ if (mapEntity is Structure s)
+ {
+ s.SpriteColor = new Color(s.SpriteColor.R, s.SpriteColor.G, s.SpriteColor.G, a);
+ }
+ else if (mapEntity is Item i)
+ {
+ i.SpriteColor = new Color(i.SpriteColor.R, i.SpriteColor.G, i.SpriteColor.G, a);
+ }
+ }
+ }
}
- else if (entity is Structure structure)
+ else
{
- structure.CreateEditingHUD();
- break;
+ ThrowError("Not enough arguments provided! One required!");
}
}
}
- }));
+ }, isCheat: true));
commands.Add(new Command("alpha", "Change the alpha (as bytes from 0 to 255) of the selected item/structure instances. Applied only in the subeditor.", (string[] args) =>
{
diff --git a/Barotrauma/BarotraumaClient/Source/GUI/VideoPlayer.cs b/Barotrauma/BarotraumaClient/Source/GUI/VideoPlayer.cs
new file mode 100644
index 000000000..18c6f0f5d
--- /dev/null
+++ b/Barotrauma/BarotraumaClient/Source/GUI/VideoPlayer.cs
@@ -0,0 +1,215 @@
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Graphics;
+using System;
+using System.Xml.Linq;
+using System.Collections.Generic;
+using Barotrauma.Media;
+
+namespace Barotrauma
+{
+ class VideoPlayer
+ {
+ private Video currentVideo;
+ private List preloadedVideos;
+
+ private GUIFrame background, videoFrame;
+ private GUITextBlock title;
+ private GUICustomComponent videoView;
+
+ private Color backgroundColor = new Color(0f, 0f, 0f, 1f);
+ private Action callbackOnStop;
+
+ private bool isPlaying;
+
+ public bool IsPlaying()
+ {
+ return isPlaying;
+ /*if (currentVideo == null) return false;
+ return currentVideo.IsPlaying;*/
+ }
+
+ private readonly Point defaultResolution = new Point(520, 300);
+ private readonly int borderSize = 20;
+
+ private class PreloadedContent
+ {
+ public string ContentName;
+ public string ContentTag;
+ public Video Video;
+ public Point Resolution;
+
+ public PreloadedContent(string name, string tag, Video video, Point resolution)
+ {
+ ContentName = name;
+ ContentTag = tag;
+ Video = video;
+ Resolution = resolution;
+ }
+ }
+
+ public VideoPlayer()
+ {
+ int width = defaultResolution.X;
+ int height = defaultResolution.Y;
+
+ background = new GUIFrame(new RectTransform(new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight), GUI.Canvas, Anchor.Center), "InnerFrame", backgroundColor);
+ videoFrame = new GUIFrame(new RectTransform(new Point(width + borderSize, height + borderSize), background.RectTransform, Anchor.Center), "SonarFrame");
+ videoView = new GUICustomComponent(new RectTransform(new Point(width, height), videoFrame.RectTransform, Anchor.Center),
+ (spriteBatch, guiCustomComponent) => { DrawVideo(spriteBatch, guiCustomComponent.Rect); });
+ title = new GUITextBlock(new RectTransform(new Vector2(1f, 0f), videoFrame.RectTransform, Anchor.TopCenter, Pivot.BottomCenter), string.Empty, font: GUI.LargeFont, textAlignment: Alignment.Center);
+
+ preloadedVideos = new List();
+ }
+
+ public void PreloadContent(string contentPath, string contentTag, string contentId, XElement contentElement)
+ {
+ if (preloadedVideos.Find(s => s.ContentName == contentId) != null) return; // Already loaded
+ Point resolution = new Point(contentElement.GetAttributeInt("width", 0), contentElement.GetAttributeInt("height", 0));
+
+ if (resolution.X == 0 || resolution.Y == 0)
+ {
+ resolution = defaultResolution;
+ }
+
+ preloadedVideos.Add(new PreloadedContent(contentId, contentTag, CreateVideo(contentPath, resolution), resolution));
+ }
+
+ public void RemoveAllPreloaded()
+ {
+ if (preloadedVideos == null || preloadedVideos.Count == 0) return;
+
+ for (int i = 0; i < preloadedVideos.Count; i++)
+ {
+ preloadedVideos[i] = null;
+ }
+
+ preloadedVideos.Clear();
+ }
+
+ public void RemovePreloadedByTag(string tag)
+ {
+ if (preloadedVideos == null || preloadedVideos.Count == 0) return;
+
+ for (int i = 0; i < preloadedVideos.Count; i++)
+ {
+ if (preloadedVideos[i].ContentTag != tag) continue;
+ preloadedVideos[i] = null;
+ preloadedVideos.RemoveAt(i);
+ i--;
+ }
+ }
+
+ public void Play()
+ {
+ isPlaying = true;
+ }
+
+ public void Stop()
+ {
+ isPlaying = false;
+ if (currentVideo == null) return;
+ currentVideo.Dispose();
+ currentVideo = null;
+ }
+
+ private bool OKButtonClicked(GUIButton button, object userData)
+ {
+ Stop();
+ callbackOnStop?.Invoke();
+ return true;
+ }
+
+ public void AddToGUIUpdateList()
+ {
+ if (!IsPlaying()) return;
+ background.AddToGUIUpdateList();
+ }
+
+ public void LoadContent(string contentPath, XElement videoElement, string contentId, bool startPlayback, bool hasButton, Action callback = null)
+ {
+ if (currentVideo != null)
+ {
+ currentVideo.Dispose();
+ currentVideo = null;
+ }
+
+ PreloadedContent preloaded = null;
+ Point resolution = new Point(0, 0);
+
+ if (preloadedVideos != null && preloadedVideos.Count > 0)
+ {
+ preloaded = preloadedVideos.Find(s => s.ContentName == contentId);
+
+ if (preloaded != null)
+ {
+ currentVideo = preloaded.Video;
+ resolution = preloaded.Resolution;
+ }
+ }
+
+ if (currentVideo == null) // No preloaded sheets found, create sheets
+ {
+ resolution = new Point(videoElement.GetAttributeInt("width", 0), videoElement.GetAttributeInt("height", 0));
+
+ if (resolution.X == 0 || resolution.Y == 0)
+ {
+ resolution = defaultResolution;
+ }
+
+ currentVideo = CreateVideo(contentPath, resolution);
+ }
+
+ videoFrame.RectTransform.NonScaledSize = resolution + new Point(borderSize, borderSize);
+ videoView.RectTransform.NonScaledSize = resolution;
+
+ title.Text = TextManager.Get(contentId);
+ title.RectTransform.NonScaledSize = new Point(resolution.X, 30);
+
+ callbackOnStop = callback;
+
+ if (hasButton)
+ {
+ var okButton = new GUIButton(new RectTransform(new Point(160, 50), videoFrame.RectTransform, Anchor.BottomCenter, Pivot.TopCenter) { AbsoluteOffset = new Point(0, -10) },
+ TextManager.Get("OK"))
+ {
+ OnClicked = OKButtonClicked
+ };
+ }
+
+ if (startPlayback) Play();
+ }
+
+ private Video CreateVideo(string contentPath, Point resolution)
+ {
+ Video video = null;
+
+ try
+ {
+ video = new Video(GameMain.Instance.GraphicsDevice, GameMain.SoundManager, contentPath, (uint)resolution.X, (uint)resolution.Y);
+ }
+ catch (Exception e)
+ {
+ DebugConsole.ThrowError("Error loading video content " + contentPath + "!", e);
+ }
+
+ return video;
+ }
+
+ private void DrawVideo(SpriteBatch spriteBatch, Rectangle rect)
+ {
+ if (!isPlaying) return;
+ spriteBatch.Draw(currentVideo.GetTexture(), rect, Color.White);
+ }
+
+ public void Remove()
+ {
+ if (currentVideo != null)
+ {
+ currentVideo.Dispose();
+ currentVideo = null;
+ }
+
+ RemoveAllPreloaded();
+ }
+ }
+}
diff --git a/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/MultiPlayerCampaign.cs b/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/MultiPlayerCampaign.cs
index 96ea38e4b..0ab86bef6 100644
--- a/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/MultiPlayerCampaign.cs
+++ b/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/MultiPlayerCampaign.cs
@@ -12,7 +12,7 @@ namespace Barotrauma
{
private UInt16 startWatchmanID, endWatchmanID;
- public static GUIComponent StartCampaignSetup( IEnumerable submarines, IEnumerable saveFiles)
+ public static GUIComponent StartCampaignSetup(IEnumerable saveFiles)
{
GUIFrame background = new GUIFrame(new RectTransform(Vector2.One, GUI.Canvas), style: "GUIBackgroundBlocker");
@@ -35,7 +35,7 @@ namespace Barotrauma
var newCampaignContainer = new GUIFrame(new RectTransform(Vector2.One, campaignContainer.RectTransform, Anchor.BottomLeft), style: null);
var loadCampaignContainer = new GUIFrame(new RectTransform(Vector2.One, campaignContainer.RectTransform, Anchor.BottomLeft), style: null);
- var campaignSetupUI = new CampaignSetupUI(true, newCampaignContainer, loadCampaignContainer, submarines, saveFiles);
+ var campaignSetupUI = new CampaignSetupUI(true, newCampaignContainer, loadCampaignContainer, saveFiles);
var newCampaignButton = new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), buttonContainer.RectTransform),
TextManager.Get("NewCampaign"))
@@ -92,7 +92,8 @@ namespace Barotrauma
if (endWatchman != null) { InitializeWatchman(endWatchman); }
}
}
-
+
+
protected override void WatchmanInteract(Character watchman, Character interactor)
{
if ((watchman.Submarine == Level.Loaded.StartOutpost && !Submarine.MainSub.AtStartPosition) ||
@@ -106,7 +107,8 @@ namespace Barotrauma
return;
}
- if (GameMain.Client != null && interactor == Character.Controlled)
+ if (GameMain.Client != null && interactor == Character.Controlled &&
+ (GameMain.Client.HasPermission(ClientPermissions.ManageRound) || GameMain.Client.HasPermission(ClientPermissions.ManageCampaign)))
{
var msgBox = new GUIMessageBox("", TextManager.Get("CampaignEnterOutpostPrompt")
.Replace("[locationname]", Submarine.MainSub.AtStartPosition ? Map.CurrentLocation.Name : Map.SelectedLocation.Name),
@@ -120,7 +122,8 @@ namespace Barotrauma
return true;
};
msgBox.Buttons[0].OnClicked += msgBox.Close;
- msgBox.Buttons[1].OnClicked += msgBox.Close;
+ msgBox.Buttons[1].OnClicked += msgBox.Close;
+
}
}
diff --git a/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/ContextualTutorial.cs b/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/ContextualTutorial.cs
index 843b7566e..923effbe7 100644
--- a/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/ContextualTutorial.cs
+++ b/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/ContextualTutorial.cs
@@ -19,6 +19,8 @@ namespace Barotrauma.Tutorials
private List segments;
private SpriteSheetPlayer spriteSheetPlayer;
+ private VideoPlayer videoPlayer;
+
private Steering navConsole;
private Reactor reactor;
private Sonar sonar;
@@ -29,7 +31,7 @@ namespace Barotrauma.Tutorials
private bool started = false;
private string playableContentPath;
-
+
private float tutorialTimer;
private float degrading2ActivationCountdown;
@@ -82,6 +84,7 @@ namespace Barotrauma.Tutorials
base.Initialize();
spriteSheetPlayer = new SpriteSheetPlayer();
+ videoPlayer = new VideoPlayer();
characterTimeOnSonar = new List>();
for (int i = 0; i < segments.Count; i++)
@@ -210,6 +213,8 @@ namespace Barotrauma.Tutorials
started = ContentRunning = Initialized = false;
spriteSheetPlayer.Remove();
spriteSheetPlayer = null;
+ videoPlayer.Remove();
+ videoPlayer = null;
characterTimeOnSonar = null;
}
@@ -220,6 +225,10 @@ namespace Barotrauma.Tutorials
{
spriteSheetPlayer.AddToGUIUpdateList();
}
+ if (videoPlayer != null)
+ {
+ videoPlayer.AddToGUIUpdateList();
+ }
}
public override void Update(float deltaTime)
@@ -325,7 +334,7 @@ namespace Barotrauma.Tutorials
foreach (Item item in Item.ItemList)
{
- if (!item.Repairables.Any() || item.ConditionPercentage > 50) continue;
+ if (!item.Repairables.Any() || item.Condition > 50.0f) continue;
degradedEquipmentFound = true;
break;
}
@@ -461,10 +470,18 @@ namespace Barotrauma.Tutorials
case ContentTypes.None:
break;
case ContentTypes.Video:
- spriteSheetPlayer.LoadContent(playableContentPath, activeSegment.Content, activeSegment.Name, true, true, CurrentSegmentStopCallback);
+ string fileName = activeSegment.Content.GetAttributeString("file", "");
+ if (fileName != "")
+ {
+ videoPlayer.LoadContent(playableContentPath + fileName, activeSegment.Content, activeSegment.Name, true, true, CurrentSegmentStopCallback);
+ }
+ else
+ {
+ spriteSheetPlayer.LoadContent(playableContentPath, activeSegment.Content, activeSegment.Name, true, true, CurrentSegmentStopCallback);
+ }
break;
case ContentTypes.Text:
- infoBox = CreateInfoFrame(TextManager.Get(activeSegment.Name), TextManager.GetFormatted(activeSegment.Content.GetAttributeString("tag", ""), false, args),
+ infoBox = CreateInfoFrame(TextManager.Get(activeSegment.Name), TextManager.Get(activeSegment.Content.GetAttributeString("tag", ""), false, args),
activeSegment.Content.GetAttributeInt("width", 300),
activeSegment.Content.GetAttributeInt("height", 80),
activeSegment.Content.GetAttributeString("anchor", "Center"), true, CurrentSegmentStopCallback);
diff --git a/Barotrauma/BarotraumaClient/Source/GameSettings.cs b/Barotrauma/BarotraumaClient/Source/GameSettings.cs
index 4ee4ab87e..9542ef2b8 100644
--- a/Barotrauma/BarotraumaClient/Source/GameSettings.cs
+++ b/Barotrauma/BarotraumaClient/Source/GameSettings.cs
@@ -47,7 +47,7 @@ namespace Barotrauma
//if "%" is found
if (index > 0)
{
- while (index > 0)
+ while (true)
{
//search for end of label
index -= 1;
@@ -439,6 +439,7 @@ namespace Barotrauma
}
};
#endif
+
var radioButtonFrame = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.6f), voiceSettings.RectTransform))
{
Stretch = true,
@@ -457,24 +458,6 @@ namespace Barotrauma
voiceMode.AddRadioButton((VoiceMode)i, tick);
}
- var micVolumeText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.18f), voiceSettings.RectTransform), TextManager.Get("MicrophoneVolume"));
- var micVolumeSlider = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.18f), voiceSettings.RectTransform),
- barSize: 0.1f)
- {
- UserData = micVolumeText,
- BarScroll = (float)Math.Sqrt(MathUtils.InverseLerp(0.2f, 5.0f, MicrophoneVolume)),
- OnMoved = (scrollBar, scroll) =>
- {
- MicrophoneVolume = MathHelper.Lerp(0.2f, 5.0f, scroll * scroll);
- MicrophoneVolume = (float)Math.Round(MicrophoneVolume, 1);
- ChangeSliderText(scrollBar, MicrophoneVolume);
- scrollBar.Step = 0.05f;
- return true;
- },
- Step = 0.05f
- };
- micVolumeSlider.OnMoved(micVolumeSlider, micVolumeSlider.BarScroll);
-
var voiceInputContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.5f, 0.2f), voiceSettings.RectTransform, Anchor.BottomCenter));
new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), voiceInputContainer.RectTransform), TextManager.Get("InputType.Voice") + ": ");
var voiceKeyBox = new GUITextBox(new RectTransform(new Vector2(0.4f, 1.0f), voiceInputContainer.RectTransform, Anchor.TopRight),
@@ -486,6 +469,7 @@ namespace Barotrauma
voiceKeyBox.SelectedColor = Color.Gold * 0.3f;
var voiceActivityGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.3f), voiceSettings.RectTransform));
+
GUITextBlock noiseGateText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), voiceActivityGroup.RectTransform), TextManager.Get("NoiseGateThreshold"))
{
TextGetter = () =>
@@ -525,13 +509,13 @@ namespace Barotrauma
if (GameMain.Client == null && VoipCapture.Instance == null)
{
VoipCapture.Create(GameMain.Config.VoiceCaptureDevice);
- if (VoipCapture.Instance == null)
- {
- VoiceSetting = vMode = VoiceMode.Disabled;
- voiceInputContainer.Visible = false;
- voiceActivityGroup.Visible = false;
- return;
- }
+ }
+ if (VoipCapture.Instance == null)
+ {
+ VoiceSetting = vMode = VoiceMode.Disabled;
+ voiceInputContainer.Visible = false;
+ voiceActivityGroup.Visible = false;
+ return;
}
}
else
diff --git a/Barotrauma/BarotraumaClient/Source/Items/Components/Door.cs b/Barotrauma/BarotraumaClient/Source/Items/Components/Door.cs
index 8a1858095..d536e9fe5 100644
--- a/Barotrauma/BarotraumaClient/Source/Items/Components/Door.cs
+++ b/Barotrauma/BarotraumaClient/Source/Items/Components/Door.cs
@@ -93,7 +93,7 @@ namespace Barotrauma.Items.Components
public void Draw(SpriteBatch spriteBatch, bool editing)
{
- Color color = item.SpriteColor;
+ Color color = Color.White;
if (brokenSprite == null)
{
//broken doors turn black if no broken sprite has been configured
@@ -108,7 +108,7 @@ namespace Barotrauma.Items.Components
weldSpritePos.Y = -weldSpritePos.Y;
weldedSprite.Draw(spriteBatch,
- weldSpritePos, item.SpriteColor * (stuck / 100.0f), scale: item.Scale);
+ weldSpritePos, Color.White * (stuck / 100.0f), scale: item.Scale);
}
if (openState == 1.0f)
diff --git a/Barotrauma/BarotraumaClient/Source/Items/Components/ItemComponent.cs b/Barotrauma/BarotraumaClient/Source/Items/Components/ItemComponent.cs
index d9927245e..681bcad91 100644
--- a/Barotrauma/BarotraumaClient/Source/Items/Components/ItemComponent.cs
+++ b/Barotrauma/BarotraumaClient/Source/Items/Components/ItemComponent.cs
@@ -313,7 +313,7 @@ namespace Barotrauma.Items.Components
if (sound == null) { return 0.0f; }
if (sound.VolumeProperty == "") { return sound.VolumeMultiplier; }
- if (SerializableProperties.TryGetValue(sound.VolumeProperty, out SerializableProperty property))
+ if (properties.TryGetValue(sound.VolumeProperty, out SerializableProperty property))
{
float newVolume = 0.0f;
try
diff --git a/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Reactor.cs b/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Reactor.cs
index d0e98ead9..68d2a9b90 100644
--- a/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Reactor.cs
+++ b/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Reactor.cs
@@ -331,18 +331,8 @@ namespace Barotrauma.Items.Components
spriteBatch.GraphicsDevice.ScissorRectangle = container.Rect;
spriteBatch.Begin(SpriteSortMode.Deferred, rasterizerState: GameMain.ScissorTestEnable);
- //make the pointer jitter a bit if it's at the upper limit of the fission rate
- float jitter = 0.0f;
- if (FissionRate > allowedFissionRate.Y - 5.0f)
- {
- float jitterAmount = Math.Min(targetFissionRate - allowedFissionRate.Y, 10.0f);
- float t = graphTimer / updateGraphInterval;
-
- jitter = (PerlinNoise.GetPerlin(t * 0.5f, t * 0.1f) - 0.5f) * jitterAmount;
- }
-
DrawMeter(spriteBatch, container.Rect,
- fissionRateMeter, FissionRate + jitter, new Vector2(0.0f, 100.0f), optimalFissionRate, allowedFissionRate);
+ fissionRateMeter, FissionRate, new Vector2(0.0f, 100.0f), optimalFissionRate, allowedFissionRate);
spriteBatch.End();
spriteBatch.GraphicsDevice.ScissorRectangle = prevScissorRect;
@@ -402,12 +392,12 @@ namespace Barotrauma.Items.Components
Vector2 pos = new Vector2(rect.Center.X, rect.Y + meterSprite.Origin.Y * scale);
Vector2 optimalRangeNormalized = new Vector2(
- MathHelper.Clamp((optimalRange.X - range.X) / (range.Y - range.X), 0.0f, 0.95f),
- MathHelper.Clamp((optimalRange.Y - range.X) / (range.Y - range.X), 0.0f, 1.0f));
+ (optimalRange.X - range.X) / (range.Y - range.X),
+ (optimalRange.Y - range.X) / (range.Y - range.X));
Vector2 allowedRangeNormalized = new Vector2(
- MathHelper.Clamp((allowedRange.X - range.X) / (range.Y - range.X), 0.0f, 0.95f),
- MathHelper.Clamp((allowedRange.Y - range.X) / (range.Y - range.X), 0.0f, 1.0f));
+ (allowedRange.X - range.X) / (range.Y - range.X),
+ (allowedRange.Y - range.X) / (range.Y - range.X));
Vector2 sectorRad = new Vector2(-1.57f, 1.57f);
@@ -427,10 +417,10 @@ namespace Barotrauma.Items.Components
{
spriteBatch.End();
Rectangle prevScissorRect = spriteBatch.GraphicsDevice.ScissorRectangle;
- spriteBatch.GraphicsDevice.ScissorRectangle = new Rectangle(0, 0, GameMain.GraphicsWidth, (int)(pos.Y + (meterSprite.size.Y - meterSprite.Origin.Y) * scale) - 3);
+ spriteBatch.GraphicsDevice.ScissorRectangle = new Rectangle(0,0,GameMain.GraphicsWidth, (int)(pos.Y + (meterSprite.size.Y - meterSprite.Origin.Y) * scale));
spriteBatch.Begin(SpriteSortMode.Deferred, rasterizerState: GameMain.ScissorTestEnable);
- sectorSprite.Draw(spriteBatch, pos, Color.LightGreen, MathHelper.PiOver2 + (allowedSectorRad.X + allowedSectorRad.Y) / 2.0f, scale);
+ sectorSprite.Draw(spriteBatch, pos, Color.LightGreen, MathHelper.PiOver2, scale);
sectorSprite.Draw(spriteBatch, pos, Color.Orange, optimalSectorRad.X, scale);
sectorSprite.Draw(spriteBatch, pos, Color.Red, allowedSectorRad.X, scale);
diff --git a/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Sonar.cs b/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Sonar.cs
index a4935fd62..da6fe39d0 100644
--- a/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Sonar.cs
+++ b/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Sonar.cs
@@ -785,9 +785,8 @@ namespace Barotrauma.Items.Components
foreach (Limb limb in c.AnimController.Limbs)
{
- if (!limb.body.Enabled) { continue; }
-
float pointDist = ((limb.WorldPosition - pingSource) * displayScale).LengthSquared();
+
if (limb.SimPosition == Vector2.Zero || pointDist > DisplayRadius * DisplayRadius) continue;
if (pointDist > prevPingRadiusSqr && pointDist < pingRadiusSqr)
diff --git a/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Steering.cs b/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Steering.cs
index dc51312ea..7fc554b01 100644
--- a/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Steering.cs
+++ b/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Steering.cs
@@ -484,14 +484,26 @@ namespace Barotrauma.Items.Components
user = Character.Controlled;
}
}
- if (!AutoPilot && Character.DisableControls && GUI.KeyboardDispatcher.Subscriber == null)
+ if (!AutoPilot && Character.DisableControls)
{
steeringAdjustSpeed = character == null ? 0.2f : MathHelper.Lerp(0.2f, 1.0f, character.GetSkillLevel("helm") / 100.0f);
Vector2 input = Vector2.Zero;
- if (PlayerInput.KeyDown(InputType.Left)) { input -= Vector2.UnitX; }
- if (PlayerInput.KeyDown(InputType.Right)) { input += Vector2.UnitX; }
- if (PlayerInput.KeyDown(InputType.Up)) { input += Vector2.UnitY; }
- if (PlayerInput.KeyDown(InputType.Down)) { input -= Vector2.UnitY; }
+ if (PlayerInput.KeyDown(InputType.Left))
+ {
+ input -= Vector2.UnitX;
+ }
+ if (PlayerInput.KeyDown(InputType.Right))
+ {
+ input += Vector2.UnitX;
+ }
+ if (PlayerInput.KeyDown(InputType.Up))
+ {
+ input += Vector2.UnitY;
+ }
+ if (PlayerInput.KeyDown(InputType.Down))
+ {
+ input -= Vector2.UnitY;
+ }
if (PlayerInput.KeyDown(Keys.LeftShift))
{
SteeringInput += input * deltaTime * 200;
diff --git a/Barotrauma/BarotraumaClient/Source/Items/Components/Repairable.cs b/Barotrauma/BarotraumaClient/Source/Items/Components/Repairable.cs
index 7e8fdc706..b1871cfe0 100644
--- a/Barotrauma/BarotraumaClient/Source/Items/Components/Repairable.cs
+++ b/Barotrauma/BarotraumaClient/Source/Items/Components/Repairable.cs
@@ -1,6 +1,4 @@
-using Barotrauma.Networking;
-using Barotrauma.Particles;
-using Lidgren.Network;
+using Barotrauma.Particles;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System.Collections.Generic;
@@ -114,7 +112,8 @@ namespace Barotrauma.Items.Components
System.Diagnostics.Debug.Assert(GuiFrame.GetChild(0) is GUILayoutGroup, "Repair UI hierarchy has changed, could not find skill texts");
foreach (GUIComponent c in GuiFrame.GetChild(0).Children)
{
- if (!(c.UserData is Skill skill)) continue;
+ Skill skill = c.UserData as Skill;
+ if (skill == null) continue;
GUITextBlock textBlock = (GUITextBlock)c;
if (character.GetSkillLevel(skill.Identifier) < skill.Level)
@@ -127,15 +126,5 @@ namespace Barotrauma.Items.Components
}
}
}
-
- public void ClientRead(ServerNetObject type, NetBuffer msg, float sendingTime)
- {
- deteriorationTimer = msg.ReadSingle();
- }
-
- public void ClientWrite(NetBuffer msg, object[] extraData = null)
- {
- //no need to write anything, just letting the server know we started repairing
- }
}
}
diff --git a/Barotrauma/BarotraumaClient/Source/Items/Components/StatusHUD.cs b/Barotrauma/BarotraumaClient/Source/Items/Components/StatusHUD.cs
index b56dd8629..8b6b5ea03 100644
--- a/Barotrauma/BarotraumaClient/Source/Items/Components/StatusHUD.cs
+++ b/Barotrauma/BarotraumaClient/Source/Items/Components/StatusHUD.cs
@@ -181,7 +181,7 @@ namespace Barotrauma.Items.Components
Dictionary combinedAfflictionStrengths = new Dictionary();
foreach (Affliction affliction in allAfflictions)
{
- if (affliction.Strength < affliction.Prefab.ShowInHealthScannerThreshold || affliction.Strength <= 0.0f) continue;
+ if (affliction.Strength < affliction.Prefab.ActivationThreshold || affliction.Strength <= 0.0f) continue;
if (combinedAfflictionStrengths.ContainsKey(affliction.Prefab))
{
combinedAfflictionStrengths[affliction.Prefab] += affliction.Strength;
diff --git a/Barotrauma/BarotraumaClient/Source/Items/Components/Turret.cs b/Barotrauma/BarotraumaClient/Source/Items/Components/Turret.cs
index 6e42a2949..77f1b1a68 100644
--- a/Barotrauma/BarotraumaClient/Source/Items/Components/Turret.cs
+++ b/Barotrauma/BarotraumaClient/Source/Items/Components/Turret.cs
@@ -237,13 +237,13 @@ namespace Barotrauma.Items.Components
railSprite?.Draw(spriteBatch,
drawPos,
- item.SpriteColor,
+ Color.White,
rotation + MathHelper.PiOver2, item.Scale,
SpriteEffects.None, item.SpriteDepth + (railSprite.Depth - item.Sprite.Depth));
barrelSprite?.Draw(spriteBatch,
- drawPos - new Vector2((float)Math.Cos(rotation), (float)Math.Sin(rotation)) * recoilOffset * item.Scale,
- item.SpriteColor,
+ drawPos - new Vector2((float)Math.Cos(rotation), (float)Math.Sin(rotation)) * recoilOffset * item.Scale,
+ Color.White,
rotation + MathHelper.PiOver2, item.Scale,
SpriteEffects.None, item.SpriteDepth + (barrelSprite.Depth - item.Sprite.Depth));
@@ -288,10 +288,7 @@ namespace Barotrauma.Items.Components
availableAmmo.AddRange(itemContainer.Inventory.Items);
}
- float chargeRate =
- powerConsumption <= 0.0f ?
- 1.0f :
- batteryCapacity > 0.0f ? batteryCharge / batteryCapacity : 0.0f;
+ float chargeRate = powerConsumption <= 0.0f ? 1.0f : batteryCharge / batteryCapacity;
bool charged = batteryCharge * 3600.0f > powerConsumption;
bool readyToFire = reload <= 0.0f && charged && availableAmmo.Any(p => p != null);
if (ShowChargeIndicator && PowerConsumption > 0.0f)
diff --git a/Barotrauma/BarotraumaClient/Source/Items/Item.cs b/Barotrauma/BarotraumaClient/Source/Items/Item.cs
index 574b97e2e..40af52153 100644
--- a/Barotrauma/BarotraumaClient/Source/Items/Item.cs
+++ b/Barotrauma/BarotraumaClient/Source/Items/Item.cs
@@ -448,7 +448,7 @@ namespace Barotrauma
}
}
- public GUIComponent CreateEditingHUD(bool inGame = false)
+ private GUIComponent CreateEditingHUD(bool inGame = false)
{
editingHUD = new GUIFrame(new RectTransform(new Vector2(0.3f, 0.25f), GUI.Canvas, Anchor.CenterRight) { MinSize = new Point(400, 0) }) { UserData = this };
GUIListBox listBox = new GUIListBox(new RectTransform(new Vector2(0.95f, 0.8f), editingHUD.RectTransform, Anchor.Center), style: null)
@@ -457,38 +457,40 @@ namespace Barotrauma
};
var itemEditor = new SerializableEntityEditor(listBox.Content.RectTransform, this, inGame, showName: true);
- if (!inGame)
+
+ if (!inGame && Linkable)
{
- if (Linkable)
+ var linkText = new GUITextBlock(new RectTransform(new Point(editingHUD.Rect.Width, 20)), TextManager.Get("HoldToLink"), font: GUI.SmallFont);
+ var itemsText = new GUITextBlock(new RectTransform(new Point(editingHUD.Rect.Width, 20)), TextManager.Get("AllowedLinks") + ": ", font: GUI.SmallFont);
+ if (AllowedLinks.None())
{
- var linkText = new GUITextBlock(new RectTransform(new Point(editingHUD.Rect.Width, 20)), TextManager.Get("HoldToLink"), font: GUI.SmallFont);
- var itemsText = new GUITextBlock(new RectTransform(new Point(editingHUD.Rect.Width, 20)), TextManager.Get("AllowedLinks") + ": ", font: GUI.SmallFont);
- if (AllowedLinks.None())
+ itemsText.Text += TextManager.Get("None");
+ }
+ else
+ {
+ for (int i = 0; i < AllowedLinks.Count; i++)
{
- itemsText.Text += TextManager.Get("None");
- }
- else
- {
- for (int i = 0; i < AllowedLinks.Count; i++)
+ itemsText.Text += AllowedLinks[i];
+ if (i < AllowedLinks.Count - 1)
{
- itemsText.Text += AllowedLinks[i];
- if (i < AllowedLinks.Count - 1)
- {
- itemsText.Text += ", ";
- }
+ itemsText.Text += ", ";
}
}
- itemEditor.AddCustomContent(linkText, 1);
- itemEditor.AddCustomContent(itemsText, 2);
- linkText.TextColor = Color.Yellow;
- itemsText.TextColor = Color.Yellow;
}
+ itemEditor.AddCustomContent(linkText, 1);
+ itemEditor.AddCustomContent(itemsText, 2);
+ linkText.TextColor = Color.Yellow;
+ itemsText.TextColor = Color.Yellow;
+ }
+
+ if (!inGame)
+ {
var buttonContainer = new GUILayoutGroup(new RectTransform(new Point(listBox.Content.Rect.Width, 20)), isHorizontal: true)
{
Stretch = true,
RelativeSpacing = 0.02f
};
- new GUIButton(new RectTransform(new Vector2(0.23f, 1.0f), buttonContainer.RectTransform), TextManager.Get("MirrorEntityX"))
+ new GUIButton(new RectTransform(new Vector2(0.25f, 1.0f), buttonContainer.RectTransform), TextManager.Get("MirrorEntityX"))
{
ToolTip = TextManager.Get("MirrorEntityXToolTip"),
OnClicked = (button, data) =>
@@ -497,7 +499,7 @@ namespace Barotrauma
return true;
}
};
- new GUIButton(new RectTransform(new Vector2(0.23f, 1.0f), buttonContainer.RectTransform), TextManager.Get("MirrorEntityY"))
+ new GUIButton(new RectTransform(new Vector2(0.25f, 1.0f), buttonContainer.RectTransform), TextManager.Get("MirrorEntityY"))
{
ToolTip = TextManager.Get("MirrorEntityYToolTip"),
OnClicked = (button, data) =>
@@ -508,7 +510,7 @@ namespace Barotrauma
};
if (Sprite != null)
{
- var reloadTextureButton = new GUIButton(new RectTransform(new Vector2(0.23f, 1.0f), buttonContainer.RectTransform), TextManager.Get("ReloadSprite"));
+ var reloadTextureButton = new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), buttonContainer.RectTransform), TextManager.Get("ReloadSprite"));
reloadTextureButton.OnClicked += (button, data) =>
{
Sprite.ReloadXML();
@@ -516,15 +518,6 @@ namespace Barotrauma
return true;
};
}
- new GUIButton(new RectTransform(new Vector2(0.23f, 1.0f), buttonContainer.RectTransform), TextManager.Get("ResetToPrefab"))
- {
- OnClicked = (button, data) =>
- {
- Reset();
- CreateEditingHUD();
- return true;
- }
- };
itemEditor.AddCustomContent(buttonContainer, itemEditor.ContentCount);
}
diff --git a/Barotrauma/BarotraumaClient/Source/Map/Hull.cs b/Barotrauma/BarotraumaClient/Source/Map/Hull.cs
index 8dc7700f0..f295160c6 100644
--- a/Barotrauma/BarotraumaClient/Source/Map/Hull.cs
+++ b/Barotrauma/BarotraumaClient/Source/Map/Hull.cs
@@ -1,13 +1,14 @@
using Barotrauma.Networking;
using Barotrauma.Particles;
using Barotrauma.Sounds;
-using Lidgren.Network;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System;
using System.Collections.Generic;
+using Microsoft.Xna.Framework.Input;
using System.Linq;
+using Lidgren.Network;
namespace Barotrauma
{
@@ -18,8 +19,6 @@ namespace Barotrauma
private List decals = new List();
private float serverUpdateDelay;
- private float remoteWaterVolume, remoteOxygenPercentage;
- private List remoteFireSources;
private bool networkUpdatePending;
private float networkUpdateTimer;
@@ -140,10 +139,6 @@ namespace Barotrauma
partial void UpdateProjSpecific(float deltaTime, Camera cam)
{
serverUpdateDelay -= deltaTime;
- if (serverUpdateDelay <= 0.0f)
- {
- ApplyRemoteState();
- }
if (networkUpdatePending)
{
@@ -552,18 +547,18 @@ namespace Barotrauma
public void ClientRead(ServerNetObject type, NetBuffer message, float sendingTime)
{
- remoteWaterVolume = message.ReadRangedSingle(0.0f, 1.5f, 8) * Volume;
- remoteOxygenPercentage = message.ReadRangedSingle(0.0f, 100.0f, 8);
+ float newWaterVolume = message.ReadRangedSingle(0.0f, 1.5f, 8) * Volume;
+ float newOxygenPercentage = message.ReadRangedSingle(0.0f, 100.0f, 8);
bool hasFireSources = message.ReadBoolean();
int fireSourceCount = 0;
- remoteFireSources = new List();
+ List newFireSources = new List();
if (hasFireSources)
{
fireSourceCount = message.ReadRangedInteger(0, 16);
for (int i = 0; i < fireSourceCount; i++)
{
- remoteFireSources.Add(new Vector3(
+ newFireSources.Add(new Vector3(
MathHelper.Clamp(message.ReadRangedSingle(0.0f, 1.0f, 8), 0.05f, 0.95f),
MathHelper.Clamp(message.ReadRangedSingle(0.0f, 1.0f, 8), 0.05f, 0.95f),
message.ReadRangedSingle(0.0f, 1.0f, 8)));
@@ -572,6 +567,41 @@ namespace Barotrauma
if (serverUpdateDelay > 0.0f) { return; }
+ WaterVolume = newWaterVolume;
+ OxygenPercentage = newOxygenPercentage;
+
+ for (int i = 0; i < fireSourceCount; i++)
+ {
+ Vector2 pos = new Vector2(
+ rect.X + rect.Width * newFireSources[i].X,
+ rect.Y - rect.Height + (rect.Height * newFireSources[i].Y));
+ float size = newFireSources[i].Z * rect.Width;
+
+ var newFire = i < FireSources.Count ?
+ FireSources[i] :
+ new FireSource(Submarine == null ? pos : pos + Submarine.Position, null, true);
+ newFire.Position = pos;
+ newFire.Size = new Vector2(size, newFire.Size.Y);
+
+ //ignore if the fire wasn't added to this room (invalid position)?
+ if (!FireSources.Contains(newFire))
+ {
+ newFire.Remove();
+ continue;
+ }
+ }
+
+ for (int i = FireSources.Count - 1; i >= fireSourceCount; i--)
+ {
+ FireSources[i].Remove();
+ if (i < FireSources.Count)
+ {
+ FireSources.RemoveAt(i);
+ }
+ }
+
+ if (serverUpdateDelay > 0.0f) { return; }
+
ApplyRemoteState();
}
diff --git a/Barotrauma/BarotraumaClient/Source/Map/Lights/LightManager.cs b/Barotrauma/BarotraumaClient/Source/Map/Lights/LightManager.cs
index c61e3821d..49f40f3dd 100644
--- a/Barotrauma/BarotraumaClient/Source/Map/Lights/LightManager.cs
+++ b/Barotrauma/BarotraumaClient/Source/Map/Lights/LightManager.cs
@@ -404,15 +404,12 @@ namespace Barotrauma.Lights
}
}
if (highlightedEntities.Count == 0) { return false; }
-
- //draw characters in light blue first
+
+ //draw characters in solid white first
graphics.SetRenderTarget(HighlightMap);
SolidColorEffect.CurrentTechnique = SolidColorEffect.Techniques["SolidColor"];
SolidColorEffect.Parameters["color"].SetValue(Color.LightBlue.ToVector4());
SolidColorEffect.CurrentTechnique.Passes[0].Apply();
- DeformableSprite.Effect.CurrentTechnique = DeformableSprite.Effect.Techniques["DeformShaderSolidColor"];
- DeformableSprite.Effect.Parameters["solidColor"].SetValue(Color.LightBlue.ToVector4());
- DeformableSprite.Effect.CurrentTechnique.Passes[0].Apply();
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Additive, samplerState: SamplerState.LinearWrap, effect: SolidColorEffect, transformMatrix: spriteBatchTransform);
foreach (Entity highlighted in highlightedEntities)
{
@@ -429,12 +426,9 @@ namespace Barotrauma.Lights
//draw characters in black with a bit of blur, leaving the white edges visible
float phase = (float)(Math.Sin(Timing.TotalTime * 3.0f) + 1.0f) / 2.0f; //phase oscillates between 0 and 1
- Vector4 overlayColor = Color.Black.ToVector4() * MathHelper.Lerp(0.5f, 0.9f, phase);
- SolidColorEffect.Parameters["color"].SetValue(overlayColor);
+ SolidColorEffect.Parameters["color"].SetValue(Color.Black.ToVector4() * MathHelper.Lerp(0.5f, 0.9f, phase));
SolidColorEffect.CurrentTechnique = SolidColorEffect.Techniques["SolidColorBlur"];
SolidColorEffect.CurrentTechnique.Passes[0].Apply();
- DeformableSprite.Effect.Parameters["solidColor"].SetValue(overlayColor);
- DeformableSprite.Effect.CurrentTechnique.Passes[0].Apply();
spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, samplerState: SamplerState.LinearWrap, effect: SolidColorEffect, transformMatrix: spriteBatchTransform);
foreach (Entity highlighted in highlightedEntities)
{
@@ -456,8 +450,6 @@ namespace Barotrauma.Lights
spriteBatch.Draw(highlightRaster, new Rectangle(0, 0, HighlightMap.Width, HighlightMap.Height), new Rectangle(0, 0, HighlightMap.Width, HighlightMap.Height), Color.White * 0.5f);
spriteBatch.End();
- DeformableSprite.Effect.CurrentTechnique = DeformableSprite.Effect.Techniques["DeformShader"];
-
return true;
}
@@ -479,10 +471,6 @@ namespace Barotrauma.Lights
Level.Loaded?.Renderer?.RenderWalls(graphics, cam, specular: true);
- DeformableSprite.Effect.CurrentTechnique = DeformableSprite.Effect.Techniques["DeformShaderSolidColor"];
- DeformableSprite.Effect.Parameters["solidColor"].SetValue(Color.Gray.ToVector4());
- DeformableSprite.Effect.CurrentTechnique.Passes[0].Apply();
-
//obstruct specular maps behind the sub and characters by drawing them on the map in solid gray
SolidColorEffect.CurrentTechnique = SolidColorEffect.Techniques["SolidColor"];
SolidColorEffect.Parameters["color"].SetValue(Color.Gray.ToVector4());
@@ -499,9 +487,6 @@ namespace Barotrauma.Lights
}
spriteBatch.End();
-
- DeformableSprite.Effect.CurrentTechnique = DeformableSprite.Effect.Techniques["DeformShader"];
-
graphics.SetRenderTarget(null);
graphics.BlendState = BlendState.AlphaBlend;
}
diff --git a/Barotrauma/BarotraumaClient/Source/Map/Map/Map.cs b/Barotrauma/BarotraumaClient/Source/Map/Map/Map.cs
index 4abd51d76..83b5d1622 100644
--- a/Barotrauma/BarotraumaClient/Source/Map/Map/Map.cs
+++ b/Barotrauma/BarotraumaClient/Source/Map/Map/Map.cs
@@ -364,23 +364,15 @@ namespace Barotrauma
}
}
- if (GUI.KeyboardDispatcher.Subscriber == null)
- {
- float moveSpeed = 1000.0f;
- Vector2 moveAmount = Vector2.Zero;
- if (PlayerInput.KeyDown(InputType.Left)) { moveAmount += Vector2.UnitX; }
- if (PlayerInput.KeyDown(InputType.Right)) { moveAmount -= Vector2.UnitX; }
- if (PlayerInput.KeyDown(InputType.Up)) { moveAmount += Vector2.UnitY; }
- if (PlayerInput.KeyDown(InputType.Down)) { moveAmount -= Vector2.UnitY; }
- drawOffset += moveAmount * moveSpeed / zoom * deltaTime;
- }
-
if (GUI.MouseOn == mapContainer)
{
zoom += PlayerInput.ScrollWheelSpeed / 1000.0f;
zoom = MathHelper.Clamp(zoom, 1.0f, 4.0f);
- if (PlayerInput.MidButtonHeld()) { drawOffset += PlayerInput.MouseSpeed / zoom; }
+ if (PlayerInput.MidButtonHeld())
+ {
+ drawOffset += PlayerInput.MouseSpeed / zoom;
+ }
#if DEBUG
if (PlayerInput.DoubleClicked() && highlightedLocation != null)
{
@@ -559,6 +551,11 @@ namespace Barotrauma
null, connectionColor * MathHelper.Clamp(a, 0.1f, 0.5f), MathUtils.VectorToAngle(end - start),
new Vector2(0, 16), SpriteEffects.None, 0.01f);
}
+ }
+
+ rect.Inflate(8, 8);
+ GUI.DrawRectangle(spriteBatch, rect, Color.Black, false, 0.0f, 8);
+ GUI.DrawRectangle(spriteBatch, rect, Color.LightGray);
if (GameMain.DebugDraw && zoom > 1.0f && generationParams.ShowLevelTypeNames)
{
diff --git a/Barotrauma/BarotraumaClient/Source/Map/Structure.cs b/Barotrauma/BarotraumaClient/Source/Map/Structure.cs
index 8adc0b920..2edd1425c 100644
--- a/Barotrauma/BarotraumaClient/Source/Map/Structure.cs
+++ b/Barotrauma/BarotraumaClient/Source/Map/Structure.cs
@@ -98,7 +98,7 @@ namespace Barotrauma
Stretch = true,
RelativeSpacing = 0.02f
};
- new GUIButton(new RectTransform(new Vector2(0.23f, 1.0f), buttonContainer.RectTransform), TextManager.Get("MirrorEntityX"))
+ new GUIButton(new RectTransform(new Vector2(0.25f, 1.0f), buttonContainer.RectTransform), TextManager.Get("MirrorEntityX"))
{
ToolTip = TextManager.Get("MirrorEntityXToolTip"),
OnClicked = (button, data) =>
@@ -107,7 +107,7 @@ namespace Barotrauma
return true;
}
};
- new GUIButton(new RectTransform(new Vector2(0.23f, 1.0f), buttonContainer.RectTransform), TextManager.Get("MirrorEntityY"))
+ new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), buttonContainer.RectTransform), TextManager.Get("MirrorEntityY"))
{
ToolTip = TextManager.Get("MirrorEntityYToolTip"),
OnClicked = (button, data) =>
@@ -116,7 +116,7 @@ namespace Barotrauma
return true;
}
};
- var reloadTextureButton = new GUIButton(new RectTransform(new Vector2(0.23f, 1.0f), buttonContainer.RectTransform), TextManager.Get("ReloadSprite"))
+ var reloadTextureButton = new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), buttonContainer.RectTransform), TextManager.Get("ReloadSprite"))
{
OnClicked = (button, data) =>
{
@@ -125,15 +125,6 @@ namespace Barotrauma
return true;
}
};
- new GUIButton(new RectTransform(new Vector2(0.23f, 1.0f), buttonContainer.RectTransform), TextManager.Get("ResetToPrefab"))
- {
- OnClicked = (button, data) =>
- {
- Reset();
- CreateEditingHUD();
- return true;
- }
- };
editor.AddCustomContent(buttonContainer, editor.ContentCount);
PositionEditingHUD();
@@ -292,7 +283,8 @@ namespace Barotrauma
{
if (damageEffect != null)
{
- float newCutoff = MathHelper.Lerp(0.0f, 0.65f, Sections[i].damage / Prefab.Health);
+ float newCutoff = Sections[i].damage > 0 ?
+ MathHelper.Lerp(0.2f, 0.65f, Sections[i].damage / Prefab.Health) : 0.0f;
if (Math.Abs(newCutoff - Submarine.DamageEffectCutoff) > 0.01f || color != Submarine.DamageEffectColor)
{
@@ -359,7 +351,6 @@ namespace Barotrauma
-Bodies[i].Rotation, Color.White);
}
}
- AiTarget?.Draw(spriteBatch);
}
}
diff --git a/Barotrauma/BarotraumaClient/Source/Networking/GameClient.cs b/Barotrauma/BarotraumaClient/Source/Networking/GameClient.cs
index fdc0164cf..cc99a09f7 100644
--- a/Barotrauma/BarotraumaClient/Source/Networking/GameClient.cs
+++ b/Barotrauma/BarotraumaClient/Source/Networking/GameClient.cs
@@ -132,7 +132,6 @@ namespace Barotrauma.Networking
var buttonContainer = new GUILayoutGroup(HUDLayoutSettings.ToRectTransform(HUDLayoutSettings.ButtonAreaTop, inGameHUD.RectTransform),
isHorizontal: true, childAnchor: Anchor.CenterRight)
{
- AbsoluteSpacing = 5,
CanBeFocused = false
};
@@ -141,32 +140,16 @@ namespace Barotrauma.Networking
{
OnClicked = (btn, userdata) =>
{
- if (!permissions.HasFlag(ClientPermissions.ManageRound)) { return false; }
- if (!Submarine.MainSub.AtStartPosition && !Submarine.MainSub.AtEndPosition)
- {
- var msgBox = new GUIMessageBox("", TextManager.Get("EndRoundSubNotAtLevelEnd"),
- new string[] { TextManager.Get("Yes"), TextManager.Get("No") });
- msgBox.Buttons[0].OnClicked = (_, __) =>
- {
- GameMain.Client.RequestRoundEnd();
- return true;
- };
- msgBox.Buttons[0].OnClicked += msgBox.Close;
- msgBox.Buttons[1].OnClicked += msgBox.Close;
- }
- else
- {
- RequestRoundEnd();
- }
+ if (!permissions.HasFlag(ClientPermissions.ManageRound)) return false;
+ RequestRoundEnd();
return true;
},
Visible = false
};
- EndVoteTickBox = new GUITickBox(new RectTransform(new Vector2(0.1f, 0.4f), buttonContainer.RectTransform) { MinSize = new Point(150, 0) },
+ EndVoteTickBox = new GUITickBox(new RectTransform(new Vector2(0.1f, 0.6f), buttonContainer.RectTransform) { MinSize = new Point(150, 0) },
TextManager.Get("EndRound"))
{
- UserData = TextManager.Get("EndRound"),
OnSelected = ToggleEndRoundVote,
Visible = false
};
@@ -340,17 +323,18 @@ namespace Barotrauma.Networking
// Loop until we are approved
//TODO: show the name of the server instead of IP when connecting through the server list (more streamer-friendly)
- string connectingText = TextManager.Get("Connecting");
+ string connectingText = TextManager.Get("ConnectingTo").Replace("[serverip]", serverIP);
while (!CanStart && !connectCancelled)
{
if (reconnectBox == null)
{
- reconnectBox = new GUIMessageBox(connectingText, TextManager.Get("ConnectingTo").Replace("[serverip]", serverIP), new string[] { TextManager.Get("Cancel") });
+ reconnectBox = new GUIMessageBox(TextManager.Get("Connecting"), connectingText, new string[] { TextManager.Get("Cancel") });
+
reconnectBox.Buttons[0].OnClicked += CancelConnect;
reconnectBox.Buttons[0].OnClicked += reconnectBox.Close;
}
- reconnectBox.Header.Text = connectingText + new string('.', ((int)Timing.TotalTime % 3 + 1));
+ reconnectBox.Text.Text = connectingText + new string('.', ((int)Timing.TotalTime % 3 + 1));
if (DateTime.Now > reqAuthTime)
{
@@ -637,7 +621,7 @@ namespace Barotrauma.Networking
if (gameStarted) SetRadioButtonColor();
- if (ShowNetStats && client?.ServerConnection != null)
+ if (ShowNetStats)
{
netStats.AddValue(NetStats.NetStatType.ReceivedBytes, client.ServerConnection.Statistics.ReceivedBytes);
netStats.AddValue(NetStats.NetStatType.SentBytes, client.ServerConnection.Statistics.SentBytes);
@@ -798,7 +782,7 @@ namespace Barotrauma.Networking
saveFiles.Add(inc.ReadString());
}
- GameMain.NetLobbyScreen.CampaignSetupUI = MultiPlayerCampaign.StartCampaignSetup(serverSubmarines, saveFiles);
+ GameMain.NetLobbyScreen.CampaignSetupUI = MultiPlayerCampaign.StartCampaignSetup(saveFiles);
break;
case ServerPacketHeader.PERMISSIONS:
ReadPermissions(inc);
@@ -851,8 +835,6 @@ namespace Barotrauma.Networking
DisconnectReason disconnectReason = DisconnectReason.Unknown;
if (splitMsg.Length > 0) Enum.TryParse(splitMsg[0], out disconnectReason);
- DebugConsole.NewMessage("Received a disconnect message (" + disconnectMsg + ")");
-
if (disconnectReason == DisconnectReason.ServerFull)
{
//already waiting for a slot to free up, do nothing
@@ -882,6 +864,14 @@ namespace Barotrauma.Networking
waitInServerQueueBox = null;
CoroutineManager.StopCoroutines("WaitInServerQueue");
}
+ else
+ {
+ //disconnected/denied for some other reason than the server being full
+ // -> stop queuing and show a message box
+ waitInServerQueueBox?.Close();
+ waitInServerQueueBox = null;
+ CoroutineManager.StopCoroutines("WaitInServerQueue");
+ }
if (allowReconnect && disconnectReason == DisconnectReason.Unknown)
{
@@ -911,6 +901,25 @@ namespace Barotrauma.Networking
DebugConsole.NewMessage("Do not attempt to reconnect (DisconnectReason doesn't allow reconnection).");
msg = TextManager.Get("DisconnectReason." + disconnectReason.ToString());
+ if (allowReconnect && disconnectReason == DisconnectReason.Unknown)
+ {
+ reconnectBox = new GUIMessageBox(
+ TextManager.Get("ConnectionLost"),
+ TextManager.Get("ConnectionLostReconnecting"), new string[0]);
+ connected = false;
+ ConnectToServer(serverIP);
+ }
+ else
+ {
+ string msg = "";
+ if (disconnectReason == DisconnectReason.Unknown)
+ {
+ msg = disconnectMsg;
+ }
+ else
+ {
+ msg = TextManager.Get("DisconnectReason." + disconnectReason.ToString());
+
for (int i = 1; i < splitMsg.Length; i++)
{
msg += TextManager.GetServerMessage(splitMsg[i]);
@@ -1048,10 +1057,9 @@ namespace Barotrauma.Networking
EndVoteTickBox.Selected = false;
- int seed = inc.ReadInt32();
- string levelSeed = inc.ReadString();
- int levelEqualityCheckVal = inc.ReadInt32();
- float levelDifficulty = inc.ReadFloat();
+ int seed = inc.ReadInt32();
+ string levelSeed = inc.ReadString();
+ float levelDifficulty = inc.ReadFloat();
byte losMode = inc.ReadByte();
@@ -1120,15 +1128,6 @@ namespace Barotrauma.Networking
mirrorLevel: campaign.Map.CurrentLocation != campaign.Map.SelectedConnection.Locations[0]);
}
- if (Level.Loaded.EqualityCheckVal != levelEqualityCheckVal)
- {
- string errorMsg = "Level equality check failed. The level generated at your end doesn't match the level generated by the server (seed " + Level.Loaded.Seed + ").";
- DebugConsole.ThrowError(errorMsg, createMessageBox: true);
- GameAnalyticsManager.AddErrorEventOnce("GameClient.StartGame:LevelsDontMatch" + levelSeed, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
- CoroutineManager.StartCoroutine(EndGame(""));
- yield return CoroutineStatus.Failure;
- }
-
if (respawnAllowed) respawnManager = new RespawnManager(this, GameMain.NetLobbyScreen.UsingShuttle ? GameMain.NetLobbyScreen.SelectedShuttle : null);
gameStarted = true;
@@ -1198,8 +1197,8 @@ namespace Barotrauma.Networking
}
}
- GameMain.NetLobbyScreen.UpdateSubList(GameMain.NetLobbyScreen.SubList, serverSubmarines);
- GameMain.NetLobbyScreen.UpdateSubList(GameMain.NetLobbyScreen.ShuttleList.ListBox, serverSubmarines);
+ GameMain.NetLobbyScreen.UpdateSubList(GameMain.NetLobbyScreen.SubList, submarines);
+ GameMain.NetLobbyScreen.UpdateSubList(GameMain.NetLobbyScreen.ShuttleList.ListBox, submarines);
gameStarted = inc.ReadBoolean();
bool allowSpectating = inc.ReadBoolean();
@@ -1392,6 +1391,9 @@ namespace Barotrauma.Networking
case ServerNetObject.CLIENT_LIST:
ReadClientList(inc);
break;
+ case ServerNetObject.CLIENT_LIST:
+ ReadClientList(inc);
+ break;
case ServerNetObject.CHAT_MESSAGE:
ChatMessage.ClientRead(inc);
break;
@@ -1715,8 +1717,6 @@ namespace Barotrauma.Networking
SaveUtil.LoadGame(GameMain.GameSession.SavePath, GameMain.GameSession);
campaign.LastSaveID = campaign.PendingSaveID;
-
- DebugConsole.Log("Campaign save received, save ID " + campaign.LastSaveID);
//decrement campaign update ID so the server will send us the latest data
//(as there may have been campaign updates after the save file was created)
campaign.LastUpdateID--;
@@ -1734,7 +1734,7 @@ namespace Barotrauma.Networking
public override void CreateEntityEvent(INetSerializable entity, object[] extraData)
{
- if (!(entity is IClientSerializable)) throw new InvalidCastException("Entity is not IClientSerializable");
+ if (!(entity is IClientSerializable)) throw new InvalidCastException("entity is not IClientSerializable");
entityEventManager.CreateEvent(entity as IClientSerializable, extraData);
}
@@ -2003,8 +2003,7 @@ namespace Barotrauma.Networking
msg.Write(true); msg.WritePadBits();
msg.Write(savePath);
msg.Write(mapSeed);
- msg.Write(sub.Name);
- msg.Write(sub.MD5Hash.Hash);
+ msg.Write(sub.FilePath);
client.SendMessage(msg, NetDeliveryMethod.ReliableUnordered);
@@ -2242,25 +2241,13 @@ namespace Barotrauma.Networking
if (EndVoteCount > 0)
{
- if (EndVoteTickBox.Visible)
- {
- EndVoteTickBox.Text =
- (EndVoteTickBox.UserData as string) + " " + EndVoteCount + "/" + EndVoteMax;
- }
- else
- {
- string endVoteText = TextManager.Get("EndRoundVotes")
- .Replace("[votes]", EndVoteCount.ToString())
- .Replace("[max]", EndVoteMax.ToString());
- GUI.DrawString(spriteBatch, EndVoteTickBox.Rect.Center.ToVector2() - GUI.SmallFont.MeasureString(endVoteText) / 2,
- endVoteText,
- Color.White,
- font: GUI.SmallFont);
- }
- }
- else
- {
- EndVoteTickBox.Text = EndVoteTickBox.UserData as string;
+ string endVoteText = TextManager.Get("EndRoundVotes")
+ .Replace("[y]", EndVoteCount.ToString())
+ .Replace("[n]", (EndVoteMax - EndVoteCount).ToString());
+ GUI.DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth - 10.0f - GUI.SmallFont.MeasureString(endVoteText).X, 40),
+ endVoteText,
+ Color.White,
+ font: GUI.SmallFont);
}
if (respawnManager != null)
diff --git a/Barotrauma/BarotraumaClient/Source/Networking/Voip/VoipCapture.cs b/Barotrauma/BarotraumaClient/Source/Networking/Voip/VoipCapture.cs
index bd1df6c87..2f85beaf6 100644
--- a/Barotrauma/BarotraumaClient/Source/Networking/Voip/VoipCapture.cs
+++ b/Barotrauma/BarotraumaClient/Source/Networking/Voip/VoipCapture.cs
@@ -1,5 +1,4 @@
using Lidgren.Network;
-using Microsoft.Xna.Framework;
using OpenTK.Audio.OpenAL;
using System;
using System.Linq;
@@ -27,11 +26,6 @@ namespace Barotrauma.Networking
get;
private set;
}
-
- public float Gain
- {
- get { return GameMain.Config?.MicrophoneVolume ?? 1.0f; }
- }
public DateTime LastEnqueueAudio;
@@ -75,7 +69,6 @@ namespace Barotrauma.Networking
{
if (!GUIMessageBox.MessageBoxes.Any(mb => mb.UserData as string == "capturedevicenotfound"))
{
- GUI.SettingsMenuOpen = false;
new GUIMessageBox(TextManager.Get("Error"), TextManager.Get("VoipCaptureDeviceNotFound"))
{
UserData = "capturedevicenotfound"
@@ -167,9 +160,8 @@ namespace Barotrauma.Networking
double maxAmplitude = 0.0f;
for (int i = 0; i < VoipConfig.BUFFER_SIZE; i++)
{
- uncompressedBuffer[i] = (short)MathHelper.Clamp((uncompressedBuffer[i] * Gain), -short.MaxValue, short.MaxValue);
- double sampleVal = uncompressedBuffer[i] / (double)short.MaxValue;
- maxAmplitude = Math.Max(maxAmplitude, Math.Abs(sampleVal));
+ double sampleVal = (double)uncompressedBuffer[i] / (double)short.MaxValue;
+ maxAmplitude = Math.Max(maxAmplitude, Math.Abs(sampleVal));
}
double dB = Math.Min(20 * Math.Log10(maxAmplitude), 0.0);
diff --git a/Barotrauma/BarotraumaClient/Source/Physics/PhysicsBody.cs b/Barotrauma/BarotraumaClient/Source/Physics/PhysicsBody.cs
index f231c83a0..1fc27d949 100644
--- a/Barotrauma/BarotraumaClient/Source/Physics/PhysicsBody.cs
+++ b/Barotrauma/BarotraumaClient/Source/Physics/PhysicsBody.cs
@@ -150,10 +150,10 @@ namespace Barotrauma
float MaxAngularVel = NetConfig.MaxPhysicsBodyAngularVelocity;
Vector2 newPosition = SimPosition;
- float? newRotation = null;
+ float newRotation = Rotation;
bool awake = body.Awake;
Vector2 newVelocity = LinearVelocity;
- float? newAngularVelocity = null;
+ float newAngularVelocity = AngularVelocity;
newPosition = new Vector2(
msg.ReadFloat(),
@@ -179,12 +179,12 @@ namespace Barotrauma
msg.ReadPadBits();
if (!MathUtils.IsValid(newPosition) ||
+ !MathUtils.IsValid(newRotation) ||
!MathUtils.IsValid(newVelocity) ||
- (newRotation.HasValue && !MathUtils.IsValid(newRotation.Value)) ||
- (newAngularVelocity.HasValue && !MathUtils.IsValid(newAngularVelocity.Value)))
+ !MathUtils.IsValid(newAngularVelocity))
{
string errorMsg = "Received invalid position data for \"" + parentDebugName
- + "\" (position: " + newPosition + ", rotation: " + (newRotation ?? 0) + ", velocity: " + newVelocity + ", angular velocity: " + (newAngularVelocity ?? 0) + ")";
+ + "\" (position: " + newPosition + ", rotation: " + newRotation + ", velocity: " + newVelocity + ", angular velocity: " + newAngularVelocity + ")";
#if DEBUG
DebugConsole.ThrowError(errorMsg);
#endif
diff --git a/Barotrauma/BarotraumaClient/Source/Screens/CampaignSetupUI.cs b/Barotrauma/BarotraumaClient/Source/Screens/CampaignSetupUI.cs
index e36c3b0dc..5d85bdb0d 100644
--- a/Barotrauma/BarotraumaClient/Source/Screens/CampaignSetupUI.cs
+++ b/Barotrauma/BarotraumaClient/Source/Screens/CampaignSetupUI.cs
@@ -33,12 +33,12 @@ namespace Barotrauma
private readonly bool isMultiplayer;
- public CampaignSetupUI(bool isMultiplayer, GUIComponent newGameContainer, GUIComponent loadGameContainer, IEnumerable submarines, IEnumerable saveFiles = null)
+ public CampaignSetupUI(bool isMultiplayer, GUIComponent newGameContainer, GUIComponent loadGameContainer, IEnumerable saveFiles=null)
{
this.isMultiplayer = isMultiplayer;
this.newGameContainer = newGameContainer;
this.loadGameContainer = loadGameContainer;
-
+
var columnContainer = new GUILayoutGroup(new RectTransform(Vector2.One, newGameContainer.RectTransform), isHorizontal: true)
{
Stretch = true,
@@ -60,7 +60,7 @@ namespace Barotrauma
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.1f), leftColumn.RectTransform), TextManager.Get("SelectedSub") + ":", textAlignment: Alignment.BottomLeft);
subList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.65f), leftColumn.RectTransform));
- UpdateSubList(submarines);
+ UpdateSubList();
// New game right side
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.1f), rightColumn.RectTransform), TextManager.Get("SaveName") + ":", textAlignment: Alignment.BottomLeft);
@@ -87,8 +87,9 @@ namespace Barotrauma
return false;
}
- if (!(subList.SelectedData is Submarine selectedSub)) { return false; }
-
+ Submarine selectedSub = subList.SelectedData as Submarine;
+ if (selectedSub == null) return false;
+
if (string.IsNullOrEmpty(selectedSub.MD5Hash.Hash))
{
((GUITextBlock)subList.SelectedComponent).TextColor = Color.DarkRed * 0.8f;
@@ -195,9 +196,9 @@ namespace Barotrauma
public void UpdateSubList(IEnumerable submarines)
{
#if DEBUG
- var subsToShow = submarines.Where(s => !s.HasTag(SubmarineTag.HideInMenus));
+ var subsToShow = Submarine.SavedSubmarines.Where(s => !s.HasTag(SubmarineTag.HideInMenus));
#else
- var subsToShow = submarines;
+ var subsToShow = Submarine.SavedSubmarines;
#endif
subList.ClearChildren();
@@ -262,6 +263,11 @@ namespace Barotrauma
saveFiles = SaveUtil.GetSaveFiles(isMultiplayer ? SaveUtil.SaveType.Multiplayer : SaveUtil.SaveType.Singleplayer);
}
+ saveList = new GUIListBox(new RectTransform(new Vector2(0.5f, 1.0f), loadGameContainer.RectTransform, Anchor.CenterLeft))
+ {
+ OnSelected = SelectSaveFile
+ };
+
saveList = new GUIListBox(new RectTransform(new Vector2(0.5f, 1.0f), loadGameContainer.RectTransform, Anchor.CenterLeft))
{
OnSelected = SelectSaveFile
@@ -269,9 +275,7 @@ namespace Barotrauma
foreach (string saveFile in saveFiles)
{
- string fileName = saveFile;
- string subName = "";
- string saveTime = "";
+ XDocument doc = SaveUtil.LoadGameSessionDoc(saveFile);
var saveFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.1f), saveList.Content.RectTransform), style: "ListBoxElement")
{
UserData = saveFile
@@ -279,38 +283,25 @@ namespace Barotrauma
var nameText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), saveFrame.RectTransform),
text: Path.GetFileNameWithoutExtension(saveFile));
+ if (doc?.Root == null)
+ {
+ DebugConsole.ThrowError("Error loading save file \"" + saveFile + "\". The file may be corrupted.");
+ nameText.Color = Color.Red;
+ continue;
+ }
- if (!isMultiplayer)
- {
- XDocument doc = SaveUtil.LoadGameSessionDoc(saveFile);
- if (doc?.Root == null)
- {
- DebugConsole.ThrowError("Error loading save file \"" + saveFile + "\". The file may be corrupted.");
- nameText.Color = Color.Red;
- continue;
- }
- subName = doc.Root.GetAttributeString("submarine", "");
- saveTime = doc.Root.GetAttributeString("savetime", "");
- }
- else
- {
- string[] splitSaveFile = saveFile.Split(';');
- saveFrame.UserData = splitSaveFile[0];
- fileName = nameText.Text = Path.GetFileNameWithoutExtension(splitSaveFile[0]);
- if (splitSaveFile.Length > 1) { subName = splitSaveFile[1]; }
- if (splitSaveFile.Length > 2) { saveTime = splitSaveFile[2]; }
- }
-
+ string submarineName = doc.Root.GetAttributeString("submarine", "");
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), saveFrame.RectTransform, Anchor.BottomLeft),
- text: subName, font: GUI.SmallFont)
+ text: submarineName, font: GUI.SmallFont)
{
- UserData = fileName
+ UserData = saveFile
};
+ string saveTime = doc.Root.GetAttributeString("savetime", "");
new GUITextBlock(new RectTransform(new Vector2(1.0f, 1.0f), saveFrame.RectTransform),
text: saveTime, textAlignment: Alignment.Right, font: GUI.SmallFont)
{
- UserData = fileName
+ UserData = saveFile
};
}
diff --git a/Barotrauma/BarotraumaClient/Source/Screens/CampaignUI.cs b/Barotrauma/BarotraumaClient/Source/Screens/CampaignUI.cs
index 3c322d12d..12d87cf51 100644
--- a/Barotrauma/BarotraumaClient/Source/Screens/CampaignUI.cs
+++ b/Barotrauma/BarotraumaClient/Source/Screens/CampaignUI.cs
@@ -459,12 +459,6 @@ namespace Barotrauma
OnClicked = (GUIButton btn, object obj) => { StartRound?.Invoke(); return true; },
Enabled = true
};
- if (GameMain.Client != null)
- {
- startButton.Visible = !GameMain.Client.GameStarted &&
- (GameMain.Client.HasPermission(Networking.ClientPermissions.ManageRound) ||
- GameMain.Client.HasPermission(Networking.ClientPermissions.ManageCampaign));
- }
}
OnLocationSelected?.Invoke(location, connection);
@@ -508,13 +502,7 @@ namespace Barotrauma
CanBeFocused = false
};
- if (startButton != null)
- {
- startButton.Enabled = true;
- startButton.Visible = GameMain.Client == null ||
- GameMain.Client.HasPermission(Networking.ClientPermissions.ManageRound) ||
- GameMain.Client.HasPermission(Networking.ClientPermissions.ManageCampaign);
- }
+ if (startButton != null) { startButton.Enabled = true; }
}
private void CreateItemFrame(PurchasedItem pi, PriceInfo priceInfo, GUIListBox listBox, int width)
diff --git a/Barotrauma/BarotraumaClient/Source/Screens/CharacterEditorScreen.cs b/Barotrauma/BarotraumaClient/Source/Screens/CharacterEditorScreen.cs
index 0034810d7..48be1e5a0 100644
--- a/Barotrauma/BarotraumaClient/Source/Screens/CharacterEditorScreen.cs
+++ b/Barotrauma/BarotraumaClient/Source/Screens/CharacterEditorScreen.cs
@@ -118,19 +118,6 @@ namespace Barotrauma
instance = this;
}
- private void Reset()
- {
- AnimParams.ForEach(a => a.Reset(true));
- RagdollParams.Reset(true);
- RagdollParams.ClearHistory();
- CurrentAnimation.ClearHistory();
- if (!character.Removed)
- {
- character.Remove();
- }
- character = null;
- }
-
public override void Deselect()
{
base.Deselect();
@@ -141,7 +128,15 @@ namespace Barotrauma
isEndlessRunner = false;
if (character != null)
{
- Reset();
+ AnimParams.ForEach(a => a.Reset(true));
+ RagdollParams.Reset(true);
+ RagdollParams.ClearHistory();
+ CurrentAnimation.ClearHistory();
+ if (!character.Removed)
+ {
+ character.Remove();
+ }
+ character = null;
}
GameMain.World.ProcessChanges();
}
@@ -398,12 +393,6 @@ namespace Barotrauma
}
if (!isFreezed)
{
- if (character.AnimController.Invalid)
- {
- Reset();
- SpawnCharacter(currentCharacterConfig);
- }
-
Submarine.MainSub.SetPrevTransform(Submarine.MainSub.Position);
Submarine.MainSub.Update((float)deltaTime);
@@ -1226,7 +1215,7 @@ namespace Barotrauma
Cam.Position = character.WorldPosition;
}
- private bool CreateCharacter(string name, string mainFolder, bool isHumanoid, params object[] ragdollConfig)
+ private bool CreateCharacter(string name, bool isHumanoid, params object[] ragdollConfig)
{
var contentPackage = GameMain.Config.SelectedContentPackages.LastOrDefault();
if (contentPackage == null)
@@ -1245,16 +1234,17 @@ namespace Barotrauma
#endif
string speciesName = name;
+ string mainFolder = $"Content/Characters/{speciesName}";
// Config file
- string configFilePath = Path.Combine(mainFolder, $"{speciesName}.xml").Replace(@"\", @"/");
+ string configFilePath = $"{mainFolder}/{speciesName}.xml";
if (ContentPackage.GetFilesOfType(GameMain.SelectedPackages, ContentType.Character).None(path => path.Contains(speciesName)))
{
// Create the config file
XElement mainElement = new XElement("Character",
new XAttribute("name", speciesName),
new XAttribute("humanoid", isHumanoid),
- new XElement("ragdolls", new XAttribute("folder", Path.Combine(mainFolder, $"Ragdolls/").Replace(@"\", @"/"))),
- new XElement("animations", new XAttribute("folder", Path.Combine(mainFolder, $"Animations/").Replace(@"\", @"/"))),
+ new XElement("ragdolls"),
+ new XElement("animations"),
new XElement("health"),
new XElement("ai"));
XDocument doc = new XDocument(mainElement);
@@ -1269,13 +1259,13 @@ namespace Barotrauma
DebugConsole.NewMessage(GetCharacterEditorTranslation("ContentPackageSaved").Replace("[path]", contentPackage.Path));
}
// Ragdoll
- string ragdollFolder = RagdollParams.GetFolder(speciesName);
+ string ragdollFolder = RagdollParams.GetDefaultFolder(speciesName);
string ragdollPath = RagdollParams.GetDefaultFile(speciesName);
RagdollParams ragdollParams = isHumanoid
? RagdollParams.CreateDefault(ragdollPath, speciesName, ragdollConfig)
: RagdollParams.CreateDefault(ragdollPath, speciesName, ragdollConfig) as RagdollParams;
// Animations
- string animFolder = AnimationParams.GetFolder(speciesName);
+ string animFolder = AnimationParams.GetDefaultFolder(speciesName);
foreach (AnimationType animType in Enum.GetValues(typeof(AnimationType)))
{
if (animType != AnimationType.NotDefined)
@@ -4662,7 +4652,7 @@ namespace Barotrauma
LimbXElements.Values,
JointXElements
};
- if (CharacterEditorScreen.instance.CreateCharacter(Name, Path.GetDirectoryName(XMLPath), IsHumanoid, ragdollParams))
+ if (CharacterEditorScreen.instance.CreateCharacter(Name, IsHumanoid, ragdollParams))
{
GUI.AddMessage(GetCharacterEditorTranslation("CharacterCreated").Replace("[name]", Name), Color.Green, font: GUI.Font);
}
diff --git a/Barotrauma/BarotraumaClient/Source/Screens/MainMenuScreen.cs b/Barotrauma/BarotraumaClient/Source/Screens/MainMenuScreen.cs
index c46668705..091909577 100644
--- a/Barotrauma/BarotraumaClient/Source/Screens/MainMenuScreen.cs
+++ b/Barotrauma/BarotraumaClient/Source/Screens/MainMenuScreen.cs
@@ -282,7 +282,7 @@ namespace Barotrauma
menuTabs[(int)Tab.LoadGame] = new GUIFrame(new RectTransform(relativeSize, GUI.Canvas, anchor, pivot, minSize, maxSize));
var paddedLoadGame = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.9f), menuTabs[(int)Tab.LoadGame].RectTransform, Anchor.Center), style: null);
- campaignSetupUI = new CampaignSetupUI(false, paddedNewGame, paddedLoadGame, Submarine.SavedSubmarines)
+ campaignSetupUI = new CampaignSetupUI(false, paddedNewGame, paddedLoadGame)
{
LoadGame = LoadGame,
StartNewGame = StartGame
@@ -336,7 +336,7 @@ namespace Barotrauma
UpdateTutorialList();
- campaignSetupUI.UpdateSubList(Submarine.SavedSubmarines);
+ campaignSetupUI.UpdateSubList();
ResetButtonStates(null);
diff --git a/Barotrauma/BarotraumaClient/Source/Screens/NetLobbyScreen.cs b/Barotrauma/BarotraumaClient/Source/Screens/NetLobbyScreen.cs
index 8c1472305..c8882034b 100644
--- a/Barotrauma/BarotraumaClient/Source/Screens/NetLobbyScreen.cs
+++ b/Barotrauma/BarotraumaClient/Source/Screens/NetLobbyScreen.cs
@@ -632,13 +632,6 @@ namespace Barotrauma
Visible = false
};
- campaignViewButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.1f), rightInfoColumn.RectTransform),
- TextManager.Get("CampaignView"), style: "GUIButtonLarge")
- {
- OnClicked = (btn, obj) => { ToggleCampaignView(true); return true; },
- Visible = false
- };
-
StartButton = new GUIButton(new RectTransform(new Vector2(0.3f, 0.1f), infoFrameContent.RectTransform, Anchor.BottomRight),
TextManager.Get("StartGameButton"), style: "GUIButtonLarge")
{
@@ -651,6 +644,13 @@ namespace Barotrauma
};
clientHiddenElements.Add(StartButton);
+ campaignViewButton = new GUIButton(new RectTransform(new Vector2(0.3f, 0.1f), infoFrameContent.RectTransform, Anchor.BottomRight) { RelativeOffset = new Vector2(0.0f, 0.06f) },
+ TextManager.Get("CampaignView"), style: "GUIButtonLarge")
+ {
+ OnClicked = (btn, obj) => { ToggleCampaignView(true); return true; },
+ Visible = false
+ };
+
spectateButton = new GUIButton(new RectTransform(new Vector2(0.3f, 0.1f), infoFrameContent.RectTransform, Anchor.BottomRight),
TextManager.Get("SpectateButton"), style: "GUIButtonLarge");
}
@@ -726,12 +726,6 @@ namespace Barotrauma
spectateButton.Visible = GameMain.Client.GameStarted;
ReadyToStartBox.Visible = !GameMain.Client.GameStarted;
ReadyToStartBox.Selected = false;
- if (campaignUI?.StartButton != null)
- {
- campaignUI.StartButton.Visible = !GameMain.Client.GameStarted &&
- (GameMain.Client.HasPermission(ClientPermissions.ManageRound) ||
- GameMain.Client.HasPermission(ClientPermissions.ManageCampaign));
- }
GameMain.Client.SetReadyToStart(ReadyToStartBox);
}
else
@@ -850,13 +844,6 @@ namespace Barotrauma
GameMain.Client.ShowLogButton.Visible = GameMain.Client.HasPermission(ClientPermissions.ServerLog);
GameMain.Client.EndRoundButton.Visible = GameMain.Client.HasPermission(ClientPermissions.ManageRound);
-
- if (campaignUI?.StartButton != null)
- {
- campaignUI.StartButton.Visible = !GameMain.Client.GameStarted &&
- (GameMain.Client.HasPermission(ClientPermissions.ManageRound) ||
- GameMain.Client.HasPermission(ClientPermissions.ManageCampaign));
- }
}
public void ShowSpectateButton()
@@ -866,21 +853,18 @@ namespace Barotrauma
spectateButton.Enabled = true;
}
- public void SetCampaignCharacterInfo(CharacterInfo newCampaignCharacterInfo)
- {
- if (newCampaignCharacterInfo != null)
+ public void SetCampaignCharacterInfo(CharacterInfo characterInfo)
+ {
+ if (CampaignCharacterDiscarded) return;
+
+ campaignCharacterInfo = characterInfo;
+ if (campaignCharacterInfo != null)
{
- if (CampaignCharacterDiscarded) { return; }
- if (campaignCharacterInfo != newCampaignCharacterInfo)
- {
- campaignCharacterInfo = newCampaignCharacterInfo;
- UpdatePlayerFrame(campaignCharacterInfo, false);
- }
+ UpdatePlayerFrame(campaignCharacterInfo, false);
}
- else if (campaignCharacterInfo != null)
+ else
{
- campaignCharacterInfo = null;
- UpdatePlayerFrame(campaignCharacterInfo, false);
+ UpdatePlayerFrame(null, true);
}
}
@@ -1207,7 +1191,7 @@ namespace Barotrauma
if (sub.HasTag(SubmarineTag.Shuttle))
{
- new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), frame.RectTransform, Anchor.CenterRight) { RelativeOffset = new Vector2(0.1f, 0.0f) },
+ new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), frame.RectTransform, Anchor.CenterRight),
TextManager.Get("Shuttle"), textAlignment: Alignment.CenterRight, font: GUI.SmallFont)
{
TextColor = subTextBlock.TextColor * 0.8f,
diff --git a/Barotrauma/BarotraumaClient/Source/Screens/ServerListScreen.cs b/Barotrauma/BarotraumaClient/Source/Screens/ServerListScreen.cs
index 3fa7dcc26..aca7905bb 100644
--- a/Barotrauma/BarotraumaClient/Source/Screens/ServerListScreen.cs
+++ b/Barotrauma/BarotraumaClient/Source/Screens/ServerListScreen.cs
@@ -716,7 +716,7 @@ namespace Barotrauma
catch (PingException ex)
{
string errorMsg = "Failed to ping a server (" + serverInfo.ServerName + ", " + serverInfo.IP + ") - " + (ex?.InnerException?.Message ?? ex.Message);
- GameAnalyticsManager.AddErrorEventOnce("ServerListScreen.PingServer:PingException" + serverInfo.IP, GameAnalyticsSDK.Net.EGAErrorSeverity.Warning, errorMsg);
+ GameAnalyticsManager.AddErrorEventOnce("ServerListScreen.PingServer:PingException" + serverInfo.IP, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
#if DEBUG
DebugConsole.NewMessage(errorMsg, Color.Red);
#endif
diff --git a/Barotrauma/BarotraumaClient/Source/Screens/SubEditorScreen.cs b/Barotrauma/BarotraumaClient/Source/Screens/SubEditorScreen.cs
index fb95c2152..7ac15f8d0 100644
--- a/Barotrauma/BarotraumaClient/Source/Screens/SubEditorScreen.cs
+++ b/Barotrauma/BarotraumaClient/Source/Screens/SubEditorScreen.cs
@@ -564,9 +564,6 @@ namespace Barotrauma
MapEntityPrefab.Selected = null;
- saveFrame = null;
- loadFrame = null;
-
MapEntity.DeselectAll();
MapEntity.SelectionGroups.Clear();
@@ -2043,10 +2040,6 @@ namespace Barotrauma
dummyCharacter.SelectedConstruction = null;
}
}
- else if (MapEntity.SelectedList.Count == 1)
- {
- (MapEntity.SelectedList[0] as Item)?.UpdateHUD(cam, dummyCharacter, (float)deltaTime);
- }
CharacterHUD.Update((float)deltaTime, dummyCharacter, cam);
}
diff --git a/Barotrauma/BarotraumaClient/Source/Sprite/DeformableSprite.cs b/Barotrauma/BarotraumaClient/Source/Sprite/DeformableSprite.cs
index 54f33dbb6..860522283 100644
--- a/Barotrauma/BarotraumaClient/Source/Sprite/DeformableSprite.cs
+++ b/Barotrauma/BarotraumaClient/Source/Sprite/DeformableSprite.cs
@@ -26,10 +26,6 @@ namespace Barotrauma
private int subDivX, subDivY;
private static Effect effect;
- public static Effect Effect
- {
- get { return effect; }
- }
private Point spritePos;
private Point spriteSize;
diff --git a/Barotrauma/BarotraumaServer/Properties/AssemblyInfo.cs b/Barotrauma/BarotraumaServer/Properties/AssemblyInfo.cs
index 1a54bc6aa..eb0a60828 100644
--- a/Barotrauma/BarotraumaServer/Properties/AssemblyInfo.cs
+++ b/Barotrauma/BarotraumaServer/Properties/AssemblyInfo.cs
@@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("0.8.9.7")]
-[assembly: AssemblyFileVersion("0.8.9.7")]
+[assembly: AssemblyVersion("0.8.9.6")]
+[assembly: AssemblyFileVersion("0.8.9.6")]
diff --git a/Barotrauma/BarotraumaServer/Source/Characters/CharacterInfo.cs b/Barotrauma/BarotraumaServer/Source/Characters/CharacterInfo.cs
index 29f5bade5..a7e0d681b 100644
--- a/Barotrauma/BarotraumaServer/Source/Characters/CharacterInfo.cs
+++ b/Barotrauma/BarotraumaServer/Source/Characters/CharacterInfo.cs
@@ -4,6 +4,11 @@ namespace Barotrauma
{
partial class CharacterInfo
{
+ partial void SpawnInventoryItemProjSpecific(Item item)
+ {
+ Entity.Spawner.CreateNetworkEvent(item, false);
+ }
+
public void ServerWrite(NetBuffer msg)
{
msg.Write(ID);
diff --git a/Barotrauma/BarotraumaServer/Source/DebugConsole.cs b/Barotrauma/BarotraumaServer/Source/DebugConsole.cs
index 1dd05bae8..18a8733c4 100644
--- a/Barotrauma/BarotraumaServer/Source/DebugConsole.cs
+++ b/Barotrauma/BarotraumaServer/Source/DebugConsole.cs
@@ -81,12 +81,11 @@ namespace Barotrauma
//dequeue messages
lock (queuedMessages)
{
- if (queuedMessages.Count > 0)
+ if (queuedMessages.Count>0)
{
- int inputLines = Math.Max((int)Math.Ceiling(input.Length / (float)Console.WindowWidth), 1);
Console.CursorLeft = 0;
Console.Write(new string(' ', consoleWidth));
- Console.CursorTop -= inputLines; Console.CursorLeft = 0;
+ Console.CursorTop--; Console.CursorLeft = 0;
while (queuedMessages.Count > 0)
{
ColoredText msg = queuedMessages.Dequeue();
@@ -178,11 +177,11 @@ namespace Barotrauma
private static void RewriteInputToCommandLine(string input)
{
- int consoleWidth = Math.Max(Console.WindowWidth, 5);
- int inputLines = Math.Max((int)Math.Ceiling(input.Length / (float)consoleWidth), 1);
- int cursorLine = Math.Max((int)Math.Ceiling((input.Length + 1) / (float)consoleWidth), 1);
-
- Console.WriteLine(""); Console.CursorTop -= inputLines;
+ Console.WriteLine(""); Console.CursorTop--;
+ int consoleWidth = Console.WindowWidth;
+ if (consoleWidth < 5) consoleWidth = 5;
+ int consoleHeight = Console.WindowHeight;
+ if (consoleHeight < 5) consoleHeight = 5;
string ln = input.Length > 0 ? AutoComplete(input, 0) : "";
ln += new string(' ', consoleWidth - (ln.Length % consoleWidth));
@@ -191,9 +190,9 @@ namespace Barotrauma
Console.Write(ln);
Console.ForegroundColor = ConsoleColor.White;
Console.CursorLeft = 0;
- Console.CursorTop -= cursorLine;
+ Console.CursorTop--;
Console.Write(input);
- Console.CursorLeft = input.Length % Console.WindowWidth;
+ Console.CursorLeft = input.Length;
}
private static void AssignOnClientRequestExecute(string names, Action onClientRequestExecute)
@@ -1555,9 +1554,9 @@ namespace Barotrauma
}));
#if DEBUG
- commands.Add(new Command("spamevents", "A debug command that creates a ton of entity events.", (string[] args) =>
+ commands.Add(new Command("spamevents", "A debug command that immediately creates entity events for all items, characters and structures.", (string[] args) =>
{
- /*foreach (Item item in Item.ItemList)
+ foreach (Item item in Item.ItemList)
{
foreach (ItemComponent component in item.Components)
{
@@ -1574,18 +1573,16 @@ namespace Barotrauma
GameMain.Server.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.Status });
}
}
+
foreach (Character c in Character.CharacterList)
{
GameMain.Server.CreateEntityEvent(c, new object[] { NetEntityEvent.Type.Status });
- }*/
- foreach (Hull hull in Hull.hullList)
- {
- GameMain.Server.CreateEntityEvent(hull);
}
+
foreach (Structure wall in Structure.WallList)
{
GameMain.Server.CreateEntityEvent(wall);
- }
+ }
}));
#endif
}
diff --git a/Barotrauma/BarotraumaServer/Source/GameSession/GameModes/MultiPlayerCampaign.cs b/Barotrauma/BarotraumaServer/Source/GameSession/GameModes/MultiPlayerCampaign.cs
index 0e1667db4..0656ea051 100644
--- a/Barotrauma/BarotraumaServer/Source/GameSession/GameModes/MultiPlayerCampaign.cs
+++ b/Barotrauma/BarotraumaServer/Source/GameSession/GameModes/MultiPlayerCampaign.cs
@@ -11,11 +11,11 @@ namespace Barotrauma
{
private List characterData = new List();
- public static void StartNewCampaign(string savePath, string subPath, string seed)
+ public static void StartNewCampaign(string savePath, string subName, string seed)
{
if (string.IsNullOrWhiteSpace(savePath)) return;
- GameMain.GameSession = new GameSession(new Submarine(subPath, ""), savePath,
+ GameMain.GameSession = new GameSession(new Submarine(subName, ""), savePath,
GameModePreset.List.Find(g => g.Identifier == "multiplayercampaign"));
var campaign = ((MultiPlayerCampaign)GameMain.GameSession.GameMode);
campaign.GenerateMap(seed);
@@ -72,27 +72,6 @@ namespace Barotrauma
});
}
- public bool AllowedToEndRound(Character interactor)
- {
- if (interactor == null || Level.Loaded?.StartOutpost == null || Level.Loaded?.EndOutpost == null)
- {
- return false;
- }
-
- if (interactor.Submarine == Level.Loaded.StartOutpost &&
- interactor.CanInteractWith(startWatchman))
- {
- return true;
- }
- if (interactor.Submarine == Level.Loaded.EndOutpost &&
- interactor.CanInteractWith(endWatchman))
- {
- return true;
- }
-
- return false;
- }
-
protected override void WatchmanInteract(Character watchman, Character interactor)
{
if ((watchman.Submarine == Level.Loaded.StartOutpost && !Submarine.MainSub.AtStartPosition) ||
@@ -106,7 +85,8 @@ namespace Barotrauma
if (GameMain.Server != null)
{
var client = GameMain.Server.ConnectedClients.Find(c => c.Character == interactor);
- hasPermissions = client != null;
+ hasPermissions = client != null &&
+ (client.HasPermission(ClientPermissions.ManageRound) || client.HasPermission(ClientPermissions.ManageCampaign));
CreateDialog(new List { watchman }, hasPermissions ? "WatchmanInteract" : "WatchmanInteractNotAllowed", 1.0f);
}
}
@@ -251,7 +231,6 @@ namespace Barotrauma
}
lastSaveID++;
- DebugConsole.Log("Campaign saved, save ID " + lastSaveID);
}
}
}
diff --git a/Barotrauma/BarotraumaServer/Source/Items/Components/Repairable.cs b/Barotrauma/BarotraumaServer/Source/Items/Components/Repairable.cs
index 7bf36f0f8..04ca33c0d 100644
--- a/Barotrauma/BarotraumaServer/Source/Items/Components/Repairable.cs
+++ b/Barotrauma/BarotraumaServer/Source/Items/Components/Repairable.cs
@@ -1,5 +1,9 @@
using Barotrauma.Networking;
-using Lidgren.Network;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
namespace Barotrauma.Items.Components
{
@@ -10,16 +14,5 @@ namespace Barotrauma.Items.Components
//let the clients know the initial deterioration delay
item.CreateServerEvent(this);
}
-
- public void ServerRead(ClientNetObject type, NetBuffer msg, Client c)
- {
- if (c.Character == null) return;
- StartRepairing(c.Character);
- }
-
- public void ServerWrite(NetBuffer msg, Client c, object[] extraData = null)
- {
- msg.Write(deteriorationTimer);
- }
}
}
diff --git a/Barotrauma/BarotraumaServer/Source/Items/Item.cs b/Barotrauma/BarotraumaServer/Source/Items/Item.cs
index beb831abf..5f88e71eb 100644
--- a/Barotrauma/BarotraumaServer/Source/Items/Item.cs
+++ b/Barotrauma/BarotraumaServer/Source/Items/Item.cs
@@ -335,14 +335,6 @@ namespace Barotrauma
{
if (GameMain.Server == null) return;
- if (!ItemList.Contains(this))
- {
- string errorMsg = "Attempted to create a network event for an item (" + Name + ") that hasn't been fully initialized yet.";
- DebugConsole.ThrowError(errorMsg);
- GameAnalyticsManager.AddErrorEventOnce("Item.CreateServerEvent:EventForUninitializedItem" + Name + ID, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
- return;
- }
-
int index = components.IndexOf(ic);
if (index == -1) return;
diff --git a/Barotrauma/BarotraumaServer/Source/Map/Hull.cs b/Barotrauma/BarotraumaServer/Source/Map/Hull.cs
index 3b10a7a24..907ba6f45 100644
--- a/Barotrauma/BarotraumaServer/Source/Map/Hull.cs
+++ b/Barotrauma/BarotraumaServer/Source/Map/Hull.cs
@@ -20,16 +20,6 @@ namespace Barotrauma
partial void UpdateProjSpecific(float deltaTime, Camera cam)
{
if (IdFreed) { return; }
-
- //don't create updates if all clients are very far from the hull
- float hullUpdateDistanceSqr = NetConfig.HullUpdateDistance * NetConfig.HullUpdateDistance;
- if (!GameMain.Server.ConnectedClients.Any(c =>
- c.Character != null &&
- Vector2.DistanceSquared(c.Character.WorldPosition, WorldPosition) < hullUpdateDistanceSqr))
- {
- return;
- }
-
//update client hulls if the amount of water has changed by >10%
//or if oxygen percentage has changed by 5%
if (Math.Abs(lastSentVolume - waterVolume) > Volume * 0.1f ||
@@ -41,8 +31,8 @@ namespace Barotrauma
GameMain.NetworkMember.CreateEntityEvent(this);
lastSentVolume = waterVolume;
lastSentOxygen = OxygenPercentage;
- sendUpdateTimer = NetConfig.HullUpdateInterval;
- }
+ sendUpdateTimer = NetworkUpdateInterval;
+ }
}
}
diff --git a/Barotrauma/BarotraumaServer/Source/Networking/Client.cs b/Barotrauma/BarotraumaServer/Source/Networking/Client.cs
index 28e291e39..78ff44d7a 100644
--- a/Barotrauma/BarotraumaServer/Source/Networking/Client.cs
+++ b/Barotrauma/BarotraumaServer/Source/Networking/Client.cs
@@ -46,7 +46,7 @@ namespace Barotrauma.Networking
//when was a specific entity event last sent to the client
// key = event id, value = NetTime.Now when sending
- public readonly Dictionary EntityEventLastSent = new Dictionary();
+ public readonly Dictionary EntityEventLastSent = new Dictionary();
//when was a position update for a given entity last sent to the client
// key = entity id, value = NetTime.Now when sending
diff --git a/Barotrauma/BarotraumaServer/Source/Networking/FileTransfer/FileSender.cs b/Barotrauma/BarotraumaServer/Source/Networking/FileTransfer/FileSender.cs
index 88ad64ba2..2303577e9 100644
--- a/Barotrauma/BarotraumaServer/Source/Networking/FileTransfer/FileSender.cs
+++ b/Barotrauma/BarotraumaServer/Source/Networking/FileTransfer/FileSender.cs
@@ -187,7 +187,7 @@ namespace Barotrauma.Networking
transfer.WaitTimer -= deltaTime;
if (transfer.WaitTimer > 0.0f) continue;
- if (!transfer.Connection.CanSendImmediately(NetDeliveryMethod.ReliableOrdered, transfer.SequenceChannel)) continue;
+ if (!transfer.Connection.CanSendImmediately(NetDeliveryMethod.ReliableOrdered, 1)) continue;
transfer.WaitTimer = 0.05f;// transfer.Connection.AverageRoundtripTime;
@@ -202,6 +202,15 @@ namespace Barotrauma.Networking
{
message = peer.CreateMessage();
message.Write((byte)ServerPacketHeader.FILE_TRANSFER);
+ message.Write((byte)FileTransferMessageType.Initiate);
+ message.Write((byte)transfer.FileType);
+ message.Write((ushort)chunkLen);
+ message.Write((ulong)transfer.Data.Length);
+ message.Write(transfer.FileName);
+ GameMain.Server.CompressOutgoingMessage(message);
+ transfer.Connection.SendMessage(message, NetDeliveryMethod.ReliableOrdered, transfer.SequenceChannel);
+
+ transfer.Status = FileTransferStatus.Sending;
//if the recipient is the owner of the server (= a client running the server from the main exe)
//we don't need to send anything, the client can just read the file directly
diff --git a/Barotrauma/BarotraumaServer/Source/Networking/GameServer.cs b/Barotrauma/BarotraumaServer/Source/Networking/GameServer.cs
index d99e30c5f..6ae2167ec 100644
--- a/Barotrauma/BarotraumaServer/Source/Networking/GameServer.cs
+++ b/Barotrauma/BarotraumaServer/Source/Networking/GameServer.cs
@@ -10,7 +10,6 @@ using System.Text;
using System.IO.Compression;
using System.IO;
using Barotrauma.Steam;
-using System.Xml.Linq;
namespace Barotrauma.Networking
{
@@ -44,7 +43,6 @@ namespace Barotrauma.Networking
private IRestResponse masterServerResponse;
private bool autoRestartTimerRunning;
- private float endRoundTimer;
public VoipServer VoipServer
{
@@ -407,38 +405,20 @@ namespace Barotrauma.Networking
}
}
- if (isCrewDead && respawnManager == null)
- {
- if (endRoundTimer <= 0.0f)
- {
- SendChatMessage(TextManager.Get("CrewDeadNoRespawns").Replace("[time]", "60"), ChatMessageType.Server);
- }
- endRoundTimer += deltaTime;
- }
- else
- {
- endRoundTimer = 0.0f;
- }
-
//restart if all characters are dead or submarine is at the end of the level
if ((serverSettings.AutoRestart && isCrewDead)
||
- (serverSettings.EndRoundAtLevelEnd && subAtLevelEnd)
- ||
- (isCrewDead && respawnManager == null && endRoundTimer >= 60.0f))
+ (serverSettings.EndRoundAtLevelEnd && subAtLevelEnd))
{
if (serverSettings.AutoRestart && isCrewDead)
{
Log("Ending round (entire crew dead)", ServerLog.MessageType.ServerMessage);
}
- else if (serverSettings.EndRoundAtLevelEnd && subAtLevelEnd)
+ else
{
Log("Ending round (submarine reached the end of the level)", ServerLog.MessageType.ServerMessage);
}
- else
- {
- Log("Ending round (no living players left and respawning is not enabled during this round)", ServerLog.MessageType.ServerMessage);
- }
+
EndGame();
return;
}
@@ -717,24 +697,13 @@ namespace Barotrauma.Networking
string savePath = inc.ReadString();
string seed = inc.ReadString();
string subName = inc.ReadString();
- string subHash = inc.ReadString();
- var matchingSub = Submarine.SavedSubmarines.FirstOrDefault(s => s.Name == subName && s.MD5Hash.Hash == subHash);
-
- if (matchingSub == null)
- {
- SendDirectChatMessage(
- TextManager.Get("CampaignStartFailedSubNotFound").Replace("[subname]", subName),
- connectedClient, ChatMessageType.MessageBox);
- }
- else
- {
- if (connectedClient.HasPermission(ClientPermissions.SelectMode)) MultiPlayerCampaign.StartNewCampaign(savePath, matchingSub.FilePath, seed);
- }
- }
+ if (connectedClient.HasPermission(ClientPermissions.SelectMode)) MultiPlayerCampaign.StartNewCampaign(savePath, subName, seed);
+ }
else
{
string saveName = inc.ReadString();
+
if (connectedClient.HasPermission(ClientPermissions.SelectMode)) MultiPlayerCampaign.LoadCampaign(saveName);
}
break;
@@ -765,64 +734,6 @@ namespace Barotrauma.Networking
fileSender.ReadFileRequest(inc, connectedClient);
}
break;
- case ClientPacketHeader.ERROR:
- HandleClientError(inc, connectedClient);
- break;
- }
- }
-
- private void HandleClientError(NetIncomingMessage inc, Client c)
- {
- string errorStr = "Unhandled error report";
-
- ClientNetError error = (ClientNetError)inc.ReadByte();
- int levelEqualityCheckVal = inc.ReadInt32();
- switch (error)
- {
- case ClientNetError.MISSING_EVENT:
- UInt16 expectedID = inc.ReadUInt16();
- UInt16 receivedID = inc.ReadUInt16();
- errorStr = "Expecting event id " + expectedID.ToString() + ", received " + receivedID.ToString();
- break;
- case ClientNetError.MISSING_ENTITY:
- UInt16 eventID = inc.ReadUInt16();
- UInt16 entityID = inc.ReadUInt16();
- Entity entity = Entity.FindEntityByID(entityID);
- if (entity == null)
- {
- errorStr = "Received an update for an entity that doesn't exist (event id " + eventID.ToString() + ", entity id " + entityID.ToString() + ").";
- }
- else if (entity is Character character)
- {
- errorStr = "Missing character " + character.Name + " (event id " + eventID.ToString() + ", entity id " + entityID.ToString() + ").";
- }
- else if (entity is Item item)
- {
- errorStr = "Missing item " + item.Name + " (event id " + eventID.ToString() + ", entity id " + entityID.ToString() + ").";
- }
- else
- {
- errorStr = "Missing entity " + entity.ToString() + " (event id " + eventID.ToString() + ", entity id " + entityID.ToString() + ").";
- }
- break;
- }
-
- if (Level.Loaded != null && levelEqualityCheckVal != Level.Loaded.EqualityCheckVal)
- {
- errorStr += " Level equality check failed. The level generated at your end doesn't match the level generated by the server (seed " + Level.Loaded.Seed + ").";
- }
-
- Log(c.Name + " has reported an error: " + errorStr, ServerLog.MessageType.Error);
- GameAnalyticsManager.AddErrorEventOnce("GameServer.HandleClientError:LevelsDontMatch" + error, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorStr);
-
- if (c.Connection == OwnerConnection)
- {
- SendDirectChatMessage(errorStr, c, ChatMessageType.MessageBox);
- EndGame();
- }
- else
- {
- KickClient(c, errorStr);
}
}
@@ -880,8 +791,8 @@ namespace Barotrauma.Networking
//(the server started a new campaign and the client isn't aware of it yet?)
if (campaign.CampaignID != campaignID)
{
- c.LastRecvCampaignSave = (ushort)(campaign.LastSaveID - 1);
- c.LastRecvCampaignUpdate = (ushort)(campaign.LastUpdateID - 1);
+ c.LastRecvCampaignSave = 0;
+ c.LastRecvCampaignUpdate = 0;
}
}
}
@@ -1035,17 +946,7 @@ namespace Barotrauma.Networking
return;
}
- //clients are allowed to end the round by talking with the watchman in multiplayer
- //campaign even if they don't have the special permission
- if (command == ClientPermissions.ManageRound && inc.PeekBoolean() &&
- GameMain.GameSession?.GameMode is MultiPlayerCampaign mpCampaign)
- {
- if (!mpCampaign.AllowedToEndRound(sender.Character) && !sender.HasPermission(command))
- {
- return;
- }
- }
- else if (!sender.HasPermission(command))
+ if (!sender.HasPermission(command))
{
Log("Client \"" + sender.Name + "\" sent a server command \"" + command + "\". Permission denied.", ServerLog.MessageType.ServerMessage);
return;
@@ -1126,22 +1027,9 @@ namespace Barotrauma.Networking
UInt16 modeIndex = inc.ReadUInt16();
if (GameMain.NetLobbyScreen.GameModes[modeIndex].Identifier.ToLowerInvariant() == "multiplayercampaign")
{
- string[] saveFiles = SaveUtil.GetSaveFiles(SaveUtil.SaveType.Multiplayer);
- for (int i = 0; i < saveFiles.Length; i++)
- {
- XDocument doc = SaveUtil.LoadGameSessionDoc(saveFiles[i]);
- if (doc?.Root != null)
- {
- saveFiles[i] =
- string.Join(";",
- saveFiles[i].Replace(';', ' '),
- doc.Root.GetAttributeString("submarine", ""),
- doc.Root.GetAttributeString("savetime", ""));
- }
- }
-
NetOutgoingMessage msg = server.CreateMessage();
msg.Write((byte)ServerPacketHeader.CAMPAIGN_SETUP_INFO);
+ string[] saveFiles = SaveUtil.GetSaveFiles(SaveUtil.SaveType.Multiplayer);
msg.Write((UInt16)saveFiles.Count());
foreach (string saveFile in saveFiles)
{
@@ -1226,7 +1114,6 @@ namespace Barotrauma.Networking
ClientWriteLobby(c);
if (GameMain.GameSession?.GameMode is MultiPlayerCampaign campaign &&
- GameMain.NetLobbyScreen.SelectedMode == campaign.Preset &&
NetIdUtils.IdMoreRecent(campaign.LastSaveID, c.LastRecvCampaignSave))
{
//already sent an up-to-date campaign save
@@ -1361,6 +1248,10 @@ namespace Barotrauma.Networking
WriteClientList(c, outmsg);
clientListBytes = outmsg.LengthBytes - clientListBytes;
+ int eventManagerBytes = outmsg.LengthBytes;
+ entityEventManager.Write(c, outmsg, out List sentEvents);
+ eventManagerBytes = outmsg.LengthBytes - eventManagerBytes;
+
int chatMessageBytes = outmsg.LengthBytes;
WriteChatMessages(outmsg, c);
chatMessageBytes = outmsg.LengthBytes - chatMessageBytes;
@@ -1409,55 +1300,25 @@ namespace Barotrauma.Networking
errorMsg +=
" Client list size: " + clientListBytes + " bytes\n" +
" Chat message size: " + chatMessageBytes + " bytes\n" +
+ " Event size: " + eventManagerBytes + " bytes\n" +
" Position update size: " + positionUpdateBytes + " bytes\n\n";
+
+ if (sentEvents != null && sentEvents.Count > 0)
+ {
+ errorMsg += "Sent events: \n";
+ foreach (var entityEvent in sentEvents)
+ {
+ errorMsg += " - " + (entityEvent.Entity?.ToString() ?? "null") + "\n";
+ }
+ }
+
DebugConsole.ThrowError(errorMsg);
- GameAnalyticsManager.AddErrorEventOnce("GameServer.ClientWriteIngame1:PacketSizeExceeded" + outmsg.LengthBytes, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
+ GameAnalyticsManager.AddErrorEventOnce("GameServer.ClientWriteIngame:PacketSizeExceeded" + outmsg.LengthBytes, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
}
CompressOutgoingMessage(outmsg);
+
server.SendMessage(outmsg, c.Connection, NetDeliveryMethod.Unreliable);
-
- //---------------------------------------------------------------------------
-
- for (int i = 0; i < NetConfig.MaxEventPacketsPerUpdate; i++)
- {
- outmsg = server.CreateMessage();
- outmsg.Write((byte)ServerPacketHeader.UPDATE_INGAME);
- outmsg.Write((float)NetTime.Now);
-
- int eventManagerBytes = outmsg.LengthBytes;
- entityEventManager.Write(c, outmsg, out List sentEvents);
- eventManagerBytes = outmsg.LengthBytes - eventManagerBytes;
-
- if (sentEvents.Count == 0)
- {
- break;
- }
-
- outmsg.Write((byte)ServerNetObject.END_OF_MESSAGE);
-
- if (outmsg.LengthBytes > NetPeerConfiguration.MaximumTransmissionUnit)
- {
- string errorMsg = "Maximum packet size exceeded (" + outmsg.LengthBytes + " > " + NetPeerConfiguration.MaximumTransmissionUnit + ")\n";
- errorMsg +=
- " Event size: " + eventManagerBytes + " bytes\n";
-
- if (sentEvents != null && sentEvents.Count > 0)
- {
- errorMsg += "Sent events: \n";
- foreach (var entityEvent in sentEvents)
- {
- errorMsg += " - " + (entityEvent.Entity?.ToString() ?? "null") + "\n";
- }
- }
-
- DebugConsole.ThrowError(errorMsg);
- GameAnalyticsManager.AddErrorEventOnce("GameServer.ClientWriteIngame2:PacketSizeExceeded" + outmsg.LengthBytes, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
- }
-
- CompressOutgoingMessage(outmsg);
- server.SendMessage(outmsg, c.Connection, NetDeliveryMethod.Unreliable);
- }
}
private void WriteClientList(Client c, NetOutgoingMessage outmsg)
@@ -1544,8 +1405,7 @@ namespace Barotrauma.Networking
}
var campaign = GameMain.GameSession?.GameMode as MultiPlayerCampaign;
- if (campaign != null && campaign.Preset == GameMain.NetLobbyScreen.SelectedMode &&
- NetIdUtils.IdMoreRecent(campaign.LastUpdateID, c.LastRecvCampaignUpdate))
+ if (campaign != null && NetIdUtils.IdMoreRecent(campaign.LastUpdateID, c.LastRecvCampaignUpdate))
{
outmsg.Write(true);
outmsg.WritePadBits();
@@ -1702,23 +1562,9 @@ namespace Barotrauma.Networking
Rand.SetSyncedSeed(roundStartSeed);
int teamCount = 1;
- MultiPlayerCampaign campaign = selectedMode == GameMain.GameSession?.GameMode.Preset ?
+ MultiPlayerCampaign campaign = GameMain.NetLobbyScreen.SelectedMode == GameMain.GameSession?.GameMode.Preset ?
GameMain.GameSession?.GameMode as MultiPlayerCampaign : null;
- if (campaign != null && campaign.Map == null)
- {
- initiatedStartGame = false;
- startGameCoroutine = null;
- string errorMsg = "Starting the round failed. Campaign was still active, but the map has been disposed. Try selecting another game mode.";
- DebugConsole.ThrowError(errorMsg);
- GameAnalyticsManager.AddErrorEventOnce("GameServer.StartGame:InvalidCampaignState", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
- if (OwnerConnection != null)
- {
- SendDirectChatMessage(errorMsg, connectedClients.Find(c => c.Connection == OwnerConnection), ChatMessageType.Error);
- }
- yield return CoroutineStatus.Failure;
- }
-
//don't instantiate a new gamesession if we're playing a campaign
if (campaign == null || GameMain.GameSession == null)
{
@@ -1743,17 +1589,15 @@ namespace Barotrauma.Networking
mirrorLevel: campaign.Map.CurrentLocation != campaign.Map.SelectedConnection.Locations[0]);
campaign.AssignClientCharacterInfos(connectedClients);
- Log("Game mode: " + selectedMode.Name, ServerLog.MessageType.ServerMessage);
- Log("Submarine: " + GameMain.GameSession.Submarine.Name, ServerLog.MessageType.ServerMessage);
- Log("Level seed: " + campaign.Map.SelectedConnection.Level.Seed, ServerLog.MessageType.ServerMessage);
}
else
{
GameMain.GameSession.StartRound(GameMain.NetLobbyScreen.LevelSeed, serverSettings.SelectedLevelDifficulty, teamCount > 1);
- Log("Game mode: " + selectedMode.Name, ServerLog.MessageType.ServerMessage);
- Log("Submarine: " + selectedSub.Name, ServerLog.MessageType.ServerMessage);
- Log("Level seed: " + GameMain.NetLobbyScreen.LevelSeed, ServerLog.MessageType.ServerMessage);
- }
+ }
+
+ Log("Submarine: " + selectedSub.Name, ServerLog.MessageType.ServerMessage);
+ Log("Game mode: " + selectedMode.Name, ServerLog.MessageType.ServerMessage);
+ Log("Level seed: " + GameMain.NetLobbyScreen.LevelSeed, ServerLog.MessageType.ServerMessage);
bool missionAllowRespawn = campaign == null &&
(!(GameMain.GameSession.GameMode is MissionMode) ||
@@ -1915,7 +1759,6 @@ namespace Barotrauma.Networking
msg.Write(seed);
msg.Write(GameMain.GameSession.Level.Seed);
- msg.Write(GameMain.GameSession.Level.EqualityCheckVal);
msg.Write(serverSettings.SelectedLevelDifficulty);
msg.Write((byte)GameMain.Config.LosMode);
@@ -1977,8 +1820,6 @@ namespace Barotrauma.Networking
Mission mission = GameMain.GameSession.Mission;
GameMain.GameSession.GameMode.End(endMessage);
-
- endRoundTimer = 0.0f;
if (serverSettings.AutoRestart)
{
@@ -2056,7 +1897,14 @@ namespace Barotrauma.Networking
public override void AddChatMessage(ChatMessage message)
{
if (string.IsNullOrEmpty(message.Text)) { return; }
- Log(message.TextWithSender, ServerLog.MessageType.Chat);
+ if (message.Sender != null)
+ {
+ Log($"{message.Sender}: {message.Text}", ServerLog.MessageType.Chat);
+ }
+ else
+ {
+ Log($"{message.Text}", ServerLog.MessageType.Chat);
+ }
base.AddChatMessage(message);
}
@@ -2519,8 +2367,6 @@ namespace Barotrauma.Networking
public void SendVoteStatus(List recipients)
{
- if (!recipients.Any()) { return; }
-
NetOutgoingMessage msg = server.CreateMessage();
msg.Write((byte)ServerPacketHeader.UPDATE_LOBBY);
msg.Write((byte)ServerNetObject.VOTE);
@@ -2573,10 +2419,7 @@ namespace Barotrauma.Networking
recipients.Add(otherClient.Connection);
}
}
- if (recipients.Any())
- {
- server.SendMessage(msg, recipients, NetDeliveryMethod.ReliableUnordered, 0);
- }
+ server.SendMessage(msg, recipients, NetDeliveryMethod.ReliableUnordered, 0);
serverSettings.SaveClientPermissions();
}
@@ -2610,15 +2453,13 @@ namespace Barotrauma.Networking
public void UpdateCheatsEnabled()
{
- if (!connectedClients.Any()) { return; }
-
var msg = server.CreateMessage();
msg.Write((byte)ServerPacketHeader.CHEATS_ENABLED);
msg.Write(DebugConsole.CheatsEnabled);
msg.WritePadBits();
CompressOutgoingMessage(msg);
-
+
server.SendMessage(msg, connectedClients.Select(c => c.Connection).ToList(), NetDeliveryMethod.ReliableUnordered, 0);
}
diff --git a/Barotrauma/BarotraumaServer/Source/Networking/GameServerLogin.cs b/Barotrauma/BarotraumaServer/Source/Networking/GameServerLogin.cs
index 4bd7a0077..fe0b66db2 100644
--- a/Barotrauma/BarotraumaServer/Source/Networking/GameServerLogin.cs
+++ b/Barotrauma/BarotraumaServer/Source/Networking/GameServerLogin.cs
@@ -158,15 +158,15 @@ namespace Barotrauma.Networking
}
//kick connected client if status becomes invalid (e.g. VAC banned, not connected to steam)
- /*if (status != Facepunch.Steamworks.ServerAuth.Status.OK && GameMain.Config.RequireSteamAuthentication)
+ if (status != Facepunch.Steamworks.ServerAuth.Status.OK && GameMain.Config.RequireSteamAuthentication)
{
var connectedClient = connectedClients.Find(c => c.SteamID == ownerID);
if (connectedClient != null)
{
Log("Disconnecting client " + connectedClient.Name + " (Steam ID: " + steamID + "). Steam authentication no longer valid (" + status + ").", ServerLog.MessageType.ServerMessage);
- KickClient(connectedClient, $"DisconnectMessage.SteamAuthNoLongerValid~[status]={status.ToString()}");
+ KickClient(connectedClient, $"DisconnectMessage.SteamAuthNoLongerValid_[status]={status.ToString()}");
}
- }*/
+ }
}
private bool IsServerOwner(NetIncomingMessage inc, NetConnection senderConnection)
@@ -342,7 +342,7 @@ namespace Barotrauma.Networking
if (clVersion != GameMain.Version.ToString())
{
DisconnectUnauthClient(inc, unauthClient, DisconnectReason.InvalidVersion,
- $"DisconnectMessage.InvalidVersion~[version]={GameMain.Version.ToString()}~[clientversion]={clVersion}");
+ $"DisconnectMessage.InvalidVersion_[version]={GameMain.Version.ToString()}_[clientversion]={clVersion}");
Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (wrong game version)", ServerLog.MessageType.Error);
DebugConsole.NewMessage(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (wrong game version)", Color.Red);
@@ -368,7 +368,7 @@ namespace Barotrauma.Networking
if (missingPackages.Count == 1)
{
- DisconnectUnauthClient(inc, unauthClient, DisconnectReason.MissingContentPackage, $"DisconnectMessage.MissingContentPackage~[missingcontentpackage]={GetPackageStr(missingPackages[0])}");
+ DisconnectUnauthClient(inc, unauthClient, DisconnectReason.MissingContentPackage, $"DisconnectMessage.MissingContentPackage_[missingcontentpackage]={GetPackageStr(missingPackages[0])}");
Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (missing content package " + GetPackageStr(missingPackages[0]) + ")", ServerLog.MessageType.Error);
return;
}
@@ -376,7 +376,7 @@ namespace Barotrauma.Networking
{
List packageStrs = new List();
missingPackages.ForEach(cp => packageStrs.Add(GetPackageStr(cp)));
- DisconnectUnauthClient(inc, unauthClient, DisconnectReason.MissingContentPackage, $"DisconnectMessage.MissingContentPackages~[missingcontentpackages]={string.Join(", ", packageStrs)}");
+ DisconnectUnauthClient(inc, unauthClient, DisconnectReason.MissingContentPackage, $"DisconnectMessage.MissingContentPackages_[missingcontentpackages]={string.Join(", ", packageStrs)}");
Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (missing content packages " + string.Join(", ", packageStrs) + ")", ServerLog.MessageType.Error);
return;
}
@@ -399,7 +399,7 @@ namespace Barotrauma.Networking
if (incompatiblePackages.Count == 1)
{
DisconnectUnauthClient(inc, unauthClient, DisconnectReason.IncompatibleContentPackage,
- $"DisconnectMessage.IncompatibleContentPackage~[incompatiblecontentpackage]={GetPackageStr2(incompatiblePackages[0])}");
+ $"DisconnectMessage.IncompatibleContentPackage_[incompatiblecontentpackage]={GetPackageStr2(incompatiblePackages[0])}");
Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (incompatible content package " + GetPackageStr2(incompatiblePackages[0]) + ")", ServerLog.MessageType.Error);
return;
}
@@ -408,7 +408,7 @@ namespace Barotrauma.Networking
List packageStrs = new List();
incompatiblePackages.ForEach(cp => packageStrs.Add(GetPackageStr2(cp)));
DisconnectUnauthClient(inc, unauthClient, DisconnectReason.IncompatibleContentPackage,
- $"DisconnectMessage.IncompatibleContentPackages~[incompatiblecontentpackages]={string.Join(", ", packageStrs)}");
+ $"DisconnectMessage.IncompatibleContentPackages_[incompatiblecontentpackages]={string.Join(", ", packageStrs)}");
Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (incompatible content packages " + string.Join(", ", packageStrs) + ")", ServerLog.MessageType.Error);
return;
}
@@ -500,7 +500,7 @@ namespace Barotrauma.Networking
private void DisconnectUnauthClient(NetIncomingMessage inc, UnauthenticatedClient unauthClient, DisconnectReason reason, string message)
{
- inc.SenderConnection.Disconnect(reason.ToString() + "/ " + TextManager.GetServerMessage(message));
+ inc.SenderConnection.Disconnect(reason.ToString() + "/ " + message);
if (unauthClient.SteamID > 0) { Steam.SteamManager.StopAuthSession(unauthClient.SteamID); }
if (unauthClient != null)
{
diff --git a/Barotrauma/BarotraumaServer/Source/Networking/NetEntityEvent/ServerEntityEventManager.cs b/Barotrauma/BarotraumaServer/Source/Networking/NetEntityEvent/ServerEntityEventManager.cs
index 326df08c3..5ab63d5e1 100644
--- a/Barotrauma/BarotraumaServer/Source/Networking/NetEntityEvent/ServerEntityEventManager.cs
+++ b/Barotrauma/BarotraumaServer/Source/Networking/NetEntityEvent/ServerEntityEventManager.cs
@@ -1,5 +1,4 @@
-using Barotrauma.Extensions;
-using Lidgren.Network;
+using Lidgren.Network;
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
@@ -209,6 +208,7 @@ namespace Barotrauma.Networking
lastSentToAll = owner.LastRecvEntityEventID;
}
}
+
inGameClients.ForEach(c => { if (NetIdUtils.IdMoreRecent(lastSentToAll, c.LastRecvEntityEventID)) lastSentToAll = c.LastRecvEntityEventID; });
clients.Where(c => c.NeedsMidRoundSync).ForEach(c => { if (NetIdUtils.IdMoreRecent(lastSentToAll, c.FirstNewEventID)) lastSentToAll = (ushort)(c.FirstNewEventID - 1); });
@@ -228,8 +228,8 @@ namespace Barotrauma.Networking
GameServer.Log("Disconnecting client " + c.Name + " due to excessive desync (expected old event "
+ (c.LastRecvEntityEventID + 1).ToString() +
" (created " + (Timing.TotalTime - firstEventToResend.CreateTime).ToString("0.##") + " s ago)" +
- " Events queued: " + events.Count + ", last sent to all: " + lastSentToAll, ServerLog.MessageType.Error);
- server.DisconnectClient(c, "", "ServerMessage.ExcessiveDesyncOldEvent");
+ " Events queued: " + events.Count + ", last sent to all: " + lastSentToAll, ServerLog.MessageType.ServerMessage);
+ server.DisconnectClient(c, "", "ServerMessage.ExcessiveDesync");
}
);
}
@@ -242,8 +242,8 @@ namespace Barotrauma.Networking
toKick.ForEach(c =>
{
DebugConsole.NewMessage(c.Name + " was kicked due to excessive desync (expected removed event " + (c.LastRecvEntityEventID + 1).ToString() + ", last available is " + events[0].ID.ToString() + ")", Color.Red);
- GameServer.Log("Disconnecting client " + c.Name + " due to excessive desync (expected removed event " + (c.LastRecvEntityEventID + 1).ToString() + ", last available is " + events[0].ID.ToString() + ")", ServerLog.MessageType.Error);
- server.DisconnectClient(c, "", "ServerMessage.ExcessiveDesyncRemovedEvent");
+ GameServer.Log("Disconnecting client " + c.Name + " due to excessive desync (expected removed event" + (c.LastRecvEntityEventID + 1).ToString() + ", last available is " + events[0].ID.ToString() + ")", ServerLog.MessageType.ServerMessage);
+ server.DisconnectClient(c, "", "ServerMessage.ExcessiveDesync");
});
}
}
@@ -251,7 +251,7 @@ namespace Barotrauma.Networking
var timedOutClients = clients.FindAll(c => c.InGame && c.NeedsMidRoundSync && Timing.TotalTime > c.MidRoundSyncTimeOut);
foreach (Client timedOutClient in timedOutClients)
{
- GameServer.Log("Disconnecting client " + timedOutClient.Name + ". Syncing the client with the server took too long.", ServerLog.MessageType.Error);
+ GameServer.Log("Disconnecting client " + timedOutClient.Name + ". Syncing the client with the server took too long.", ServerLog.MessageType.ServerMessage);
GameMain.Server.DisconnectClient(timedOutClient, "", "ServerMessage.SyncTimeout");
}
@@ -305,7 +305,19 @@ namespace Barotrauma.Networking
}
//too many events for one packet
- if (eventsToSync.Count > 200)
+ if (eventsToSync.Count > MaxEventsPerWrite)
+ {
+ if (eventsToSync.Count > MaxEventsPerWrite * 3 && !client.NeedsMidRoundSync)
+ {
+ Color color = eventsToSync.Count > MaxEventsPerWrite * 20 ? Color.Red : Color.Orange;
+ if (eventsToSync.Count < MaxEventsPerWrite * 5) { color = Color.Yellow; }
+ DebugConsole.NewMessage("WARNING: event count very high: " + eventsToSync.Count + "/" + MaxEventsPerWrite, color);
+ }
+
+ eventsToSync.RemoveRange(MaxEventsPerWrite, eventsToSync.Count - MaxEventsPerWrite);
+ }
+
+ foreach (NetEntityEvent entityEvent in eventsToSync)
{
if (eventsToSync.Count > 200 && !client.NeedsMidRoundSync)
{
@@ -334,11 +346,19 @@ namespace Barotrauma.Networking
if (client.NeedsMidRoundSync)
{
- msg.Write((byte)ServerNetObject.ENTITY_EVENT_INITIAL);
+ msg.Write((byte)ServerNetObject.ENTITY_EVENT_INITIAL);
+
+ //how many (unique) events the clients had missed before joining
+ client.UnreceivedEntityEventCount = (UInt16)uniqueEvents.Count;
+ //ID of the first event sent after the client joined
+ //(after the client has been synced they'll switch their lastReceivedID
+ //to the one before this, and the eventmanagers will start to function "normally")
+ client.FirstNewEventID = events.Count == 0 ? (UInt16)0 : events[events.Count - 1].ID;
+
msg.Write(client.UnreceivedEntityEventCount);
msg.Write(client.FirstNewEventID);
- Write(msg, eventsToSync, out sentEvents, client);
+ Write(msg, eventsToSync, client);
}
else
{
@@ -351,6 +371,7 @@ namespace Barotrauma.Networking
(entityEvent as ServerEntityEvent).Sent = true;
client.EntityEventLastSent[entityEvent.ID] = NetTime.Now;
}
+ sentEvents = eventsToSync;
}
///
@@ -374,10 +395,10 @@ namespace Barotrauma.Networking
for (int i = startIndex; i < eventList.Count; i++)
{
- //find the first event that hasn't been sent in roundtriptime or at all
- client.EntityEventLastSent.TryGetValue(eventList[i].ID, out double lastSent);
+ //find the first event that hasn't been sent in 1.5 * roundtriptime or at all
+ client.EntityEventLastSent.TryGetValue(eventList[i].ID, out float lastSent);
- float minInterval = Math.Max(client.Connection.AverageRoundtripTime, (float)server.UpdateInterval.TotalSeconds * 2);
+ float minInterval = Math.Max(client.Connection.AverageRoundtripTime * 1.5f, (float)server.UpdateInterval.TotalSeconds * 2);
if (lastSent > NetTime.Now - Math.Min(minInterval, 0.5f))
{
@@ -403,7 +424,7 @@ namespace Barotrauma.Networking
}
else
{
- double midRoundSyncTimeOut = uniqueEvents.Count / 100 * server.UpdateInterval.TotalSeconds;
+ double midRoundSyncTimeOut = uniqueEvents.Count / MaxEventsPerWrite * server.UpdateInterval.TotalSeconds;
midRoundSyncTimeOut = Math.Max(10.0f, midRoundSyncTimeOut * 10.0f);
client.UnreceivedEntityEventCount = (UInt16)uniqueEvents.Count;
diff --git a/Barotrauma/BarotraumaServer/Source/Networking/Voip/VoipServer.cs b/Barotrauma/BarotraumaServer/Source/Networking/Voip/VoipServer.cs
index b282901ce..7432cf88f 100644
--- a/Barotrauma/BarotraumaServer/Source/Networking/Voip/VoipServer.cs
+++ b/Barotrauma/BarotraumaServer/Source/Networking/Voip/VoipServer.cs
@@ -78,7 +78,6 @@ namespace Barotrauma.Networking
bool senderSpectating = sender.Character == null || sender.Character.IsDead;
//spectators cannot speak with in-game players or vice versa
- //TODO: allow spectators to hear the voice chat if close enough to the speaker?
if (recipientSpectating != senderSpectating) { return false; }
//both spectating, no need to do radio/distance checks
diff --git a/Barotrauma/BarotraumaServer/Source/Networking/Voting.cs b/Barotrauma/BarotraumaServer/Source/Networking/Voting.cs
index 67f5012ba..6aa489dc4 100644
--- a/Barotrauma/BarotraumaServer/Source/Networking/Voting.cs
+++ b/Barotrauma/BarotraumaServer/Source/Networking/Voting.cs
@@ -116,8 +116,8 @@ namespace Barotrauma
msg.Write(AllowEndVoting);
if (AllowEndVoting)
{
- msg.Write((byte)GameMain.Server.ConnectedClients.Count(c => c.HasSpawned && c.GetVote(VoteType.EndRound)));
- msg.Write((byte)GameMain.Server.ConnectedClients.Count(c => c.HasSpawned));
+ msg.Write((byte)GameMain.Server.ConnectedClients.Count(v => v.GetVote(VoteType.EndRound)));
+ msg.Write((byte)GameMain.Server.ConnectedClients.Count);
}
msg.Write(AllowVoteKick);
diff --git a/Barotrauma/BarotraumaShared/Data/ContentPackages/Vanilla 0.9.xml b/Barotrauma/BarotraumaShared/Data/ContentPackages/Vanilla 0.9.xml
index 7a10d5467..c65e80969 100644
--- a/Barotrauma/BarotraumaShared/Data/ContentPackages/Vanilla 0.9.xml
+++ b/Barotrauma/BarotraumaShared/Data/ContentPackages/Vanilla 0.9.xml
@@ -56,7 +56,6 @@
-
@@ -71,12 +70,9 @@
-
+
-
-
-
diff --git a/Barotrauma/BarotraumaShared/SharedContent.projitems b/Barotrauma/BarotraumaShared/SharedContent.projitems
index 011b0af16..e8ccac6d1 100644
--- a/Barotrauma/BarotraumaShared/SharedContent.projitems
+++ b/Barotrauma/BarotraumaShared/SharedContent.projitems
@@ -10,7 +10,7 @@
-
+
@@ -45,27 +45,12 @@
PreserveNewest
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
PreserveNewest
PreserveNewest
-
- PreserveNewest
-
-
- PreserveNewest
-
PreserveNewest
@@ -912,13 +897,13 @@
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
@@ -1658,12 +1643,6 @@
PreserveNewest
-
- PreserveNewest
-
-
- PreserveNewest
-
PreserveNewest
@@ -2371,7 +2350,7 @@
PreserveNewest
-
+
PreserveNewest
@@ -3129,7 +3108,7 @@
PreserveNewest
- Never
+ PreserveNewest
PreserveNewest
@@ -3144,13 +3123,8 @@
PreserveNewest
- PreserveNewest
- PreserveNewest
-
-
- PreserveNewest
PreserveNewest
diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/AITarget.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/AITarget.cs
index 5384ef408..4ce4ecd37 100644
--- a/Barotrauma/BarotraumaShared/Source/Characters/AI/AITarget.cs
+++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/AITarget.cs
@@ -110,7 +110,7 @@ namespace Barotrauma
SonarLabel = element.GetAttributeString("sonarlabel", "");
}
- public AITarget(Entity e, float sightRange = 3000, float soundRange = 0)
+ public AITarget(Entity e)
{
Entity = e;
SightRange = sightRange;
diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/EnemyAIController.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/EnemyAIController.cs
index be6ca7fcb..2f0623bd3 100644
--- a/Barotrauma/BarotraumaShared/Source/Characters/AI/EnemyAIController.cs
+++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/EnemyAIController.cs
@@ -26,6 +26,7 @@ namespace Barotrauma
}
}
+
public class TargetingPriority
{
public string TargetTag;
@@ -99,9 +100,6 @@ namespace Barotrauma
private readonly float aggressiongreed;
private readonly float aggressionhurt;
- // TODO: expose?
- private readonly float priorityFearIncreasement = 2;
- private readonly float memoryFadeTime = 0.5f;
public bool AttackHumans
{
@@ -251,7 +249,8 @@ namespace Barotrauma
public override void SelectTarget(AITarget target)
{
SelectedAiTarget = target;
- selectedTargetMemory = GetTargetMemory(target);
+ selectedTargetMemory = FindTargetMemory(target);
+
targetValue = 100.0f;
}
@@ -288,7 +287,8 @@ namespace Barotrauma
}
else
{
- UpdateTargets(Character, out TargetingPriority targetingPriority);
+ TargetingPriority targetingPriority = null;
+ UpdateTargets(Character, out targetingPriority);
updateTargetsTimer = UpdateTargetsInterval;
if (SelectedAiTarget == null)
@@ -395,44 +395,13 @@ namespace Barotrauma
State = AIState.Idle;
return;
}
- else if (selectedTargetMemory != null)
+
+ Vector2 escapeDir = Vector2.Normalize(SimPosition - SelectedAiTarget.SimPosition);
+ if (!MathUtils.IsValid(escapeDir)) escapeDir = Vector2.UnitY;
+ SteeringManager.SteeringManual(deltaTime, escapeDir);
+ SteeringManager.SteeringWander();
+ if (Character.CurrentHull == null)
{
- selectedTargetMemory.Priority += deltaTime * priorityFearIncreasement;
- }
- if (Character.CurrentHull != null)
- {
- // Seek exit, if inside
- if (SteeringManager is IndoorsSteeringManager indoorSteering && escapePoint == Vector2.Zero)
- {
- foreach (Gap gap in Gap.GapList)
- {
- if (gap.Submarine != Character.Submarine) { continue; }
- if (gap.Open < 1 || gap.IsRoomToRoom) { continue; }
- var path = indoorSteering.PathFinder.FindPath(Character.SimPosition, gap.SimPosition);
- if (!path.Unreachable)
- {
- if (escapePoint != Vector2.Zero)
- {
- // Ignore the gap if it's further away than the previously assigned escape point
- if (Vector2.DistanceSquared(Character.SimPosition, gap.SimPosition) > Vector2.DistanceSquared(Character.SimPosition, escapePoint)) { continue; }
- }
- escapePoint = gap.SimPosition;
- }
- }
- }
- }
- if (escapePoint != Vector2.Zero && Vector2.DistanceSquared(Character.SimPosition, escapePoint) > 1)
- {
- SteeringManager.SteeringSeek(escapePoint);
- }
- else
- {
- // If outside or near enough the escapePoint, steer away
- escapePoint = Vector2.Zero;
- Vector2 escapeDir = Vector2.Normalize(WorldPosition - SelectedAiTarget.WorldPosition);
- if (!MathUtils.IsValid(escapeDir)) escapeDir = Vector2.UnitY;
- SteeringManager.SteeringManual(deltaTime, escapeDir);
- SteeringManager.SteeringWander();
SteeringManager.SteeringAvoid(deltaTime, colliderSize * 3.0f);
}
}
@@ -449,8 +418,14 @@ namespace Barotrauma
return;
}
- Vector2 attackWorldPos = SelectedAiTarget.WorldPosition;
- Vector2 attackSimPos = SelectedAiTarget.SimPosition;
+ selectedTargetMemory.Priority -= deltaTime * 0.1f;
+
+ Vector2 attackSimPosition = Character.Submarine == null ? ConvertUnits.ToSimUnits(SelectedAiTarget.WorldPosition) : SelectedAiTarget.SimPosition;
+
+ if (Character.Submarine != null && SelectedAiTarget.Entity.Submarine != null && Character.Submarine != SelectedAiTarget.Entity.Submarine)
+ {
+ attackSimPosition = ConvertUnits.ToSimUnits(SelectedAiTarget.WorldPosition - Character.Submarine.Position);
+ }
if (SelectedAiTarget.Entity is Item item)
{
@@ -466,27 +441,22 @@ namespace Barotrauma
}
}
- if (raycastTimer > 0.0)
+ if (wallTarget != null)
{
- raycastTimer -= deltaTime;
- }
- else
- {
- if (!IsProperlyLatched)
+ attackSimPosition = ConvertUnits.ToSimUnits(wallTarget.Position);
+ if (Character.Submarine == null && SelectedAiTarget.Entity?.Submarine != null)
{
- UpdateWallTarget();
+ attackSimPosition += ConvertUnits.ToSimUnits(SelectedAiTarget.Entity.Submarine.Position);
}
- raycastTimer = RaycastInterval;
}
-
- if (SelectedAiTarget.Entity is Character c)
+ else if (SelectedAiTarget.Entity is Character c)
{
//target the closest limb if the target is a character
- float closestDist = Vector2.DistanceSquared(SelectedAiTarget.WorldPosition, WorldPosition) * 10.0f;
- foreach (Limb limb in c.AnimController.Limbs)
+ float closestDist = Vector2.DistanceSquared(SelectedAiTarget.SimPosition, SimPosition) * 10.0f;
+ foreach (Limb limb in ((Character)SelectedAiTarget.Entity).AnimController.Limbs)
{
if (limb == null) continue;
- float dist = Vector2.DistanceSquared(limb.WorldPosition, WorldPosition) / Math.Max(limb.AttackPriority, 0.1f);
+ float dist = Vector2.DistanceSquared(limb.SimPosition, SimPosition) / Math.Max(limb.AttackPriority, 0.1f);
if (dist < closestDist)
{
closestDist = dist;
@@ -518,12 +488,7 @@ namespace Barotrauma
}
}
- if (Math.Abs(Character.AnimController.movement.X) > 0.1f && !Character.AnimController.InWater)
- {
- Character.AnimController.TargetDir = Character.WorldPosition.X < attackWorldPos.X ? Direction.Right : Direction.Left;
- }
-
- if (aggressiveBoarding)
+ if (raycastTimer > 0.0)
{
//targeting a wall section that can be passed through -> steer manually through the hole
if (wallTarget != null && wallTarget.SectionIndex > -1 && CanPassThroughHole(wallTarget.Structure, wallTarget.SectionIndex))
@@ -582,6 +547,74 @@ namespace Barotrauma
}
}
+ bool canAttack = true;
+ if (IsCoolDownRunning)
+ {
+ UpdateWallTarget();
+ raycastTimer = RaycastInterval;
+ }
+
+ if (aggressiveBoarding)
+ {
+ //targeting a wall section that can be passed through -> steer manually through the hole
+ if (wallTarget != null && wallTarget.SectionIndex > -1 && CanPassThroughHole(wallTarget.Structure, wallTarget.SectionIndex))
+ {
+ WallSection section = wallTarget.Structure.GetSection(wallTarget.SectionIndex);
+ Hull targetHull = section.gap?.FlowTargetHull;
+ if (targetHull != null && !section.gap.IsRoomToRoom)
+ {
+ Vector2 targetPos = wallTarget.Structure.SectionPosition(wallTarget.SectionIndex, true);
+ if (wallTarget.Structure.IsHorizontal)
+ {
+ targetPos.Y = targetHull.WorldRect.Y - targetHull.Rect.Height / 2;
+ }
+ else
+ {
+ targetPos.X = targetHull.WorldRect.Center.X;
+ }
+
+ latchOntoAI?.DeattachFromBody();
+ Character.AnimController.ReleaseStuckLimbs();
+ if (steeringManager is IndoorsSteeringManager)
+ {
+ steeringManager.SteeringManual(deltaTime, Vector2.Normalize(targetPos - Character.WorldPosition));
+ }
+ else
+ {
+ steeringManager.SteeringSeek(ConvertUnits.ToSimUnits(targetPos));
+ }
+ return;
+ }
+ }
+ else if (SelectedAiTarget.Entity is Item)
+ {
+ var door = ((Item)SelectedAiTarget.Entity).GetComponent();
+ //steer through the door manually if it's open or broken
+ if (door?.LinkedGap?.FlowTargetHull != null && !door.LinkedGap.IsRoomToRoom && (door.IsOpen || door.Item.Condition <= 0.0f))
+ {
+ var velocity = Vector2.Normalize(door.LinkedGap.FlowTargetHull.WorldPosition - Character.WorldPosition);
+ if (door.LinkedGap.IsHorizontal)
+ {
+ if (Character.WorldPosition.Y < door.Item.WorldRect.Y && Character.WorldPosition.Y > door.Item.WorldRect.Y - door.Item.Rect.Height)
+ {
+ velocity.Y = 0;
+ steeringManager.SteeringManual(deltaTime, velocity);
+ return;
+ }
+ }
+ else
+ {
+ if (Character.WorldPosition.X < door.Item.WorldRect.X && Character.WorldPosition.X > door.Item.WorldRect.Right)
+ {
+ velocity.X = 0;
+ steeringManager.SteeringManual(deltaTime, velocity);
+ return;
+ }
+ }
+ }
+ }
+ }
+
bool canAttack = true;
if (IsCoolDownRunning)
{
@@ -598,7 +631,7 @@ namespace Barotrauma
}
else
{
- UpdateFallBack(attackWorldPos, deltaTime);
+ UpdateFallBack(attackSimPosition, deltaTime);
return;
}
}
@@ -606,14 +639,14 @@ namespace Barotrauma
{
if (attackingLimb.attack.SecondaryCoolDownTimer <= 0)
{
- // Don't allow attacking when the attack target has just changed.
+ // Don't allow attacking when the attack target has changed.
if (_previousAiTarget != null && SelectedAiTarget != _previousAiTarget)
{
canAttack = false;
if (attackingLimb.attack.AfterAttack == AIBehaviorAfterAttack.PursueIfCanAttack)
{
// Fall back if cannot attack.
- UpdateFallBack(attackWorldPos, deltaTime);
+ UpdateFallBack(attackSimPosition, deltaTime);
return;
}
attackingLimb = null;
@@ -622,7 +655,7 @@ namespace Barotrauma
{
// If the secondary cooldown is defined and expired, check if we can switch the attack
var previousLimb = attackingLimb;
- var newLimb = GetAttackLimb(attackWorldPos, previousLimb);
+ var newLimb = GetAttackLimb(attackSimPosition, previousLimb);
if (newLimb != null)
{
attackingLimb = newLimb;
@@ -636,7 +669,7 @@ namespace Barotrauma
}
else
{
- UpdateFallBack(attackWorldPos, deltaTime);
+ UpdateFallBack(attackSimPosition, deltaTime);
return;
}
}
@@ -651,15 +684,15 @@ namespace Barotrauma
break;
case AIBehaviorAfterAttack.FallBack:
default:
- UpdateFallBack(attackWorldPos, deltaTime);
+ UpdateFallBack(attackSimPosition, deltaTime);
return;
}
}
- if (attackingLimb == null || _previousAiTarget != SelectedAiTarget)
+ if (attackingLimb == null)
{
- attackingLimb = GetAttackLimb(attackWorldPos);
+ attackingLimb = GetAttackLimb(attackSimPosition);
}
if (canAttack)
{
@@ -669,39 +702,24 @@ namespace Barotrauma
if (canAttack)
{
// Check that we can reach the target
- distance = Vector2.Distance(attackingLimb.WorldPosition, attackWorldPos);
+ distance = ConvertUnits.ToDisplayUnits(Vector2.Distance(attackingLimb.SimPosition, attackSimPosition));
canAttack = distance < attackingLimb.attack.Range;
}
- // If the attacking limb is a hand or claw, for example, using it as the steering limb can end in the result where the character circles around the target. For example the Hammerhead steering with the claws when it should use the torso.
- // If we always use the main limb, this causes the character to seek the target with it's torso/head, when it should not. For example Mudraptor steering with it's belly, when it should use it's head.
- // So let's use the one that's closer to the attacking limb.
- Limb steeringLimb;
- var torso = Character.AnimController.GetLimb(LimbType.Torso);
- var head = Character.AnimController.GetLimb(LimbType.Head);
- if (attackingLimb == null)
- {
- steeringLimb = head ?? torso;
- }
- else
- {
- if (head != null && torso != null)
- {
- steeringLimb = Vector2.DistanceSquared(attackingLimb.SimPosition, head.SimPosition) < Vector2.DistanceSquared(attackingLimb.SimPosition, torso.SimPosition) ? head : torso;
- }
- else
- {
- steeringLimb = head ?? torso;
- }
- }
+ Limb steeringLimb = Character.AnimController.MainLimb;
if (steeringLimb != null)
{
- Vector2 offset = Character.SimPosition - steeringLimb.SimPosition;
- // Offset so that we don't overshoot the movement
- Vector2 steerPos = attackSimPos + offset;
- SteeringManager.SteeringSeek(steerPos, 10);
+ Vector2 steeringVector = attackSimPosition - steeringLimb.SimPosition;
+ Vector2 targetingVector = Vector2.Normalize(steeringVector) * attackingLimb.attack.Range;
+ // Offset the position a bit so that we don't overshoot the movement.
+ Vector2 steerPos = attackSimPosition + targetingVector;
+ steeringManager.SteeringSeek(steerPos, 10);
+ if (Character.CurrentHull == null)
+ {
+ SteeringManager.SteeringAvoid(deltaTime, colliderSize * 1.5f);
+ }
- if (SteeringManager is IndoorsSteeringManager indoorsSteering)
+ if (steeringManager is IndoorsSteeringManager indoorsSteering)
{
if (indoorsSteering.CurrentPath != null && !indoorsSteering.IsPathDirty)
{
@@ -716,7 +734,7 @@ namespace Barotrauma
}
else if (indoorsSteering.CurrentPath.Finished)
{
- SteeringManager.SteeringManual(deltaTime, Vector2.Normalize(attackSimPos - steeringLimb.SimPosition));
+ steeringManager.SteeringManual(deltaTime, Vector2.Normalize(steeringVector));
}
else if (indoorsSteering.CurrentPath.CurrentNode?.ConnectedDoor != null)
{
@@ -730,42 +748,40 @@ namespace Barotrauma
}
}
}
- else if (Character.CurrentHull == null)
- {
- SteeringManager.SteeringAvoid(deltaTime, colliderSize * 1.5f);
- }
}
if (canAttack)
{
- UpdateLimbAttack(deltaTime, attackingLimb, attackSimPos, distance);
+ UpdateLimbAttack(deltaTime, attackingLimb, attackSimPosition, distance);
}
}
- private bool SteerThroughGap(Structure wall, WallSection section, Vector2 targetWorldPos, float deltaTime)
+ private Limb GetAttackLimb(Vector2 attackSimPosition, Limb ignoredLimb = null)
{
- Hull targetHull = section.gap?.FlowTargetHull;
- if (targetHull != null)
- {
- if (wall.IsHorizontal)
- {
- targetWorldPos.Y = targetHull.WorldRect.Y - targetHull.Rect.Height / 2;
- }
- else
- {
- targetWorldPos.X = targetHull.WorldRect.Center.X;
- }
- latchOntoAI?.DeattachFromBody();
- Character.AnimController.ReleaseStuckLimbs();
- if (steeringManager is IndoorsSteeringManager)
- {
- steeringManager.SteeringManual(deltaTime, Vector2.Normalize(targetWorldPos - Character.WorldPosition));
- }
- else
- {
- steeringManager.SteeringSeek(ConvertUnits.ToSimUnits(targetWorldPos));
- }
- return true;
+ AttackContext currentContext = Character.GetAttackContext();
+ var target = wallTarget != null ? wallTarget.Structure : SelectedAiTarget.Entity;
+ var limbs = Character.AnimController.Limbs
+ .Where(l =>
+ l != ignoredLimb &&
+ l.attack != null &&
+ !l.IsSevered &&
+ !l.IsStuck &&
+ l.attack.IsValidContext(currentContext) &&
+ l.attack.IsValidTarget(target) &&
+ l.attack.Conditionals.All(c => (target is ISerializableEntity se && c.Matches(se)) || !(target is ISerializableEntity) || !(target is Character)))
+ .OrderByDescending(l => l.attack.Priority)
+ .ThenBy(l => ConvertUnits.ToDisplayUnits(Vector2.Distance(l.SimPosition, attackSimPosition)));
+ // TODO: priority should probably not override the distance -> use values instead of booleans
+ return limbs.FirstOrDefault();
+ }
+
+ private void UpdateWallTarget()
+ {
+ wallTarget = null;
+
+ if (Character.AnimController.CurrentHull != null)
+ {
+ return;
}
return false;
}
@@ -794,66 +810,84 @@ namespace Barotrauma
wallTarget = null;
//check if there's a wall between the target and the Character
- Vector2 rayStart = SimPosition;
+ Vector2 rayStart = Character.SimPosition;
Vector2 rayEnd = SelectedAiTarget.SimPosition;
- bool offset = SelectedAiTarget.Entity.Submarine != null && Character.Submarine == null;
- if (offset)
+ if (SelectedAiTarget.Entity.Submarine != null && Character.Submarine == null)
{
- rayStart -= SelectedAiTarget.Entity.Submarine.SimPosition;
+ rayStart -= ConvertUnits.ToSimUnits(SelectedAiTarget.Entity.Submarine.Position);
}
- Body closestBody = Submarine.CheckVisibility(rayStart, rayEnd, ignoreSubs: true);
-
+ Body closestBody = Submarine.CheckVisibility(rayStart, rayEnd);
if (Submarine.LastPickedFraction == 1.0f || closestBody == null)
{
return;
}
- if (closestBody.UserData is Structure wall && wall.Submarine != null)
+ Structure wall = closestBody.UserData as Structure;
+ if (wall?.Submarine == null)
+ {
+ return;
+ /*if (selectedAiTarget.Entity.Submarine != null)
+ {
+ wallTarget = new WallTarget(ConvertUnits.ToDisplayUnits(Submarine.LastPickedPosition), selectedAiTarget.Entity.Submarine);
+ latchOntoAI?.SetAttachTarget(closestBody, selectedAiTarget.Entity.Submarine, Submarine.LastPickedPosition);
+ }*/
+ //if (selectedAiTarget.Entity.Submarine != null && Character.Submarine == null) wallAttackPos += ConvertUnits.ToSimUnits(selectedAiTarget.Entity.Submarine.Position);
+ }
+ else
{
int sectionIndex = wall.FindSectionIndex(ConvertUnits.ToDisplayUnits(Submarine.LastPickedPosition));
+ int passableHoleCount = GetMinimumPassableHoleCount();
float sectionDamage = wall.SectionDamage(sectionIndex);
for (int i = sectionIndex - 2; i <= sectionIndex + 2; i++)
{
if (wall.SectionBodyDisabled(i))
{
- if (aggressiveBoarding && CanPassThroughHole(wall, i))
+ if (aggressiveBoarding && CanPassThroughHole(wall, i)) //aggressive boarders always target holes they can pass through
{
- //aggressive boarders always target holes they can pass through
sectionIndex = i;
break;
}
- else
+ else //otherwise ignore and keep breaking other sections
{
- //otherwise ignore and keep breaking other sections
continue;
}
}
if (wall.SectionDamage(i) > sectionDamage) sectionIndex = i;
}
- Vector2 sectionPos = wall.SectionPosition(sectionIndex);
+ Vector2 sectionPos = ConvertUnits.ToSimUnits(wall.SectionPosition(sectionIndex));
Vector2 attachTargetNormal;
if (wall.IsHorizontal)
{
- attachTargetNormal = new Vector2(0.0f, Math.Sign(WorldPosition.Y - wall.WorldPosition.Y));
- sectionPos.Y += (wall.BodyHeight <= 0.0f ? wall.Rect.Height : wall.BodyHeight) / 2 * attachTargetNormal.Y;
+ attachTargetNormal = new Vector2(0.0f, Math.Sign(Character.WorldPosition.Y - wall.WorldPosition.Y));
+ sectionPos.Y += ConvertUnits.ToSimUnits((wall.BodyHeight <= 0.0f ? wall.Rect.Height : wall.BodyHeight) / 2) * attachTargetNormal.Y;
}
else
{
- attachTargetNormal = new Vector2(Math.Sign(WorldPosition.X - wall.WorldPosition.X), 0.0f);
- sectionPos.X += (wall.BodyWidth <= 0.0f ? wall.Rect.Width : wall.BodyWidth) / 2 * attachTargetNormal.X;
+ attachTargetNormal = new Vector2(Math.Sign(Character.WorldPosition.X - wall.WorldPosition.X), 0.0f);
+ sectionPos.X += ConvertUnits.ToSimUnits((wall.BodyWidth <= 0.0f ? wall.Rect.Width : wall.BodyWidth) / 2) * attachTargetNormal.X;
}
- latchOntoAI?.SetAttachTarget(wall.Submarine.PhysicsBody.FarseerBody, wall.Submarine, ConvertUnits.ToSimUnits(sectionPos), attachTargetNormal);
- wallTarget = new WallTarget(sectionPos, wall, sectionIndex);
+ wallTarget = new WallTarget(ConvertUnits.ToDisplayUnits(sectionPos), wall, sectionIndex);
+ latchOntoAI?.SetAttachTarget(wall.Submarine.PhysicsBody.FarseerBody, wall.Submarine, sectionPos, attachTargetNormal);
}
}
public override void OnAttacked(Character attacker, AttackResult attackResult)
{
updateTargetsTimer = Math.Min(updateTargetsTimer, 0.1f);
+
+ // Reduce the cooldown so that the character can react
+ foreach (var limb in Character.AnimController.Limbs)
+ {
+ if (limb.attack != null)
+ {
+ limb.attack.CoolDownTimer *= 0.1f;
+ // secondary cooldown?
+ }
+ }
if (attackResult.Damage > 0.0f && attackWhenProvoked)
{
@@ -868,60 +902,37 @@ namespace Barotrauma
Character.AnimController.ReleaseStuckLimbs();
if (attacker == null || attacker.AiTarget == null) return;
- AITargetMemory targetMemory = GetTargetMemory(attacker.AiTarget);
+ AITargetMemory targetMemory = FindTargetMemory(attacker.AiTarget);
targetMemory.Priority += GetRelativeDamage(attackResult.Damage, Character.Vitality) * aggressionhurt;
-
- // Reduce the cooldown so that the character can react
- // Only allow to react once. Otherwise would attack the target with only a fraction of cooldown
- if (SelectedAiTarget != attacker.AiTarget)
- {
- foreach (var limb in Character.AnimController.Limbs)
- {
- if (limb.attack != null)
- {
- limb.attack.CoolDownTimer *= 0.1f;
- }
- }
- }
}
// 10 dmg, 100 health -> 0.1
private float GetRelativeDamage(float dmg, float vitality) => dmg / Math.Max(vitality, 1.0f);
- private void UpdateLimbAttack(float deltaTime, Limb limb, Vector2 attackSimPos, float distance = -1)
+ private void UpdateLimbAttack(float deltaTime, Limb limb, Vector2 attackPosition, float distance = -1)
{
- if (SelectedAiTarget == null) { return; }
- if (wallTarget != null)
+ var damageTarget = wallTarget != null ? wallTarget.Structure : SelectedAiTarget.Entity as IDamageable;
+ if (damageTarget == null) return;
+
+ float prevHealth = damageTarget.Health;
+ if (limb.UpdateAttack(deltaTime, attackPosition, damageTarget, out AttackResult attackResult, distance))
{
- // If the selected target is not the wall target, make the wall target the selected target.
- var aiTarget = wallTarget.Structure.AiTarget;
- if (aiTarget != null && SelectedAiTarget != aiTarget)
+ if (damageTarget.Health > 0)
{
- SelectTarget(aiTarget);
+ // Managed to hit a living/non-destroyed target. Increase the priority more if the target is low in health -> dies easily/soon
+ selectedTargetMemory.Priority += GetRelativeDamage(attackResult.Damage, damageTarget.Health) * aggressiongreed;
}
}
- if (SelectedAiTarget.Entity is IDamageable damageTarget)
+
+ if (!limb.attack.IsRunning)
{
- float prevHealth = damageTarget.Health;
- if (limb.UpdateAttack(deltaTime, attackSimPos, damageTarget, out AttackResult attackResult, distance))
- {
- if (damageTarget.Health > 0)
- {
- // Managed to hit a living/non-destroyed target. Increase the priority more if the target is low in health -> dies easily/soon
- selectedTargetMemory.Priority += GetRelativeDamage(attackResult.Damage, damageTarget.Health) * aggressiongreed;
- }
- else
- {
- selectedTargetMemory.Priority = 0;
- }
- }
+ wallTarget = null;
}
}
- private void UpdateFallBack(Vector2 attackWorldPos, float deltaTime)
+ private void UpdateFallBack(Vector2 attackPosition, float deltaTime)
{
- Vector2 attackVector = attackWorldPos - WorldPosition;
- float dist = attackVector.Length();
+ float dist = Vector2.Distance(attackPosition, Character.SimPosition);
float desiredDist = colliderSize * 2.0f;
if (dist < desiredDist)
{
@@ -929,6 +940,7 @@ namespace Barotrauma
if (!MathUtils.IsValid(attackDir)) attackDir = Vector2.UnitY;
steeringManager.SteeringManual(deltaTime, attackDir * (1.0f - (dist / 500.0f)));
}
+
steeringManager.SteeringAvoid(deltaTime, colliderSize * 3.0f);
}
@@ -979,20 +991,15 @@ namespace Barotrauma
//goes through all the AItargets, evaluates how preferable it is to attack the target,
//whether the Character can see/hear the target and chooses the most preferable target within
//sight/hearing range
- public AITarget UpdateTargets(Character character, out TargetingPriority priority)
+ public void UpdateTargets(Character character, out TargetingPriority targetingPriority)
{
- if (IsProperlyLatched)
- {
- // If attached to a valid target, just keep the target.
- // Priority not used in this case.
- priority = null;
- return SelectedAiTarget;
- }
- AITarget newTarget = null;
- priority = null;
+ targetingPriority = null;
+ SelectedAiTarget = null;
selectedTargetMemory = null;
targetValue = 0.0f;
+ UpdateTargetMemories();
+
foreach (AITarget target in AITarget.List)
{
if (!target.Enabled) continue;
@@ -1001,57 +1008,29 @@ namespace Barotrauma
continue;
}
+ float valueModifier = 1.0f;
+ float dist = 0.0f;
+
Character targetCharacter = target.Entity as Character;
//ignore the aitarget if it is the Character itself
if (targetCharacter == character) continue;
- float valueModifier = 1;
string targetingTag = null;
if (targetCharacter != null)
{
- if (targetCharacter.IsDead)
+ if (targetCharacter.Submarine != null && Character.Submarine == null)
+ {
+ //target inside, AI outside -> we'll be attacking a wall between the characters so use the priority for attacking rooms
+ targetingTag = "room";
+ }
+ else if (targetCharacter.IsDead)
{
targetingTag = "dead";
- if (targetCharacter.Submarine != Character.Submarine)
- {
- // In a different sub or the target is outside when we are inside or vice versa -> Ignore the target
- continue;
- }
- else if (targetCharacter.CurrentHull != Character.CurrentHull)
- {
- // In the same sub, halve the priority, if not in the same hull.
- valueModifier = 0.5f;
- }
}
- else if (targetCharacter.AIController is EnemyAIController enemy)
+ else if (targetingPriorities.ContainsKey(targetCharacter.SpeciesName.ToLowerInvariant()))
{
- if (enemy.combatStrength > combatStrength)
- {
- targetingTag = "stronger";
- }
- else if (enemy.combatStrength < combatStrength)
- {
- targetingTag = "weaker";
- }
- if (State == AIState.Escape && targetingTag == "stronger")
- {
- // Frightened
- valueModifier = 2;
- }
- else
- {
- if (targetCharacter.Submarine != Character.Submarine)
- {
- // In a different sub or the target is outside when we are inside or vice versa -> Ignore the target
- continue;
- }
- else if (targetCharacter.CurrentHull != Character.CurrentHull)
- {
- // In the same sub, halve the priority, if not in the same hull.
- valueModifier = 0.5f;
- }
- }
+ targetingTag = targetCharacter.SpeciesName.ToLowerInvariant();
}
else if (targetCharacter.Submarine != null && Character.Submarine == null)
{
@@ -1068,6 +1047,42 @@ namespace Barotrauma
//skip the target if it's a room and the character is already inside a sub
if (character.CurrentHull != null && target.Entity is Hull) continue;
+ Door door = null;
+ if (target.Entity is Item item)
+ {
+ if (targetCharacter.AIController is EnemyAIController enemy)
+ {
+ targetingTag = "room";
+ }
+
+ door = item.GetComponent();
+ foreach (TargetingPriority prio in targetingPriorities.Values)
+ {
+ if (item.HasTag(prio.TargetTag))
+ {
+ targetingTag = "stronger";
+ }
+ }
+ }
+ else if (target.Entity is Structure s)
+ {
+ targetingTag = "wall";
+ if (aggressiveBoarding)
+ {
+ // Ignore walls when inside.
+ valueModifier = character.CurrentHull == null ? 2 : 0;
+ if (valueModifier > 0)
+ {
+ targetingTag = "weaker";
+ }
+ }
+ }
+ }
+ else if (target.Entity != null)
+ {
+ //skip the target if it's a room and the character is already inside a sub
+ if (character.CurrentHull != null && target.Entity is Hull) continue;
+
Door door = null;
if (target.Entity is Item item)
{
@@ -1087,63 +1102,19 @@ namespace Barotrauma
}
}
}
- else if (target.Entity is Structure s)
- {
- targetingTag = "wall";
- if (aggressiveBoarding)
- {
- // Ignore walls when inside.
- valueModifier = character.CurrentHull == null ? 2 : 0;
- if (valueModifier > 0)
- {
- // Ignore structures that doesn't have a body (not walls)
- valueModifier *= s.HasBody ? 1 : 0;
- }
- for (int i = 0; i < s.Sections.Length; i++)
- {
- var section = s.Sections[i];
- if (CanPassThroughHole(s, i))
- {
- // Ignore walls that can be passed through
- valueModifier = 0;
- break;
- }
- else if (section.gap != null)
- {
- // up to 100% priority increase for every gap in the wall
- valueModifier *= 1 + section.gap.Open;
- }
- }
- }
- }
else
{
targetingTag = "room";
}
+
if (door != null)
{
- // If there's not a more specific tag for the door
- if (string.IsNullOrEmpty(targetingTag) || targetingTag == "room")
- {
- targetingTag = "door";
- }
- bool isOutdoor = door.LinkedGap?.FlowTargetHull != null && !door.LinkedGap.IsRoomToRoom;
- bool isOpen = door.IsOpen || door.Item.Condition <= 0.0f;
//increase priority if the character is outside and an aggressive boarder, and the door is from outside to inside
- if (aggressiveBoarding)
+ if (character.CurrentHull == null && aggressiveBoarding && !door.LinkedGap.IsRoomToRoom)
{
- if (character.CurrentHull == null)
- {
- valueModifier = isOutdoor ? 1 : 0;
- valueModifier *= isOpen ? 5 : 1;
- }
- else
- {
- valueModifier = isOutdoor ? 0 : 1;
- valueModifier *= isOpen ? 0 : 1;
- }
+ valueModifier = door.IsOpen ? 10 : 5;
}
- else if (isOpen) //ignore broken and open doors
+ else if (door.IsOpen || door.Item.Condition <= 0.0f) //ignore broken and open doors
{
continue;
}
@@ -1162,7 +1133,7 @@ namespace Barotrauma
if (valueModifier == 0.0f) continue;
Vector2 toTarget = target.WorldPosition - character.WorldPosition;
- float dist = toTarget.Length();
+ dist = toTarget.Length();
//if the target has been within range earlier, the character will notice it more easily
//(i.e. remember where the target was)
@@ -1176,29 +1147,28 @@ namespace Barotrauma
// -> just ignore the distance and attack whatever has the highest priority
dist = Math.Max(dist, 100.0f);
- AITargetMemory targetMemory = GetTargetMemory(target);
+ AITargetMemory targetMemory = FindTargetMemory(target);
if (Character.CurrentHull != null && Math.Abs(toTarget.Y) > Character.CurrentHull.Size.Y)
{
// Inside the sub, treat objects that are up or down, as they were farther away.
dist *= 3;
}
- valueModifier *= targetMemory.Priority / (float)Math.Sqrt(dist);
+ valueModifier = valueModifier * targetMemory.Priority / (float)Math.Sqrt(dist);
if (valueModifier > targetValue)
{
- newTarget = target;
+ SelectedAiTarget = target;
selectedTargetMemory = targetMemory;
- priority = targetingPriorities[targetingTag];
+ targetingPriority = targetingPriorities[targetingTag];
targetValue = valueModifier;
}
}
- SelectedAiTarget = newTarget;
if (SelectedAiTarget != _previousAiTarget)
{
wallTarget = null;
}
- return SelectedAiTarget;
+ _previousAiTarget = SelectedAiTarget;
}
private AITargetMemory GetTargetMemory(AITarget target)
@@ -1208,21 +1178,24 @@ namespace Barotrauma
memory = new AITargetMemory(10);
targetMemories.Add(target, memory);
}
+
+ memory = new AITargetMemory(10.0f);
+ targetMemories.Add(target, memory);
+
return memory;
}
private List removals = new List();
private void UpdateTargetMemories(float deltaTime)
{
- removals.Clear();
- foreach (var memory in targetMemories)
+ List toBeRemoved = null;
+ foreach (KeyValuePair memory in targetMemories)
{
- // Slowly decrease all memories
- memory.Value.Priority -= memoryFadeTime * deltaTime;
- // Remove targets that have no priority or have been removed
- if (memory.Value.Priority <= 1 || !AITarget.List.Contains(memory.Key))
+ memory.Value.Priority += 0.1f;
+ if (Math.Abs(memory.Value.Priority) < 1.0f || !AITarget.List.Contains(memory.Key))
{
- removals.Add(memory.Key);
+ if (toBeRemoved == null) toBeRemoved = new List();
+ toBeRemoved.Add(memory.Key);
}
}
removals.ForEach(r => targetMemories.Remove(r));
@@ -1238,9 +1211,25 @@ namespace Barotrauma
wallTarget = null;
}
+ if (toBeRemoved != null)
+ {
+ foreach (AITarget target in toBeRemoved)
+ {
+ targetMemories.Remove(target);
+ }
+ }
+
+ #endregion
+
+ protected override void OnStateChanged(AIState from, AIState to)
+ {
+ latchOntoAI?.DeattachFromBody();
+ Character.AnimController.ReleaseStuckLimbs();
+ }
+
private int GetMinimumPassableHoleCount()
{
- return (int)Math.Ceiling(ConvertUnits.ToDisplayUnits(colliderSize) / Structure.WallSectionSize);
+ return (int)Math.Ceiling(ConvertUnits.ToDisplayUnits(colliderSize) / Structure.WallSectionSize);
}
private bool CanPassThroughHole(Structure wall, int sectionIndex)
diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/HumanAIController.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/HumanAIController.cs
index a232f65d1..76a151069 100644
--- a/Barotrauma/BarotraumaShared/Source/Characters/AI/HumanAIController.cs
+++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/HumanAIController.cs
@@ -245,7 +245,7 @@ namespace Barotrauma
foreach (Character c in Character.CharacterList)
{
if (c.CurrentHull == Character.CurrentHull && !c.IsDead &&
- (c.AIController is EnemyAIController || (c.TeamID != Character.TeamID && Character.TeamID != Character.TeamType.FriendlyNPC && c.TeamID != Character.TeamType.FriendlyNPC)))
+ (c.AIController is EnemyAIController || c.TeamID != Character.TeamID))
{
var orderPrefab = Order.PrefabList.Find(o => o.AITag == "reportintruders");
newOrder = new Order(orderPrefab, Character.CurrentHull, null);
@@ -290,7 +290,7 @@ namespace Barotrauma
public override void OnAttacked(Character attacker, AttackResult attackResult)
{
float damage = attackResult.Damage;
- if (damage <= 0) { return; }
+ if (damage < 0) { return; }
if (attacker == null || attacker.IsDead || attacker.Removed)
{
if (objectiveManager.CurrentOrder == null)
@@ -466,9 +466,7 @@ namespace Barotrauma
// Even the smallest fire reduces the safety by 50%
float fire = hull.FireSources.Count * 0.5f + hull.FireSources.Sum(fs => fs.DamageRange) / hull.Size.X;
float fireFactor = ignoreFire ? 1 : MathHelper.Lerp(1, 0, MathHelper.Clamp(fire, 0, 1));
- int enemyCount = Character.CharacterList.Count(e =>
- e.CurrentHull == hull && !e.IsDead && !e.IsUnconscious &&
- (e.AIController is EnemyAIController || (e.TeamID != character.TeamID && character.TeamID != Character.TeamType.FriendlyNPC && e.TeamID != Character.TeamType.FriendlyNPC)));
+ int enemyCount = Character.CharacterList.Count(e => e.CurrentHull == hull && !e.IsDead && !e.IsUnconscious && (e.AIController is EnemyAIController || e.TeamID != character.TeamID));
// The hull safety decreases 90% per enemy up to 100% (TODO: test smaller percentages)
float enemyFactor = ignoreEnemies ? 1 : MathHelper.Lerp(1, 0, MathHelper.Clamp(enemyCount * 0.9f, 0, 1));
float safety = oxygenFactor * waterFactor * fireFactor * enemyFactor;
diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/LatchOntoAI.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/LatchOntoAI.cs
index fe5304a4c..200e20a5a 100644
--- a/Barotrauma/BarotraumaShared/Source/Characters/AI/LatchOntoAI.cs
+++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/LatchOntoAI.cs
@@ -193,7 +193,7 @@ namespace Barotrauma
// is not attached or is attached to something else
if (!IsAttached || IsAttached && attachJoints[0].BodyB == attachTargetBody)
{
- if (Vector2.DistanceSquared(ConvertUnits.ToDisplayUnits(transformedAttachPos), enemyAI.AttackingLimb.WorldPosition) < enemyAI.AttackingLimb.attack.DamageRange * enemyAI.AttackingLimb.attack.DamageRange)
+ if (Vector2.DistanceSquared(ConvertUnits.ToDisplayUnits(transformedAttachPos), enemyAI.AttackingLimb.WorldPosition) < enemyAI.AttackingLimb.attack.Range * enemyAI.AttackingLimb.attack.Range)
{
AttachToBody(character.AnimController.Collider, attachLimb, attachTargetBody, transformedAttachPos);
}
diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveContainItem.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveContainItem.cs
index 7fccbf418..398b37f6b 100644
--- a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveContainItem.cs
+++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveContainItem.cs
@@ -95,7 +95,7 @@ namespace Barotrauma
getItemObjective = new AIObjectiveGetItem(character, itemIdentifiers)
{
GetItemPriority = GetItemPriority,
- ignoredContainerIdentifiers = ignoredContainerIdentifiers
+ IgnoreContainedItems = IgnoreAlreadyContainedItems
};
AddSubObjective(getItemObjective);
return;
diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveFindSafety.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveFindSafety.cs
index f3afac468..a7b1f8993 100644
--- a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveFindSafety.cs
+++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveFindSafety.cs
@@ -115,7 +115,6 @@ namespace Barotrauma
unreachable.Add(goToObjective.Target as Hull);
}
goToObjective = null;
- SteeringManager.SteeringWander();
}
}
else if (currentHull != null)
@@ -132,11 +131,6 @@ namespace Barotrauma
foreach (Character enemy in Character.CharacterList)
{
- //don't run from friendly NPCs
- if (enemy.TeamID == Character.TeamType.FriendlyNPC) { continue; }
- //friendly NPCs don't run away from anything but characters controlled by EnemyAIController (= monsters)
- if (character.TeamID == Character.TeamType.FriendlyNPC && !(enemy.AIController is EnemyAIController)) { continue; }
-
if (enemy.CurrentHull == currentHull && !enemy.IsDead && !enemy.IsUnconscious &&
(enemy.AIController is EnemyAIController || enemy.TeamID != character.TeamID))
{
diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveGetItem.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveGetItem.cs
index 7f20924c1..1a2ce2e76 100644
--- a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveGetItem.cs
+++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveGetItem.cs
@@ -17,7 +17,7 @@ namespace Barotrauma
private string[] itemIdentifiers;
private Item targetItem, moveToTarget;
private int currSearchIndex;
- public string[] ignoredContainerIdentifiers;
+ public bool IgnoreContainedItems;
private AIObjectiveGoTo goToObjective;
private float currItemPriority;
private bool equip;
@@ -99,12 +99,11 @@ namespace Barotrauma
FindTargetItem();
if (targetItem == null || moveToTarget == null)
{
- SteeringManager.SteeringWander();
+ SteeringManager.Reset();
return;
}
- if (moveToTarget.CurrentHull == character.CurrentHull &&
- Vector2.DistanceSquared(character.Position, moveToTarget.Position) < MathUtils.Pow(targetItem.InteractDistance * 2, 2))
+ if (Vector2.DistanceSquared(character.Position, moveToTarget.Position) < MathUtils.Pow(targetItem.InteractDistance * 2, 2))
{
int targetSlot = -1;
if (equip)
@@ -197,12 +196,8 @@ namespace Barotrauma
else if (character.Submarine != null && !character.Submarine.IsEntityFoundOnThisSub(item, true)) { continue; }
if (item.CurrentHull == null || item.Condition <= 0.0f) { continue; }
- if (itemIdentifiers.None(id => item.Prefab.Identifier == id || item.HasTag(id))) { continue; }
-
- if (ignoredContainerIdentifiers != null && item.Container != null)
- {
- if (ignoredContainerIdentifiers.Contains(item.ContainerIdentifier)) { continue; }
- }
+ if (IgnoreContainedItems && item.Container != null) { continue; }
+ if (!itemIdentifiers.Any(id => item.Prefab.Identifier == id || item.HasTag(id))) { continue; }
//if the item is inside a character's inventory, don't steal it unless the character is dead
if (item.ParentInventory is CharacterInventory)
diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Animation/FishAnimController.cs b/Barotrauma/BarotraumaShared/Source/Characters/Animation/FishAnimController.cs
index 37364e0bf..11a8756a6 100644
--- a/Barotrauma/BarotraumaShared/Source/Characters/Animation/FishAnimController.cs
+++ b/Barotrauma/BarotraumaShared/Source/Characters/Animation/FishAnimController.cs
@@ -369,16 +369,7 @@ namespace Barotrauma
float movementAngle = MathUtils.VectorToAngle(movement) - MathHelper.PiOver2;
- float mainLimbAngle = 0;
- if (MainLimb.type == LimbType.Torso && TorsoAngle.HasValue)
- {
- mainLimbAngle = TorsoAngle.Value;
- }
- else if (MainLimb.type == LimbType.Head && HeadAngle.HasValue)
- {
- mainLimbAngle = HeadAngle.Value;
- }
- mainLimbAngle *= Dir;
+ float mainLimbAngle = (MainLimb.type == LimbType.Torso ? TorsoAngle.Value : HeadAngle.Value) * Dir;
while (MainLimb.Rotation - (movementAngle + mainLimbAngle) > MathHelper.Pi)
{
movementAngle += MathHelper.TwoPi;
@@ -417,7 +408,7 @@ namespace Barotrauma
}
}
}
- else
+ else if (MainLimb.type == LimbType.Head && HeadAngle.HasValue)
{
movementAngle = Dir > 0 ? -MathHelper.PiOver2 : MathHelper.PiOver2;
if (MainLimb.type == LimbType.Head && HeadAngle.HasValue)
@@ -692,6 +683,12 @@ namespace Barotrauma
limb.body.ApplyForce(diff * (float)(Math.Sin(WalkPos) * Math.Sqrt(limb.Mass)) * 30.0f * animStrength);
}
+ while (referenceLimb.Rotation - angle < -MathHelper.TwoPi)
+ {
+ angle -= MathHelper.TwoPi;
+ }
+
+ limb?.body.SmoothRotate(angle, torque, wrapAngle: false);
}
private void SmoothRotateWithoutWrapping(Limb limb, float angle, Limb referenceLimb, float torque)
diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Animation/Params/Animation/AnimationParams.cs b/Barotrauma/BarotraumaShared/Source/Characters/Animation/Params/Animation/AnimationParams.cs
index 0d3b77f8a..4c8d56679 100644
--- a/Barotrauma/BarotraumaShared/Source/Characters/Animation/Params/Animation/AnimationParams.cs
+++ b/Barotrauma/BarotraumaShared/Source/Characters/Animation/Params/Animation/AnimationParams.cs
@@ -99,7 +99,7 @@ namespace Barotrauma
public static string GetDefaultFolder(string speciesName) => $"Content/Characters/{speciesName.CapitaliseFirstInvariant()}/Animations/";
public static string GetDefaultFile(string speciesName, AnimationType animType) => $"{GetFolder(speciesName)}{GetDefaultFileName(speciesName, animType)}.xml";
- public static string GetFolder(string speciesName)
+ protected static string GetFolder(string speciesName)
{
var folder = XMLExtensions.TryLoadXml(Character.GetConfigFile(speciesName))?.Root?.Element("animations")?.GetAttributeString("folder", string.Empty);
if (string.IsNullOrEmpty(folder) || folder.ToLowerInvariant() == "default")
diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Animation/Params/Ragdoll/RagdollParams.cs b/Barotrauma/BarotraumaShared/Source/Characters/Animation/Params/Ragdoll/RagdollParams.cs
index 3f32ca43d..bb2a4d0b4 100644
--- a/Barotrauma/BarotraumaShared/Source/Characters/Animation/Params/Ragdoll/RagdollParams.cs
+++ b/Barotrauma/BarotraumaShared/Source/Characters/Animation/Params/Ragdoll/RagdollParams.cs
@@ -79,7 +79,7 @@ namespace Barotrauma
new XAttribute("sourcerect", $"0, 0, 1, 1")))
};
- public static string GetFolder(string speciesName)
+ protected static string GetFolder(string speciesName)
{
var folder = XMLExtensions.TryLoadXml(Character.GetConfigFile(speciesName))?.Root?.Element("ragdolls")?.GetAttributeString("folder", string.Empty);
if (string.IsNullOrEmpty(folder) || folder.ToLowerInvariant() == "default")
diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Animation/Ragdoll.cs b/Barotrauma/BarotraumaShared/Source/Characters/Animation/Ragdoll.cs
index 82467a761..52dc40baf 100644
--- a/Barotrauma/BarotraumaShared/Source/Characters/Animation/Ragdoll.cs
+++ b/Barotrauma/BarotraumaShared/Source/Characters/Animation/Ragdoll.cs
@@ -1035,6 +1035,8 @@ namespace Barotrauma
CheckValidity();
+ CheckValidity();
+
UpdateNetPlayerPosition(deltaTime);
CheckDistFromCollider();
UpdateCollisionCategories();
@@ -1295,42 +1297,17 @@ namespace Barotrauma
UpdateProjSpecific(deltaTime);
}
- public bool Invalid { get; private set; }
- private int validityResets;
- private bool CheckValidity()
+ private void CheckValidity()
{
- bool isColliderValid = CheckValidity(Collider);
- bool limbsValid = true;
+ CheckValidity(Collider);
foreach (Limb limb in limbs)
{
if (limb.body == null || !limb.body.Enabled) { continue; }
- if (!CheckValidity(limb.body))
- {
- limbsValid = false;
- break;
- }
+ CheckValidity(limb.body);
}
- bool isValid = isColliderValid && limbsValid;
- if (!isValid)
- {
- validityResets++;
- if (validityResets > 1)
- {
- Invalid = true;
- DebugConsole.ThrowError("Invalid ragdoll physics. Ragdoll freezed to prevent crashes.");
- Collider.SetTransform(Vector2.Zero, 0.0f);
- foreach (Limb limb in Limbs)
- {
- limb.body.SetTransform(Collider.SimPosition, 0.0f);
- limb.body.ResetDynamics();
- }
- Frozen = true;
- }
- }
- return isValid;
}
- private bool CheckValidity(PhysicsBody body)
+ private void CheckValidity(PhysicsBody body)
{
string errorMsg = null;
string bodyName = body.UserData is Limb ? "Limb" : "Collider";
@@ -1352,19 +1329,6 @@ namespace Barotrauma
}
if (errorMsg != null)
{
- if (character.IsRemotePlayer)
- {
- errorMsg += " Ragdoll controlled remotely.";
- }
- if (SimplePhysicsEnabled)
- {
- errorMsg += " Simple physics enabled.";
- }
- if (GameMain.NetworkMember != null)
- {
- errorMsg += GameMain.NetworkMember.IsClient ? " Playing as a client." : " Hosting a server.";
- }
-
#if DEBUG
DebugConsole.ThrowError(errorMsg);
#else
@@ -1382,7 +1346,7 @@ namespace Barotrauma
limb.body.ResetDynamics();
}
SetInitialLimbPositions();
- return false;
+ return;
}
return true;
}
diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Character.cs b/Barotrauma/BarotraumaShared/Source/Characters/Character.cs
index c45253b0b..b2dd6e674 100644
--- a/Barotrauma/BarotraumaShared/Source/Characters/Character.cs
+++ b/Barotrauma/BarotraumaShared/Source/Characters/Character.cs
@@ -808,7 +808,6 @@ namespace Barotrauma
public void LoadHeadAttachments()
{
- if (Info == null) { return; }
if (AnimController == null) { return; }
var head = AnimController.GetLimb(LimbType.Head);
if (head == null) { return; }
@@ -1111,15 +1110,13 @@ namespace Barotrauma
ViewTarget = null;
if (!AllowInput) return;
- if (Controlled == this || (GameMain.NetworkMember != null && GameMain.NetworkMember.IsServer))
+ Vector2 smoothedCursorDiff = cursorPosition - SmoothedCursorPosition;
+ if (Controlled == this)
{
SmoothedCursorPosition = cursorPosition;
}
else
{
- //apply some smoothing to the cursor positions of remote players when playing as a client
- //to make aiming look a little less choppy
- Vector2 smoothedCursorDiff = cursorPosition - SmoothedCursorPosition;
smoothedCursorDiff = NetConfig.InterpolateCursorPositionError(smoothedCursorDiff);
SmoothedCursorPosition = cursorPosition - smoothedCursorDiff;
}
@@ -1667,12 +1664,10 @@ namespace Barotrauma
focusedItem = null;
}
findFocusedTimer -= deltaTime;
- }
+ }
#endif
//climb ladders automatically when pressing up/down inside their trigger area
- Ladder currentLadder = SelectedConstruction?.GetComponent();
- if ((SelectedConstruction == null || currentLadder != null) &&
- !AnimController.InWater && Screen.Selected != GameMain.SubEditorScreen)
+ if (SelectedConstruction == null && !AnimController.InWater && Screen.Selected != GameMain.SubEditorScreen)
{
bool climbInput = IsKeyDown(InputType.Up) || IsKeyDown(InputType.Down);
bool isControlled = Controlled == this;
@@ -1683,19 +1678,6 @@ namespace Barotrauma
float minDist = float.PositiveInfinity;
foreach (Ladder ladder in Ladder.List)
{
- if (ladder == currentLadder)
- {
- continue;
- }
- else if (currentLadder != null)
- {
- //only switch from ladder to another if the ladders are above the current ladders and pressing up, or vice versa
- if (ladder.Item.WorldPosition.Y > currentLadder.Item.WorldPosition.Y != IsKeyDown(InputType.Up))
- {
- continue;
- }
- }
-
if (CanInteractWith(ladder.Item, out float dist, checkLinked: false) && dist < minDist)
{
minDist = dist;
@@ -1894,6 +1876,8 @@ namespace Barotrauma
}
speechImpedimentSet = false;
+
+
if (needsAir)
{
bool protectedFromPressure = PressureProtection > 0.0f;
@@ -1950,23 +1934,9 @@ namespace Barotrauma
//Do ragdoll shenanigans before Stun because it's still technically a stun, innit? Less network updates for us!
bool allowRagdoll = GameMain.NetworkMember != null ? GameMain.NetworkMember.ServerSettings.AllowRagdollButton : true;
if (IsForceRagdolled)
- {
IsRagdolled = IsForceRagdolled;
- }
- //Keep us ragdolled if we were forced or we're too speedy to unragdoll
- else if (allowRagdoll && (!IsRagdolled || AnimController.Collider.LinearVelocity.LengthSquared() < 1f))
- {
- if (ragdollingLockTimer > 0.0f)
- {
- ragdollingLockTimer -= deltaTime;
- }
- else
- {
- bool wasRagdolled = IsRagdolled;
- IsRagdolled = IsKeyDown(InputType.Ragdoll); //Handle this here instead of Control because we can stop being ragdolled ourselves
- if (wasRagdolled != IsRagdolled) { ragdollingLockTimer = 0.25f; }
- }
- }
+ else if (allowRagdoll && (!IsRagdolled || AnimController.Collider.LinearVelocity.LengthSquared() < 1f)) //Keep us ragdolled if we were forced or we're too speedy to unragdoll
+ IsRagdolled = IsKeyDown(InputType.Ragdoll); //Handle this here instead of Control because we can stop being ragdolled ourselves
UpdateSightRange();
UpdateSoundRange();
@@ -2548,14 +2518,7 @@ namespace Barotrauma
{
item.Submarine = inventory.Owner.Submarine;
var itemElement = item.Save(parentElement);
-
- List slotIndices = new List();
- for (int i = 0; i < inventory.Capacity; i++)
- {
- if (inventory.Items[i] == item) { slotIndices.Add(i); }
- }
-
- itemElement.Add(new XAttribute("i", string.Join(",", slotIndices)));
+ itemElement.Add(new XAttribute("i", Array.IndexOf(inventory.Items, item)));
foreach (ItemContainer container in item.GetComponents())
{
diff --git a/Barotrauma/BarotraumaShared/Source/Characters/CharacterInfo.cs b/Barotrauma/BarotraumaShared/Source/Characters/CharacterInfo.cs
index aeae1644d..574e99435 100644
--- a/Barotrauma/BarotraumaShared/Source/Characters/CharacterInfo.cs
+++ b/Barotrauma/BarotraumaShared/Source/Characters/CharacterInfo.cs
@@ -801,37 +801,13 @@ namespace Barotrauma
{
foreach (XElement itemElement in element.Elements())
{
- var newItem = Item.Load(itemElement, inventory.Owner.Submarine, createNetworkEvent: true);
- if (newItem == null) { continue; }
+ var newItem = Item.Load(itemElement, inventory.Owner.Submarine);
+ int slotIndex = itemElement.GetAttributeInt("i", 0);
+ if (newItem == null) continue;
- if (!MathUtils.NearlyEqual(newItem.Condition, newItem.MaxCondition))
- {
- GameMain.NetworkMember.CreateEntityEvent(newItem, new object[] { NetEntityEvent.Type.Status });
- }
+ SpawnInventoryItemProjSpecific(newItem);
- int[] slotIndices = itemElement.GetAttributeIntArray("i", new int[] { 0 });
- if (!slotIndices.Any())
- {
- DebugConsole.ThrowError("Invalid inventory data in character \"" + Name + "\" - no slot indices found");
- continue;
- }
-
- inventory.TryPutItem(newItem, slotIndices[0], false, false, null);
-
- //force the item to the correct slots
- // e.g. putting the item in a hand slot will also put it in the first available Any-slot,
- // which may not be where it actually was
- for (int i = 0; i < inventory.Capacity; i++)
- {
- if (slotIndices.Contains(i))
- {
- inventory.Items[i] = newItem;
- }
- else if (inventory.Items[i] == newItem)
- {
- inventory.Items[i] = null;
- }
- }
+ inventory.TryPutItem(newItem, slotIndex, false, false, null);
int itemContainerIndex = 0;
var itemContainers = newItem.GetComponents().ToList();
@@ -845,6 +821,8 @@ namespace Barotrauma
}
}
+ partial void SpawnInventoryItemProjSpecific(Item item);
+
public void ReloadHeadAttachments()
{
ResetLoadedAttachments();
diff --git a/Barotrauma/BarotraumaShared/Source/Characters/CharacterNetworking.cs b/Barotrauma/BarotraumaShared/Source/Characters/CharacterNetworking.cs
index 500b69c5e..f0b5af9d2 100644
--- a/Barotrauma/BarotraumaShared/Source/Characters/CharacterNetworking.cs
+++ b/Barotrauma/BarotraumaShared/Source/Characters/CharacterNetworking.cs
@@ -13,17 +13,17 @@ namespace Barotrauma
public readonly AnimController.Animation Animation;
- public CharacterStateInfo(Vector2 pos, float? rotation, Vector2 velocity, float? angularVelocity, float time, Direction dir, Entity interact, AnimController.Animation animation = AnimController.Animation.None)
+ public CharacterStateInfo(Vector2 pos, float rotation, Vector2 velocity, float angularVelocity, float time, Direction dir, Entity interact, AnimController.Animation animation = AnimController.Animation.None)
: this(pos, rotation, velocity, angularVelocity, 0, time, dir, interact, animation)
{
}
- public CharacterStateInfo(Vector2 pos, float? rotation, UInt16 ID, Direction dir, Entity interact, AnimController.Animation animation = AnimController.Animation.None)
+ public CharacterStateInfo(Vector2 pos, float rotation, UInt16 ID, Direction dir, Entity interact, AnimController.Animation animation = AnimController.Animation.None)
: this(pos, rotation, Vector2.Zero, 0.0f, ID, 0.0f, dir, interact, animation)
{
}
- protected CharacterStateInfo(Vector2 pos, float? rotation, Vector2 velocity, float? angularVelocity, UInt16 ID, float time, Direction dir, Entity interact, AnimController.Animation animation = AnimController.Animation.None)
+ protected CharacterStateInfo(Vector2 pos, float rotation, Vector2 velocity, float angularVelocity, UInt16 ID, float time, Direction dir, Entity interact, AnimController.Animation animation = AnimController.Animation.None)
: base(pos, rotation, velocity, angularVelocity, ID, time)
{
Direction = dir;
diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Health/Afflictions/AfflictionPrefab.cs b/Barotrauma/BarotraumaShared/Source/Characters/Health/Afflictions/AfflictionPrefab.cs
index 708e62bee..ad1261170 100644
--- a/Barotrauma/BarotraumaShared/Source/Characters/Health/Afflictions/AfflictionPrefab.cs
+++ b/Barotrauma/BarotraumaShared/Source/Characters/Health/Afflictions/AfflictionPrefab.cs
@@ -151,12 +151,9 @@ namespace Barotrauma
//how high the strength has to be for the affliction to take affect
public readonly float ActivationThreshold = 0.0f;
//how high the strength has to be for the affliction icon to be shown in the UI
- public readonly float ShowIconThreshold = 0.05f;
+ public readonly float ShowIconThreshold = 0.0f;
public readonly float MaxStrength = 100.0f;
-
- //how high the strength has to be for the affliction icon to be shown with a health scanner
- public readonly float ShowInHealthScannerThreshold = 0.05f;
-
+
public float BurnOverlayAlpha;
public float DamageOverlayAlpha;
@@ -257,11 +254,9 @@ namespace Barotrauma
}
ActivationThreshold = element.GetAttributeFloat("activationthreshold", 0.0f);
- ShowIconThreshold = element.GetAttributeFloat("showiconthreshold", Math.Max(ActivationThreshold, 0.05f));
+ ShowIconThreshold = element.GetAttributeFloat("showiconthreshold", ActivationThreshold);
MaxStrength = element.GetAttributeFloat("maxstrength", 100.0f);
- ShowInHealthScannerThreshold = element.GetAttributeFloat("showinhealthscannerthreshold", Math.Max(ActivationThreshold, 0.05f));
-
DamageOverlayAlpha = element.GetAttributeFloat("damageoverlayalpha", 0.0f);
BurnOverlayAlpha = element.GetAttributeFloat("burnoverlayalpha", 0.0f);
diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Health/CharacterHealth.cs b/Barotrauma/BarotraumaShared/Source/Characters/Health/CharacterHealth.cs
index 5d6f70a83..dff106cfb 100644
--- a/Barotrauma/BarotraumaShared/Source/Characters/Health/CharacterHealth.cs
+++ b/Barotrauma/BarotraumaShared/Source/Characters/Health/CharacterHealth.cs
@@ -460,7 +460,6 @@ namespace Barotrauma
{
affliction.Strength = 0.0f;
}
- CalculateVitality();
}
private void AddLimbAffliction(Limb limb, Affliction newAffliction)
diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Limb.cs b/Barotrauma/BarotraumaShared/Source/Characters/Limb.cs
index b19684c74..bb595803c 100644
--- a/Barotrauma/BarotraumaShared/Source/Characters/Limb.cs
+++ b/Barotrauma/BarotraumaShared/Source/Characters/Limb.cs
@@ -491,10 +491,10 @@ namespace Barotrauma
///
/// Returns true if the attack successfully hit something. If the distance is not given, it will be calculated.
///
- public bool UpdateAttack(float deltaTime, Vector2 attackSimPos, IDamageable damageTarget, out AttackResult attackResult, float distance = -1)
+ public bool UpdateAttack(float deltaTime, Vector2 attackPosition, IDamageable damageTarget, out AttackResult attackResult, float distance = -1)
{
attackResult = default(AttackResult);
- float dist = distance > -1 ? distance : ConvertUnits.ToDisplayUnits(Vector2.Distance(SimPosition, attackSimPos));
+ float dist = distance > -1 ? distance : ConvertUnits.ToDisplayUnits(Vector2.Distance(SimPosition, attackPosition));
bool wasRunning = attack.IsRunning;
attack.UpdateAttackTimer(deltaTime);
@@ -511,7 +511,7 @@ namespace Barotrauma
ignoredBodies.Add(character.AnimController.Collider.FarseerBody);
structureBody = Submarine.PickBody(
- SimPosition, attackSimPos,
+ SimPosition, attackPosition,
ignoredBodies, Physics.CollisionWall);
if (damageTarget is Item)
@@ -520,15 +520,14 @@ namespace Barotrauma
// Ignore blocking on items, because it causes cases where a Mudraptor cannot hit the hatch, for example.
wasHit = true;
}
- else if (damageTarget is Structure wall && structureBody != null &&
- (structureBody.UserData is Structure || (structureBody.UserData is Submarine sub && sub == wall.Submarine)))
+ else if (damageTarget is Structure && structureBody?.UserData is Structure)
{
- // If the attack is aimed to a structure (wall) and hits a structure or the sub, it's successful
+ // If the attack is aimed to a structure and hits a structure, it's successful
wasHit = true;
}
else
{
- // If there is nothing between, the hit is successful
+ // If the attack is aimed to a character but hits a structure, the hit is blocked.
wasHit = structureBody == null;
}
}
@@ -608,7 +607,7 @@ namespace Barotrauma
attack.SetCoolDown();
}
- Vector2 diff = attackSimPos - SimPosition;
+ Vector2 diff = attackPosition - SimPosition;
bool applyForces = (!attack.ApplyForcesOnlyOnce || !wasRunning) && diff.LengthSquared() > 0.00001f;
if (applyForces)
{
@@ -621,13 +620,13 @@ namespace Barotrauma
Limb limb = character.AnimController.Limbs[limbIndex];
Vector2 forcePos = limb.pullJoint == null ? limb.body.SimPosition : limb.pullJoint.WorldAnchorA;
- limb.body.ApplyLinearImpulse(limb.Mass * attack.Force * Vector2.Normalize(attackSimPos - SimPosition), forcePos);
+ limb.body.ApplyLinearImpulse(limb.Mass * attack.Force * Vector2.Normalize(attackPosition - SimPosition), forcePos);
}
}
else
{
Vector2 forcePos = pullJoint == null ? body.SimPosition : pullJoint.WorldAnchorA;
- body.ApplyLinearImpulse(Mass * attack.Force * Vector2.Normalize(attackSimPos - SimPosition), forcePos);
+ body.ApplyLinearImpulse(Mass * attack.Force * Vector2.Normalize(attackPosition - SimPosition), forcePos);
}
}
return wasHit;
diff --git a/Barotrauma/BarotraumaShared/Source/DebugConsole.cs b/Barotrauma/BarotraumaShared/Source/DebugConsole.cs
index 3cdabed81..17347cacc 100644
--- a/Barotrauma/BarotraumaShared/Source/DebugConsole.cs
+++ b/Barotrauma/BarotraumaShared/Source/DebugConsole.cs
@@ -912,7 +912,7 @@ namespace Barotrauma
ThrowError(args[0] + " is not a valid latency value.");
return;
}
- if (!float.TryParse(args[1], NumberStyles.Any, CultureInfo.InvariantCulture, out float randomLatency))
+ if (!float.TryParse(args[0], NumberStyles.Any, CultureInfo.InvariantCulture, out float randomLatency))
{
ThrowError(args[1] + " is not a valid latency value.");
return;
diff --git a/Barotrauma/BarotraumaShared/Source/Events/Missions/Mission.cs b/Barotrauma/BarotraumaShared/Source/Events/Missions/Mission.cs
index e8f5e87fd..adc0b0d8d 100644
--- a/Barotrauma/BarotraumaShared/Source/Events/Missions/Mission.cs
+++ b/Barotrauma/BarotraumaShared/Source/Events/Missions/Mission.cs
@@ -103,6 +103,12 @@ namespace Barotrauma
if (missionType == MissionType.Random)
{
allowedMissions.AddRange(MissionPrefab.List);
+#if SERVER
+ if (GameMain.Server != null)
+ {
+ allowedMissions.RemoveAll(mission => !GameMain.Server.ServerSettings.AllowedRandomMissionTypes.Contains(mission.type));
+ }
+#endif
}
else if (missionType == MissionType.None)
{
@@ -118,11 +124,6 @@ namespace Barotrauma
{
allowedMissions.RemoveAll(m => !m.IsAllowed(locations[0], locations[1]));
}
-
- if (allowedMissions.Count == 0)
- {
- return null;
- }
int probabilitySum = allowedMissions.Sum(m => m.Commonness);
int randomNumber = rand.NextInt32() % probabilitySum;
diff --git a/Barotrauma/BarotraumaShared/Source/GameSession/GameSession.cs b/Barotrauma/BarotraumaShared/Source/GameSession/GameSession.cs
index ffe7cf9d3..d5778c9cc 100644
--- a/Barotrauma/BarotraumaShared/Source/GameSession/GameSession.cs
+++ b/Barotrauma/BarotraumaShared/Source/GameSession/GameSession.cs
@@ -208,7 +208,7 @@ namespace Barotrauma
DockingPort myPort = null, outPostPort = null;
foreach (DockingPort port in DockingPort.List)
{
- if (port.IsHorizontal || port.Docked) { continue; }
+ if (port.IsHorizontal) { continue; }
if (port.Item.Submarine == level.StartOutpost)
{
outPostPort = port;
diff --git a/Barotrauma/BarotraumaShared/Source/GameSettings.cs b/Barotrauma/BarotraumaShared/Source/GameSettings.cs
index 2fd21c4aa..400a45443 100644
--- a/Barotrauma/BarotraumaShared/Source/GameSettings.cs
+++ b/Barotrauma/BarotraumaShared/Source/GameSettings.cs
@@ -168,7 +168,7 @@ namespace Barotrauma
}
}
- private float soundVolume = 0.5f, musicVolume = 0.3f, voiceChatVolume = 0.5f, microphoneVolume = 1.0f;
+ private float soundVolume = 0.5f, musicVolume = 0.3f, voiceChatVolume = 0.5f;
public float SoundVolume
{
@@ -211,14 +211,6 @@ namespace Barotrauma
}
}
- public float MicrophoneVolume
- {
- get { return microphoneVolume; }
- set
- {
- microphoneVolume = MathHelper.Clamp(value, 0.1f, 5.0f);
- }
- }
public string Language
{
get { return TextManager.Language; }
diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Door.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Door.cs
index 91d669c94..7058ea85c 100644
--- a/Barotrauma/BarotraumaShared/Source/Items/Components/Door.cs
+++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Door.cs
@@ -51,11 +51,6 @@ namespace Barotrauma.Items.Components
public PhysicsBody Body { get; private set; }
- private float RepairThreshold
- {
- get { return item.GetComponent()?.ShowRepairUIThreshold ?? 0.0f; }
- }
-
private float stuck;
[Serialize(0.0f, false)]
public float Stuck
diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/Throwable.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/Throwable.cs
index 7fb161dfa..fc74c2b70 100644
--- a/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/Throwable.cs
+++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/Throwable.cs
@@ -105,7 +105,7 @@ namespace Barotrauma.Items.Components
GameServer.Log(picker.LogName + " threw " + item.Name, ServerLog.MessageType.ItemInteraction);
#endif
- item.Drop(picker, createNetworkEvent: GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer);
+ item.Drop(picker);
item.body.ApplyLinearImpulse(throwVector * throwForce * item.body.Mass * 3.0f);
ac.GetLimb(LimbType.Head).body.ApplyLinearImpulse(throwVector*10.0f);
diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/ItemComponent.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/ItemComponent.cs
index 28638ff15..ea482bfa5 100644
--- a/Barotrauma/BarotraumaShared/Source/Items/Components/ItemComponent.cs
+++ b/Barotrauma/BarotraumaShared/Source/Items/Components/ItemComponent.cs
@@ -208,9 +208,8 @@ namespace Barotrauma.Items.Components
public ItemComponent(Item item, XElement element)
{
this.item = item;
- originalElement = element;
name = element.Name.ToString();
- SerializableProperties = SerializableProperty.GetProperties(this);
+ properties = SerializableProperty.GetProperties(this);
requiredItems = new Dictionary>();
requiredSkills = new List();
@@ -244,9 +243,18 @@ namespace Barotrauma.Items.Components
DebugConsole.ThrowError("Invalid pick key in " + element + "!", e);
}
- SerializableProperties = SerializableProperty.DeserializeProperties(this, element);
- ParseMsg();
-
+ properties = SerializableProperty.DeserializeProperties(this, element);
+#if CLIENT
+ string msg = TextManager.Get(Msg, true);
+ if (msg != null)
+ {
+ foreach (InputType inputType in Enum.GetValues(typeof(InputType)))
+ {
+ msg = msg.Replace("[" + inputType.ToString().ToLowerInvariant() + "]", GameMain.Config.KeyBind(inputType).ToString());
+ }
+ Msg = msg;
+ }
+#endif
foreach (XElement subElement in element.Elements())
{
switch (subElement.Name.ToString().ToLowerInvariant())
@@ -534,6 +542,7 @@ namespace Barotrauma.Items.Components
GameAnalyticsManager.AddErrorEventOnce("ItemComponent.DegreeOfSuccess:CharacterNull", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
return 0.0f;
}
+ float average = skillSuccessSum / requiredSkills.Count;
float skillSuccessSum = 0.0f;
for (int i = 0; i < requiredSkills.Count; i++)
@@ -622,11 +631,53 @@ namespace Barotrauma.Items.Components
public virtual void Load(XElement componentElement)
{
if (componentElement == null) return;
+
foreach (XAttribute attribute in componentElement.Attributes())
{
- if (!SerializableProperties.TryGetValue(attribute.Name.ToString().ToLowerInvariant(), out SerializableProperty property)) continue;
+ if (!properties.TryGetValue(attribute.Name.ToString().ToLowerInvariant(), out SerializableProperty property)) continue;
property.TrySetValue(this, attribute.Value);
}
+#if CLIENT
+ string msg = TextManager.Get(Msg, true);
+ if (msg != null)
+ {
+ foreach (InputType inputType in Enum.GetValues(typeof(InputType)))
+ {
+ msg = msg.Replace("[" + inputType.ToString().ToLowerInvariant() + "]", GameMain.Config.KeyBind(inputType).ToString());
+ }
+ Msg = msg;
+ }
+#endif
+ var prevRequiredItems = new Dictionary>(requiredItems);
+ bool overrideRequiredItems = false;
+
+ foreach (XElement subElement in componentElement.Elements())
+ {
+ switch (subElement.Name.ToString().ToLowerInvariant())
+ {
+ case "requireditem":
+ if (!overrideRequiredItems) requiredItems.Clear();
+ overrideRequiredItems = true;
+
+ RelatedItem newRequiredItem = RelatedItem.Load(subElement, item.Name);
+ if (newRequiredItem == null) continue;
+
+ var prevRequiredItem = prevRequiredItems.ContainsKey(newRequiredItem.Type) ?
+ prevRequiredItems[newRequiredItem.Type].Find(ri => ri.JoinedIdentifiers == newRequiredItem.JoinedIdentifiers) : null;
+ if (prevRequiredItem != null)
+ {
+ newRequiredItem.statusEffects = prevRequiredItem.statusEffects;
+ newRequiredItem.Msg = prevRequiredItem.Msg;
+ }
+
+ if (!requiredItems.ContainsKey(newRequiredItem.Type))
+ {
+ requiredItems[newRequiredItem.Type] = new List();
+ }
+ requiredItems[newRequiredItem.Type].Add(newRequiredItem);
+ break;
+ }
+ }
ParseMsg();
OverrideRequiredItems(componentElement);
}
diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Reactor.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Reactor.cs
index 0f790a004..660bc5dd8 100644
--- a/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Reactor.cs
+++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Reactor.cs
@@ -201,19 +201,19 @@ namespace Barotrauma.Items.Components
tolerance = MathHelper.Lerp(5.0f, 20.0f, degreeOfSuccess);
allowedTurbineOutput = new Vector2(correctTurbineOutput - tolerance, correctTurbineOutput + tolerance);
+ float temperatureTolerance = MathHelper.Lerp(10.0f, 20.0f, degreeOfSuccess);
optimalTemperature = Vector2.Lerp(new Vector2(40.0f, 60.0f), new Vector2(30.0f, 70.0f), degreeOfSuccess);
allowedTemperature = Vector2.Lerp(new Vector2(30.0f, 70.0f), new Vector2(10.0f, 90.0f), degreeOfSuccess);
-
- optimalFissionRate = Vector2.Lerp(new Vector2(30, AvailableFuel - 20), new Vector2(20, AvailableFuel - 10), degreeOfSuccess);
- optimalFissionRate.X = Math.Min(optimalFissionRate.X, optimalFissionRate.Y - 10);
- allowedFissionRate = Vector2.Lerp(new Vector2(20, AvailableFuel), new Vector2(10, AvailableFuel), degreeOfSuccess);
- allowedFissionRate.X = Math.Min(allowedFissionRate.X, allowedFissionRate.Y - 10);
+
+ float fissionRateTolerance = MathHelper.Lerp(10.0f, 20.0f, degreeOfSuccess);
+ optimalFissionRate = Vector2.Lerp(new Vector2(40.0f, 70.0f), new Vector2(30.0f, 85.0f), degreeOfSuccess);
+ allowedFissionRate = Vector2.Lerp(new Vector2(30.0f, 85.0f), new Vector2(20.0f, 98.0f), degreeOfSuccess);
float heatAmount = fissionRate * (AvailableFuel / 100.0f) * 2.0f;
float temperatureDiff = (heatAmount - turbineOutput) - Temperature;
Temperature += MathHelper.Clamp(Math.Sign(temperatureDiff) * 10.0f * deltaTime, -Math.Abs(temperatureDiff), Math.Abs(temperatureDiff));
if (item.InWater && AvailableFuel < 100.0f) Temperature -= 12.0f * deltaTime;
-
+
FissionRate = MathHelper.Lerp(fissionRate, Math.Min(targetFissionRate, AvailableFuel), deltaTime);
TurbineOutput = MathHelper.Lerp(turbineOutput, targetTurbineOutput, deltaTime);
@@ -364,7 +364,7 @@ namespace Barotrauma.Items.Components
}
else if (-currPowerConsumption < load)
{
- targetFissionRate = Math.Min(targetFissionRate + speed * 2 * deltaTime, 100.0f);
+ targetFissionRate = Math.Min(targetFissionRate + speed * 2 * deltaTime, allowedFissionRate.Y);
}
targetFissionRate = MathHelper.Clamp(targetFissionRate, 0.0f, 100.0f);
}
diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Power/PowerContainer.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Power/PowerContainer.cs
index b5d448e79..542f66087 100644
--- a/Barotrauma/BarotraumaShared/Source/Items/Components/Power/PowerContainer.cs
+++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Power/PowerContainer.cs
@@ -153,7 +153,7 @@ namespace Barotrauma.Items.Components
}
continue;
}
- if (!pt.IsActive || !pt.CanTransfer) { continue; }
+ if (!pt.IsActive) { continue; }
gridLoad += pt.PowerLoad;
gridPower -= pt.CurrPowerConsumption;
@@ -209,9 +209,9 @@ namespace Barotrauma.Items.Components
Charge -= CurrPowerOutput / 3600.0f;
}
- item.SendSignal(0, ((int)Charge).ToString(), "charge", null);
- item.SendSignal(0, ((int)((Charge / capacity) * 100)).ToString(), "charge_%", null);
- item.SendSignal(0, ((int)((RechargeSpeed / maxRechargeSpeed) * 100)).ToString(), "charge_rate", null);
+ item.SendSignal(0, Charge.ToString(), "charge", null);
+ item.SendSignal(0, ((Charge / capacity) * 100).ToString(), "charge_%", null);
+ item.SendSignal(0, ((RechargeSpeed / maxRechargeSpeed) * 100).ToString(), "charge_rate", null);
foreach (Pair connected in directlyConnected)
{
diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Power/PowerTransfer.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Power/PowerTransfer.cs
index 233e30f68..f15e8dc8c 100644
--- a/Barotrauma/BarotraumaShared/Source/Items/Components/Power/PowerTransfer.cs
+++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Power/PowerTransfer.cs
@@ -319,13 +319,7 @@ namespace Barotrauma.Items.Components
ApplyStatusEffects(ActionType.OnActive, deltaTime, null);
- //float maxPower = this is RelayComponent relayComponent ? relayComponent.MaxPower : float.PositiveInfinity;
- RelayComponent thisRelayComponent = this as RelayComponent;
- if (thisRelayComponent != null)
- {
- clampPower = Math.Min(Math.Min(clampPower, thisRelayComponent.MaxPower), powerLoad);
- clampLoad = Math.Min(clampLoad, thisRelayComponent.MaxPower);
- }
+ float maxPower = this is RelayComponent relayComponent ? relayComponent.MaxPower : float.PositiveInfinity;
foreach (Connection c in PowerConnections)
{
@@ -363,8 +357,6 @@ namespace Barotrauma.Items.Components
continue;
}
- float addLoad = 0.0f;
- float addPower = 0.0f;
if (powered is PowerContainer powerContainer)
{
if (recipient.Name == "power_in")
@@ -373,7 +365,7 @@ namespace Barotrauma.Items.Components
}
else
{
- addPower = powerContainer.CurrPowerOutput;
+ fullPower += Math.Min(powerContainer.CurrPowerOutput, maxPower);
}
}
else
@@ -388,16 +380,10 @@ namespace Barotrauma.Items.Components
//negative power consumption = the construction is a
//generator/battery or another junction box
{
- addPower -= powered.CurrPowerConsumption;
+ fullPower -= Math.Max(powered.CurrPowerConsumption, -maxPower);
}
}
-
- if (addPower + fullPower > clampPower) { addPower -= (addPower + fullPower) - clampPower; };
- if (addPower > 0) { fullPower += addPower; }
-
- if (addLoad + fullLoad > clampLoad) { addLoad -= (addLoad + fullLoad) - clampLoad; };
- if (addLoad > 0) { fullLoad += addLoad; }
- }
+ }
}
}
}
diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Repairable.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Repairable.cs
index 8d3baec86..3f33c4df2 100644
--- a/Barotrauma/BarotraumaShared/Source/Items/Components/Repairable.cs
+++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Repairable.cs
@@ -12,6 +12,8 @@ namespace Barotrauma.Items.Components
public static float SkillIncreaseMultiplier = 0.4f;
private string header;
+
+ private float fixDurationLowSkill, fixDurationHighSkill;
private float deteriorationTimer;
@@ -50,20 +52,17 @@ namespace Barotrauma.Items.Components
set;
}
- [Serialize(100.0f, true), Editable(MinValueFloat = 0.0f, MaxValueFloat = 100.0f, ToolTip = "The amount of time it takes to fix the item with insufficient skill levels.")]
- public float FixDurationLowSkill
+ /*private float repairProgress;
+ public float RepairProgress
{
- get;
- set;
- }
-
- [Serialize(10.0f, true), Editable(MinValueFloat = 0.0f, MaxValueFloat = 100.0f, ToolTip = "The amount of time it takes to fix the item with sufficient skill levels.")]
- public float FixDurationHighSkill
- {
- get;
- set;
- }
-
+ get { return repairProgress; }
+ set
+ {
+ repairProgress = MathHelper.Clamp(value, 0.0f, 1.0f);
+ if (repairProgress >= 1.0f && currentFixer != null) currentFixer.AnimController.Anim = AnimController.Animation.None;
+ }
+ }*/
+
private Character currentFixer;
public Character CurrentFixer
{
@@ -84,6 +83,8 @@ namespace Barotrauma.Items.Components
this.item = item;
header = element.GetAttributeString("name", "");
+ fixDurationLowSkill = element.GetAttributeFloat("fixdurationlowskill", 100.0f);
+ fixDurationHighSkill = element.GetAttributeFloat("fixdurationhighskill", 5.0f);
InitProjSpecific(element);
}
@@ -159,7 +160,7 @@ namespace Barotrauma.Items.Components
}
bool wasBroken = !item.IsFullCondition;
- float fixDuration = MathHelper.Lerp(FixDurationLowSkill, FixDurationHighSkill, successFactor);
+ float fixDuration = MathHelper.Lerp(fixDurationLowSkill, fixDurationHighSkill, successFactor);
if (fixDuration <= 0.0f)
{
item.Condition = item.MaxCondition;
@@ -185,5 +186,26 @@ namespace Barotrauma.Items.Components
{
character.AnimController.UpdateUseItem(false, item.WorldPosition + new Vector2(0.0f, 100.0f) * ((item.Condition / item.MaxCondition) % 0.1f));
}
+
+ public void ServerWrite(NetBuffer msg, Client c, object[] extraData = null)
+ {
+ msg.Write(deteriorationTimer);
+ }
+
+ public void ClientRead(ServerNetObject type, NetBuffer msg, float sendingTime)
+ {
+ deteriorationTimer = msg.ReadSingle();
+ }
+
+ public void ClientWrite(NetBuffer msg, object[] extraData = null)
+ {
+ //no need to write anything, just letting the server know we started repairing
+ }
+
+ public void ServerRead(ClientNetObject type, NetBuffer msg, Client c)
+ {
+ if (c.Character == null) return;
+ StartRepairing(c.Character);
+ }
}
}
diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Signal/LightComponent.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Signal/LightComponent.cs
index 9a93d357f..021ad6197 100644
--- a/Barotrauma/BarotraumaShared/Source/Items/Components/Signal/LightComponent.cs
+++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Signal/LightComponent.cs
@@ -77,7 +77,7 @@ namespace Barotrauma.Items.Components
IsActive = value;
#if SERVER
- if (GameMain.Server != null && GameMain.Server.GameStarted) { item.CreateServerEvent(this); }
+ if (GameMain.Server != null) item.CreateServerEvent(this);
#endif
}
}
diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Signal/Wire.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Signal/Wire.cs
index 8b89d237a..2291509bf 100644
--- a/Barotrauma/BarotraumaShared/Source/Items/Components/Signal/Wire.cs
+++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Signal/Wire.cs
@@ -177,21 +177,14 @@ namespace Barotrauma.Items.Components
Vector2 nodePos = refSub == null ?
newConnection.Item.Position :
newConnection.Item.Position - refSub.HiddenSubPosition;
-
+
+
if (nodes.Count > 0 && nodes[0] == nodePos) break;
if (nodes.Count > 1 && nodes[nodes.Count - 1] == nodePos) break;
//make sure we place the node at the correct end of the wire (the end that's closest to the new node pos)
int newNodeIndex = 0;
if (nodes.Count > 1)
- {
- if (Vector2.DistanceSquared(nodes[nodes.Count-1], nodePos) < Vector2.DistanceSquared(nodes[0], nodePos))
- {
- newNodeIndex = nodes.Count;
- }
- }
-
- if (newNodeIndex == 0)
{
nodes.Insert(0, nodePos);
}
diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Turret.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Turret.cs
index 3dfbf16d9..a74c4f4e2 100644
--- a/Barotrauma/BarotraumaShared/Source/Items/Components/Turret.cs
+++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Turret.cs
@@ -433,10 +433,9 @@ namespace Barotrauma.Items.Components
if (usableProjectileCount == 0 || (usableProjectileCount < maxProjectileCount && objective.Option.ToLowerInvariant() != "fireatwill"))
{
ItemContainer container = null;
- Item containerItem = null;
foreach (MapEntity e in item.linkedTo)
{
- containerItem = e as Item;
+ var containerItem = e as Item;
if (containerItem == null) continue;
container = containerItem.GetComponent();
@@ -454,7 +453,7 @@ namespace Barotrauma.Items.Components
var containShellObjective = new AIObjectiveContainItem(character, container.ContainableItems[0].Identifiers[0], container);
character?.Speak(TextManager.Get("DialogLoadTurret").Replace("[itemname]", item.Name), null, 0.0f, "loadturret", 30.0f);
containShellObjective.MinContainedAmount = usableProjectileCount + 1;
- containShellObjective.ignoredContainerIdentifiers = new string[] { containerItem.prefab.Identifier };
+ containShellObjective.IgnoreAlreadyContainedItems = true;
objective.AddSubObjective(containShellObjective);
return false;
}
diff --git a/Barotrauma/BarotraumaShared/Source/Items/Item.cs b/Barotrauma/BarotraumaShared/Source/Items/Item.cs
index 11c413b9b..5244c3978 100644
--- a/Barotrauma/BarotraumaShared/Source/Items/Item.cs
+++ b/Barotrauma/BarotraumaShared/Source/Items/Item.cs
@@ -59,7 +59,8 @@ namespace Barotrauma
public PhysicsBody body;
public readonly XElement StaticBodyConfig;
-
+
+ private bool needsPositionUpdate;
private float lastSentCondition;
private float sendConditionUpdateTimer;
private bool conditionUpdatePending;
@@ -88,7 +89,7 @@ namespace Barotrauma
if (hasInGameEditableProperties == null)
{
hasInGameEditableProperties = false;
- if (SerializableProperties.Values.Any(p => p.Attributes.OfType().Any()))
+ if (properties.Values.Any(p => p.Attributes.OfType().Any()))
{
hasInGameEditableProperties = true;
}
@@ -97,7 +98,7 @@ namespace Barotrauma
foreach (ItemComponent component in components)
{
if (!component.AllowInGameEditing) { continue; }
- if (component.SerializableProperties.Values.Any(p => p.Attributes.OfType().Any()))
+ if (component.properties.Values.Any(p => p.Attributes.OfType().Any()))
{
hasInGameEditableProperties = true;
break;
@@ -211,14 +212,14 @@ namespace Barotrauma
set { spriteColor = value; }
}
- [Serialize("1.0,1.0,1.0,1.0", true), Editable]
+ [Serialize("1.0,1.0,1.0,1.0", false), Editable]
public Color InventoryIconColor
{
get;
protected set;
}
- [Serialize("1.0,1.0,1.0,1.0", true), Editable(ToolTip = "Changes the color of the item this item is contained inside. Only has an effect if either of the UseContainedSpriteColor or UseContainedInventoryIconColor property of the container is set to true.")]
+ [Serialize("1.0,1.0,1.0,1.0", false), Editable(ToolTip = "Changes the color of the item this item is contained inside. Only has an effect if either of the UseContainedSpriteColor or UseContainedInventoryIconColor property of the container is set to true.")]
public Color ContainerColor
{
get;
@@ -274,11 +275,12 @@ namespace Barotrauma
SetActiveSprite();
- if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsServer && !MathUtils.NearlyEqual(lastSentCondition, condition))
+ if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsServer && lastSentCondition != condition)
{
if (Math.Abs(lastSentCondition - condition) > 1.0f || condition == 0.0f || condition == Prefab.Health)
{
- conditionUpdatePending = true;
+ GameMain.NetworkMember.CreateEntityEvent(this, new object[] { NetEntityEvent.Type.Status });
+ lastSentCondition = condition;
}
}
}
@@ -583,10 +585,10 @@ namespace Barotrauma
public override MapEntity Clone()
{
Item clone = new Item(rect, Prefab, Submarine, callOnItemLoaded: false);
- foreach (KeyValuePair property in SerializableProperties)
+ foreach (KeyValuePair property in properties)
{
if (!property.Value.Attributes.OfType().Any()) continue;
- clone.SerializableProperties[property.Key].TrySetValue(clone, property.Value.GetValue(this));
+ clone.properties[property.Key].TrySetValue(clone, property.Value.GetValue(this));
}
if (components.Count != clone.components.Count)
@@ -603,7 +605,7 @@ namespace Barotrauma
foreach (KeyValuePair property in components[i].SerializableProperties)
{
if (!property.Value.Attributes.OfType().Any()) continue;
- clone.components[i].SerializableProperties[property.Key].TrySetValue(clone.components[i], property.Value.GetValue(components[i]));
+ clone.components[i].properties[property.Key].TrySetValue(clone.components[i], property.Value.GetValue(components[i]));
}
//clone requireditem identifiers
@@ -995,21 +997,6 @@ namespace Barotrauma
aiTarget.SightRange -= deltaTime * 1000.0f;
aiTarget.SoundRange -= deltaTime * 1000.0f;
}
-
- if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsServer)
- {
- sendConditionUpdateTimer -= deltaTime;
- if (conditionUpdatePending)
- {
- if (sendConditionUpdateTimer <= 0.0f)
- {
- GameMain.NetworkMember.CreateEntityEvent(this, new object[] { NetEntityEvent.Type.Status });
- lastSentCondition = condition;
- sendConditionUpdateTimer = NetConfig.ItemConditionUpdateInterval;
- conditionUpdatePending = false;
- }
- }
- }
ApplyStatusEffects(ActionType.Always, deltaTime, null);
@@ -1574,15 +1561,12 @@ namespace Barotrauma
return isCombined;
}
- public void Drop(Character dropper, bool createNetworkEvent = true)
+ public void Drop(Character dropper)
{
- if (createNetworkEvent)
+ if (parentInventory != null && !parentInventory.Owner.Removed && !Removed &&
+ GameMain.NetworkMember != null && (GameMain.NetworkMember.IsServer || Character.Controlled == dropper))
{
- if (parentInventory != null && !parentInventory.Owner.Removed && !Removed &&
- GameMain.NetworkMember != null && (GameMain.NetworkMember.IsServer || Character.Controlled == dropper))
- {
- parentInventory.CreateNetworkEvent();
- }
+ parentInventory.CreateNetworkEvent();
}
foreach (ItemComponent ic in components) { ic.Drop(dropper); }
@@ -1825,20 +1809,8 @@ namespace Barotrauma
}
partial void UpdateNetPosition(float deltaTime);
-
+
public static Item Load(XElement element, Submarine submarine)
- {
- return Load(element, submarine, createNetworkEvent: false);
- }
-
- ///
- /// Instantiate a new item and load its data from the XML element.
- ///
- /// The element containing the data of the item
- /// The submarine to spawn the item in (can be null)
- /// Should an EntitySpawner event be created to notify clients about the item being created.
- ///
- public static Item Load(XElement element, Submarine submarine, bool createNetworkEvent)
{
string name = element.Attribute("name").Value;
string identifier = element.GetAttributeString("identifier", "");
@@ -1884,16 +1856,9 @@ namespace Barotrauma
linkedToID = new List()
};
-#if SERVER
- if (createNetworkEvent)
- {
- Spawner.CreateNetworkEvent(item, remove: false);
- }
-#endif
-
foreach (XAttribute attribute in element.Attributes())
{
- if (!item.SerializableProperties.TryGetValue(attribute.Name.ToString(), out SerializableProperty property)) continue;
+ if (!item.properties.TryGetValue(attribute.Name.ToString(), out SerializableProperty property)) continue;
bool shouldBeLoaded = false;
foreach (var propertyAttribute in property.Attributes.OfType())
{
@@ -1937,7 +1902,7 @@ namespace Barotrauma
{
component.OnItemLoaded();
}
-
+
return item;
}
diff --git a/Barotrauma/BarotraumaShared/Source/Items/ItemInventory.cs b/Barotrauma/BarotraumaShared/Source/Items/ItemInventory.cs
index 76866dfdf..6e177f7a3 100644
--- a/Barotrauma/BarotraumaShared/Source/Items/ItemInventory.cs
+++ b/Barotrauma/BarotraumaShared/Source/Items/ItemInventory.cs
@@ -91,7 +91,8 @@ namespace Barotrauma
public override void CreateNetworkEvent()
{
- if (!Item.ItemList.Contains(container.Item))
+ int componentIndex = container.Item.GetComponentIndex(container);
+ if (componentIndex == -1)
{
string errorMsg = "Attempted to create a network event for an item (" + container.Item.Name + ") that hasn't been fully initialized yet.";
DebugConsole.ThrowError(errorMsg);
@@ -100,13 +101,6 @@ namespace Barotrauma
GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
return;
}
-
- int componentIndex = container.Item.GetComponentIndex(container);
- if (componentIndex == -1)
- {
- DebugConsole.Log("Creating a network event for the item \"" + container.Item + "\" failed, ItemContainer not found in components");
- return;
- }
if (GameMain.NetworkMember != null)
{
diff --git a/Barotrauma/BarotraumaShared/Source/Map/Explosion.cs b/Barotrauma/BarotraumaShared/Source/Map/Explosion.cs
index 13c6965e9..c94dffa0f 100644
--- a/Barotrauma/BarotraumaShared/Source/Map/Explosion.cs
+++ b/Barotrauma/BarotraumaShared/Source/Map/Explosion.cs
@@ -28,10 +28,8 @@ namespace Barotrauma
public Explosion(float range, float force, float damage, float structureDamage, float empStrength = 0.0f)
{
- attack = new Attack(damage, 0.0f, 0.0f, structureDamage, range)
- {
- SeverLimbsProbability = 1.0f
- };
+ attack = new Attack(damage, 0.0f, 0.0f, structureDamage, range);
+ attack.SeverLimbsProbability = 1.0f;
this.force = force;
this.empStrength = empStrength;
sparks = true;
@@ -185,6 +183,9 @@ namespace Barotrauma
Hull hull = Hull.FindHull(ConvertUnits.ToDisplayUnits(explosionPos), null, false);
bool underWater = hull == null || explosionPos.Y < hull.Surface;
+ Hull hull = Hull.FindHull(ConvertUnits.ToDisplayUnits(explosionPos), null, false);
+ bool underWater = hull == null || explosionPos.Y < hull.Surface;
+
explosionPos = ConvertUnits.ToSimUnits(explosionPos);
Dictionary distFactors = new Dictionary();
diff --git a/Barotrauma/BarotraumaShared/Source/Map/FireSource.cs b/Barotrauma/BarotraumaShared/Source/Map/FireSource.cs
index c252c399a..83ea002c0 100644
--- a/Barotrauma/BarotraumaShared/Source/Map/FireSource.cs
+++ b/Barotrauma/BarotraumaShared/Source/Map/FireSource.cs
@@ -175,11 +175,12 @@ namespace Barotrauma
LimitSize();
UpdateProjSpecific(growModifier);
-
- if (size.X < 1.0f && (GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer))
- {
- Remove();
- }
+
+#if CLIENT
+ if (GameMain.Client != null) return;
+#endif
+
+ if (size.X < 1.0f) Remove();
}
partial void UpdateProjSpecific(float growModifier);
@@ -292,6 +293,10 @@ namespace Barotrauma
//evaporate some of the water
hull.WaterVolume -= extinguishAmount;
+#if CLIENT
+ if (GameMain.Client != null) return;
+#endif
+
if (size.X < 1.0f && (GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer))
{
Remove();
@@ -320,11 +325,12 @@ namespace Barotrauma
size.X -= extinguishAmount;
hull.WaterVolume -= extinguishAmount;
-
- if (size.X < 1.0f && (GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer))
- {
- Remove();
- }
+
+#if CLIENT
+ if (GameMain.Client != null) return;
+#endif
+
+ if (size.X < 1.0f) Remove();
}
public void Extinguish(float deltaTime, float amount, Vector2 worldPosition)
diff --git a/Barotrauma/BarotraumaShared/Source/Map/Levels/Level.cs b/Barotrauma/BarotraumaShared/Source/Map/Levels/Level.cs
index 0bb9df3e9..8ffc5630e 100644
--- a/Barotrauma/BarotraumaShared/Source/Map/Levels/Level.cs
+++ b/Barotrauma/BarotraumaShared/Source/Map/Levels/Level.cs
@@ -231,7 +231,7 @@ namespace Barotrauma
public static Level CreateRandom(LocationConnection locationConnection)
{
- string seed = locationConnection.Locations[0].BaseName + locationConnection.Locations[1].BaseName;
+ string seed = locationConnection.Locations[0].Name + locationConnection.Locations[1].Name;
float sizeFactor = MathUtils.InverseLerp(
MapGenerationParams.Instance.SmallLevelConnectionLength,
@@ -1522,40 +1522,14 @@ namespace Barotrauma
outpost.MakeOutpost();
Point? minSize = null;
- DockingPort subPort = null;
if (Submarine.MainSub != null)
{
Point subSize = Submarine.MainSub.GetDockedBorders().Size;
Point outpostSize = outpost.GetDockedBorders().Size;
minSize = new Point(Math.Max(subSize.X, outpostSize.X), subSize.Y + outpostSize.Y);
-
- float closestDistance = float.MaxValue;
- foreach (DockingPort port in DockingPort.List)
- {
- if (port.IsHorizontal || port.Docked) { continue; }
- if (port.Item.Submarine != Submarine.MainSub) { continue; }
- //the submarine port has to be at the top of the sub
- if (port.Item.WorldPosition.Y < Submarine.MainSub.WorldPosition.Y) { continue; }
- float dist = Math.Abs(port.Item.WorldPosition.X - Submarine.MainSub.WorldPosition.X);
- if (dist < closestDistance)
- {
- subPort = port;
- closestDistance = dist;
- }
- }
}
- float subDockingPortOffset = subPort == null ? 0.0f : subPort.Item.WorldPosition.X - Submarine.MainSub.WorldPosition.X;
- //don't try to compensate if the port is very far from the sub's center of mass
- if (Math.Abs(subDockingPortOffset) > 2000.0f)
- {
- subDockingPortOffset = MathHelper.Clamp(subDockingPortOffset, -2000.0f, 2000.0f);
- string warningMsg = "Docking port very far from the sub's center of mass (submarine: " + Submarine.MainSub.Name + ", dist: " + subDockingPortOffset + "). The level generator may not be able to place the outpost so that docking is possible.";
- DebugConsole.NewMessage(warningMsg, Color.Orange);
- GameAnalyticsManager.AddErrorEventOnce("Lever.CreateOutposts:DockingPortVeryFar" + Submarine.MainSub.Name, GameAnalyticsSDK.Net.EGAErrorSeverity.Warning, warningMsg);
- }
-
- outpost.SetPosition(outpost.FindSpawnPos(i == 0 ? StartPosition : EndPosition, minSize, subDockingPortOffset));
+ outpost.SetPosition(outpost.FindSpawnPos(i == 0 ? StartPosition : EndPosition, minSize));
if ((i == 0) == !Mirrored)
{
StartOutpost = outpost;
diff --git a/Barotrauma/BarotraumaShared/Source/Map/Levels/LevelObjects/LevelObject.cs b/Barotrauma/BarotraumaShared/Source/Map/Levels/LevelObjects/LevelObject.cs
index 3874415b6..d96da098c 100644
--- a/Barotrauma/BarotraumaShared/Source/Map/Levels/LevelObjects/LevelObject.cs
+++ b/Barotrauma/BarotraumaShared/Source/Map/Levels/LevelObjects/LevelObject.cs
@@ -15,6 +15,7 @@ namespace Barotrauma
public Vector3 Position;
public float NetworkUpdateTimer;
+ public const float NetworkUpdateInterval = 0.2f;
public float Scale;
diff --git a/Barotrauma/BarotraumaShared/Source/Map/Levels/LevelObjects/LevelObjectManager.cs b/Barotrauma/BarotraumaShared/Source/Map/Levels/LevelObjects/LevelObjectManager.cs
index b75965a40..40469cea9 100644
--- a/Barotrauma/BarotraumaShared/Source/Map/Levels/LevelObjects/LevelObjectManager.cs
+++ b/Barotrauma/BarotraumaShared/Source/Map/Levels/LevelObjects/LevelObjectManager.cs
@@ -343,7 +343,7 @@ namespace Barotrauma
{
GameMain.NetworkMember.CreateEntityEvent(this, new object[] { obj });
obj.NeedsNetworkSyncing = false;
- obj.NetworkUpdateTimer = NetConfig.LevelObjectUpdateInterval;
+ obj.NetworkUpdateTimer = LevelObject.NetworkUpdateInterval;
}
}
diff --git a/Barotrauma/BarotraumaShared/Source/Map/Levels/LevelObjects/LevelTrigger.cs b/Barotrauma/BarotraumaShared/Source/Map/Levels/LevelObjects/LevelTrigger.cs
index 1c3ec2339..83033e604 100644
--- a/Barotrauma/BarotraumaShared/Source/Map/Levels/LevelObjects/LevelTrigger.cs
+++ b/Barotrauma/BarotraumaShared/Source/Map/Levels/LevelObjects/LevelTrigger.cs
@@ -432,16 +432,12 @@ namespace Barotrauma
{
if (ForceFluctuationStrength > 0.0f)
{
- //no need for force fluctuation (or network updates) if the trigger limits velocity and there are no triggerers
- if (forceMode != TriggerForceMode.LimitVelocity || triggerers.Any())
+ forceFluctuationTimer += deltaTime;
+ if (forceFluctuationTimer > ForceFluctuationInterval)
{
- forceFluctuationTimer += deltaTime;
- if (forceFluctuationTimer > ForceFluctuationInterval)
- {
- NeedsNetworkSyncing = true;
- currentForceFluctuation = Rand.Range(1.0f - ForceFluctuationStrength, 1.0f);
- forceFluctuationTimer = 0.0f;
- }
+ NeedsNetworkSyncing = true;
+ currentForceFluctuation = Rand.Range(1.0f - ForceFluctuationStrength, 1.0f);
+ forceFluctuationTimer = 0.0f;
}
}
diff --git a/Barotrauma/BarotraumaShared/Source/Map/Map/Location.cs b/Barotrauma/BarotraumaShared/Source/Map/Map/Location.cs
index e397d485f..c2e449bc8 100644
--- a/Barotrauma/BarotraumaShared/Source/Map/Map/Location.cs
+++ b/Barotrauma/BarotraumaShared/Source/Map/Map/Location.cs
@@ -15,8 +15,6 @@ namespace Barotrauma
public int TypeChangeTimer;
- public string BaseName { get => baseName; }
-
public string Name { get; private set; }
public Vector2 MapPosition { get; private set; }
@@ -33,10 +31,10 @@ namespace Barotrauma
get
{
CheckMissionCompleted();
-
+
for (int i = availableMissions.Count; i < Connections.Count * 2; i++)
{
- int seed = (ToolBox.StringToInt(BaseName) + MissionsCompleted * 10 + i) % int.MaxValue;
+ int seed = (ToolBox.StringToInt(Name) + MissionsCompleted * 10 + i) % int.MaxValue;
MTRandom rand = new MTRandom(seed);
LocationConnection connection = Connections[(MissionsCompleted + i) % Connections.Count];
@@ -47,7 +45,7 @@ namespace Barotrauma
if (availableMissions.Any(m => m.Prefab == mission.Prefab)) { continue; }
if (GameSettings.VerboseLogging && mission != null)
{
- DebugConsole.NewMessage("Generated a new mission for a location (location: " + Name + ", seed: " + seed.ToString("X") + ", missions completed: " + MissionsCompleted + ", type: " + mission.Name + ")", Color.White);
+ DebugConsole.NewMessage("Generated a new mission for a location connection (seed: " + seed.ToString("X") + ", type: " + mission.Name + ")", Color.White);
}
availableMissions.Add(mission);
}
@@ -100,16 +98,7 @@ namespace Barotrauma
public void ChangeType(LocationType newType)
{
- if (newType == Type) { return; }
-
- //clear missions from this and adjacent locations (they may be invalid now)
- availableMissions.Clear();
- foreach (LocationConnection connection in Connections)
- {
- connection.OtherLocation(this)?.availableMissions.Clear();
- }
-
- DebugConsole.Log("Location " + baseName + " changed it's type from " + Type + " to " + newType);
+ if (newType == Type) return;
Type = newType;
Name = Type.NameFormats[nameFormatIndex % Type.NameFormats.Count].Replace("[name]", baseName);
@@ -121,7 +110,6 @@ namespace Barotrauma
{
if (mission.Completed)
{
- DebugConsole.Log("Mission \"" + mission.Name + "\" completed in \"" + Name + "\".");
MissionsCompleted++;
}
}
diff --git a/Barotrauma/BarotraumaShared/Source/Map/Map/Map.cs b/Barotrauma/BarotraumaShared/Source/Map/Map/Map.cs
index 5776ce80b..ba0ba04d5 100644
--- a/Barotrauma/BarotraumaShared/Source/Map/Map/Map.cs
+++ b/Barotrauma/BarotraumaShared/Source/Map/Map/Map.cs
@@ -578,12 +578,10 @@ namespace Barotrauma
location.MissionsCompleted = missionsCompleted;
if (showNotifications && prevLocationType != location.Type)
{
- var change = prevLocationType.CanChangeTo.Find(c =>
- c.ChangeToType.ToLowerInvariant() == location.Type.Identifier.ToLowerInvariant());
- if (change != null)
- {
- ChangeLocationType(location, prevLocationName, change);
- }
+ ChangeLocationType(
+ location,
+ prevLocationName,
+ prevLocationType.CanChangeTo.Find(c => c.ChangeToType.ToLowerInvariant() == location.Type.Identifier.ToLowerInvariant()));
}
break;
case "connection":
diff --git a/Barotrauma/BarotraumaShared/Source/Map/MapEntity.cs b/Barotrauma/BarotraumaShared/Source/Map/MapEntity.cs
index 569b5ccff..b5a5bc508 100644
--- a/Barotrauma/BarotraumaShared/Source/Map/MapEntity.cs
+++ b/Barotrauma/BarotraumaShared/Source/Map/MapEntity.cs
@@ -407,7 +407,7 @@ namespace Barotrauma
try
{
- MethodInfo loadMethod = t.GetMethod("Load", new [] { typeof(XElement), typeof(Submarine) });
+ MethodInfo loadMethod = t.GetMethod("Load");
if (loadMethod == null)
{
DebugConsole.ThrowError("Could not find the method \"Load\" in " + t + ".");
diff --git a/Barotrauma/BarotraumaShared/Source/Map/Structure.cs b/Barotrauma/BarotraumaShared/Source/Map/Structure.cs
index 82d0dad3e..6e4fe089b 100644
--- a/Barotrauma/BarotraumaShared/Source/Map/Structure.cs
+++ b/Barotrauma/BarotraumaShared/Source/Map/Structure.cs
@@ -297,13 +297,7 @@ namespace Barotrauma
CreateStairBodies();
}
}
-
- // Only add ai targets automatically to walls
- if (aiTarget == null && HasBody && Tags.Contains("wall"))
- {
- aiTarget = new AITarget(this);
- }
-
+
InsertToList();
}
diff --git a/Barotrauma/BarotraumaShared/Source/Map/StructurePrefab.cs b/Barotrauma/BarotraumaShared/Source/Map/StructurePrefab.cs
index 037364597..75ec3391b 100644
--- a/Barotrauma/BarotraumaShared/Source/Map/StructurePrefab.cs
+++ b/Barotrauma/BarotraumaShared/Source/Map/StructurePrefab.cs
@@ -8,8 +8,6 @@ namespace Barotrauma
{
partial class StructurePrefab : MapEntityPrefab
{
- public XElement ConfigElement { get; private set; }
-
private bool canSpriteFlipX, canSpriteFlipY;
private float health;
@@ -152,7 +150,6 @@ namespace Barotrauma
{
name = element.GetAttributeString("name", "")
};
- sp.ConfigElement = element;
if (string.IsNullOrEmpty(sp.name)) sp.name = element.Name.ToString();
sp.identifier = element.GetAttributeString("identifier", "");
@@ -217,10 +214,6 @@ namespace Barotrauma
}
SerializableProperty.DeserializeProperties(sp, element);
- if (sp.Body)
- {
- sp.Tags.Add("wall");
- }
string translatedDescription = TextManager.Get("EntityDescription." + sp.identifier, true);
if (!string.IsNullOrEmpty(translatedDescription)) sp.Description = translatedDescription;
diff --git a/Barotrauma/BarotraumaShared/Source/Map/Submarine.cs b/Barotrauma/BarotraumaShared/Source/Map/Submarine.cs
index 89d3155f7..f185a891f 100644
--- a/Barotrauma/BarotraumaShared/Source/Map/Submarine.cs
+++ b/Barotrauma/BarotraumaShared/Source/Map/Submarine.cs
@@ -10,7 +10,6 @@ using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
-using System.Threading;
using System.Xml.Linq;
using Voronoi2;
@@ -494,7 +493,7 @@ namespace Barotrauma
}
}
- public Vector2 FindSpawnPos(Vector2 spawnPos, Point? submarineSize = null, float subDockingPortOffset = 0.0f)
+ public Vector2 FindSpawnPos(Vector2 spawnPos, Point? submarineSize = null)
{
Rectangle dockedBorders = GetDockedBorders();
Vector2 diffFromDockedBorders =
@@ -542,17 +541,17 @@ namespace Barotrauma
else if (minX < 0)
{
//no wall found at the left side, spawn to the left from the right-side wall
- spawnPos.X = maxX - minWidth - 100.0f + subDockingPortOffset;
+ spawnPos.X = maxX - minWidth - 100.0f;
}
else if (maxX > Level.Loaded.Size.X)
{
//no wall found at right side, spawn to the right from the left-side wall
- spawnPos.X = minX + minWidth + 100.0f + subDockingPortOffset;
+ spawnPos.X = minX + minWidth + 100.0f;
}
else
{
//walls found at both sides, use their midpoint
- spawnPos.X = (minX + maxX) / 2 + subDockingPortOffset;
+ spawnPos.X = (minX + maxX) / 2;
}
spawnPos.Y = Math.Min(spawnPos.Y, Level.Loaded.Size.Y - dockedBorders.Height / 2 - 10);
diff --git a/Barotrauma/BarotraumaShared/Source/Map/SubmarineBody.cs b/Barotrauma/BarotraumaShared/Source/Map/SubmarineBody.cs
index a0d500ade..0a1b5fa21 100644
--- a/Barotrauma/BarotraumaShared/Source/Map/SubmarineBody.cs
+++ b/Barotrauma/BarotraumaShared/Source/Map/SubmarineBody.cs
@@ -700,23 +700,6 @@ namespace Barotrauma
Vector2 impulse = direction * impact * 0.5f;
impulse = impulse.ClampLength(5.0f);
- if (!MathUtils.IsValid(impulse))
- {
- string errorMsg =
- "Invalid impulse in SubmarineBody.ApplyImpact: " + impulse +
- ". Direction: " + direction + ", body position: " + Body.SimPosition + ", impact: " + impact + ".";
- if (GameMain.NetworkMember != null)
- {
- errorMsg += GameMain.NetworkMember.IsClient ? " Playing as a client." : " Hosting a server.";
- }
- if (GameSettings.VerboseLogging) DebugConsole.ThrowError(errorMsg);
- GameAnalyticsManager.AddErrorEventOnce(
- "SubmarineBody.ApplyImpact:InvalidImpulse",
- GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
- errorMsg);
- return;
- }
-
#if CLIENT
if (Character.Controlled != null && Character.Controlled.Submarine == submarine)
{
diff --git a/Barotrauma/BarotraumaShared/Source/Networking/ChatMessage.cs b/Barotrauma/BarotraumaShared/Source/Networking/ChatMessage.cs
index e40d6c714..2876896aa 100644
--- a/Barotrauma/BarotraumaShared/Source/Networking/ChatMessage.cs
+++ b/Barotrauma/BarotraumaShared/Source/Networking/ChatMessage.cs
@@ -129,10 +129,10 @@ namespace Barotrauma.Networking
if (listener.WorldPosition == sender.WorldPosition) { return 0.0f; }
float dist = Vector2.Distance(listener.WorldPosition, sender.WorldPosition);
- if (dist > range) { return 1.0f; }
+ if (dist > range) { return 0.0f; }
if (Submarine.CheckVisibility(listener.SimPosition, sender.SimPosition) != null) dist = (dist + 100f) * obstructionmult;
- if (dist > range) { return 1.0f; }
+ if (dist > range) { return 0.0f; }
return dist / range;
}
@@ -152,7 +152,7 @@ namespace Barotrauma.Networking
public static string ApplyDistanceEffect(string text, float garbleAmount)
{
if (garbleAmount < 0.3f) return text;
- if (garbleAmount >= 1.0f) return "";
+ if (garbleAmount > 1.0f) return "";
int startIndex = Math.Max(text.IndexOf(':') + 1, 1);
diff --git a/Barotrauma/BarotraumaShared/Source/Networking/FileTransfer/FileTransfer.cs b/Barotrauma/BarotraumaShared/Source/Networking/FileTransfer/FileTransfer.cs
index a5d48f5eb..51a489698 100644
--- a/Barotrauma/BarotraumaShared/Source/Networking/FileTransfer/FileTransfer.cs
+++ b/Barotrauma/BarotraumaShared/Source/Networking/FileTransfer/FileTransfer.cs
@@ -7,7 +7,7 @@
enum FileTransferMessageType
{
- Unknown, Initiate, Data, TransferOnSameMachine, Cancel
+ Unknown, Initiate, Data, Cancel
}
enum FileTransferType
diff --git a/Barotrauma/BarotraumaShared/Source/Networking/NetConfig.cs b/Barotrauma/BarotraumaShared/Source/Networking/NetConfig.cs
index 74b6afcb2..d7a36e28c 100644
--- a/Barotrauma/BarotraumaShared/Source/Networking/NetConfig.cs
+++ b/Barotrauma/BarotraumaShared/Source/Networking/NetConfig.cs
@@ -32,14 +32,11 @@ namespace Barotrauma.Networking
public const float HighPrioCharacterPositionUpdateInterval = 0.0f;
public const float LowPrioCharacterPositionUpdateInterval = 1.0f;
- public const float DeleteDisconnectedTime = 20.0f;
-
- public const float ItemConditionUpdateInterval = 0.15f;
- public const float LevelObjectUpdateInterval = 0.5f;
- public const float HullUpdateInterval = 0.5f;
- public const float HullUpdateDistance = 20000.0f;
-
- public const int MaxEventPacketsPerUpdate = 4;
+ //how much the physics body of an item has to move until the server
+ //send a position update to clients (in sim units)
+ public const float ItemPosUpdateDistance = 2.0f;
+
+ public const float DeleteDisconnectedTime = 10.0f;
///
/// Interpolates the positional error of a physics body towards zero.
diff --git a/Barotrauma/BarotraumaShared/Source/Networking/NetEntityEvent/NetEntityEventManager.cs b/Barotrauma/BarotraumaShared/Source/Networking/NetEntityEvent/NetEntityEventManager.cs
index 20cb9b39a..03e28f3d4 100644
--- a/Barotrauma/BarotraumaShared/Source/Networking/NetEntityEvent/NetEntityEventManager.cs
+++ b/Barotrauma/BarotraumaShared/Source/Networking/NetEntityEvent/NetEntityEventManager.cs
@@ -58,8 +58,15 @@ namespace Barotrauma.Networking
eventCount++;
continue;
}
-
- if (msg.LengthBytes + tempBuffer.LengthBytes + tempEventBuffer.LengthBytes > MaxEventBufferLength)
+ //the ID has been taken by another entity (the original entity has been removed) -> write an empty event
+ /*else if (Entity.FindEntityByID(e.Entity.ID) != e.Entity || e.Entity.IdFreed)
+ {
+ //technically the clients don't have any use for these, but removing events and shifting the IDs of all
+ //consecutive ones is so error-prone that I think this is a safer option
+ tempBuffer.Write(Entity.NullEntityID);
+ tempBuffer.WritePadBits();
+ }*/
+ else
{
//no more room in this packet
break;
diff --git a/Barotrauma/BarotraumaShared/Source/Networking/ServerSettings.cs b/Barotrauma/BarotraumaShared/Source/Networking/ServerSettings.cs
index 3a4f36a23..5732a9955 100644
--- a/Barotrauma/BarotraumaShared/Source/Networking/ServerSettings.cs
+++ b/Barotrauma/BarotraumaShared/Source/Networking/ServerSettings.cs
@@ -513,29 +513,11 @@ namespace Barotrauma.Networking
set;
}
- private SelectionMode subSelectionMode;
[Serialize(SelectionMode.Manual, true)]
- public SelectionMode SubSelectionMode
- {
- get { return subSelectionMode; }
- set
- {
- subSelectionMode = value;
- Voting.AllowSubVoting = subSelectionMode == SelectionMode.Vote;
- }
- }
+ public SelectionMode SubSelectionMode { get; private set; }
- private SelectionMode modeSelectionMode;
[Serialize(SelectionMode.Manual, true)]
- public SelectionMode ModeSelectionMode
- {
- get { return modeSelectionMode; }
- set
- {
- modeSelectionMode = value;
- Voting.AllowModeVoting = modeSelectionMode == SelectionMode.Vote;
- }
- }
+ public SelectionMode ModeSelectionMode { get; private set; }
public BanList BanList { get; private set; }
diff --git a/Barotrauma/BarotraumaShared/Source/Physics/PhysicsBody.cs b/Barotrauma/BarotraumaShared/Source/Physics/PhysicsBody.cs
index d87c6ab3b..071cb99a3 100644
--- a/Barotrauma/BarotraumaShared/Source/Physics/PhysicsBody.cs
+++ b/Barotrauma/BarotraumaShared/Source/Physics/PhysicsBody.cs
@@ -36,20 +36,32 @@ namespace Barotrauma
private set;
}
+ public Vector2 LinearVelocity
+ {
+ get;
+ private set;
+ }
+
+ public float AngularVelocity
+ {
+ get;
+ private set;
+ }
+
public readonly float Timestamp;
public readonly UInt16 ID;
- public PosInfo(Vector2 pos, float? rotation, Vector2 linearVelocity, float? angularVelocity, float time)
+ public PosInfo(Vector2 pos, float rotation, Vector2 linearVelocity, float angularVelocity, float time)
: this(pos, rotation, linearVelocity, angularVelocity, 0, time)
{
}
- public PosInfo(Vector2 pos, float? rotation, Vector2 linearVelocity, float? angularVelocity, UInt16 ID)
+ public PosInfo(Vector2 pos, float rotation, Vector2 linearVelocity, float angularVelocity, UInt16 ID)
: this(pos, rotation, linearVelocity, angularVelocity, ID, 0.0f)
{
}
- protected PosInfo(Vector2 pos, float? rotation, Vector2 linearVelocity, float? angularVelocity, UInt16 ID, float time)
+ protected PosInfo(Vector2 pos, float rotation, Vector2 linearVelocity, float angularVelocity, UInt16 ID, float time)
{
Position = pos;
Rotation = rotation;
@@ -775,8 +787,8 @@ namespace Barotrauma
newVelocity = positionBuffer[0].LinearVelocity;
newPosition = positionBuffer[0].Position;
- newRotation = positionBuffer[0].Rotation ?? Rotation;
- newAngularVelocity = positionBuffer[0].AngularVelocity ?? AngularVelocity;
+ newRotation = positionBuffer[0].Rotation;
+ newAngularVelocity = positionBuffer[0].AngularVelocity;
positionBuffer.RemoveAt(0);
}
diff --git a/Barotrauma/BarotraumaShared/Source/StatusEffects/StatusEffect.cs b/Barotrauma/BarotraumaShared/Source/StatusEffects/StatusEffect.cs
index 072c260ab..55d8c62fe 100644
--- a/Barotrauma/BarotraumaShared/Source/StatusEffects/StatusEffect.cs
+++ b/Barotrauma/BarotraumaShared/Source/StatusEffects/StatusEffect.cs
@@ -107,7 +107,7 @@ namespace Barotrauma
public string[] propertyNames;
private object[] propertyEffects;
- private PropertyConditional.Comparison conditionalComparison = PropertyConditional.Comparison.Or;
+ private PropertyConditional.Comparison conditionalComparison = PropertyConditional.Comparison.And;
private List propertyConditionals;
private bool setValue;
@@ -465,13 +465,6 @@ namespace Barotrauma
if (target == null || target.SerializableProperties == null) { continue; }
foreach (PropertyConditional pc in propertyConditionals)
{
- if (!string.IsNullOrEmpty(pc.TargetItemComponentName))
- {
- if (!(target is ItemComponent ic) || ic.Name != pc.TargetItemComponentName)
- {
- continue;
- }
- }
if (pc.Matches(target)) { return true; }
}
}
@@ -482,13 +475,6 @@ namespace Barotrauma
if (target == null || target.SerializableProperties == null) { continue; }
foreach (PropertyConditional pc in propertyConditionals)
{
- if (!string.IsNullOrEmpty(pc.TargetItemComponentName))
- {
- if (!(target is ItemComponent ic) || ic.Name != pc.TargetItemComponentName)
- {
- continue;
- }
- }
if (!pc.Matches(target)) { return false; }
}
}
@@ -710,8 +696,6 @@ namespace Barotrauma
foreach (Limb limb in character.AnimController.Limbs)
{
limb.character.DamageLimb(entity.WorldPosition, limb, new List() { multipliedAffliction }, stun: 0.0f, playSound: false, attackImpulse: 0.0f);
- //only apply non-limb-specific afflictions to the first limb
- if (!affliction.Prefab.LimbSpecific) { break; }
}
}
else if (target is Limb limb)
diff --git a/Barotrauma/BarotraumaShared/Source/TextManager.cs b/Barotrauma/BarotraumaShared/Source/TextManager.cs
index 1d5d074c8..a4b006c84 100644
--- a/Barotrauma/BarotraumaShared/Source/TextManager.cs
+++ b/Barotrauma/BarotraumaShared/Source/TextManager.cs
@@ -153,59 +153,49 @@ namespace Barotrauma
string[] messages = serverMessage.Split('/');
- try
+ for (int i = 0; i < messages.Length; i++)
{
- for (int i = 0; i < messages.Length; i++)
+ if (!IsServerMessageWithVariables(messages[i])) // No variables, try to translate
{
- if (!IsServerMessageWithVariables(messages[i])) // No variables, try to translate
+ if (messages[i].Contains(" ")) continue; // Spaces found, do not translate
+
+ string msg = Get(messages[i], true);
+
+ if (msg != null) // If a translation was found, otherwise use the original
{
- if (messages[i].Contains(" ")) continue; // Spaces found, do not translate
- string msg = Get(messages[i], true);
- if (msg != null) // If a translation was found, otherwise use the original
- {
- messages[i] = msg;
- }
+ messages[i] = msg;
+ }
+ }
+ else
+ {
+ string[] messageWithVariables = messages[i].Split('~');
+ string msg = Get(messageWithVariables[0], true);
+
+ if (msg != null) // If a translation was found, otherwise use the original
+ {
+ messages[i] = msg;
}
else
{
- string[] messageWithVariables = messages[i].Split('~');
- string msg = Get(messageWithVariables[0], true);
+ continue; // No translation found, probably caused by player input -> skip variable handling
+ }
- if (msg != null) // If a translation was found, otherwise use the original
- {
- messages[i] = msg;
- }
- else
- {
- continue; // No translation found, probably caused by player input -> skip variable handling
- }
-
- // First index is always the message identifier -> start at 1
- for (int j = 1; j < messageWithVariables.Length; j++)
- {
- string[] variableAndValue = messageWithVariables[j].Split('=');
- messages[i] = messages[i].Replace(variableAndValue[0], variableAndValue[1]);
- }
+ // First index is always the message identifier -> start at 1
+ for (int j = 1; j < messageWithVariables.Length; j++)
+ {
+ string[] variableAndValue = messageWithVariables[j].Split('=');
+ messages[i] = messages[i].Replace(variableAndValue[0], variableAndValue[1]);
}
}
-
- string translatedServerMessage = string.Empty;
- for (int i = 0; i < messages.Length; i++)
- {
- translatedServerMessage += messages[i];
- }
- return translatedServerMessage;
}
- catch (IndexOutOfRangeException exception)
+ string translatedServerMessage = string.Empty;
+ for (int i = 0; i < messages.Length; i++)
{
- string errorMsg = "Failed to translate server message \"" + serverMessage + "\".";
-#if DEBUG
- DebugConsole.ThrowError(errorMsg, exception);
-#endif
- GameAnalyticsManager.AddErrorEventOnce("TextManager.GetServerMessage:" + serverMessage, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
- return errorMsg;
+ translatedServerMessage += messages[i];
}
+
+ return translatedServerMessage;
}
public static bool IsServerMessageWithVariables(string message)
diff --git a/Barotrauma/BarotraumaShared/Source/Utils/MathUtils.cs b/Barotrauma/BarotraumaShared/Source/Utils/MathUtils.cs
index bb12617b7..31760c6d5 100644
--- a/Barotrauma/BarotraumaShared/Source/Utils/MathUtils.cs
+++ b/Barotrauma/BarotraumaShared/Source/Utils/MathUtils.cs
@@ -753,15 +753,6 @@ namespace Barotrauma
}
}
- ///
- /// Float comparison. Note that may still fail in some cases.
- ///
- public static bool NearlyEqual(Vector2 a, Vector2 b, float epsilon = 0.0001f)
- {
- return NearlyEqual(a.X, b.X, epsilon) && NearlyEqual(a.Y, b.Y, epsilon);
- }
-
- ///
/// Returns a position in a curve.
///
public static Vector2 Bezier(Vector2 start, Vector2 control, Vector2 end, float t)
diff --git a/Barotrauma/BarotraumaShared/Source/Utils/SaveUtil.cs b/Barotrauma/BarotraumaShared/Source/Utils/SaveUtil.cs
index 3fbf744cc..5ad818e21 100644
--- a/Barotrauma/BarotraumaShared/Source/Utils/SaveUtil.cs
+++ b/Barotrauma/BarotraumaShared/Source/Utils/SaveUtil.cs
@@ -403,18 +403,18 @@ namespace Barotrauma
}
}
- public static void ClearFolder(string FolderName, string[] ignoredFileNames = null)
+ public static void ClearFolder(string FolderName, string[] ignoredFiles = null)
{
DirectoryInfo dir = new DirectoryInfo(FolderName);
foreach (FileInfo fi in dir.GetFiles())
{
- if (ignoredFileNames != null)
+ if (ignoredFiles != null)
{
bool ignore = false;
- foreach (string ignoredFile in ignoredFileNames)
+ foreach (string ignoredFile in ignoredFiles)
{
- if (Path.GetFileName(fi.FullName).Equals(Path.GetFileName(ignoredFile)))
+ if (Path.GetFullPath(fi.FullName).Equals(Path.GetFullPath(ignoredFile)))
{
ignore = true;
break;
diff --git a/Barotrauma/BarotraumaShared/Submarines/Dugong.sub b/Barotrauma/BarotraumaShared/Submarines/Dugong.sub
index 5b887ece3..dd01ea22b 100644
Binary files a/Barotrauma/BarotraumaShared/Submarines/Dugong.sub and b/Barotrauma/BarotraumaShared/Submarines/Dugong.sub differ
diff --git a/Barotrauma/BarotraumaShared/Submarines/Humpback.sub b/Barotrauma/BarotraumaShared/Submarines/Humpback.sub
index 50d1e74b4..aacc41a31 100644
Binary files a/Barotrauma/BarotraumaShared/Submarines/Humpback.sub and b/Barotrauma/BarotraumaShared/Submarines/Humpback.sub differ
diff --git a/Barotrauma/BarotraumaShared/Submarines/Muikku.sub b/Barotrauma/BarotraumaShared/Submarines/Muikku.sub
index 386de54c9..759d33ff4 100644
Binary files a/Barotrauma/BarotraumaShared/Submarines/Muikku.sub and b/Barotrauma/BarotraumaShared/Submarines/Muikku.sub differ
diff --git a/Barotrauma/BarotraumaShared/Submarines/Orca.sub b/Barotrauma/BarotraumaShared/Submarines/Orca.sub
index 3d9685698..6f8e91fd6 100644
Binary files a/Barotrauma/BarotraumaShared/Submarines/Orca.sub and b/Barotrauma/BarotraumaShared/Submarines/Orca.sub differ
diff --git a/Barotrauma/BarotraumaShared/Submarines/PAX.sub b/Barotrauma/BarotraumaShared/Submarines/PAX.sub
index 58e7cc9a0..1ce31fef0 100644
Binary files a/Barotrauma/BarotraumaShared/Submarines/PAX.sub and b/Barotrauma/BarotraumaShared/Submarines/PAX.sub differ
diff --git a/Barotrauma/BarotraumaShared/Submarines/Remora.sub b/Barotrauma/BarotraumaShared/Submarines/Remora.sub
index 74c05a493..4207a60d2 100644
Binary files a/Barotrauma/BarotraumaShared/Submarines/Remora.sub and b/Barotrauma/BarotraumaShared/Submarines/Remora.sub differ
diff --git a/Barotrauma/BarotraumaShared/Submarines/RemoraDrone.sub b/Barotrauma/BarotraumaShared/Submarines/RemoraDrone.sub
index 57f8fc56f..1c829b2d6 100644
Binary files a/Barotrauma/BarotraumaShared/Submarines/RemoraDrone.sub and b/Barotrauma/BarotraumaShared/Submarines/RemoraDrone.sub differ
diff --git a/Barotrauma/BarotraumaShared/changelog.txt b/Barotrauma/BarotraumaShared/changelog.txt
index 421c3d7df..40dd2231f 100644
--- a/Barotrauma/BarotraumaShared/changelog.txt
+++ b/Barotrauma/BarotraumaShared/changelog.txt
@@ -1,48 +1,3 @@
----------------------------------------------------------------------------------------------------------
-v0.8.9.7
----------------------------------------------------------------------------------------------------------
-
-Additions and changes:
-- The fission rate gauge on the reactor now visualizes the amount of fuel available.
-- Doors and hatches can now also be repaired with wrenches.
-- Changed default StatusEffect conditional comparison type back to OR.
-- Clients communicate syncing errors to the server, and the server logs a more descriptive error about
-what went wrong. Should make it easier to diagnose disconnection issues from now on.
-- Ending a multiplayer campaign round by talking to watchman doesn't require any special permissions.
-- Server automatically ends rounds if there have been no players alive in 60 seconds and respawning
-is not allowed during the round.
-- Added a button for resetting an entity's properties to the default values to the sub editor.
-- Updated handheld sonar UI graphics.
-
-Bugfixes:
-- Fixed non-radio chat/VOIP having an unlimited distance.
-- Fixed a networking bug that caused the server to send item state changes to the clients before sending
-a message about the item being spawned. For example, spawning any item with a LightComponent would always
-cause clients to get disconnected.
-- Changes to the way the clients are put in sync with the server when joining mid-round. Should make it
-less likely for clients to get disconnected immediately after starting a round.
-- StatusEffects only apply non-limb-specific afflictions to one limb even if targeting the whole character.
-Fixes drugs like fentanyl and morphine being way too harmful due to the oxygen loss affliction being
-applied once per every limb.
-- Fixed TargetItemComponentName not working in StatusEffect conditionals (making it impossible to create
-conditionals that target a specific component of an item).
-- Made all of the new medical items combinable and usable in a syringe gun (assuming the drug is in a syringe).
-- Fixed inability to throw anything in the multiplayer.
-- Fixed multiplayer campaign setup UI showing the client's subs instead of the server's.
-- Fixed campaign view button overlapping with the "ready to start" tickbox in the server lobby.
-- Fixed sub/mode voting not being enabled when changing the setting after the server has been started.
-- Fixed character inventories occasionally being saved incorrectly in the multiplayer campaign when an
-- Fixed flares not activating by left clicking.
-- Fixed affliction icons flickering rapidly in the health interface and above the health bar if their
-strength is fluctuating around the threshold where the icon becomes visible.
-- Fixed dedicated server crashing when typing in more text than can fit on one line.
-- Fixed enemies "fleeing" after they have been shot. There was a steering issue when they targeted characters
-inside the sub while being outside.
-- Fixed Hammerhead attack causing warping.
-- Fixed incorrect submarine and level seed in server logs when playing campaign mode.
-- Hide the start button from the campaign UI if the client doesn't have the permission to manage
-the campaign or rounds.
-
---------------------------------------------------------------------------------------------------------
v0.8.9.6
---------------------------------------------------------------------------------------------------------
@@ -58,7 +13,6 @@ themselves alive and less likely to get stuck.
- New husk sprites.
- Improved item/character highlight effect.
- New signal items (divide, multiply, subtract, memory, equals, greater than, color, xor).
-- Option to adjust microphone volume in multiplayer.
- Added a console commands for changing the gender and race of the character.
- More intuitive BrokenSprite condition logic: a BrokenSprite with a MaxCondition of 50 will start
fading in at 50 (and be fully visible when the condition drops to 0 or down to the MaxCondition of
@@ -89,8 +43,6 @@ suitable capture device.
- Fixed crashing when starting a round if a submarine name contains underscores.
- Fixed clients console errors when attempting to modify the properties of an ItemComponent in-game
(for example, the color of a light component).
-- Added some more information to the console messages and error popups when a client gets disconnected.
-- Fixed enablecheats command crashing the server if it's used when there are no clients present.
Misc bugfixes:
- Audio fixes (less snap, crackle and pop).
@@ -103,18 +55,12 @@ identifiers.
- Fixed item interfaces getting repositioned every frame when the editing HUD is open.
- Fixed held items clipping with the sleeves of the character (e.g. when holding a revolver while an
uniform is equipped).
-- Fixed being able to levitate by spamming the ragdoll button.
- Fixed dead characters draining oxygen tanks inside diving suits/masks.
-- Fixed reactor gauges getting messed up if the optimal fission rate is more than 100% (which may happen
-if the power consumption is larger than what the reactor can generate).
- Fixed mud raptors not having an inventory (nor lootable items).
- Fixed inability to interact with any items when aim assist is set to 0%.
- Fixed info panel flickering out and Tab getting "inverted" (= info panel shown when tab is not being held)
when selecting crew members in the panel.
- Fixed characters arms occasionally getting stuck above their shoulders.
-- Fixed wire nodes occasionally being created at the wrong end of a wire (e.g. when moving a wire between
-connections in a connection panel, the wire stretched from the device at the other end of the wire to
-the device that's being rewired).
Misc:
- Changed the way arguments are given to the "setclientcharacter" command (no semicolon to separate the
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 652dc4fb7..25fbbf2f3 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -35,8 +35,6 @@ The client project includes the code only required by the client executable: gra
### Building the game
Before building, you should choose the build configuration. The available configurations are `DebugWindows`, `DebugMac`, `DebugLinux`, `ReleaseWindows`, `ReleaseMac` and `ReleaseLinux`. Additionally, unless you want to work on the dedicated server, you may want to make sure `WindowsClient`, `MacClient` or `LinuxClient` are selected as the startup project.
-The `BarotraumaShared\Content` folder, which contains Barotrauma's art, item XMLs, sounds, and other assets, is not included in the GitHub repository. If you have a legal copy of the game, you can copy the `Content` folder from the game's files to `BarotraumaShared\Content`.
-
The debug build configurations include some features that make debugging and testing a little easier: things such as additional console commands, being able to move the submarine with the IJKL keys and allowing clients to use any console command in multiplayer. The debug builds don't create crash reports when an unhandled exception occurs - the intention behind this is to allow exceptions to be caught by the debugger instead of having the game close and write a report.
To build through the command line (recommended if you're on Linux), use the following command:
diff --git a/git-strip-merge b/git-strip-merge
index 3bae2789e..318a93d46 100644
--- a/git-strip-merge
+++ b/git-strip-merge
@@ -120,21 +120,8 @@ gitbranch() {
original=$(gitbranch HEAD)
branchsha=$(gitsha "$branch")
-branchshortsha="${branchsha:0:7}"
-#get the hash of the last merged remote commit from the latest commit msg in this repo
-#assumes that the commit message starts with hash1...hash2
-prevcommitmsg="$(git log -1 --pretty=%B)"
-prevcommitsha="${prevcommitmsg:10:7}"
-
-#create a commit message for out new "merge commit"
-# hash1...hash2 + logs of the merged commits
-logmsg="$prevcommitsha"
-logmsg+="..."
-logmsg+="$branchshortsha"
-logmsg+="
-
-$(git log "$prevcommitsha"..."$branchsha")"
+logmsg="$(git log .."$branchsha")"
trap 'git checkout --quiet "$original"' EXIT
@@ -143,10 +130,11 @@ git rm -rf -r "${files[@]}" "${quiet[@]}" &&
git commit -m "$msgcommit" "${quiet[@]}" &&
newsha=$(gitsha HEAD) &&
git checkout "$original" "${quiet[@]}" &&
+#original
+#git merge -m "$msgmerge" "${mergeopts[@]}" "$newsha"
-git merge -m "$msgmerge" -X theirs "--squash" "$newsha"
-git checkout HEAD .gitignore
+#baro additions
+git merge -m "$msgmerge" "--squash" "$newsha"
git commit -m "$logmsg"
-#example usage
-#./git-strip-merge barotrauma-development/dev -f Barotrauma/BarotraumaShared/Content/*
+#./git-strip-merge --no-commit --no-ff barotrauma-development/dev -f Barotrauma/BarotraumaShared/Content/*