v0.13.0.11
This commit is contained in:
@@ -37,7 +37,7 @@ namespace Barotrauma
|
|||||||
public float MinZoom
|
public float MinZoom
|
||||||
{
|
{
|
||||||
get { return minZoom;}
|
get { return minZoom;}
|
||||||
set { minZoom = MathHelper.Clamp(value, 0.01f, 10.0f); }
|
set { minZoom = MathHelper.Clamp(value, 0.001f, 10.0f); }
|
||||||
}
|
}
|
||||||
|
|
||||||
private float maxZoom = 2.0f;
|
private float maxZoom = 2.0f;
|
||||||
@@ -51,8 +51,6 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private float zoom;
|
private float zoom;
|
||||||
|
|
||||||
private float offsetAmount;
|
|
||||||
|
|
||||||
private Matrix transform, shaderTransform, viewMatrix;
|
private Matrix transform, shaderTransform, viewMatrix;
|
||||||
private Vector2 position;
|
private Vector2 position;
|
||||||
private float rotation;
|
private float rotation;
|
||||||
@@ -67,16 +65,9 @@ namespace Barotrauma
|
|||||||
public float Shake;
|
public float Shake;
|
||||||
private Vector2 shakePosition;
|
private Vector2 shakePosition;
|
||||||
private float shakeTimer;
|
private float shakeTimer;
|
||||||
|
|
||||||
//the area of the world inside the camera view
|
|
||||||
private Rectangle worldView;
|
|
||||||
|
|
||||||
private float globalZoomScale = 1.0f;
|
private float globalZoomScale = 1.0f;
|
||||||
|
|
||||||
private Point resolution;
|
|
||||||
|
|
||||||
private Vector2 targetPos;
|
|
||||||
|
|
||||||
//used to smooth out the movement when in freecam
|
//used to smooth out the movement when in freecam
|
||||||
private float targetZoom;
|
private float targetZoom;
|
||||||
private Vector2 velocity;
|
private Vector2 velocity;
|
||||||
@@ -89,10 +80,10 @@ namespace Barotrauma
|
|||||||
zoom = MathHelper.Clamp(value, GameMain.DebugDraw ? 0.01f : MinZoom, MaxZoom);
|
zoom = MathHelper.Clamp(value, GameMain.DebugDraw ? 0.01f : MinZoom, MaxZoom);
|
||||||
|
|
||||||
Vector2 center = WorldViewCenter;
|
Vector2 center = WorldViewCenter;
|
||||||
float newWidth = resolution.X / zoom;
|
float newWidth = Resolution.X / zoom;
|
||||||
float newHeight = resolution.Y / zoom;
|
float newHeight = Resolution.Y / zoom;
|
||||||
|
|
||||||
worldView = new Rectangle(
|
WorldView = new Rectangle(
|
||||||
(int)(center.X - newWidth / 2.0f),
|
(int)(center.X - newWidth / 2.0f),
|
||||||
(int)(center.Y + newHeight / 2.0f),
|
(int)(center.Y + newHeight / 2.0f),
|
||||||
(int)newWidth,
|
(int)newWidth,
|
||||||
@@ -122,29 +113,20 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public float OffsetAmount
|
public float OffsetAmount { get; set; }
|
||||||
{
|
|
||||||
get { return offsetAmount; }
|
|
||||||
set { offsetAmount = value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public Point Resolution
|
public Point Resolution { get; private set; }
|
||||||
{
|
|
||||||
get { return resolution; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public Rectangle WorldView
|
//the area of the world inside the camera view
|
||||||
{
|
public Rectangle WorldView { get; private set; }
|
||||||
get { return worldView; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public Vector2 WorldViewCenter
|
public Vector2 WorldViewCenter
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return new Vector2(
|
return new Vector2(
|
||||||
worldView.X + worldView.Width / 2.0f,
|
WorldView.X + WorldView.Width / 2.0f,
|
||||||
worldView.Y - worldView.Height / 2.0f);
|
WorldView.Y - WorldView.Height / 2.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,12 +153,13 @@ namespace Barotrauma
|
|||||||
UpdateTransform(false);
|
UpdateTransform(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector2 TargetPos
|
~Camera()
|
||||||
{
|
{
|
||||||
get { return targetPos; }
|
GameMain.Instance.ResolutionChanged -= CreateMatrices;
|
||||||
set { targetPos = value; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Vector2 TargetPos { get; set; }
|
||||||
|
|
||||||
public Vector2 GetPosition()
|
public Vector2 GetPosition()
|
||||||
{
|
{
|
||||||
return position;
|
return position;
|
||||||
@@ -204,21 +187,29 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public void SetResolution(Point res)
|
public void SetResolution(Point res)
|
||||||
{
|
{
|
||||||
resolution = res;
|
Resolution = res;
|
||||||
|
|
||||||
worldView = new Rectangle(0, 0, res.X, res.Y);
|
WorldView = new Rectangle(0, 0, res.X, res.Y);
|
||||||
viewMatrix = Matrix.CreateTranslation(new Vector3(res.X / 2.0f, res.Y / 2.0f, 0));
|
viewMatrix = Matrix.CreateTranslation(new Vector3(res.X / 2.0f, res.Y / 2.0f, 0));
|
||||||
globalZoomScale = (float)Math.Pow(new Vector2(GUI.UIWidth, resolution.Y).Length() / GUI.ReferenceResolution.Length(), 2);
|
float newGlobalZoomScale = (float)new Vector2(GUI.UIWidth, Resolution.Y).Length() / GUI.ReferenceResolution.Length();
|
||||||
|
if (globalZoomScale > 0.0f)
|
||||||
|
{
|
||||||
|
Zoom *= newGlobalZoomScale / globalZoomScale;
|
||||||
|
targetZoom *= newGlobalZoomScale / globalZoomScale;
|
||||||
|
prevZoom *= newGlobalZoomScale / globalZoomScale;
|
||||||
|
}
|
||||||
|
globalZoomScale = newGlobalZoomScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateTransform(bool interpolate = true)
|
public void UpdateTransform(bool interpolate = true, bool updateListener = true)
|
||||||
{
|
{
|
||||||
Vector2 interpolatedPosition = interpolate ? Timing.Interpolate(prevPosition, position) : position;
|
Vector2 interpolatedPosition = interpolate ? Timing.Interpolate(prevPosition, position) : position;
|
||||||
|
|
||||||
float interpolatedZoom = interpolate ? Timing.Interpolate(prevZoom, zoom) : zoom;
|
float interpolatedZoom = interpolate ? Timing.Interpolate(prevZoom, zoom) : zoom;
|
||||||
|
|
||||||
worldView.X = (int)(interpolatedPosition.X - worldView.Width / 2.0);
|
WorldView = new Rectangle((int)(interpolatedPosition.X - WorldView.Width / 2.0),
|
||||||
worldView.Y = (int)(interpolatedPosition.Y + worldView.Height / 2.0);
|
(int)(interpolatedPosition.Y + WorldView.Height / 2.0),
|
||||||
|
WorldView.Width, WorldView.Height);
|
||||||
|
|
||||||
transform = Matrix.CreateTranslation(
|
transform = Matrix.CreateTranslation(
|
||||||
new Vector3(-interpolatedPosition.X, interpolatedPosition.Y, 0)) *
|
new Vector3(-interpolatedPosition.X, interpolatedPosition.Y, 0)) *
|
||||||
@@ -227,19 +218,22 @@ namespace Barotrauma
|
|||||||
|
|
||||||
shaderTransform = Matrix.CreateTranslation(
|
shaderTransform = Matrix.CreateTranslation(
|
||||||
new Vector3(
|
new Vector3(
|
||||||
-interpolatedPosition.X - resolution.X / interpolatedZoom / 2.0f,
|
-interpolatedPosition.X - Resolution.X / interpolatedZoom / 2.0f,
|
||||||
-interpolatedPosition.Y - resolution.Y / interpolatedZoom / 2.0f, 0)) *
|
-interpolatedPosition.Y - Resolution.Y / interpolatedZoom / 2.0f, 0)) *
|
||||||
Matrix.CreateScale(new Vector3(interpolatedZoom, interpolatedZoom, 1)) *
|
Matrix.CreateScale(new Vector3(interpolatedZoom, interpolatedZoom, 1)) *
|
||||||
|
|
||||||
viewMatrix * Matrix.CreateRotationZ(-rotation);
|
viewMatrix * Matrix.CreateRotationZ(-rotation);
|
||||||
|
|
||||||
if (Character.Controlled == null)
|
if (updateListener)
|
||||||
{
|
{
|
||||||
GameMain.SoundManager.ListenerPosition = new Vector3(WorldViewCenter.X, WorldViewCenter.Y, -(100.0f / zoom));
|
if (Character.Controlled == null)
|
||||||
}
|
{
|
||||||
else
|
GameMain.SoundManager.ListenerPosition = new Vector3(WorldViewCenter.X, WorldViewCenter.Y, -(100.0f / zoom));
|
||||||
{
|
}
|
||||||
GameMain.SoundManager.ListenerPosition = new Vector3(Character.Controlled.WorldPosition.X, Character.Controlled.WorldPosition.Y, -(100.0f / zoom));
|
else
|
||||||
|
{
|
||||||
|
GameMain.SoundManager.ListenerPosition = new Vector3(Character.Controlled.WorldPosition.X, Character.Controlled.WorldPosition.Y, -(100.0f / zoom));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -257,7 +251,7 @@ namespace Barotrauma
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool Freeze { get; set; }
|
public bool Freeze { get; set; }
|
||||||
|
|
||||||
public void MoveCamera(float deltaTime, bool allowMove = true, bool allowZoom = true)
|
public void MoveCamera(float deltaTime, bool allowMove = true, bool allowZoom = true, bool? followSub = null)
|
||||||
{
|
{
|
||||||
prevPosition = position;
|
prevPosition = position;
|
||||||
prevZoom = zoom;
|
prevZoom = zoom;
|
||||||
@@ -265,7 +259,7 @@ namespace Barotrauma
|
|||||||
float moveSpeed = 20.0f / zoom;
|
float moveSpeed = 20.0f / zoom;
|
||||||
|
|
||||||
Vector2 moveCam = Vector2.Zero;
|
Vector2 moveCam = Vector2.Zero;
|
||||||
if (targetPos == Vector2.Zero)
|
if (TargetPos == Vector2.Zero)
|
||||||
{
|
{
|
||||||
Vector2 moveInput = Vector2.Zero;
|
Vector2 moveInput = Vector2.Zero;
|
||||||
if (allowMove && !Freeze)
|
if (allowMove && !Freeze)
|
||||||
@@ -284,7 +278,7 @@ namespace Barotrauma
|
|||||||
velocity = Vector2.Lerp(velocity, moveInput, deltaTime * 10.0f);
|
velocity = Vector2.Lerp(velocity, moveInput, deltaTime * 10.0f);
|
||||||
moveCam = velocity * moveSpeed * deltaTime * FreeCamMoveSpeed * 60.0f;
|
moveCam = velocity * moveSpeed * deltaTime * FreeCamMoveSpeed * 60.0f;
|
||||||
|
|
||||||
if (Screen.Selected == GameMain.GameScreen && FollowSub)
|
if (Screen.Selected == GameMain.GameScreen && (followSub ?? FollowSub))
|
||||||
{
|
{
|
||||||
var closestSub = Submarine.FindClosest(WorldViewCenter);
|
var closestSub = Submarine.FindClosest(WorldViewCenter);
|
||||||
if (closestSub != null)
|
if (closestSub != null)
|
||||||
@@ -294,7 +288,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (allowZoom && GUI.MouseOn == null)
|
if (allowZoom)
|
||||||
{
|
{
|
||||||
Vector2 mouseInWorld = ScreenToWorld(PlayerInput.MousePosition);
|
Vector2 mouseInWorld = ScreenToWorld(PlayerInput.MousePosition);
|
||||||
Vector2 diffViewCenter;
|
Vector2 diffViewCenter;
|
||||||
@@ -318,14 +312,15 @@ namespace Barotrauma
|
|||||||
else if (allowMove)
|
else if (allowMove)
|
||||||
{
|
{
|
||||||
Vector2 mousePos = PlayerInput.MousePosition;
|
Vector2 mousePos = PlayerInput.MousePosition;
|
||||||
Vector2 offset = mousePos - resolution.ToVector2() / 2;
|
Vector2 offset = mousePos - Resolution.ToVector2() / 2;
|
||||||
offset.X = offset.X / (resolution.X * 0.4f);
|
offset.X = offset.X / (Resolution.X * 0.4f);
|
||||||
offset.Y = -offset.Y / (resolution.Y * 0.3f);
|
offset.Y = -offset.Y / (Resolution.Y * 0.3f);
|
||||||
if (offset.LengthSquared() > 1.0f) offset.Normalize();
|
if (offset.LengthSquared() > 1.0f) offset.Normalize();
|
||||||
offset *= offsetAmount;
|
float offsetUnscaledLen = offset.Length();
|
||||||
|
offset *= OffsetAmount;
|
||||||
// Freeze the camera movement by default, when the cursor is on top of an ui element.
|
// Freeze the camera movement by default, when the cursor is on top of an ui element.
|
||||||
// Setting a positive value to the OffsetAmount, will override this behaviour.
|
// Setting a positive value to the OffsetAmount, will override this behaviour.
|
||||||
if (GUI.MouseOn != null && offsetAmount > 0)
|
if (GUI.MouseOn != null && OffsetAmount > 0)
|
||||||
{
|
{
|
||||||
Freeze = true;
|
Freeze = true;
|
||||||
}
|
}
|
||||||
@@ -336,7 +331,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
if (Freeze)
|
if (Freeze)
|
||||||
{
|
{
|
||||||
offset = previousOffset;
|
if (offset.LengthSquared() > 0.001f) { offset = previousOffset; }
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -344,24 +339,19 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
//how much to zoom out (zoom completely out when offset is 1000)
|
//how much to zoom out (zoom completely out when offset is 1000)
|
||||||
float zoomOutAmount = GetZoomAmount(offset);
|
float zoomOutAmount = GetZoomAmount(offset);
|
||||||
//zoom amount when resolution is not taken into account
|
//scaled zoom amount
|
||||||
float unscaledZoom = MathHelper.Lerp(DefaultZoom, MinZoom, zoomOutAmount);
|
float scaledZoom = MathHelper.Lerp(DefaultZoom, MinZoom, zoomOutAmount) * globalZoomScale;
|
||||||
//zoom with resolution taken into account (zoom further out on smaller resolutions)
|
//zoom in further if zoomOutAmount is low and resolution is lower than reference
|
||||||
float scaledZoom = unscaledZoom * globalZoomScale;
|
float newZoom = scaledZoom * (MathHelper.Lerp(0.3f * (1f - Math.Min(globalZoomScale, 1f)), 0f,
|
||||||
|
(GameMain.Config == null || GameMain.Config.EnableMouseLook) ? (float)Math.Sqrt(offsetUnscaledLen) : 0.3f) + 1f);
|
||||||
//an ad-hoc way of allowing the players to have roughly the same maximum view distance regardless of the resolution,
|
|
||||||
//while still keeping the zoom around 1.0 when not looking further away (because otherwise we'd always be downsampling
|
|
||||||
//on lower resolutions, which doesn't look that good)
|
|
||||||
float newZoom = MathHelper.Lerp(unscaledZoom, scaledZoom,
|
|
||||||
(GameMain.Config == null || GameMain.Config.EnableMouseLook) ? (float)Math.Sqrt(zoomOutAmount) : 0.3f);
|
|
||||||
|
|
||||||
Zoom += (newZoom - zoom) / ZoomSmoothness;
|
Zoom += (newZoom - zoom) / ZoomSmoothness;
|
||||||
|
|
||||||
//force targetzoom to the current zoom value, so the camera stays at the same zoom when switching to freecam
|
//force targetzoom to the current zoom value, so the camera stays at the same zoom when switching to freecam
|
||||||
targetZoom = Zoom;
|
targetZoom = Zoom;
|
||||||
|
|
||||||
Vector2 diff = (targetPos + offset) - position;
|
Vector2 diff = (TargetPos + offset) - position;
|
||||||
|
|
||||||
moveCam = diff / MoveSmoothness;
|
moveCam = diff / MoveSmoothness;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (!ShowAITargets) { return; }
|
if (!ShowAITargets) { return; }
|
||||||
var pos = new Vector2(WorldPosition.X, -WorldPosition.Y);
|
var pos = new Vector2(WorldPosition.X, -WorldPosition.Y);
|
||||||
|
float thickness = 1 / Screen.Selected.Cam.Zoom;
|
||||||
|
|
||||||
|
float offset = MathUtils.VectorToAngle(new Vector2(sectorDir.X, -sectorDir.Y)) - (sectorRad / 2f);
|
||||||
if (soundRange > 0.0f)
|
if (soundRange > 0.0f)
|
||||||
{
|
{
|
||||||
Color color;
|
Color color;
|
||||||
@@ -26,8 +29,16 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
color = Color.OrangeRed;
|
color = Color.OrangeRed;
|
||||||
}
|
}
|
||||||
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 (sectorRad < MathHelper.TwoPi)
|
||||||
|
{
|
||||||
|
spriteBatch.DrawSector(pos, SoundRange, sectorRad, 100, color, offset: offset, thickness: thickness);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
spriteBatch.DrawCircle(pos, SoundRange, 100, color, thickness: thickness);
|
||||||
|
}
|
||||||
|
spriteBatch.DrawCircle(pos, 3, 8, color, thickness: 2 / Screen.Selected.Cam.Zoom);
|
||||||
GUI.DrawLine(spriteBatch, pos, pos + Vector2.UnitY * SoundRange, color, width: (int)(1 / Screen.Selected.Cam.Zoom) + 1);
|
GUI.DrawLine(spriteBatch, pos, pos + Vector2.UnitY * SoundRange, color, width: (int)(1 / Screen.Selected.Cam.Zoom) + 1);
|
||||||
}
|
}
|
||||||
if (sightRange > 0.0f)
|
if (sightRange > 0.0f)
|
||||||
@@ -47,7 +58,14 @@ namespace Barotrauma
|
|||||||
// disable the indicators for structures and hulls, because they clutter the debug view
|
// disable the indicators for structures and hulls, because they clutter the debug view
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ShapeExtensions.DrawCircle(spriteBatch, pos, SightRange, 100, color, thickness: 1 / Screen.Selected.Cam.Zoom);
|
if (sectorRad < MathHelper.TwoPi)
|
||||||
|
{
|
||||||
|
spriteBatch.DrawSector(pos, SightRange, sectorRad, 100, color, offset: offset, thickness: thickness);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
spriteBatch.DrawCircle(pos, SightRange, 100, color, thickness: thickness);
|
||||||
|
}
|
||||||
ShapeExtensions.DrawCircle(spriteBatch, pos, 6, 8, color, thickness: 2 / Screen.Selected.Cam.Zoom);
|
ShapeExtensions.DrawCircle(spriteBatch, pos, 6, 8, color, thickness: 2 / Screen.Selected.Cam.Zoom);
|
||||||
GUI.DrawLine(spriteBatch, pos, pos + Vector2.UnitY * SightRange, color, width: (int)(1 / Screen.Selected.Cam.Zoom) + 1);
|
GUI.DrawLine(spriteBatch, pos, pos + Vector2.UnitY * SightRange, color, width: (int)(1 / Screen.Selected.Cam.Zoom) + 1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,12 @@
|
|||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using FarseerPhysics;
|
using FarseerPhysics;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
partial class HumanAIController : AIController
|
partial class HumanAIController : AIController
|
||||||
{
|
{
|
||||||
partial void InitProjSpecific()
|
|
||||||
{
|
|
||||||
/*if (GameMain.GameSession != null && GameMain.GameSession.CrewManager != null)
|
|
||||||
{
|
|
||||||
CurrentOrder = Order.GetPrefab("dismissed");
|
|
||||||
objectiveManager.SetOrder(CurrentOrder, "", null);
|
|
||||||
GameMain.GameSession.CrewManager.SetCharacterOrder(Character, CurrentOrder, null, null);
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void DebugDraw(Microsoft.Xna.Framework.Graphics.SpriteBatch spriteBatch)
|
public override void DebugDraw(Microsoft.Xna.Framework.Graphics.SpriteBatch spriteBatch)
|
||||||
{
|
{
|
||||||
if (Character == Character.Controlled) { return; }
|
if (Character == Character.Controlled) { return; }
|
||||||
@@ -22,6 +14,7 @@ namespace Barotrauma
|
|||||||
Vector2 pos = Character.WorldPosition;
|
Vector2 pos = Character.WorldPosition;
|
||||||
pos.Y = -pos.Y;
|
pos.Y = -pos.Y;
|
||||||
Vector2 textOffset = new Vector2(-40, -160);
|
Vector2 textOffset = new Vector2(-40, -160);
|
||||||
|
textOffset.Y -= Math.Max(ObjectiveManager.CurrentOrders.Count - 1, 0) * 20;
|
||||||
|
|
||||||
if (SelectedAiTarget?.Entity != null)
|
if (SelectedAiTarget?.Entity != null)
|
||||||
{
|
{
|
||||||
@@ -29,56 +22,55 @@ namespace Barotrauma
|
|||||||
//GUI.DrawString(spriteBatch, pos + textOffset, $"AI TARGET: {SelectedAiTarget.Entity.ToString()}", Color.White, Color.Black);
|
//GUI.DrawString(spriteBatch, pos + textOffset, $"AI TARGET: {SelectedAiTarget.Entity.ToString()}", Color.White, Color.Black);
|
||||||
}
|
}
|
||||||
|
|
||||||
GUI.DrawString(spriteBatch, pos + textOffset, Character.Name, Color.White, Color.Black);
|
Vector2 stringDrawPos = pos + textOffset;
|
||||||
|
GUI.DrawString(spriteBatch, stringDrawPos, Character.Name, Color.White, Color.Black);
|
||||||
|
|
||||||
var currentOrder = ObjectiveManager.CurrentOrder;
|
var currentOrder = ObjectiveManager.CurrentOrder;
|
||||||
if (currentOrder != null)
|
if (ObjectiveManager.CurrentOrders.Any())
|
||||||
{
|
{
|
||||||
GUI.DrawString(spriteBatch, pos + textOffset + new Vector2(0, 20), $"ORDER: {currentOrder.DebugTag} ({currentOrder.Priority.FormatZeroDecimal()})", Color.White, Color.Black);
|
var currentOrders = ObjectiveManager.CurrentOrders;
|
||||||
|
currentOrders.Sort((x, y) => y.ManualPriority.CompareTo(x.ManualPriority));
|
||||||
|
for (int i = 0; i < currentOrders.Count; i++)
|
||||||
|
{
|
||||||
|
stringDrawPos += new Vector2(0, 20);
|
||||||
|
var order = currentOrders[i];
|
||||||
|
GUI.DrawString(spriteBatch, stringDrawPos, $"ORDER {i + 1}: {order.Objective.DebugTag} ({order.Objective.Priority.FormatZeroDecimal()})", Color.White, Color.Black);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (ObjectiveManager.WaitTimer > 0)
|
else if (ObjectiveManager.WaitTimer > 0)
|
||||||
{
|
{
|
||||||
GUI.DrawString(spriteBatch, pos + new Vector2(0, 20), $"Waiting... {ObjectiveManager.WaitTimer.FormatZeroDecimal()}", Color.White, Color.Black);
|
stringDrawPos += new Vector2(0, 20);
|
||||||
|
GUI.DrawString(spriteBatch, stringDrawPos - textOffset, $"Waiting... {ObjectiveManager.WaitTimer.FormatZeroDecimal()}", Color.White, Color.Black);
|
||||||
}
|
}
|
||||||
var currentObjective = ObjectiveManager.CurrentObjective;
|
var currentObjective = ObjectiveManager.CurrentObjective;
|
||||||
if (currentObjective != null)
|
if (currentObjective != null)
|
||||||
{
|
{
|
||||||
int offset = currentOrder != null ? 20 : 0;
|
int offset = currentOrder != null ? 20 + ((ObjectiveManager.CurrentOrders.Count - 1) * 20) : 0;
|
||||||
if (currentOrder == null || currentOrder.Priority <= 0)
|
if (currentOrder == null || currentOrder.Priority <= 0)
|
||||||
{
|
{
|
||||||
GUI.DrawString(spriteBatch, pos + textOffset + new Vector2(0, 20 + offset), $"MAIN OBJECTIVE: {currentObjective.DebugTag} ({currentObjective.Priority.FormatZeroDecimal()})", Color.White, Color.Black);
|
stringDrawPos += new Vector2(0, 20);
|
||||||
|
GUI.DrawString(spriteBatch, stringDrawPos, $"MAIN OBJECTIVE: {currentObjective.DebugTag} ({currentObjective.Priority.FormatZeroDecimal()})", Color.White, Color.Black);
|
||||||
}
|
}
|
||||||
var subObjective = currentObjective.CurrentSubObjective;
|
var subObjective = currentObjective.CurrentSubObjective;
|
||||||
if (subObjective != null)
|
if (subObjective != null)
|
||||||
{
|
{
|
||||||
GUI.DrawString(spriteBatch, pos + textOffset + new Vector2(0, 40 + offset), $"SUBOBJECTIVE: {subObjective.DebugTag} ({subObjective.Priority.FormatZeroDecimal()})", Color.White, Color.Black);
|
stringDrawPos += new Vector2(0, 20);
|
||||||
|
GUI.DrawString(spriteBatch, stringDrawPos, $"SUBOBJECTIVE: {subObjective.DebugTag} ({subObjective.Priority.FormatZeroDecimal()})", Color.White, Color.Black);
|
||||||
}
|
}
|
||||||
var activeObjective = ObjectiveManager.GetActiveObjective();
|
var activeObjective = ObjectiveManager.GetActiveObjective();
|
||||||
if (activeObjective != null)
|
if (activeObjective != null)
|
||||||
{
|
{
|
||||||
GUI.DrawString(spriteBatch, pos + textOffset + new Vector2(0, 60 + offset), $"ACTIVE OBJECTIVE: {activeObjective.DebugTag} ({activeObjective.Priority.FormatZeroDecimal()})", Color.White, Color.Black);
|
stringDrawPos += new Vector2(0, 20);
|
||||||
|
GUI.DrawString(spriteBatch, stringDrawPos, $"ACTIVE OBJECTIVE: {activeObjective.DebugTag} ({activeObjective.Priority.FormatZeroDecimal()})", Color.White, Color.Black);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector2 objectiveStringDrawPos = stringDrawPos + new Vector2(120, 40);
|
||||||
for (int i = 0; i < ObjectiveManager.Objectives.Count; i++)
|
for (int i = 0; i < ObjectiveManager.Objectives.Count; i++)
|
||||||
{
|
{
|
||||||
var objective = ObjectiveManager.Objectives[i];
|
var objective = ObjectiveManager.Objectives[i];
|
||||||
int offsetMultiplier;
|
GUI.DrawString(spriteBatch, objectiveStringDrawPos, $"{objective.DebugTag} ({objective.Priority.FormatZeroDecimal()})", Color.White, Color.Black * 0.5f);
|
||||||
if (ObjectiveManager.CurrentOrder == null)
|
objectiveStringDrawPos += new Vector2(0, 18);
|
||||||
{
|
|
||||||
if (i == 0)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
offsetMultiplier = i - 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
offsetMultiplier = i + 1;
|
|
||||||
}
|
|
||||||
GUI.DrawString(spriteBatch, pos + textOffset + new Vector2(120, offsetMultiplier * 18 + 100), $"{objective.DebugTag} ({objective.Priority.FormatZeroDecimal()})", Color.White, Color.Black * 0.5f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (steeringManager is IndoorsSteeringManager pathSteering)
|
if (steeringManager is IndoorsSteeringManager pathSteering)
|
||||||
@@ -106,7 +98,7 @@ namespace Barotrauma
|
|||||||
new Vector2(path.CurrentNode.DrawPosition.X, -path.CurrentNode.DrawPosition.Y),
|
new Vector2(path.CurrentNode.DrawPosition.X, -path.CurrentNode.DrawPosition.Y),
|
||||||
Color.BlueViolet, 0, 3);
|
Color.BlueViolet, 0, 3);
|
||||||
|
|
||||||
GUI.DrawString(spriteBatch, pos + textOffset + new Vector2(0, 100), "Path cost: " + path.Cost.FormatZeroDecimal(), Color.White, Color.Black * 0.5f);
|
GUI.DrawString(spriteBatch, stringDrawPos + new Vector2(0, 40), "Path cost: " + path.Cost.FormatZeroDecimal(), Color.White, Color.Black * 0.5f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,6 +55,11 @@ namespace Barotrauma
|
|||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (controlled == value) return;
|
if (controlled == value) return;
|
||||||
|
if ((!(controlled is null)) && (!(Screen.Selected?.Cam is null)) && value is null)
|
||||||
|
{
|
||||||
|
Screen.Selected.Cam.TargetPos = Vector2.Zero;
|
||||||
|
Lights.LightManager.ViewTarget = null;
|
||||||
|
}
|
||||||
controlled = value;
|
controlled = value;
|
||||||
if (controlled != null) controlled.Enabled = true;
|
if (controlled != null) controlled.Enabled = true;
|
||||||
CharacterHealth.OpenHealthWindow = null;
|
CharacterHealth.OpenHealthWindow = null;
|
||||||
@@ -96,6 +101,13 @@ namespace Barotrauma
|
|||||||
get { return chromaticAberrationStrength; }
|
get { return chromaticAberrationStrength; }
|
||||||
set { chromaticAberrationStrength = MathHelper.Clamp(value, 0.0f, 100.0f); }
|
set { chromaticAberrationStrength = MathHelper.Clamp(value, 0.0f, 100.0f); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private float grainStrength;
|
||||||
|
public float GrainStrength
|
||||||
|
{
|
||||||
|
get => grainStrength;
|
||||||
|
set => grainStrength = MathHelper.Clamp(value, 0.0f, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
private readonly List<ParticleEmitter> bloodEmitters = new List<ParticleEmitter>();
|
private readonly List<ParticleEmitter> bloodEmitters = new List<ParticleEmitter>();
|
||||||
public IEnumerable<ParticleEmitter> BloodEmitters
|
public IEnumerable<ParticleEmitter> BloodEmitters
|
||||||
@@ -115,6 +127,9 @@ namespace Barotrauma
|
|||||||
get { return gibEmitters; }
|
get { return gibEmitters; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool IsMouseOnUI => GUI.MouseOn != null ||
|
||||||
|
(CharacterInventory.IsMouseOnInventory() && !CharacterInventory.DraggingItemToWorld);
|
||||||
|
|
||||||
public class ObjectiveEntity
|
public class ObjectiveEntity
|
||||||
{
|
{
|
||||||
public Entity Entity;
|
public Entity Entity;
|
||||||
@@ -217,8 +232,7 @@ namespace Barotrauma
|
|||||||
float targetOffsetAmount = 0.0f;
|
float targetOffsetAmount = 0.0f;
|
||||||
if (moveCam)
|
if (moveCam)
|
||||||
{
|
{
|
||||||
if (NeedsAir &&
|
if (NeedsAir && !IsProtectedFromPressure() &&
|
||||||
pressureProtection < 80.0f &&
|
|
||||||
(AnimController.CurrentHull == null || AnimController.CurrentHull.LethalPressure > 0.0f))
|
(AnimController.CurrentHull == null || AnimController.CurrentHull.LethalPressure > 0.0f))
|
||||||
{
|
{
|
||||||
float pressure = AnimController.CurrentHull == null ? 100.0f : AnimController.CurrentHull.LethalPressure;
|
float pressure = AnimController.CurrentHull == null ? 100.0f : AnimController.CurrentHull.LethalPressure;
|
||||||
@@ -285,6 +299,10 @@ namespace Barotrauma
|
|||||||
cam.OffsetAmount = targetOffsetAmount = 0.0f;
|
cam.OffsetAmount = targetOffsetAmount = 0.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (IsMouseOnUI)
|
||||||
|
{
|
||||||
|
targetOffsetAmount = cam.OffsetAmount;
|
||||||
|
}
|
||||||
else if (Vector2.DistanceSquared(AnimController.Limbs[0].SimPosition, mouseSimPos) > 1.0f)
|
else if (Vector2.DistanceSquared(AnimController.Limbs[0].SimPosition, mouseSimPos) > 1.0f)
|
||||||
{
|
{
|
||||||
Body body = Submarine.CheckVisibility(AnimController.Limbs[0].SimPosition, mouseSimPos);
|
Body body = Submarine.CheckVisibility(AnimController.Limbs[0].SimPosition, mouseSimPos);
|
||||||
@@ -375,25 +393,63 @@ namespace Barotrauma
|
|||||||
|
|
||||||
partial void KillProjSpecific(CauseOfDeathType causeOfDeath, Affliction causeOfDeathAffliction, bool log)
|
partial void KillProjSpecific(CauseOfDeathType causeOfDeath, Affliction causeOfDeathAffliction, bool log)
|
||||||
{
|
{
|
||||||
|
HintManager.OnCharacterKilled(this);
|
||||||
|
|
||||||
if (GameMain.NetworkMember != null && controlled == this)
|
if (GameMain.NetworkMember != null && controlled == this)
|
||||||
{
|
{
|
||||||
string chatMessage = CauseOfDeath.Type == CauseOfDeathType.Affliction ?
|
string chatMessage = CauseOfDeath.Type == CauseOfDeathType.Affliction ?
|
||||||
CauseOfDeath.Affliction.SelfCauseOfDeathDescription :
|
CauseOfDeath.Affliction.SelfCauseOfDeathDescription :
|
||||||
TextManager.Get("Self_CauseOfDeathDescription." + CauseOfDeath.Type.ToString(), fallBackTag: "Self_CauseOfDeathDescription.Damage");
|
TextManager.Get("Self_CauseOfDeathDescription." + CauseOfDeath.Type.ToString(), fallBackTag: "Self_CauseOfDeathDescription.Damage");
|
||||||
|
|
||||||
if (GameMain.Client != null) chatMessage += " " + TextManager.Get("DeathChatNotification");
|
if (GameMain.Client != null) { chatMessage += " " + TextManager.Get("DeathChatNotification"); }
|
||||||
|
|
||||||
|
if (GameMain.NetworkMember.RespawnManager?.UseRespawnPrompt ?? false)
|
||||||
|
{
|
||||||
|
CoroutineManager.InvokeAfter(() =>
|
||||||
|
{
|
||||||
|
if (controlled != null || (!(GameMain.GameSession?.IsRunning ?? false))) { return; }
|
||||||
|
var respawnPrompt = new GUIMessageBox(
|
||||||
|
TextManager.Get("tutorial.tryagainheader"), TextManager.Get("respawnquestionprompt"),
|
||||||
|
new string[] { TextManager.Get("respawnquestionpromptrespawn"), TextManager.Get("respawnquestionpromptwait") });
|
||||||
|
respawnPrompt.Buttons[0].OnClicked += (btn, userdata) =>
|
||||||
|
{
|
||||||
|
GameMain.Client?.SendRespawnPromptResponse(waitForNextRoundRespawn: false);
|
||||||
|
respawnPrompt.Close();
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
respawnPrompt.Buttons[1].OnClicked += (btn, userdata) =>
|
||||||
|
{
|
||||||
|
GameMain.Client?.SendRespawnPromptResponse(waitForNextRoundRespawn: true);
|
||||||
|
respawnPrompt.Close();
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
}, delay: 5.0f);
|
||||||
|
}
|
||||||
|
|
||||||
GameMain.NetworkMember.AddChatMessage(chatMessage, ChatMessageType.Dead);
|
GameMain.NetworkMember.AddChatMessage(chatMessage, ChatMessageType.Dead);
|
||||||
GameMain.LightManager.LosEnabled = false;
|
GameMain.LightManager.LosEnabled = false;
|
||||||
controlled = null;
|
controlled = null;
|
||||||
|
if (!(Screen.Selected?.Cam is null))
|
||||||
|
{
|
||||||
|
Screen.Selected.Cam.TargetPos = Vector2.Zero;
|
||||||
|
Lights.LightManager.ViewTarget = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PlaySound(CharacterSound.SoundType.Die);
|
PlaySound(CharacterSound.SoundType.Die);
|
||||||
}
|
}
|
||||||
|
|
||||||
partial void DisposeProjSpecific()
|
partial void DisposeProjSpecific()
|
||||||
{
|
{
|
||||||
if (controlled == this) controlled = null;
|
if (controlled == this)
|
||||||
|
{
|
||||||
|
controlled = null;
|
||||||
|
if (!(Screen.Selected?.Cam is null))
|
||||||
|
{
|
||||||
|
Screen.Selected.Cam.TargetPos = Vector2.Zero;
|
||||||
|
Lights.LightManager.ViewTarget = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (GameMain.GameSession?.CrewManager != null &&
|
if (GameMain.GameSession?.CrewManager != null &&
|
||||||
GameMain.GameSession.CrewManager.GetCharacters().Contains(this))
|
GameMain.GameSession.CrewManager.GetCharacters().Contains(this))
|
||||||
@@ -634,9 +690,9 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
partial void SetOrderProjSpecific(Order order, string orderOption)
|
partial void SetOrderProjSpecific(Order order, string orderOption, int priority)
|
||||||
{
|
{
|
||||||
GameMain.GameSession?.CrewManager?.AddCurrentOrderIcon(this, order, orderOption);
|
GameMain.GameSession?.CrewManager?.AddCurrentOrderIcon(this, order, orderOption, priority);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void AddAllToGUIUpdateList()
|
public static void AddAllToGUIUpdateList()
|
||||||
@@ -815,7 +871,7 @@ namespace Barotrauma
|
|||||||
iconPos.Y = -iconPos.Y;
|
iconPos.Y = -iconPos.Y;
|
||||||
nameColor = iconStyle.Color;
|
nameColor = iconStyle.Color;
|
||||||
var icon = iconStyle.Sprites[GUIComponent.ComponentState.None].First();
|
var icon = iconStyle.Sprites[GUIComponent.ComponentState.None].First();
|
||||||
float iconScale = 30.0f / icon.Sprite.size.X / cam.Zoom;
|
float iconScale = (30.0f / icon.Sprite.size.X / cam.Zoom) * GUI.Scale;
|
||||||
icon.Sprite.Draw(spriteBatch, iconPos + new Vector2(-35.0f, -25.0f), iconStyle.Color * hudInfoAlpha, scale: iconScale);
|
icon.Sprite.Draw(spriteBatch, iconPos + new Vector2(-35.0f, -25.0f), iconStyle.Color * hudInfoAlpha, scale: iconScale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Barotrauma.Items.Components;
|
using Barotrauma.Extensions;
|
||||||
|
using Barotrauma.Items.Components;
|
||||||
using FarseerPhysics;
|
using FarseerPhysics;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
@@ -10,7 +11,57 @@ using System.Linq;
|
|||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
class CharacterHUD
|
class CharacterHUD
|
||||||
{
|
{
|
||||||
|
const float BossHealthBarDuration = 120.0f;
|
||||||
|
|
||||||
|
class BossHealthBar
|
||||||
|
{
|
||||||
|
public readonly Character Character;
|
||||||
|
public float FadeTimer;
|
||||||
|
|
||||||
|
public readonly GUIComponent TopContainer;
|
||||||
|
public readonly GUIComponent SideContainer;
|
||||||
|
|
||||||
|
public readonly GUIProgressBar TopHealthBar;
|
||||||
|
public readonly GUIProgressBar SideHealthBar;
|
||||||
|
|
||||||
|
public BossHealthBar(Character character)
|
||||||
|
{
|
||||||
|
Character = character;
|
||||||
|
FadeTimer = BossHealthBarDuration;
|
||||||
|
|
||||||
|
TopContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.18f, 0.03f), HUDFrame.RectTransform, Anchor.TopCenter)
|
||||||
|
{
|
||||||
|
MinSize = new Point(100, 50),
|
||||||
|
RelativeOffset = new Vector2(0.0f, 0.01f)
|
||||||
|
}, isHorizontal: false, childAnchor: Anchor.TopCenter);
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.4f), TopContainer.RectTransform), character.DisplayName, textAlignment: Alignment.Center, textColor: GUI.Style.Red);
|
||||||
|
TopHealthBar = new GUIProgressBar(new RectTransform(new Vector2(1.0f, 0.6f), TopContainer.RectTransform)
|
||||||
|
{
|
||||||
|
MinSize = new Point(100, HUDLayoutSettings.HealthBarArea.Size.Y)
|
||||||
|
}, barSize: 0.0f, style: "CharacterHealthBarCentered")
|
||||||
|
{
|
||||||
|
Color = GUI.Style.Red
|
||||||
|
};
|
||||||
|
|
||||||
|
SideContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), bossHealthContainer.RectTransform)
|
||||||
|
{
|
||||||
|
MinSize = new Point(80, 60)
|
||||||
|
}, isHorizontal: false, childAnchor: Anchor.TopRight);
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.3f), SideContainer.RectTransform), character.DisplayName, textAlignment: Alignment.CenterRight, textColor: GUI.Style.Red);
|
||||||
|
SideHealthBar = new GUIProgressBar(new RectTransform(new Vector2(1.0f, 0.7f), SideContainer.RectTransform), barSize: 0.0f, style: "CharacterHealthBar")
|
||||||
|
{
|
||||||
|
Color = GUI.Style.Red
|
||||||
|
};
|
||||||
|
|
||||||
|
TopContainer.Visible = SideContainer.Visible = false;
|
||||||
|
TopContainer.CanBeFocused = false;
|
||||||
|
TopContainer.Children.ForEach(c => c.CanBeFocused = false);
|
||||||
|
SideContainer.CanBeFocused = false;
|
||||||
|
SideContainer.Children.ForEach(c => c.CanBeFocused = false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static readonly Dictionary<ISpatialEntity, int> orderIndicatorCount = new Dictionary<ISpatialEntity, int>();
|
private static readonly Dictionary<ISpatialEntity, int> orderIndicatorCount = new Dictionary<ISpatialEntity, int>();
|
||||||
const float ItemOverlayDelay = 1.0f;
|
const float ItemOverlayDelay = 1.0f;
|
||||||
private static Item focusedItem;
|
private static Item focusedItem;
|
||||||
@@ -19,8 +70,12 @@ namespace Barotrauma
|
|||||||
private static readonly List<Item> brokenItems = new List<Item>();
|
private static readonly List<Item> brokenItems = new List<Item>();
|
||||||
private static float brokenItemsCheckTimer;
|
private static float brokenItemsCheckTimer;
|
||||||
|
|
||||||
|
private static readonly List<BossHealthBar> bossHealthBars = new List<BossHealthBar>();
|
||||||
|
|
||||||
private static readonly Dictionary<string, string> cachedHudTexts = new Dictionary<string, string>();
|
private static readonly Dictionary<string, string> cachedHudTexts = new Dictionary<string, string>();
|
||||||
|
|
||||||
|
private static GUILayoutGroup bossHealthContainer;
|
||||||
|
|
||||||
private static GUIFrame hudFrame;
|
private static GUIFrame hudFrame;
|
||||||
public static GUIFrame HUDFrame
|
public static GUIFrame HUDFrame
|
||||||
{
|
{
|
||||||
@@ -33,6 +88,13 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
CanBeFocused = false
|
CanBeFocused = false
|
||||||
};
|
};
|
||||||
|
bossHealthContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.15f, 0.5f), hudFrame.RectTransform, Anchor.CenterRight)
|
||||||
|
{
|
||||||
|
RelativeOffset = new Vector2(0.005f, 0.0f)
|
||||||
|
})
|
||||||
|
{
|
||||||
|
AbsoluteSpacing = GUI.IntScale(10)
|
||||||
|
};
|
||||||
}
|
}
|
||||||
return hudFrame;
|
return hudFrame;
|
||||||
}
|
}
|
||||||
@@ -70,7 +132,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public static void AddToGUIUpdateList(Character character)
|
public static void AddToGUIUpdateList(Character character)
|
||||||
{
|
{
|
||||||
if (GUI.DisableHUD) return;
|
if (GUI.DisableHUD) { return; }
|
||||||
|
|
||||||
if (!character.IsIncapacitated && character.Stun <= 0.0f && !IsCampaignInterfaceOpen)
|
if (!character.IsIncapacitated && character.Stun <= 0.0f && !IsCampaignInterfaceOpen)
|
||||||
{
|
{
|
||||||
@@ -83,7 +145,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
foreach (ItemComponent ic in item.Components)
|
foreach (ItemComponent ic in item.Components)
|
||||||
{
|
{
|
||||||
if (ic.DrawHudWhenEquipped) ic.AddToGUIUpdateList();
|
if (ic.DrawHudWhenEquipped) { ic.AddToGUIUpdateList(); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -99,13 +161,14 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public static void Update(float deltaTime, Character character, Camera cam)
|
public static void Update(float deltaTime, Character character, Camera cam)
|
||||||
{
|
{
|
||||||
|
UpdateBossHealthBars(deltaTime);
|
||||||
|
|
||||||
if (GUI.DisableHUD)
|
if (GUI.DisableHUD)
|
||||||
{
|
{
|
||||||
if (character.Inventory != null && !LockInventory(character))
|
if (character.Inventory != null && !LockInventory(character))
|
||||||
{
|
{
|
||||||
character.Inventory.UpdateSlotInput();
|
character.Inventory.UpdateSlotInput();
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,17 +193,6 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
character.Inventory.ClearSubInventories();
|
character.Inventory.ClearSubInventories();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < character.Inventory.Capacity; i++)
|
|
||||||
{
|
|
||||||
var item = character.Inventory.GetItemAt(i);
|
|
||||||
if (item == null || character.Inventory.SlotTypes[i] == InvSlotType.Any) { continue; }
|
|
||||||
|
|
||||||
foreach (ItemComponent ic in item.Components)
|
|
||||||
{
|
|
||||||
if (ic.DrawHudWhenEquipped) ic.UpdateHUD(character, deltaTime, cam);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (character.IsHumanoid && character.SelectedCharacter != null && character.SelectedCharacter.Inventory != null)
|
if (character.IsHumanoid && character.SelectedCharacter != null && character.SelectedCharacter.Inventory != null)
|
||||||
@@ -221,10 +273,10 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DrawIcon(character.CurrentOrder))
|
if (character.GetCurrentOrderWithTopPriority()?.Order is Order currentOrder && DrawIcon(currentOrder))
|
||||||
{
|
{
|
||||||
DrawOrderIndicator(spriteBatch, cam, character, character.CurrentOrder, 1.0f);
|
DrawOrderIndicator(spriteBatch, cam, character, currentOrder, 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool DrawIcon(Order o) =>
|
static bool DrawIcon(Order o) =>
|
||||||
o != null &&
|
o != null &&
|
||||||
@@ -253,7 +305,7 @@ namespace Barotrauma
|
|||||||
return Math.Min((maxDistance - dist) / maxDistance * 2.0f, 1.0f);
|
return Math.Min((maxDistance - dist) / maxDistance * 2.0f, 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!character.IsIncapacitated && character.Stun <= 0.0f && !IsCampaignInterfaceOpen && (!character.IsKeyDown(InputType.Aim) || character.HeldItems.Any(it => it?.GetComponent<Sprayer>() == null)))
|
if (!character.IsIncapacitated && character.Stun <= 0.0f && !IsCampaignInterfaceOpen && (!character.IsKeyDown(InputType.Aim) || character.HeldItems.None(it => it?.GetComponent<Sprayer>() != null)))
|
||||||
{
|
{
|
||||||
if (character.FocusedCharacter != null && character.FocusedCharacter.CanBeSelected)
|
if (character.FocusedCharacter != null && character.FocusedCharacter.CanBeSelected)
|
||||||
{
|
{
|
||||||
@@ -499,6 +551,86 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void ShowBossHealthBar(Character character)
|
||||||
|
{
|
||||||
|
if (character == null || character.IsDead || character.Removed) { return; }
|
||||||
|
|
||||||
|
var existingBar = bossHealthBars.Find(b => b.Character == character);
|
||||||
|
if (existingBar != null)
|
||||||
|
{
|
||||||
|
existingBar.FadeTimer = BossHealthBarDuration;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bossHealthBars.Count > 5)
|
||||||
|
{
|
||||||
|
BossHealthBar oldestHealthBar = bossHealthBars.First();
|
||||||
|
foreach (var bar in bossHealthBars)
|
||||||
|
{
|
||||||
|
if (bar.TopHealthBar.BarSize < oldestHealthBar.TopHealthBar.BarSize)
|
||||||
|
{
|
||||||
|
oldestHealthBar = bar;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
oldestHealthBar.FadeTimer = Math.Min(oldestHealthBar.FadeTimer, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
bossHealthBars.Add(new BossHealthBar(character));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void UpdateBossHealthBars(float deltaTime)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < bossHealthBars.Count; i++)
|
||||||
|
{
|
||||||
|
var bossHealthBar = bossHealthBars[i];
|
||||||
|
|
||||||
|
bool showTopBar = i == 0;
|
||||||
|
if (showTopBar != bossHealthBar.TopContainer.Visible)
|
||||||
|
{
|
||||||
|
bossHealthContainer.Recalculate();
|
||||||
|
}
|
||||||
|
|
||||||
|
bossHealthBar.TopContainer.Visible = showTopBar;
|
||||||
|
bossHealthBar.SideContainer.Visible = !bossHealthBar.TopContainer.Visible;
|
||||||
|
|
||||||
|
float health = bossHealthBar.Character.Vitality / bossHealthBar.Character.MaxVitality;
|
||||||
|
|
||||||
|
float alpha = Math.Min(bossHealthBar.FadeTimer, 1.0f);
|
||||||
|
foreach (var c in bossHealthBar.SideContainer.GetAllChildren().Concat(bossHealthBar.TopContainer.GetAllChildren()))
|
||||||
|
{
|
||||||
|
c.Color = new Color(c.Color, (byte)(alpha * 255));
|
||||||
|
if (c is GUITextBlock textBlock)
|
||||||
|
{
|
||||||
|
textBlock.TextColor = new Color(bossHealthBar.Character.IsDead ? Color.Gray : textBlock.TextColor, (byte)(alpha * 255));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bossHealthBar.TopHealthBar.BarSize = bossHealthBar.SideHealthBar.BarSize = health;
|
||||||
|
|
||||||
|
if (bossHealthBar.Character.Removed || !bossHealthBar.Character.Enabled)
|
||||||
|
{
|
||||||
|
bossHealthBar.FadeTimer = Math.Min(bossHealthBar.FadeTimer, 1.0f);
|
||||||
|
}
|
||||||
|
else if (bossHealthBar.Character.IsDead)
|
||||||
|
{
|
||||||
|
bossHealthBar.FadeTimer = Math.Min(bossHealthBar.FadeTimer, 5.0f);
|
||||||
|
}
|
||||||
|
bossHealthBar.FadeTimer -= deltaTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = bossHealthBars.Count - 1; i >= 0 ; i--)
|
||||||
|
{
|
||||||
|
var bossHealthBar = bossHealthBars[i];
|
||||||
|
if (bossHealthBar.FadeTimer <= 0)
|
||||||
|
{
|
||||||
|
bossHealthBar.SideContainer.Parent?.RemoveChild(bossHealthBar.SideContainer);
|
||||||
|
bossHealthBar.TopContainer.Parent?.RemoveChild(bossHealthBar.TopContainer);
|
||||||
|
bossHealthBars.RemoveAt(i);
|
||||||
|
bossHealthContainer.Recalculate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static bool LockInventory(Character character)
|
private static bool LockInventory(Character character)
|
||||||
{
|
{
|
||||||
if (character?.Inventory == null || !character.AllowInput || character.LockHands || IsCampaignInterfaceOpen) { return true; }
|
if (character?.Inventory == null || !character.AllowInput || character.LockHands || IsCampaignInterfaceOpen) { return true; }
|
||||||
|
|||||||
@@ -100,7 +100,22 @@ namespace Barotrauma
|
|||||||
Color textColor = Color.White * (0.5f + skill.Level / 200.0f);
|
Color textColor = Color.White * (0.5f + skill.Level / 200.0f);
|
||||||
|
|
||||||
var skillName = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), skillsArea.RectTransform), TextManager.Get("SkillName." + skill.Identifier), textColor: textColor, font: font) { Padding = Vector4.Zero };
|
var skillName = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), skillsArea.RectTransform), TextManager.Get("SkillName." + skill.Identifier), textColor: textColor, font: font) { Padding = Vector4.Zero };
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 1.0f), skillName.RectTransform), ((int)skill.Level).ToString(), textColor: textColor, font: font, textAlignment: Alignment.CenterRight);
|
|
||||||
|
float modifiedSkillLevel = skill.Level;
|
||||||
|
if (Character != null)
|
||||||
|
{
|
||||||
|
modifiedSkillLevel = Character.GetSkillLevel(skill.Identifier);
|
||||||
|
}
|
||||||
|
if (!MathUtils.NearlyEqual(MathF.Round(modifiedSkillLevel), MathF.Round(skill.Level)))
|
||||||
|
{
|
||||||
|
int skillChange = (int)MathF.Round(modifiedSkillLevel - skill.Level);
|
||||||
|
string changeText = $"{(skillChange > 0 ? "+" : "") + skillChange}";
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 1.0f), skillName.RectTransform), $"{(int)skill.Level} ({changeText})", textColor: textColor, font: font, textAlignment: Alignment.CenterRight);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 1.0f), skillName.RectTransform), ((int)skill.Level).ToString(), textColor: textColor, font: font, textAlignment: Alignment.CenterRight);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (Character != null && Character.IsDead)
|
else if (Character != null && Character.IsDead)
|
||||||
@@ -529,6 +544,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
ushort infoID = inc.ReadUInt16();
|
ushort infoID = inc.ReadUInt16();
|
||||||
string newName = inc.ReadString();
|
string newName = inc.ReadString();
|
||||||
|
string originalName = inc.ReadString();
|
||||||
int gender = inc.ReadByte();
|
int gender = inc.ReadByte();
|
||||||
int race = inc.ReadByte();
|
int race = inc.ReadByte();
|
||||||
int headSpriteID = inc.ReadByte();
|
int headSpriteID = inc.ReadByte();
|
||||||
@@ -556,7 +572,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: animations
|
// TODO: animations
|
||||||
CharacterInfo ch = new CharacterInfo(speciesName, newName, jobPrefab, ragdollFile, variant)
|
CharacterInfo ch = new CharacterInfo(speciesName, newName, originalName, jobPrefab, ragdollFile, variant)
|
||||||
{
|
{
|
||||||
ID = infoID,
|
ID = infoID,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -292,7 +292,7 @@ namespace Barotrauma
|
|||||||
break;
|
break;
|
||||||
case ServerNetObject.ENTITY_EVENT:
|
case ServerNetObject.ENTITY_EVENT:
|
||||||
|
|
||||||
int eventType = msg.ReadRangedInteger(0, 5);
|
int eventType = msg.ReadRangedInteger(0, 6);
|
||||||
switch (eventType)
|
switch (eventType)
|
||||||
{
|
{
|
||||||
case 0: //NetEntityEvent.Type.InventoryState
|
case 0: //NetEntityEvent.Type.InventoryState
|
||||||
@@ -330,6 +330,8 @@ namespace Barotrauma
|
|||||||
GameMain.Client.HasSpawned = true;
|
GameMain.Client.HasSpawned = true;
|
||||||
GameMain.Client.Character = this;
|
GameMain.Client.Character = this;
|
||||||
GameMain.LightManager.LosEnabled = true;
|
GameMain.LightManager.LosEnabled = true;
|
||||||
|
GameMain.LightManager.LosAlpha = 1f;
|
||||||
|
GameMain.Client.WaitForNextRoundRespawn = null;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -390,6 +392,19 @@ namespace Barotrauma
|
|||||||
byte campaignInteractionType = msg.ReadByte();
|
byte campaignInteractionType = msg.ReadByte();
|
||||||
(GameMain.GameSession?.GameMode as CampaignMode)?.AssignNPCMenuInteraction(this, (CampaignMode.InteractionType)campaignInteractionType);
|
(GameMain.GameSession?.GameMode as CampaignMode)?.AssignNPCMenuInteraction(this, (CampaignMode.InteractionType)campaignInteractionType);
|
||||||
break;
|
break;
|
||||||
|
case 6: //NetEntityEvent.Type.ObjectiveManagerOrderState
|
||||||
|
bool properData = msg.ReadBoolean();
|
||||||
|
if (!properData) { break; }
|
||||||
|
int orderIndex = msg.ReadRangedInteger(0, Order.PrefabList.Count);
|
||||||
|
var orderPrefab = Order.PrefabList[orderIndex];
|
||||||
|
string option = null;
|
||||||
|
if (orderPrefab.HasOptions)
|
||||||
|
{
|
||||||
|
int optionIndex = msg.ReadRangedInteger(0, orderPrefab.Options.Length);
|
||||||
|
option = orderPrefab.Options[optionIndex];
|
||||||
|
}
|
||||||
|
GameMain.GameSession.CrewManager.SetHighlightedOrderIcon(this, orderPrefab.Identifier, option);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
msg.ReadPadBits();
|
msg.ReadPadBits();
|
||||||
break;
|
break;
|
||||||
@@ -441,13 +456,15 @@ namespace Barotrauma
|
|||||||
(GameMain.GameSession.GameMode as CampaignMode)?.AssignNPCMenuInteraction(character, character.CampaignInteractionType);
|
(GameMain.GameSession.GameMode as CampaignMode)?.AssignNPCMenuInteraction(character, character.CampaignInteractionType);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the character has a current order
|
// Check if the character has current orders
|
||||||
if (inc.ReadBoolean())
|
int orderCount = inc.ReadByte();
|
||||||
|
for (int i = 0; i < orderCount; i++)
|
||||||
{
|
{
|
||||||
int orderPrefabIndex = inc.ReadByte();
|
int orderPrefabIndex = inc.ReadByte();
|
||||||
Entity targetEntity = FindEntityByID(inc.ReadUInt16());
|
Entity targetEntity = FindEntityByID(inc.ReadUInt16());
|
||||||
Character orderGiver = inc.ReadBoolean() ? FindEntityByID(inc.ReadUInt16()) as Character : null;
|
Character orderGiver = inc.ReadBoolean() ? FindEntityByID(inc.ReadUInt16()) as Character : null;
|
||||||
int orderOptionIndex = inc.ReadByte();
|
int orderOptionIndex = inc.ReadByte();
|
||||||
|
int orderPriority = inc.ReadByte();
|
||||||
OrderTarget targetPosition = null;
|
OrderTarget targetPosition = null;
|
||||||
if (inc.ReadBoolean())
|
if (inc.ReadBoolean())
|
||||||
{
|
{
|
||||||
@@ -468,7 +485,7 @@ namespace Barotrauma
|
|||||||
new Order(orderPrefab, targetPosition, orderGiver: orderGiver);
|
new Order(orderPrefab, targetPosition, orderGiver: orderGiver);
|
||||||
character.SetOrder(order,
|
character.SetOrder(order,
|
||||||
orderOptionIndex >= 0 && orderOptionIndex < orderPrefab.Options.Length ? orderPrefab.Options[orderOptionIndex] : null,
|
orderOptionIndex >= 0 && orderOptionIndex < orderPrefab.Options.Length ? orderPrefab.Options[orderOptionIndex] : null,
|
||||||
orderGiver, speak: false);
|
orderPriority, orderGiver, speak: false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -487,7 +504,7 @@ namespace Barotrauma
|
|||||||
character.ReadStatus(inc);
|
character.ReadStatus(inc);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (character.IsHuman && character.TeamID != CharacterTeamType.FriendlyNPC && !character.IsDead)
|
if (character.IsHuman && character.TeamID != CharacterTeamType.FriendlyNPC && character.TeamID != CharacterTeamType.None && !character.IsDead)
|
||||||
{
|
{
|
||||||
CharacterInfo duplicateCharacterInfo = GameMain.GameSession.CrewManager.GetCharacterInfos().FirstOrDefault(c => c.ID == info.ID);
|
CharacterInfo duplicateCharacterInfo = GameMain.GameSession.CrewManager.GetCharacterInfos().FirstOrDefault(c => c.ID == info.ID);
|
||||||
GameMain.GameSession.CrewManager.RemoveCharacterInfo(duplicateCharacterInfo);
|
GameMain.GameSession.CrewManager.RemoveCharacterInfo(duplicateCharacterInfo);
|
||||||
@@ -501,6 +518,7 @@ namespace Barotrauma
|
|||||||
if (!character.IsDead) { Controlled = character; }
|
if (!character.IsDead) { Controlled = character; }
|
||||||
|
|
||||||
GameMain.LightManager.LosEnabled = true;
|
GameMain.LightManager.LosEnabled = true;
|
||||||
|
GameMain.LightManager.LosAlpha = 1f;
|
||||||
|
|
||||||
character.memInput.Clear();
|
character.memInput.Clear();
|
||||||
character.memState.Clear();
|
character.memState.Clear();
|
||||||
|
|||||||
@@ -240,6 +240,8 @@ namespace Barotrauma
|
|||||||
Character.Controlled.SelectedConstruction = null;
|
Character.Controlled.SelectedConstruction = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HintManager.OnShowHealthInterface();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -295,6 +297,7 @@ namespace Barotrauma
|
|||||||
barSize: 1.0f, color: GUI.Style.HealthBarColorHigh, style: horizontal ? "CharacterHealthBar" : "GUIProgressBarVertical")
|
barSize: 1.0f, color: GUI.Style.HealthBarColorHigh, style: horizontal ? "CharacterHealthBar" : "GUIProgressBarVertical")
|
||||||
{
|
{
|
||||||
HoverCursor = CursorState.Hand,
|
HoverCursor = CursorState.Hand,
|
||||||
|
ToolTip = TextManager.GetWithVariable("hudbutton.healthinterface", "[key]", GameMain.Config.KeyBindText(InputType.Health)),
|
||||||
Enabled = true,
|
Enabled = true,
|
||||||
IsHorizontal = horizontal
|
IsHorizontal = horizontal
|
||||||
};
|
};
|
||||||
@@ -668,12 +671,17 @@ namespace Barotrauma
|
|||||||
bloodParticleTimer -= deltaTime * (affliction.Strength / 10.0f);
|
bloodParticleTimer -= deltaTime * (affliction.Strength / 10.0f);
|
||||||
if (bloodParticleTimer <= 0.0f)
|
if (bloodParticleTimer <= 0.0f)
|
||||||
{
|
{
|
||||||
|
var emitter = Character.BloodEmitters.FirstOrDefault();
|
||||||
|
float particleMinScale = emitter != null ? emitter.Prefab.ScaleMin : 0.5f;
|
||||||
|
float particleMaxScale = emitter != null ? emitter.Prefab.ScaleMax : 1;
|
||||||
|
float severity = Math.Min(affliction.Strength / affliction.Prefab.MaxStrength * Character.Params.BleedParticleMultiplier, 1);
|
||||||
|
float bloodParticleSize = MathHelper.Lerp(particleMinScale, particleMaxScale, severity);
|
||||||
bool inWater = Character.AnimController.InWater;
|
bool inWater = Character.AnimController.InWater;
|
||||||
float bloodParticleSize = MathHelper.Lerp(0.5f, 1.0f, affliction.Strength / 100.0f);
|
|
||||||
if (!inWater)
|
if (!inWater)
|
||||||
{
|
{
|
||||||
bloodParticleSize *= 2.0f;
|
bloodParticleSize *= 2.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
var blood = GameMain.ParticleManager.CreateParticle(
|
var blood = GameMain.ParticleManager.CreateParticle(
|
||||||
inWater ? Character.Params.BleedParticleWater : Character.Params.BleedParticleAir,
|
inWater ? Character.Params.BleedParticleWater : Character.Params.BleedParticleAir,
|
||||||
targetLimb.WorldPosition, Rand.Vector(affliction.Strength), 0.0f, Character.AnimController.CurrentHull);
|
targetLimb.WorldPosition, Rand.Vector(affliction.Strength), 0.0f, Character.AnimController.CurrentHull);
|
||||||
@@ -682,7 +690,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
blood.Size *= bloodParticleSize;
|
blood.Size *= bloodParticleSize;
|
||||||
}
|
}
|
||||||
bloodParticleTimer = 1.0f;
|
bloodParticleTimer = MathHelper.Lerp(2, 0.5f, severity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -713,6 +721,7 @@ namespace Barotrauma
|
|||||||
int dmgPerSecond = Math.Sign(a2.DamagePerSecond - a1.DamagePerSecond);
|
int dmgPerSecond = Math.Sign(a2.DamagePerSecond - a1.DamagePerSecond);
|
||||||
return dmgPerSecond != 0 ? dmgPerSecond : Math.Sign(a1.Strength - a1.Strength);
|
return dmgPerSecond != 0 ? dmgPerSecond : Math.Sign(a1.Strength - a1.Strength);
|
||||||
});
|
});
|
||||||
|
HintManager.OnAfflictionDisplayed(Character, currentDisplayedAfflictions);
|
||||||
updateDisplayedAfflictionsTimer = UpdateDisplayedAfflictionsInterval;
|
updateDisplayedAfflictionsTimer = UpdateDisplayedAfflictionsInterval;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -732,6 +741,7 @@ namespace Barotrauma
|
|||||||
float distortSpeed = 0.0f;
|
float distortSpeed = 0.0f;
|
||||||
float radialDistortStrength = 0.0f;
|
float radialDistortStrength = 0.0f;
|
||||||
float chromaticAberrationStrength = 0.0f;
|
float chromaticAberrationStrength = 0.0f;
|
||||||
|
float grainStrength = 0.0f;
|
||||||
|
|
||||||
if (Character.IsUnconscious)
|
if (Character.IsUnconscious)
|
||||||
{
|
{
|
||||||
@@ -752,6 +762,7 @@ namespace Barotrauma
|
|||||||
blurStrength = Math.Max(blurStrength, affliction.GetScreenBlurStrength());
|
blurStrength = Math.Max(blurStrength, affliction.GetScreenBlurStrength());
|
||||||
radialDistortStrength = Math.Max(radialDistortStrength, affliction.GetRadialDistortStrength());
|
radialDistortStrength = Math.Max(radialDistortStrength, affliction.GetRadialDistortStrength());
|
||||||
chromaticAberrationStrength = Math.Max(chromaticAberrationStrength, affliction.GetChromaticAberrationStrength());
|
chromaticAberrationStrength = Math.Max(chromaticAberrationStrength, affliction.GetChromaticAberrationStrength());
|
||||||
|
grainStrength = Math.Max(grainStrength, affliction.GetScreenGrainStrength());
|
||||||
}
|
}
|
||||||
foreach (LimbHealth limbHealth in limbHealths)
|
foreach (LimbHealth limbHealth in limbHealths)
|
||||||
{
|
{
|
||||||
@@ -766,6 +777,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
Character.RadialDistortStrength = radialDistortStrength;
|
Character.RadialDistortStrength = radialDistortStrength;
|
||||||
Character.ChromaticAberrationStrength = chromaticAberrationStrength;
|
Character.ChromaticAberrationStrength = chromaticAberrationStrength;
|
||||||
|
Character.GrainStrength = grainStrength;
|
||||||
if (blurStrength > 0.0f)
|
if (blurStrength > 0.0f)
|
||||||
{
|
{
|
||||||
distortTimer = (distortTimer + deltaTime * distortSpeed) % MathHelper.TwoPi;
|
distortTimer = (distortTimer + deltaTime * distortSpeed) % MathHelper.TwoPi;
|
||||||
@@ -986,8 +998,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
cprButton.Visible =
|
cprButton.Visible =
|
||||||
Character == Character.Controlled?.SelectedCharacter
|
Character == Character.Controlled?.SelectedCharacter
|
||||||
&& (Character.IsUnconscious || Character.Stun > 0.0f)
|
|
||||||
&& !Character.IsDead
|
&& !Character.IsDead
|
||||||
|
&& Character.IsKnockedDown
|
||||||
&& openHealthWindow == this;
|
&& openHealthWindow == this;
|
||||||
cprButton.IgnoreLayoutGroups = !cprButton.Visible;
|
cprButton.IgnoreLayoutGroups = !cprButton.Visible;
|
||||||
cprButton.Selected =
|
cprButton.Selected =
|
||||||
@@ -1183,7 +1195,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Color GetAfflictionIconColor(AfflictionPrefab prefab, Affliction affliction)
|
public static Color GetAfflictionIconColor(AfflictionPrefab prefab, Affliction affliction)
|
||||||
{
|
{
|
||||||
// No specific colors, use generic
|
// No specific colors, use generic
|
||||||
if (prefab.IconColors == null)
|
if (prefab.IconColors == null)
|
||||||
@@ -1203,6 +1215,8 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Color GetAfflictionIconColor(Affliction affliction) => GetAfflictionIconColor(affliction.Prefab, affliction);
|
||||||
|
|
||||||
private void UpdateAfflictionContainer(LimbHealth selectedLimb)
|
private void UpdateAfflictionContainer(LimbHealth selectedLimb)
|
||||||
{
|
{
|
||||||
selectedLimbText.Text = selectedLimb == null ? "" : selectedLimb.Name;
|
selectedLimbText.Text = selectedLimb == null ? "" : selectedLimb.Name;
|
||||||
@@ -1270,7 +1284,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
var afflictionIcon = new GUIImage(new RectTransform(Vector2.One * 0.8f, button.RectTransform, Anchor.Center), affliction.Prefab.Icon, scaleToFit: true)
|
var afflictionIcon = new GUIImage(new RectTransform(Vector2.One * 0.8f, button.RectTransform, Anchor.Center), affliction.Prefab.Icon, scaleToFit: true)
|
||||||
{
|
{
|
||||||
Color = GetAfflictionIconColor(affliction.Prefab, affliction),
|
Color = GetAfflictionIconColor(affliction),
|
||||||
CanBeFocused = false
|
CanBeFocused = false
|
||||||
};
|
};
|
||||||
afflictionIcon.PressedColor = afflictionIcon.Color;
|
afflictionIcon.PressedColor = afflictionIcon.Color;
|
||||||
@@ -1906,7 +1920,7 @@ namespace Barotrauma
|
|||||||
float alpha = MathHelper.Lerp(0.3f, 1.0f,
|
float alpha = MathHelper.Lerp(0.3f, 1.0f,
|
||||||
(affliction.Strength - showIconThreshold) / Math.Min(affliction.Prefab.MaxStrength - showIconThreshold, 10.0f));
|
(affliction.Strength - showIconThreshold) / Math.Min(affliction.Prefab.MaxStrength - showIconThreshold, 10.0f));
|
||||||
|
|
||||||
affliction.Prefab.Icon.Draw(spriteBatch, iconPos - iconSize / 2.0f, GetAfflictionIconColor(affliction.Prefab, affliction) * alpha, 0, iconScale);
|
affliction.Prefab.Icon.Draw(spriteBatch, iconPos - iconSize / 2.0f, GetAfflictionIconColor(affliction) * alpha, 0, iconScale);
|
||||||
iconPos += new Vector2(10.0f, 20.0f) * iconScale;
|
iconPos += new Vector2(10.0f, 20.0f) * iconScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -299,7 +299,12 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
var textContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.0f), listBox.Content.RectTransform), style: "InnerFrame", color: Color.White)
|
var textContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.0f), listBox.Content.RectTransform), style: "InnerFrame", color: Color.White)
|
||||||
{
|
{
|
||||||
CanBeFocused = false
|
CanBeFocused = true,
|
||||||
|
OnSecondaryClicked = (component, data) =>
|
||||||
|
{
|
||||||
|
GUIContextMenu.CreateContextMenu(new ContextMenuOption("editor.copytoclipboard", true, () => { Clipboard.SetText(msg.Text); }));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
var textBlock = new GUITextBlock(new RectTransform(new Point(listBox.Content.Rect.Width - 5, 0), textContainer.RectTransform, Anchor.TopLeft) { AbsoluteOffset = new Point(2, 2) },
|
var textBlock = new GUITextBlock(new RectTransform(new Point(listBox.Content.Rect.Width - 5, 0), textContainer.RectTransform, Anchor.TopLeft) { AbsoluteOffset = new Point(2, 2) },
|
||||||
msg.Text, textAlignment: Alignment.TopLeft, font: GUI.SmallFont, wrap: true)
|
msg.Text, textAlignment: Alignment.TopLeft, font: GUI.SmallFont, wrap: true)
|
||||||
@@ -480,7 +485,7 @@ namespace Barotrauma
|
|||||||
var subInfo = new SubmarineInfo(string.Join(" ", args));
|
var subInfo = new SubmarineInfo(string.Join(" ", args));
|
||||||
Submarine.MainSub = Submarine.Load(subInfo, true);
|
Submarine.MainSub = Submarine.Load(subInfo, true);
|
||||||
}
|
}
|
||||||
GameMain.SubEditorScreen.Select();
|
GameMain.SubEditorScreen.Select(enableAutoSave: Screen.Selected != GameMain.GameScreen);
|
||||||
}, isCheat: true));
|
}, isCheat: true));
|
||||||
|
|
||||||
commands.Add(new Command("editparticles|particleeditor", "editparticles/particleeditor: Switch to the Particle Editor to edit particle effects.", (string[] args) =>
|
commands.Add(new Command("editparticles|particleeditor", "editparticles/particleeditor: Switch to the Particle Editor to edit particle effects.", (string[] args) =>
|
||||||
@@ -620,6 +625,11 @@ namespace Barotrauma
|
|||||||
NewMessage(SubEditorScreen.ShouldDrawGrid ? "Enabled submarine grid." : "Disabled submarine grid.", GUI.Style.Green);
|
NewMessage(SubEditorScreen.ShouldDrawGrid ? "Enabled submarine grid." : "Disabled submarine grid.", GUI.Style.Green);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
commands.Add(new Command("spreadsheetexport", "Export items in format recognized by the spreadsheet importer.", (string[] args) =>
|
||||||
|
{
|
||||||
|
SpreadsheetExport.Export();
|
||||||
|
}));
|
||||||
|
|
||||||
commands.Add(new Command("wikiimage_character", "Save an image of the currently controlled character with a transparent background.", (string[] args) =>
|
commands.Add(new Command("wikiimage_character", "Save an image of the currently controlled character with a transparent background.", (string[] args) =>
|
||||||
{
|
{
|
||||||
if (Character.Controlled == null) { return; }
|
if (Character.Controlled == null) { return; }
|
||||||
@@ -649,6 +659,7 @@ namespace Barotrauma
|
|||||||
AssignRelayToServer("bindkey", false);
|
AssignRelayToServer("bindkey", false);
|
||||||
AssignRelayToServer("unbindkey", false);
|
AssignRelayToServer("unbindkey", false);
|
||||||
AssignRelayToServer("savebinds", false);
|
AssignRelayToServer("savebinds", false);
|
||||||
|
AssignRelayToServer("spreadsheetexport", false);
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
AssignRelayToServer("crash", false);
|
AssignRelayToServer("crash", false);
|
||||||
AssignRelayToServer("showballastflorasprite", false);
|
AssignRelayToServer("showballastflorasprite", false);
|
||||||
@@ -1236,6 +1247,7 @@ namespace Barotrauma
|
|||||||
GameMain.DebugDraw = false;
|
GameMain.DebugDraw = false;
|
||||||
GameMain.LightManager.LightingEnabled = true;
|
GameMain.LightManager.LightingEnabled = true;
|
||||||
GameMain.LightManager.LosEnabled = true;
|
GameMain.LightManager.LosEnabled = true;
|
||||||
|
GameMain.LightManager.LosAlpha = 1f;
|
||||||
}
|
}
|
||||||
NewMessage(HumanAIController.debugai ? "AI debug info visible" : "AI debug info hidden", Color.White);
|
NewMessage(HumanAIController.debugai ? "AI debug info visible" : "AI debug info hidden", Color.White);
|
||||||
});
|
});
|
||||||
@@ -1523,7 +1535,9 @@ namespace Barotrauma
|
|||||||
List<string> lines = missingTags.Select(t => "\"" + t.Key + "\"\n missing from " + string.Join(", ", t.Value)).ToList();
|
List<string> lines = missingTags.Select(t => "\"" + t.Key + "\"\n missing from " + string.Join(", ", t.Value)).ToList();
|
||||||
|
|
||||||
string filePath = "missingloca.txt";
|
string filePath = "missingloca.txt";
|
||||||
|
Barotrauma.IO.Validation.SkipValidationInDebugBuilds = true;
|
||||||
File.WriteAllLines(filePath, lines);
|
File.WriteAllLines(filePath, lines);
|
||||||
|
Barotrauma.IO.Validation.SkipValidationInDebugBuilds = false;
|
||||||
ToolBox.OpenFileWithShell(Path.GetFullPath(filePath));
|
ToolBox.OpenFileWithShell(Path.GetFullPath(filePath));
|
||||||
TextManager.Language = "English";
|
TextManager.Language = "English";
|
||||||
}));
|
}));
|
||||||
@@ -1532,7 +1546,9 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
var debugLines = EventSet.GetDebugStatistics();
|
var debugLines = EventSet.GetDebugStatistics();
|
||||||
string filePath = "eventstats.txt";
|
string filePath = "eventstats.txt";
|
||||||
|
Barotrauma.IO.Validation.SkipValidationInDebugBuilds = true;
|
||||||
File.WriteAllLines(filePath, debugLines);
|
File.WriteAllLines(filePath, debugLines);
|
||||||
|
Barotrauma.IO.Validation.SkipValidationInDebugBuilds = false;
|
||||||
ToolBox.OpenFileWithShell(Path.GetFullPath(filePath));
|
ToolBox.OpenFileWithShell(Path.GetFullPath(filePath));
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@@ -1705,6 +1721,15 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
GameMain.Client?.ForceTimeOut();
|
GameMain.Client?.ForceTimeOut();
|
||||||
}, isCheat: false));
|
}, isCheat: false));
|
||||||
|
commands.Add(new Command("bumpitem", "", (string[] args) =>
|
||||||
|
{
|
||||||
|
float vel = 10.0f;
|
||||||
|
if (args.Length > 0)
|
||||||
|
{
|
||||||
|
float.TryParse(args[0], NumberStyles.Number, CultureInfo.InvariantCulture, out vel);
|
||||||
|
}
|
||||||
|
Character.Controlled?.FocusedItem?.body?.ApplyLinearImpulse(Rand.Vector(vel));
|
||||||
|
}, isCheat: false));
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -1813,7 +1838,9 @@ namespace Barotrauma
|
|||||||
lines.Add("<EntityName." + me.Identifier + ">" + me.Name + "</EntityName." + me.Identifier + ">");
|
lines.Add("<EntityName." + me.Identifier + ">" + me.Name + "</EntityName." + me.Identifier + ">");
|
||||||
lines.Add("<EntityDescription." + me.Identifier + ">" + me.Description + "</EntityDescription." + me.Identifier + ">");
|
lines.Add("<EntityDescription." + me.Identifier + ">" + me.Description + "</EntityDescription." + me.Identifier + ">");
|
||||||
}
|
}
|
||||||
|
Barotrauma.IO.Validation.SkipValidationInDebugBuilds = true;
|
||||||
File.WriteAllLines(filePath, lines);
|
File.WriteAllLines(filePath, lines);
|
||||||
|
Barotrauma.IO.Validation.SkipValidationInDebugBuilds = false;
|
||||||
}));
|
}));
|
||||||
|
|
||||||
commands.Add(new Command("dumpeventtexts", "dumpeventtexts [filepath]: gets the texts from event files and and writes them into a file along with xml tags that can be used in translation files. If the filepath is omitted, the file is written to Content/Texts/EventTexts.txt", (string[] args) =>
|
commands.Add(new Command("dumpeventtexts", "dumpeventtexts [filepath]: gets the texts from event files and and writes them into a file along with xml tags that can be used in translation files. If the filepath is omitted, the file is written to Content/Texts/EventTexts.txt", (string[] args) =>
|
||||||
@@ -1832,16 +1859,15 @@ namespace Barotrauma
|
|||||||
docs.Add(eventPrefab.ConfigElement.Document);
|
docs.Add(eventPrefab.ConfigElement.Document);
|
||||||
getTextsFromElement(eventPrefab.ConfigElement, lines, eventPrefab.Identifier);
|
getTextsFromElement(eventPrefab.ConfigElement, lines, eventPrefab.Identifier);
|
||||||
}
|
}
|
||||||
|
Barotrauma.IO.Validation.SkipValidationInDebugBuilds = true;
|
||||||
File.WriteAllLines(filePath, lines);
|
File.WriteAllLines(filePath, lines);
|
||||||
|
|
||||||
ToolBox.OpenFileWithShell(Path.GetFullPath(filePath));
|
ToolBox.OpenFileWithShell(Path.GetFullPath(filePath));
|
||||||
|
|
||||||
System.Xml.XmlWriterSettings settings = new System.Xml.XmlWriterSettings
|
System.Xml.XmlWriterSettings settings = new System.Xml.XmlWriterSettings
|
||||||
{
|
{
|
||||||
Indent = true,
|
Indent = true,
|
||||||
NewLineOnAttributes = false
|
NewLineOnAttributes = false
|
||||||
};
|
};
|
||||||
|
|
||||||
foreach (XDocument doc in docs)
|
foreach (XDocument doc in docs)
|
||||||
{
|
{
|
||||||
using (var writer = XmlWriter.Create(new System.Uri(doc.BaseUri).LocalPath, settings))
|
using (var writer = XmlWriter.Create(new System.Uri(doc.BaseUri).LocalPath, settings))
|
||||||
@@ -1850,6 +1876,7 @@ namespace Barotrauma
|
|||||||
writer.Flush();
|
writer.Flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Barotrauma.IO.Validation.SkipValidationInDebugBuilds = false;
|
||||||
|
|
||||||
void getTextsFromElement(XElement element, List<string> list, string parentName)
|
void getTextsFromElement(XElement element, List<string> list, string parentName)
|
||||||
{
|
{
|
||||||
@@ -1996,10 +2023,17 @@ namespace Barotrauma
|
|||||||
lines.Add("[/table]");
|
lines.Add("[/table]");
|
||||||
lines.Add("");
|
lines.Add("");
|
||||||
}
|
}
|
||||||
|
Barotrauma.IO.Validation.SkipValidationInDebugBuilds = true;
|
||||||
File.WriteAllLines(filePath, lines);
|
File.WriteAllLines(filePath, lines);
|
||||||
|
Barotrauma.IO.Validation.SkipValidationInDebugBuilds = false;
|
||||||
ToolBox.OpenFileWithShell(Path.GetFullPath(filePath));
|
ToolBox.OpenFileWithShell(Path.GetFullPath(filePath));
|
||||||
}));
|
}));
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
|
commands.Add(new Command("playovervc", "Plays a sound over voice chat.", (args) =>
|
||||||
|
{
|
||||||
|
VoipCapture.Instance?.SetOverrideSound(args.Length > 0 ? args[0] : null);
|
||||||
|
}));
|
||||||
|
|
||||||
commands.Add(new Command("querylobbies", "Queries all SteamP2P lobbies", (args) =>
|
commands.Add(new Command("querylobbies", "Queries all SteamP2P lobbies", (args) =>
|
||||||
{
|
{
|
||||||
TaskPool.Add("DebugQueryLobbies",
|
TaskPool.Add("DebugQueryLobbies",
|
||||||
@@ -2033,7 +2067,9 @@ namespace Barotrauma
|
|||||||
commands.Add(new Command("printproperties", "Goes through the currently collected property list for missing localizations and writes them to a file.", (string[] args) =>
|
commands.Add(new Command("printproperties", "Goes through the currently collected property list for missing localizations and writes them to a file.", (string[] args) =>
|
||||||
{
|
{
|
||||||
string path = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\\propertylocalization.txt";
|
string path = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\\propertylocalization.txt";
|
||||||
|
Barotrauma.IO.Validation.SkipValidationInDebugBuilds = true;
|
||||||
File.WriteAllLines(path, SerializableEntityEditor.MissingLocalizations);
|
File.WriteAllLines(path, SerializableEntityEditor.MissingLocalizations);
|
||||||
|
Barotrauma.IO.Validation.SkipValidationInDebugBuilds = false;
|
||||||
}));
|
}));
|
||||||
|
|
||||||
commands.Add(new Command("getproperties", "Goes through the MapEntity prefabs and checks their serializable properties for localization issues.", (string[] args) =>
|
commands.Add(new Command("getproperties", "Goes through the MapEntity prefabs and checks their serializable properties for localization issues.", (string[] args) =>
|
||||||
@@ -2248,12 +2284,15 @@ namespace Barotrauma
|
|||||||
"revokeperm",
|
"revokeperm",
|
||||||
(string[] args) =>
|
(string[] args) =>
|
||||||
{
|
{
|
||||||
if (args.Length < 1) return;
|
if (args.Length < 1) { return; }
|
||||||
|
|
||||||
NewMessage("Valid permissions are:", Color.White);
|
if (args.Length < 2)
|
||||||
foreach (ClientPermissions permission in Enum.GetValues(typeof(ClientPermissions)))
|
|
||||||
{
|
{
|
||||||
NewMessage(" - " + permission.ToString(), Color.White);
|
NewMessage("Valid permissions are:", Color.White);
|
||||||
|
foreach (ClientPermissions permission in Enum.GetValues(typeof(ClientPermissions)))
|
||||||
|
{
|
||||||
|
NewMessage(" - " + permission.ToString(), Color.White);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ShowQuestionPrompt("Permission to revoke from client " + args[0] + "?", (perm) =>
|
ShowQuestionPrompt("Permission to revoke from client " + args[0] + "?", (perm) =>
|
||||||
|
|||||||
@@ -560,6 +560,22 @@ namespace Barotrauma
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case NetworkEventType.UNLOCKPATH:
|
||||||
|
UInt16 connectionIndex = msg.ReadUInt16();
|
||||||
|
if (GameMain.GameSession?.Map?.Connections != null)
|
||||||
|
{
|
||||||
|
if (connectionIndex >= GameMain.GameSession.Map.Connections.Count)
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError($"Failed to unlock a path on the campaign map. Connection index out of bounds (index: {connectionIndex}, number of connections: {GameMain.GameSession.Map.Connections.Count})");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GameMain.GameSession.Map.Connections[connectionIndex].Locked = false;
|
||||||
|
new GUIMessageBox(string.Empty, TextManager.Get("pathunlockedgeneric"),
|
||||||
|
new string[0], type: GUIMessageBox.Type.InGame, iconStyle: "UnlockPathIcon", relativeSize: new Vector2(0.3f, 0.15f), minSize: new Point(512, 128));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,64 @@
|
|||||||
|
using Barotrauma.Networking;
|
||||||
|
|
||||||
|
namespace Barotrauma
|
||||||
|
{
|
||||||
|
partial class AbandonedOutpostMission : Mission
|
||||||
|
{
|
||||||
|
public override int State
|
||||||
|
{
|
||||||
|
get { return base.State; }
|
||||||
|
protected set
|
||||||
|
{
|
||||||
|
if (state != value)
|
||||||
|
{
|
||||||
|
base.State = value;
|
||||||
|
if (state == HostagesKilledState && !string.IsNullOrEmpty(hostagesKilledMessage))
|
||||||
|
{
|
||||||
|
CreateMessageBox(string.Empty, hostagesKilledMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void ClientReadInitial(IReadMessage msg)
|
||||||
|
{
|
||||||
|
byte characterCount = msg.ReadByte();
|
||||||
|
|
||||||
|
for (int i = 0; i < characterCount; i++)
|
||||||
|
{
|
||||||
|
Character character = Character.ReadSpawnData(msg);
|
||||||
|
characters.Add(character);
|
||||||
|
if (msg.ReadBoolean()) { requireKill.Add(character); }
|
||||||
|
if (msg.ReadBoolean())
|
||||||
|
{
|
||||||
|
requireRescue.Add(character);
|
||||||
|
#if CLIENT
|
||||||
|
GameMain.GameSession.CrewManager.AddCharacterToCrewList(character);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
ushort itemCount = msg.ReadUInt16();
|
||||||
|
for (int j = 0; j < itemCount; j++)
|
||||||
|
{
|
||||||
|
Item.ReadSpawnData(msg);
|
||||||
|
}
|
||||||
|
if (character.Submarine != null && character.AIController is EnemyAIController enemyAi)
|
||||||
|
{
|
||||||
|
enemyAi.UnattackableSubmarines.Add(character.Submarine);
|
||||||
|
enemyAi.UnattackableSubmarines.Add(Submarine.MainSub);
|
||||||
|
foreach (Submarine sub in Submarine.MainSub.DockedTo)
|
||||||
|
{
|
||||||
|
enemyAi.UnattackableSubmarines.Add(sub);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (characters.Contains(null))
|
||||||
|
{
|
||||||
|
throw new System.Exception("Error in AbandonedOutpostMission.ClientReadInitial: character list contains null (mission: " + Prefab.Identifier + ")");
|
||||||
|
}
|
||||||
|
if (characters.Count != characterCount)
|
||||||
|
{
|
||||||
|
throw new System.Exception("Error in AbandonedOutpostMission.ClientReadInitial: character count does not match the server count (" + characters + " != " + characters.Count + "mission: " + Prefab.Identifier + ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,66 @@
|
|||||||
using Barotrauma.Networking;
|
using Barotrauma.Networking;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
abstract partial class Mission
|
abstract partial class Mission
|
||||||
{
|
{
|
||||||
|
private readonly List<string> shownMessages = new List<string>();
|
||||||
|
public IEnumerable<string> ShownMessages
|
||||||
|
{
|
||||||
|
get { return shownMessages; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color GetDifficultyColor()
|
||||||
|
{
|
||||||
|
int v = Difficulty ?? MissionPrefab.MinDifficulty;
|
||||||
|
float t = MathUtils.InverseLerp(MissionPrefab.MinDifficulty, MissionPrefab.MaxDifficulty, v);
|
||||||
|
return ToolBox.GradientLerp(t, GUI.Style.Green, GUI.Style.Orange, GUI.Style.Red);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetMissionRewardText()
|
||||||
|
{
|
||||||
|
string rewardText = TextManager.GetWithVariable("currencyformat", "[credits]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", Reward));
|
||||||
|
return TextManager.GetWithVariable("missionreward", "[reward]", $"‖color:gui.orange‖{rewardText}‖end‖");
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetReputationRewardText(Location currLocation)
|
||||||
|
{
|
||||||
|
List<string> reputationRewardTexts = new List<string>();
|
||||||
|
foreach (var reputationReward in ReputationRewards)
|
||||||
|
{
|
||||||
|
string name = "";
|
||||||
|
|
||||||
|
if (reputationReward.Key.Equals("location", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
name = $"‖color:gui.orange‖{currLocation.Name}‖end‖";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var faction = FactionPrefab.Prefabs.Find(f => f.Identifier.Equals(reputationReward.Key, StringComparison.OrdinalIgnoreCase));
|
||||||
|
if (faction != null)
|
||||||
|
{
|
||||||
|
name = $"‖color:{XMLExtensions.ColorToString(faction.IconColor)}‖{faction.Name}‖end‖";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
name = TextManager.Get(reputationReward.Key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
float normalizedValue = MathUtils.InverseLerp(-100.0f, 100.0f, reputationReward.Value);
|
||||||
|
string formattedValue = ((int)reputationReward.Value).ToString("+#;-#;0"); //force plus sign for positive numbers
|
||||||
|
string rewardText = TextManager.GetWithVariables(
|
||||||
|
"reputationformat",
|
||||||
|
new string[] { "[reputationname]", "[reputationvalue]" },
|
||||||
|
new string[] { name, $"‖color:{XMLExtensions.ColorToString(Reputation.GetReputationColor(normalizedValue))}‖{formattedValue}‖end‖" });
|
||||||
|
reputationRewardTexts.Add(rewardText);
|
||||||
|
}
|
||||||
|
return TextManager.AddPunctuation(':', TextManager.Get("reputation"), string.Join(", ", reputationRewardTexts));
|
||||||
|
}
|
||||||
|
|
||||||
partial void ShowMessageProjSpecific(int missionState)
|
partial void ShowMessageProjSpecific(int missionState)
|
||||||
{
|
{
|
||||||
int messageIndex = missionState - 1;
|
int messageIndex = missionState - 1;
|
||||||
@@ -23,11 +79,17 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
yield return new WaitForSeconds(1.0f);
|
yield return new WaitForSeconds(1.0f);
|
||||||
}
|
}
|
||||||
new GUIMessageBox(header, message, buttons: new string[0], type: GUIMessageBox.Type.InGame, icon: Prefab.Icon)
|
CreateMessageBox(header, message);
|
||||||
|
yield return CoroutineStatus.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void CreateMessageBox(string header, string message)
|
||||||
|
{
|
||||||
|
shownMessages.Add(message);
|
||||||
|
new GUIMessageBox(header, message, buttons: new string[0], type: GUIMessageBox.Type.InGame, icon: Prefab.Icon, parseRichText: true)
|
||||||
{
|
{
|
||||||
IconColor = Prefab.IconColor
|
IconColor = Prefab.IconColor
|
||||||
};
|
};
|
||||||
yield return CoroutineStatus.Success;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientRead(IReadMessage msg)
|
public void ClientRead(IReadMessage msg)
|
||||||
|
|||||||
@@ -1,19 +1,17 @@
|
|||||||
using Microsoft.Xna.Framework;
|
namespace Barotrauma
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace Barotrauma
|
|
||||||
{
|
{
|
||||||
abstract partial class MissionMode : GameMode
|
abstract partial class MissionMode : GameMode
|
||||||
{
|
{
|
||||||
public override void ShowStartMessage()
|
public override void ShowStartMessage()
|
||||||
{
|
{
|
||||||
if (mission == null) return;
|
foreach (Mission mission in missions)
|
||||||
|
|
||||||
new GUIMessageBox(mission.Name, mission.Description, new string[0], type: GUIMessageBox.Type.InGame, icon: mission.Prefab.Icon)
|
|
||||||
{
|
{
|
||||||
IconColor = mission.Prefab.IconColor,
|
new GUIMessageBox(mission.Name, mission.Description, new string[0], type: GUIMessageBox.Type.InGame, icon: mission.Prefab.Icon, parseRichText: true)
|
||||||
UserData = "missionstartmessage"
|
{
|
||||||
};
|
IconColor = mission.Prefab.IconColor,
|
||||||
|
UserData = "missionstartmessage"
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
using Barotrauma.Networking;
|
||||||
|
|
||||||
|
namespace Barotrauma
|
||||||
|
{
|
||||||
|
partial class OutpostDestroyMission : AbandonedOutpostMission
|
||||||
|
{
|
||||||
|
public override void ClientReadInitial(IReadMessage msg)
|
||||||
|
{
|
||||||
|
base.ClientReadInitial(msg);
|
||||||
|
ushort itemCount = msg.ReadUInt16();
|
||||||
|
for (int i = 0; i < itemCount; i++)
|
||||||
|
{
|
||||||
|
var item = Item.ReadSpawnData(msg);
|
||||||
|
items.Add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -422,12 +422,12 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DrawStringWithColors(SpriteBatch sb, string text, Vector2 position, Color color, float rotation, Vector2 origin, float scale, SpriteEffects se, float layerDepth, List<RichTextData> richTextData)
|
public void DrawStringWithColors(SpriteBatch sb, string text, Vector2 position, Color color, float rotation, Vector2 origin, float scale, SpriteEffects se, float layerDepth, List<RichTextData> richTextData, int rtdOffset = 0)
|
||||||
{
|
{
|
||||||
DrawStringWithColors(sb, text, position, color, rotation, origin, new Vector2(scale), se, layerDepth, richTextData);
|
DrawStringWithColors(sb, text, position, color, rotation, origin, new Vector2(scale), se, layerDepth, richTextData, rtdOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DrawStringWithColors(SpriteBatch sb, string text, Vector2 position, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects se, float layerDepth, List<RichTextData> richTextData)
|
public void DrawStringWithColors(SpriteBatch sb, string text, Vector2 position, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects se, float layerDepth, List<RichTextData> richTextData, int rtdOffset = 0)
|
||||||
{
|
{
|
||||||
if (textures.Count == 0 && !DynamicLoading) { return; }
|
if (textures.Count == 0 && !DynamicLoading) { return; }
|
||||||
|
|
||||||
@@ -457,15 +457,15 @@ namespace Barotrauma
|
|||||||
|
|
||||||
Color currentTextColor;
|
Color currentTextColor;
|
||||||
|
|
||||||
if (currentRichTextData != null && i > currentRichTextData.EndIndex + lineNum)
|
while (currentRichTextData != null && i + rtdOffset > currentRichTextData.EndIndex + lineNum)
|
||||||
{
|
{
|
||||||
richTextDataIndex++;
|
richTextDataIndex++;
|
||||||
currentRichTextData = richTextDataIndex < richTextData.Count ? richTextData[richTextDataIndex] : null;
|
currentRichTextData = richTextDataIndex < richTextData.Count ? richTextData[richTextDataIndex] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentRichTextData != null && currentRichTextData.StartIndex + lineNum <= i && i <= currentRichTextData.EndIndex + lineNum)
|
if (currentRichTextData != null && currentRichTextData.StartIndex + lineNum <= i + rtdOffset && i + rtdOffset <= currentRichTextData.EndIndex + lineNum)
|
||||||
{
|
{
|
||||||
currentTextColor = currentRichTextData.Color ?? color;
|
currentTextColor = currentRichTextData.Color * currentRichTextData.Alpha ?? color;
|
||||||
if (!string.IsNullOrEmpty(currentRichTextData.Metadata))
|
if (!string.IsNullOrEmpty(currentRichTextData.Metadata))
|
||||||
{
|
{
|
||||||
currentTextColor = Color.Lerp(currentTextColor, Color.White, 0.5f);
|
currentTextColor = Color.Lerp(currentTextColor, Color.White, 0.5f);
|
||||||
|
|||||||
@@ -321,6 +321,7 @@ namespace Barotrauma
|
|||||||
float prevSize = chatBox.BarSize;
|
float prevSize = chatBox.BarSize;
|
||||||
|
|
||||||
string displayedText = message.TranslatedText;
|
string displayedText = message.TranslatedText;
|
||||||
|
|
||||||
string senderName = "";
|
string senderName = "";
|
||||||
Color senderColor = Color.White;
|
Color senderColor = Color.White;
|
||||||
if (!string.IsNullOrWhiteSpace(message.SenderName))
|
if (!string.IsNullOrWhiteSpace(message.SenderName))
|
||||||
@@ -377,13 +378,29 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
var msgText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), msgHolder.RectTransform)
|
var msgText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), msgHolder.RectTransform)
|
||||||
{ AbsoluteOffset = new Point((int)(10 * GUI.Scale), senderNameTimestamp == null ? 0 : senderNameTimestamp.Rect.Height) },
|
{ AbsoluteOffset = new Point((int)(10 * GUI.Scale), senderNameTimestamp == null ? 0 : senderNameTimestamp.Rect.Height) },
|
||||||
displayedText, textColor: message.Color, font: GUI.SmallFont, textAlignment: Alignment.TopLeft, style: null, wrap: true,
|
displayedText, textColor: message.Color, font: GUI.SmallFont, textAlignment: Alignment.TopLeft, style: null, wrap: true,
|
||||||
color: ((chatBox.Content.CountChildren % 2) == 0) ? Color.Transparent : Color.Black * 0.1f)
|
color: ((chatBox.Content.CountChildren % 2) == 0) ? Color.Transparent : Color.Black * 0.1f, parseRichText: true)
|
||||||
{
|
{
|
||||||
UserData = message.SenderName,
|
UserData = message.SenderName,
|
||||||
CanBeFocused = true
|
CanBeFocused = false
|
||||||
};
|
};
|
||||||
|
msgText.CalculateHeightFromText();
|
||||||
|
if (msgText.RichTextData != null)
|
||||||
|
{
|
||||||
|
foreach (var data in msgText.RichTextData)
|
||||||
|
{
|
||||||
|
var clickableArea = new GUITextBlock.ClickableArea()
|
||||||
|
{
|
||||||
|
Data = data
|
||||||
|
};
|
||||||
|
if (GameMain.NetLobbyScreen != null && GameMain.NetworkMember != null)
|
||||||
|
{
|
||||||
|
clickableArea.OnClick = GameMain.NetLobbyScreen.SelectPlayer;
|
||||||
|
}
|
||||||
|
msgText.ClickableAreas.Add(clickableArea);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (message is OrderChatMessage orderChatMsg &&
|
if (message is OrderChatMessage orderChatMsg &&
|
||||||
Character.Controlled != null &&
|
Character.Controlled != null &&
|
||||||
@@ -444,7 +461,7 @@ namespace Barotrauma
|
|||||||
senderText.RectTransform.MinSize = new Point(0, senderText.Rect.Height);
|
senderText.RectTransform.MinSize = new Point(0, senderText.Rect.Height);
|
||||||
}
|
}
|
||||||
var msgPopupText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), content.RectTransform),
|
var msgPopupText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), content.RectTransform),
|
||||||
displayedText, textColor: message.Color, font: GUI.SmallFont, textAlignment: Alignment.BottomLeft, style: null, wrap: true)
|
displayedText, textColor: message.Color, font: GUI.SmallFont, textAlignment: Alignment.BottomLeft, style: null, wrap: true, parseRichText: true)
|
||||||
{
|
{
|
||||||
CanBeFocused = false
|
CanBeFocused = false
|
||||||
};
|
};
|
||||||
@@ -523,6 +540,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (ToggleButton != null)
|
if (ToggleButton != null)
|
||||||
{
|
{
|
||||||
|
ToggleButton.Selected = ToggleOpen;
|
||||||
ToggleButton.RectTransform.AbsoluteOffset = new Point(GUIFrame.Rect.Right, GUIFrame.Rect.Y + HUDLayoutSettings.ChatBoxArea.Height - ToggleButton.Rect.Height);
|
ToggleButton.RectTransform.AbsoluteOffset = new Point(GUIFrame.Rect.Right, GUIFrame.Rect.Y + HUDLayoutSettings.ChatBoxArea.Height - ToggleButton.Rect.Height);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -566,6 +584,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (ToggleOpen)
|
if (ToggleOpen)
|
||||||
{
|
{
|
||||||
|
GUIFrame.CanBeFocused = true;
|
||||||
openState += deltaTime * 5.0f;
|
openState += deltaTime * 5.0f;
|
||||||
//delete all popup messages when the chatbox is open
|
//delete all popup messages when the chatbox is open
|
||||||
foreach (var popupMsg in popupMessages)
|
foreach (var popupMsg in popupMessages)
|
||||||
@@ -576,6 +595,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
GUIFrame.CanBeFocused = false;
|
||||||
openState -= deltaTime * 5.0f;
|
openState -= deltaTime * 5.0f;
|
||||||
|
|
||||||
int yOffset = 0;
|
int yOffset = 0;
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
using Barotrauma.Extensions;
|
using Barotrauma.Extensions;
|
||||||
|
using Barotrauma.Networking;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Barotrauma.Networking;
|
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
@@ -91,9 +91,10 @@ namespace Barotrauma
|
|||||||
UserData = "container"
|
UserData = "container"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int panelMaxWidth = (int)(GUI.xScale * (GUI.HorizontalAspectRatio < 1.4f ? 650 : 560));
|
||||||
var availableMainGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.4f, 1.0f), campaignUI.GetTabContainer(CampaignMode.InteractionType.Crew).RectTransform)
|
var availableMainGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.4f, 1.0f), campaignUI.GetTabContainer(CampaignMode.InteractionType.Crew).RectTransform)
|
||||||
{
|
{
|
||||||
MaxSize = new Point(560, campaignUI.GetTabContainer(CampaignMode.InteractionType.Crew).Rect.Height)
|
MaxSize = new Point(panelMaxWidth, campaignUI.GetTabContainer(CampaignMode.InteractionType.Crew).Rect.Height)
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
Stretch = true,
|
Stretch = true,
|
||||||
@@ -149,7 +150,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
var pendingAndCrewMainGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.4f, 1.0f), campaignUI.GetTabContainer(CampaignMode.InteractionType.Crew).RectTransform, anchor: Anchor.TopRight)
|
var pendingAndCrewMainGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.4f, 1.0f), campaignUI.GetTabContainer(CampaignMode.InteractionType.Crew).RectTransform, anchor: Anchor.TopRight)
|
||||||
{
|
{
|
||||||
MaxSize = new Point(560, campaignUI.GetTabContainer(CampaignMode.InteractionType.Crew).Rect.Height)
|
MaxSize = new Point(panelMaxWidth, campaignUI.GetTabContainer(CampaignMode.InteractionType.Crew).Rect.Height)
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
Stretch = true,
|
Stretch = true,
|
||||||
@@ -177,7 +178,7 @@ namespace Barotrauma
|
|||||||
var pendingAndCrewGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.95f), anchor: Anchor.Center,
|
var pendingAndCrewGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.95f), anchor: Anchor.Center,
|
||||||
parent: new GUIFrame(new RectTransform(new Vector2(1.0f, 13.25f / 14.0f), pendingAndCrewMainGroup.RectTransform)
|
parent: new GUIFrame(new RectTransform(new Vector2(1.0f, 13.25f / 14.0f), pendingAndCrewMainGroup.RectTransform)
|
||||||
{
|
{
|
||||||
MaxSize = new Point(560, campaignUI.GetTabContainer(CampaignMode.InteractionType.Crew).Rect.Height)
|
MaxSize = new Point(panelMaxWidth, campaignUI.GetTabContainer(CampaignMode.InteractionType.Crew).Rect.Height)
|
||||||
}).RectTransform));
|
}).RectTransform));
|
||||||
|
|
||||||
float height = 0.05f;
|
float height = 0.05f;
|
||||||
@@ -188,7 +189,7 @@ namespace Barotrauma
|
|||||||
};
|
};
|
||||||
|
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, height), pendingAndCrewGroup.RectTransform), TextManager.Get("campaignmenucrew"), font: GUI.SubHeadingFont);
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, height), pendingAndCrewGroup.RectTransform), TextManager.Get("campaignmenucrew"), font: GUI.SubHeadingFont);
|
||||||
crewList = new GUIListBox(new RectTransform(new Vector2(1.0f, (8)* height), pendingAndCrewGroup.RectTransform))
|
crewList = new GUIListBox(new RectTransform(new Vector2(1.0f, 8 * height), pendingAndCrewGroup.RectTransform))
|
||||||
{
|
{
|
||||||
Spacing = 1
|
Spacing = 1
|
||||||
};
|
};
|
||||||
@@ -207,7 +208,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
ClickSound = GUISoundType.HireRepairClick,
|
ClickSound = GUISoundType.HireRepairClick,
|
||||||
ForceUpperCase = true,
|
ForceUpperCase = true,
|
||||||
OnClicked = (b, o) => ValidatePendingHires(true)
|
OnClicked = (b, o) => ValidateHires(PendingHires, true)
|
||||||
};
|
};
|
||||||
clearAllButton = new GUIButton(new RectTransform(new Vector2(1.0f / 3.0f, 1.0f), group.RectTransform), text: TextManager.Get("campaignstore.clearall"))
|
clearAllButton = new GUIButton(new RectTransform(new Vector2(1.0f / 3.0f, 1.0f), group.RectTransform), text: TextManager.Get("campaignstore.clearall"))
|
||||||
{
|
{
|
||||||
@@ -335,9 +336,9 @@ namespace Barotrauma
|
|||||||
jobColor = characterInfo.Job.Prefab.UIColor;
|
jobColor = characterInfo.Job.Prefab.UIColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
GUIFrame frame = new GUIFrame(new RectTransform(new Point(listBox.Content.Rect.Width, 55), parent: listBox.Content.RectTransform), "ListBoxElement")
|
GUIFrame frame = new GUIFrame(new RectTransform(new Point(listBox.Content.Rect.Width, (int)(GUI.yScale * 55)), parent: listBox.Content.RectTransform), "ListBoxElement")
|
||||||
{
|
{
|
||||||
UserData = new Tuple<CharacterInfo, float>(characterInfo, skill != null ? skill.Level : 0.0f)
|
UserData = new Tuple<CharacterInfo, float>(characterInfo, skill?.Level ?? 0.0f)
|
||||||
};
|
};
|
||||||
GUILayoutGroup mainGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), frame.RectTransform, anchor: Anchor.Center), isHorizontal: true, childAnchor: Anchor.CenterLeft)
|
GUILayoutGroup mainGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), frame.RectTransform, anchor: Anchor.Center), isHorizontal: true, childAnchor: Anchor.CenterLeft)
|
||||||
{
|
{
|
||||||
@@ -345,19 +346,22 @@ namespace Barotrauma
|
|||||||
};
|
};
|
||||||
|
|
||||||
float portraitWidth = (0.8f * mainGroup.Rect.Height) / mainGroup.Rect.Width;
|
float portraitWidth = (0.8f * mainGroup.Rect.Height) / mainGroup.Rect.Width;
|
||||||
new GUICustomComponent(new RectTransform(new Vector2(portraitWidth, 0.8f), mainGroup.RectTransform),
|
var icon = new GUICustomComponent(new RectTransform(new Vector2(portraitWidth, 0.8f), mainGroup.RectTransform),
|
||||||
onDraw: (sb, component) => characterInfo.DrawIcon(sb, component.Rect.Center.ToVector2(), targetAreaSize: component.Rect.Size.ToVector2()))
|
onDraw: (sb, component) => characterInfo.DrawIcon(sb, component.Rect.Center.ToVector2(), targetAreaSize: component.Rect.Size.ToVector2()))
|
||||||
{
|
{
|
||||||
CanBeFocused = false
|
CanBeFocused = false
|
||||||
};
|
};
|
||||||
|
|
||||||
GUILayoutGroup nameAndJobGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.4f - portraitWidth, 0.8f), mainGroup.RectTransform));
|
GUILayoutGroup nameAndJobGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.4f - portraitWidth, 0.8f), mainGroup.RectTransform)) { CanBeFocused = false };
|
||||||
GUITextBlock nameBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), nameAndJobGroup.RectTransform),
|
GUILayoutGroup nameGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.5f), nameAndJobGroup.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft) { CanBeFocused = false };
|
||||||
characterInfo.Name, textColor: jobColor, textAlignment: Alignment.BottomLeft)
|
GUITextBlock nameBlock = new GUITextBlock(new RectTransform(Vector2.One, nameGroup.RectTransform),
|
||||||
|
listBox == hireableList ? characterInfo.OriginalName : characterInfo.Name,
|
||||||
|
textColor: jobColor, textAlignment: Alignment.BottomLeft)
|
||||||
{
|
{
|
||||||
CanBeFocused = false
|
CanBeFocused = false
|
||||||
};
|
};
|
||||||
nameBlock.Text = ToolBox.LimitString(nameBlock.Text, nameBlock.Font, nameBlock.Rect.Width);
|
nameBlock.Text = ToolBox.LimitString(nameBlock.Text, nameBlock.Font, nameBlock.Rect.Width);
|
||||||
|
|
||||||
GUITextBlock jobBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), nameAndJobGroup.RectTransform),
|
GUITextBlock jobBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), nameAndJobGroup.RectTransform),
|
||||||
characterInfo.Job.Name, textColor: Color.White, font: GUI.SmallFont, textAlignment: Alignment.TopLeft)
|
characterInfo.Job.Name, textColor: Color.White, font: GUI.SmallFont, textAlignment: Alignment.TopLeft)
|
||||||
{
|
{
|
||||||
@@ -366,7 +370,7 @@ namespace Barotrauma
|
|||||||
jobBlock.Text = ToolBox.LimitString(jobBlock.Text, jobBlock.Font, jobBlock.Rect.Width);
|
jobBlock.Text = ToolBox.LimitString(jobBlock.Text, jobBlock.Font, jobBlock.Rect.Width);
|
||||||
|
|
||||||
float width = 0.6f / 3;
|
float width = 0.6f / 3;
|
||||||
if (characterInfo.Job != null)
|
if (characterInfo.Job != null && skill != null)
|
||||||
{
|
{
|
||||||
GUILayoutGroup skillGroup = new GUILayoutGroup(new RectTransform(new Vector2(width, 0.6f), mainGroup.RectTransform), isHorizontal: true);
|
GUILayoutGroup skillGroup = new GUILayoutGroup(new RectTransform(new Vector2(width, 0.6f), mainGroup.RectTransform), isHorizontal: true);
|
||||||
float iconWidth = (float)skillGroup.Rect.Height / skillGroup.Rect.Width;
|
float iconWidth = (float)skillGroup.Rect.Height / skillGroup.Rect.Width;
|
||||||
@@ -383,11 +387,18 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (listBox != crewList)
|
if (listBox != crewList)
|
||||||
{
|
{
|
||||||
new GUITextBlock(new RectTransform(new Vector2(width, 1.0f), mainGroup.RectTransform), FormatCurrency(characterInfo.Salary), textAlignment: Alignment.Center)
|
new GUITextBlock(new RectTransform(new Vector2(width, 1.0f), mainGroup.RectTransform),
|
||||||
|
FormatCurrency(characterInfo.Salary),
|
||||||
|
textAlignment: Alignment.Center)
|
||||||
{
|
{
|
||||||
CanBeFocused = false
|
CanBeFocused = false
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Just a bit of padding to make list layouts similar
|
||||||
|
new GUIFrame(new RectTransform(new Vector2(width, 1.0f), mainGroup.RectTransform), style: null) { CanBeFocused = false };
|
||||||
|
}
|
||||||
|
|
||||||
if (listBox == hireableList)
|
if (listBox == hireableList)
|
||||||
{
|
{
|
||||||
@@ -446,6 +457,23 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (listBox == pendingList || listBox == crewList)
|
||||||
|
{
|
||||||
|
nameBlock.RectTransform.Resize(new Point(nameBlock.Rect.Width - nameBlock.Rect.Height, nameBlock.Rect.Height));
|
||||||
|
nameBlock.Text = ToolBox.LimitString(nameBlock.Text, nameBlock.Font, nameBlock.Rect.Width);
|
||||||
|
nameBlock.RectTransform.Resize(new Point((int)(nameBlock.Padding.X + nameBlock.TextSize.X + nameBlock.Padding.Z), nameBlock.Rect.Height));
|
||||||
|
Point size = new Point((int)(0.7f * nameBlock.Rect.Height));
|
||||||
|
new GUIImage(new RectTransform(size, nameGroup.RectTransform), "EditIcon") { CanBeFocused = false };
|
||||||
|
size = new Point(3 * mainGroup.AbsoluteSpacing + icon.Rect.Width + nameAndJobGroup.Rect.Width, mainGroup.Rect.Height);
|
||||||
|
new GUIButton(new RectTransform(size, frame.RectTransform) { RelativeOffset = new Vector2(0.025f) }, style: null)
|
||||||
|
{
|
||||||
|
Enabled = HasPermission,
|
||||||
|
ToolTip = TextManager.GetWithVariable("campaigncrew.givenicknametooltip", "[mouseprimary]", TextManager.Get($"input.{(PlayerInput.MouseButtonsSwapped() ? "rightmouse" : "leftmouse")}")),
|
||||||
|
UserData = characterInfo,
|
||||||
|
OnClicked = CreateRenamingComponent
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CreateCharacterPreviewFrame(GUIListBox listBox, GUIFrame characterFrame, CharacterInfo characterInfo)
|
private void CreateCharacterPreviewFrame(GUIListBox listBox, GUIFrame characterFrame, CharacterInfo characterInfo)
|
||||||
@@ -478,7 +506,10 @@ namespace Barotrauma
|
|||||||
GUILayoutGroup infoValueGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.6f, 1.0f), infoGroup.RectTransform)) { Stretch = true };
|
GUILayoutGroup infoValueGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.6f, 1.0f), infoGroup.RectTransform)) { Stretch = true };
|
||||||
float blockHeight = 1.0f / 4;
|
float blockHeight = 1.0f / 4;
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, blockHeight), infoLabelGroup.RectTransform), TextManager.Get("name"));
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, blockHeight), infoLabelGroup.RectTransform), TextManager.Get("name"));
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, blockHeight), infoValueGroup.RectTransform), characterInfo.Name);
|
GUITextBlock nameBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, blockHeight), infoValueGroup.RectTransform), "");
|
||||||
|
string name = listBox == hireableList ? characterInfo.OriginalName : characterInfo.Name;
|
||||||
|
nameBlock.Text = ToolBox.LimitString(name, nameBlock.Font, nameBlock.Rect.Width);
|
||||||
|
|
||||||
if (characterInfo.HasGenders)
|
if (characterInfo.HasGenders)
|
||||||
{
|
{
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, blockHeight), infoLabelGroup.RectTransform), TextManager.Get("gender"));
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, blockHeight), infoLabelGroup.RectTransform), TextManager.Get("gender"));
|
||||||
@@ -553,9 +584,18 @@ namespace Barotrauma
|
|||||||
if (PendingHires.Contains(characterInfo)) { PendingHires.Remove(characterInfo); }
|
if (PendingHires.Contains(characterInfo)) { PendingHires.Remove(characterInfo); }
|
||||||
pendingList.Content.RemoveChild(pendingList.Content.FindChild(c => (c.UserData as Tuple<CharacterInfo, float>).Item1 == characterInfo));
|
pendingList.Content.RemoveChild(pendingList.Content.FindChild(c => (c.UserData as Tuple<CharacterInfo, float>).Item1 == characterInfo));
|
||||||
pendingList.UpdateScrollBarSize();
|
pendingList.UpdateScrollBarSize();
|
||||||
CreateCharacterFrame(characterInfo, hireableList);
|
|
||||||
SortCharacters(hireableList, (SortingMethod)sortingDropDown.SelectedItemData);
|
// Server will reset the names to originals in multiplayer
|
||||||
hireableList.UpdateScrollBarSize();
|
if (!GameMain.IsMultiplayer) { characterInfo?.ResetName(); }
|
||||||
|
|
||||||
|
if (campaign.Map.CurrentLocation.HireManager.AvailableCharacters.Any(info => info.GetIdentifierUsingOriginalName() == characterInfo.GetIdentifierUsingOriginalName()) &&
|
||||||
|
hireableList.Content.Children.None(c => c.UserData is Tuple<CharacterInfo, float> userData && userData.Item1.GetIdentifierUsingOriginalName() == characterInfo.GetIdentifierUsingOriginalName()))
|
||||||
|
{
|
||||||
|
CreateCharacterFrame(characterInfo, hireableList);
|
||||||
|
SortCharacters(hireableList, (SortingMethod)sortingDropDown.SelectedItemData);
|
||||||
|
hireableList.UpdateScrollBarSize();
|
||||||
|
}
|
||||||
|
|
||||||
if (setTotalHireCost) { SetTotalHireCost(); }
|
if (setTotalHireCost) { SetTotalHireCost(); }
|
||||||
if (createNetworkMessage) { SendCrewState(true); }
|
if (createNetworkMessage) { SendCrewState(true); }
|
||||||
return true;
|
return true;
|
||||||
@@ -572,36 +612,41 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (pendingList == null || totalBlock == null || validateHiresButton == null) { return; }
|
if (pendingList == null || totalBlock == null || validateHiresButton == null) { return; }
|
||||||
int total = 0;
|
int total = 0;
|
||||||
pendingList.Content.Children.ForEach(c => total += (c.UserData as Tuple<CharacterInfo, float>).Item1.Salary);
|
pendingList.Content.Children.ForEach(c =>
|
||||||
|
{
|
||||||
|
total += (c.UserData as Tuple<CharacterInfo, float>).Item1.Salary;
|
||||||
|
});
|
||||||
totalBlock.Text = FormatCurrency(total);
|
totalBlock.Text = FormatCurrency(total);
|
||||||
bool enoughMoney = campaign != null ? total <= campaign.Money : true;
|
bool enoughMoney = campaign != null ? total <= campaign.Money : true;
|
||||||
totalBlock.TextColor = enoughMoney ? Color.White : Color.Red;
|
totalBlock.TextColor = enoughMoney ? Color.White : Color.Red;
|
||||||
validateHiresButton.Enabled = enoughMoney && pendingList.Content.RectTransform.Children.Any();
|
validateHiresButton.Enabled = enoughMoney && pendingList.Content.RectTransform.Children.Any();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ValidatePendingHires(bool createNetworkEvent = false)
|
public bool ValidateHires(List<CharacterInfo> hires, bool createNetworkEvent = false)
|
||||||
{
|
{
|
||||||
List<CharacterInfo> hires = new List<CharacterInfo>();
|
if (hires == null || hires.None()) { return false; }
|
||||||
int total = 0;
|
|
||||||
foreach (GUIComponent c in pendingList.Content.Children.ToList())
|
|
||||||
{
|
|
||||||
if (c.UserData is Tuple<CharacterInfo, float> info)
|
|
||||||
{
|
|
||||||
hires.Add(info.Item1);
|
|
||||||
total += info.Item1.Salary;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hires.None() || total > campaign.Money) { return false; }
|
List<CharacterInfo> nonDuplicateHires = new List<CharacterInfo>();
|
||||||
|
hires.ForEach(hireInfo =>
|
||||||
|
{
|
||||||
|
if(campaign.CrewManager.GetCharacterInfos().None(crewInfo => crewInfo.IsNewHire && crewInfo.GetIdentifierUsingOriginalName() == hireInfo.GetIdentifierUsingOriginalName()))
|
||||||
|
{
|
||||||
|
nonDuplicateHires.Add(hireInfo);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (nonDuplicateHires.None()) { return false; }
|
||||||
|
|
||||||
|
int total = nonDuplicateHires.Aggregate(0, (total, info) => total + info.Salary);
|
||||||
|
|
||||||
|
if (total > campaign.Money) { return false; }
|
||||||
|
|
||||||
bool atLeastOneHired = false;
|
bool atLeastOneHired = false;
|
||||||
foreach (CharacterInfo ci in hires)
|
foreach (CharacterInfo ci in nonDuplicateHires)
|
||||||
{
|
{
|
||||||
if (campaign.TryHireCharacter(campaign.Map.CurrentLocation, ci))
|
if (campaign.TryHireCharacter(campaign.Map.CurrentLocation, ci))
|
||||||
{
|
{
|
||||||
atLeastOneHired = true;
|
atLeastOneHired = true;
|
||||||
PendingHires.Remove(ci);
|
|
||||||
pendingList.Content.RemoveChild(pendingList.Content.FindChild(c => (c.UserData as Tuple<CharacterInfo, float>).Item1 == ci));
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -628,6 +673,93 @@ namespace Barotrauma
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool CreateRenamingComponent(GUIButton button, object userData)
|
||||||
|
{
|
||||||
|
if (!HasPermission || !(userData is CharacterInfo characterInfo)) { return false; }
|
||||||
|
var outerGlowFrame = new GUIFrame(new RectTransform(new Vector2(1.25f, 1.25f), parentComponent.RectTransform, Anchor.Center),
|
||||||
|
style: "OuterGlow", color: Color.Black * 0.7f);
|
||||||
|
var frame = new GUIFrame(new RectTransform(new Vector2(0.33f, 0.4f), outerGlowFrame.RectTransform, anchor: Anchor.Center)
|
||||||
|
{
|
||||||
|
MaxSize = new Point(400, 300).Multiply(GUI.Scale)
|
||||||
|
});
|
||||||
|
var layoutGroup = new GUILayoutGroup(new RectTransform((frame.Rect.Size - GUIStyle.ItemFrameMargin).Multiply(new Vector2(0.75f, 1.0f)), frame.RectTransform, anchor: Anchor.Center), childAnchor: Anchor.TopCenter)
|
||||||
|
{
|
||||||
|
RelativeSpacing = 0.02f,
|
||||||
|
Stretch = true
|
||||||
|
};
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), layoutGroup.RectTransform), TextManager.Get("campaigncrew.givenickname"), font: GUI.SubHeadingFont, textAlignment: Alignment.Center, wrap: true);
|
||||||
|
var groupElementSize = new Vector2(1.0f, 0.25f);
|
||||||
|
var nameBox = new GUITextBox(new RectTransform(groupElementSize, layoutGroup.RectTransform))
|
||||||
|
{
|
||||||
|
MaxTextLength = Client.MaxNameLength
|
||||||
|
};
|
||||||
|
new GUIButton(new RectTransform(groupElementSize, layoutGroup.RectTransform), text: TextManager.Get("confirm"))
|
||||||
|
{
|
||||||
|
OnClicked = (button, userData) =>
|
||||||
|
{
|
||||||
|
if (RenameCharacter(characterInfo, nameBox.Text?.Trim()))
|
||||||
|
{
|
||||||
|
parentComponent.RemoveChild(outerGlowFrame);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nameBox.Flash(color: Color.Red);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
new GUIButton(new RectTransform(groupElementSize, layoutGroup.RectTransform), text: TextManager.Get("cancel"))
|
||||||
|
{
|
||||||
|
OnClicked = (button, userData) =>
|
||||||
|
{
|
||||||
|
parentComponent.RemoveChild(outerGlowFrame);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
layoutGroup.Recalculate();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool RenameCharacter(CharacterInfo characterInfo, string newName)
|
||||||
|
{
|
||||||
|
if (characterInfo == null || string.IsNullOrEmpty(newName)) { return false; }
|
||||||
|
if (newName == characterInfo.Name) { return false; }
|
||||||
|
if (GameMain.IsMultiplayer)
|
||||||
|
{
|
||||||
|
SendCrewState(false, renameCharacter: (characterInfo, newName));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var crewComponent = crewList.Content.FindChild(c => (c.UserData as Tuple<CharacterInfo, float>).Item1 == characterInfo);
|
||||||
|
if (crewComponent != null)
|
||||||
|
{
|
||||||
|
crewList.Content.RemoveChild(crewComponent);
|
||||||
|
campaign.CrewManager.RenameCharacter(characterInfo, newName);
|
||||||
|
CreateCharacterFrame(characterInfo, crewList);
|
||||||
|
SortCharacters(crewList, SortingMethod.JobAsc);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var pendingComponent = pendingList.Content.FindChild(c => (c.UserData as Tuple<CharacterInfo, float>).Item1 == characterInfo);
|
||||||
|
if (pendingComponent != null)
|
||||||
|
{
|
||||||
|
pendingList.Content.RemoveChild(pendingComponent);
|
||||||
|
campaign.Map.CurrentLocation.HireManager.RenameCharacter(characterInfo, newName);
|
||||||
|
CreateCharacterFrame(characterInfo, pendingList);
|
||||||
|
SortCharacters(pendingList, SortingMethod.JobAsc);
|
||||||
|
SetTotalHireCost();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private bool FireCharacter(GUIButton button, object selection)
|
private bool FireCharacter(GUIButton button, object selection)
|
||||||
{
|
{
|
||||||
if (!(selection is CharacterInfo characterInfo)) { return false; }
|
if (!(selection is CharacterInfo characterInfo)) { return false; }
|
||||||
@@ -648,9 +780,10 @@ namespace Barotrauma
|
|||||||
UpdateLocationView(campaign.Map.CurrentLocation, false);
|
UpdateLocationView(campaign.Map.CurrentLocation, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((GUI.MouseOn?.UserData as Tuple<CharacterInfo, float>)?.Item1 is CharacterInfo characterInfo)
|
(GUIComponent highlightedFrame, CharacterInfo highlightedInfo) = FindHighlightedCharacter(GUI.MouseOn);
|
||||||
|
if (highlightedFrame != null && highlightedInfo != null)
|
||||||
{
|
{
|
||||||
if (characterPreviewFrame == null || characterInfo != characterPreviewFrame.UserData)
|
if (characterPreviewFrame == null || highlightedInfo != characterPreviewFrame.UserData)
|
||||||
{
|
{
|
||||||
GUIComponent component = GUI.MouseOn;
|
GUIComponent component = GUI.MouseOn;
|
||||||
GUIListBox listBox = null;
|
GUIListBox listBox = null;
|
||||||
@@ -673,7 +806,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (listBox != null)
|
if (listBox != null)
|
||||||
{
|
{
|
||||||
SelectCharacter(listBox, GUI.MouseOn as GUIFrame, characterInfo);
|
SelectCharacter(listBox, highlightedFrame as GUIFrame, highlightedInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -687,6 +820,27 @@ namespace Barotrauma
|
|||||||
characterPreviewFrame.Parent?.RemoveChild(characterPreviewFrame);
|
characterPreviewFrame.Parent?.RemoveChild(characterPreviewFrame);
|
||||||
characterPreviewFrame = null;
|
characterPreviewFrame = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static (GUIComponent, CharacterInfo) FindHighlightedCharacter(GUIComponent c)
|
||||||
|
{
|
||||||
|
if (c == null)
|
||||||
|
{
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
if (c.UserData is Tuple<CharacterInfo, float> highlightedData)
|
||||||
|
{
|
||||||
|
return (c, highlightedData.Item1);
|
||||||
|
}
|
||||||
|
if (c.Parent != null)
|
||||||
|
{
|
||||||
|
if (c.Parent is GUIListBox)
|
||||||
|
{
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
return FindHighlightedCharacter(c.Parent);
|
||||||
|
}
|
||||||
|
return default;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetPendingHires(List<int> characterInfos, Location location)
|
public void SetPendingHires(List<int> characterInfos, Location location)
|
||||||
@@ -699,7 +853,7 @@ namespace Barotrauma
|
|||||||
PendingHires.Clear();
|
PendingHires.Clear();
|
||||||
foreach (int identifier in characterInfos)
|
foreach (int identifier in characterInfos)
|
||||||
{
|
{
|
||||||
CharacterInfo match = location.HireManager.AvailableCharacters.Find(info => info.GetIdentifier() == identifier);
|
CharacterInfo match = location.HireManager.AvailableCharacters.Find(info => info.GetIdentifierUsingOriginalName() == identifier);
|
||||||
if (match != null)
|
if (match != null)
|
||||||
{
|
{
|
||||||
PendingHires.Add(match);
|
PendingHires.Add(match);
|
||||||
@@ -716,9 +870,10 @@ namespace Barotrauma
|
|||||||
/// Notify the server of crew changes
|
/// Notify the server of crew changes
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="updatePending">When set to true will tell the server to update the pending hires</param>
|
/// <param name="updatePending">When set to true will tell the server to update the pending hires</param>
|
||||||
|
/// <param name="renameCharacter">When not null tell the server to rename this character. Item1 is the character to rename, Item2 is the new name, Item3 indicates whether the renamed character is already a part of the crew.</param>
|
||||||
/// <param name="firedCharacter">When not null tell the server to fire this character</param>
|
/// <param name="firedCharacter">When not null tell the server to fire this character</param>
|
||||||
/// <param name="validateHires">When set to true will tell the server to validate pending hires</param>
|
/// <param name="validateHires">When set to true will tell the server to validate pending hires</param>
|
||||||
public void SendCrewState(bool updatePending, CharacterInfo firedCharacter = null, bool validateHires = false)
|
public void SendCrewState(bool updatePending, (CharacterInfo info, string newName) renameCharacter = default, CharacterInfo firedCharacter = null, bool validateHires = false)
|
||||||
{
|
{
|
||||||
if (campaign is MultiPlayerCampaign)
|
if (campaign is MultiPlayerCampaign)
|
||||||
{
|
{
|
||||||
@@ -731,12 +886,23 @@ namespace Barotrauma
|
|||||||
msg.Write((ushort)PendingHires.Count);
|
msg.Write((ushort)PendingHires.Count);
|
||||||
foreach (CharacterInfo pendingHire in PendingHires)
|
foreach (CharacterInfo pendingHire in PendingHires)
|
||||||
{
|
{
|
||||||
msg.Write(pendingHire.GetIdentifier());
|
msg.Write(pendingHire.GetIdentifierUsingOriginalName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
msg.Write(validateHires);
|
msg.Write(validateHires);
|
||||||
|
|
||||||
|
bool validRenaming = renameCharacter.info != null && !string.IsNullOrEmpty(renameCharacter.newName);
|
||||||
|
msg.Write(validRenaming);
|
||||||
|
if (validRenaming)
|
||||||
|
{
|
||||||
|
int identifier = renameCharacter.info.GetIdentifierUsingOriginalName();
|
||||||
|
msg.Write(identifier);
|
||||||
|
msg.Write(renameCharacter.newName);
|
||||||
|
bool existingCrewMember = campaign.CrewManager?.GetCharacterInfos().Any(ci => ci.GetIdentifierUsingOriginalName() == identifier) ?? false;
|
||||||
|
msg.Write(existingCrewMember);
|
||||||
|
}
|
||||||
|
|
||||||
msg.Write(firedCharacter != null);
|
msg.Write(firedCharacter != null);
|
||||||
if (firedCharacter != null)
|
if (firedCharacter != null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -218,6 +218,21 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public static bool DisableHUD, DisableUpperHUD, DisableItemHighlights, DisableCharacterNames;
|
public static bool DisableHUD, DisableUpperHUD, DisableItemHighlights, DisableCharacterNames;
|
||||||
|
|
||||||
|
private static bool isSavingIndicatorEnabled;
|
||||||
|
private static Color savingIndicatorColor = Color.Transparent;
|
||||||
|
private static bool IsSavingIndicatorVisible => savingIndicatorColor.A > 0;
|
||||||
|
private static float savingIndicatorSpriteIndex;
|
||||||
|
private static float savingIndicatorColorLerpAmount;
|
||||||
|
private static SavingIndicatorState savingIndicatorState = SavingIndicatorState.None;
|
||||||
|
private static float? timeUntilSavingIndicatorDisabled;
|
||||||
|
|
||||||
|
private enum SavingIndicatorState
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
FadingIn,
|
||||||
|
FadingOut
|
||||||
|
}
|
||||||
|
|
||||||
public static void Init(GameWindow window, IEnumerable<ContentPackage> selectedContentPackages, GraphicsDevice graphicsDevice)
|
public static void Init(GameWindow window, IEnumerable<ContentPackage> selectedContentPackages, GraphicsDevice graphicsDevice)
|
||||||
{
|
{
|
||||||
GraphicsDevice = graphicsDevice;
|
GraphicsDevice = graphicsDevice;
|
||||||
@@ -345,7 +360,11 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (DisableHUD) { return; }
|
if (DisableHUD)
|
||||||
|
{
|
||||||
|
DrawSavingIndicator(spriteBatch);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (GameMain.ShowFPS || GameMain.DebugDraw)
|
if (GameMain.ShowFPS || GameMain.DebugDraw)
|
||||||
{
|
{
|
||||||
@@ -539,60 +558,42 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IEnumerable<string> strings;
|
||||||
if (MouseOn != null)
|
if (MouseOn != null)
|
||||||
{
|
{
|
||||||
RectTransform mouseOnRect = MouseOn.RectTransform;
|
RectTransform mouseOnRect = MouseOn.RectTransform;
|
||||||
bool isAbsoluteOffsetInUse = mouseOnRect.AbsoluteOffset != Point.Zero || mouseOnRect.RelativeOffset == Vector2.Zero;
|
bool isAbsoluteOffsetInUse = mouseOnRect.AbsoluteOffset != Point.Zero || mouseOnRect.RelativeOffset == Vector2.Zero;
|
||||||
|
|
||||||
string selectedString = $"Selected UI Element: {MouseOn.GetType().Name} ({ MouseOn.Style?.Element.Name.LocalName ?? "no style" }, {MouseOn.Rect}";
|
strings = new string[]
|
||||||
string offsetString = $"Relative Offset: {mouseOnRect.RelativeOffset} | Absolute Offset: {(isAbsoluteOffsetInUse ? mouseOnRect.AbsoluteOffset : mouseOnRect.ParentRect.MultiplySize(mouseOnRect.RelativeOffset))}{(isAbsoluteOffsetInUse ? "" : " (Calculated from RelativeOffset)")}";
|
{
|
||||||
string anchorPivotString = $"Anchor: {mouseOnRect.Anchor} | Pivot: {mouseOnRect.Pivot}";
|
$"Selected UI Element: {MouseOn.GetType().Name} ({ MouseOn.Style?.Element.Name.LocalName ?? "no style" }, {MouseOn.Rect}",
|
||||||
Vector2 selectedStringSize = SmallFont.MeasureString(selectedString);
|
$"Relative Offset: {mouseOnRect.RelativeOffset} | Absolute Offset: {(isAbsoluteOffsetInUse ? mouseOnRect.AbsoluteOffset : mouseOnRect.ParentRect.MultiplySize(mouseOnRect.RelativeOffset))}{(isAbsoluteOffsetInUse ? "" : " (Calculated from RelativeOffset)")}",
|
||||||
Vector2 offsetStringSize = SmallFont.MeasureString(offsetString);
|
$"Anchor: {mouseOnRect.Anchor} | Pivot: {mouseOnRect.Pivot}"
|
||||||
Vector2 anchorPivotStringSize = SmallFont.MeasureString(anchorPivotString);
|
};
|
||||||
|
|
||||||
int padding = IntScale(10);
|
|
||||||
int yPos = padding;
|
|
||||||
|
|
||||||
DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth - (int)selectedStringSize.X - padding, yPos), selectedString, Color.LightGreen, Color.Black, 0, SmallFont);
|
|
||||||
yPos += (int)selectedStringSize.Y + padding / 2;
|
|
||||||
|
|
||||||
DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth - (int)offsetStringSize.X - padding, yPos), offsetString, Color.LightGreen, Color.Black, 0, SmallFont);
|
|
||||||
yPos += (int)offsetStringSize.Y + padding / 2;
|
|
||||||
|
|
||||||
DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth - (int)anchorPivotStringSize.X - padding, yPos), anchorPivotString, Color.LightGreen, Color.Black, 0, SmallFont);
|
|
||||||
yPos += (int)anchorPivotStringSize.Y + padding / 2;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
string guiScaleString = $"GUI.Scale: {Scale}";
|
strings = new string[]
|
||||||
string guixScaleString = $"GUI.xScale: {xScale}";
|
{
|
||||||
string guiyScaleString = $"GUI.yScale: {yScale}";
|
$"GUI.Scale: {Scale}",
|
||||||
string relativeHorizontalAspectRatioString = $"RelativeHorizontalAspectRatio: {RelativeHorizontalAspectRatio}";
|
$"GUI.xScale: {xScale}",
|
||||||
string relativeVerticalAspectRatioString = $"RelativeVerticalAspectRatio: {RelativeVerticalAspectRatio}";
|
$"GUI.yScale: {yScale}",
|
||||||
Vector2 guiScaleStringSize = SmallFont.MeasureString(guiScaleString);
|
$"RelativeHorizontalAspectRatio: {RelativeHorizontalAspectRatio}",
|
||||||
Vector2 guixScaleStringSize = SmallFont.MeasureString(guixScaleString);
|
$"RelativeVerticalAspectRatio: {RelativeVerticalAspectRatio}",
|
||||||
Vector2 guiyScaleStringSize = SmallFont.MeasureString(guiyScaleString);
|
};
|
||||||
Vector2 relativeHorizontalAspectRatioStringSize = SmallFont.MeasureString(relativeHorizontalAspectRatioString);
|
}
|
||||||
Vector2 relativeVerticalAspectRatioStringSize = SmallFont.MeasureString(relativeVerticalAspectRatioString);
|
|
||||||
|
|
||||||
int padding = IntScale(10);
|
strings = strings.Concat(new string[] { $"Cam.Zoom: {Screen.Selected.Cam?.Zoom ?? 0f}" });
|
||||||
int yPos = padding;
|
|
||||||
|
|
||||||
DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth - (int)guiScaleStringSize.X - padding, yPos), guiScaleString, Color.LightGreen, Color.Black, 0, SmallFont);
|
int padding = IntScale(10);
|
||||||
yPos += (int)guiScaleStringSize.Y + padding / 2;
|
int yPos = padding;
|
||||||
|
|
||||||
DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth - (int)guixScaleStringSize.X - padding, yPos), guixScaleString, Color.LightGreen, Color.Black, 0, SmallFont);
|
foreach (string str in strings)
|
||||||
yPos += (int)guixScaleStringSize.Y + padding / 2;
|
{
|
||||||
|
Vector2 stringSize = SmallFont.MeasureString(str);
|
||||||
|
|
||||||
DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth - (int)guiyScaleStringSize.X - padding, yPos), guiyScaleString, Color.LightGreen, Color.Black, 0, SmallFont);
|
DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth - (int)stringSize.X - padding, yPos), str, Color.LightGreen, Color.Black, 0, SmallFont);
|
||||||
yPos += (int)guiyScaleStringSize.Y + padding / 2;
|
yPos += (int)stringSize.Y + padding / 2;
|
||||||
|
|
||||||
DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth - (int)relativeHorizontalAspectRatioStringSize.X - padding, yPos), relativeHorizontalAspectRatioString, Color.LightGreen, Color.Black, 0, SmallFont);
|
|
||||||
yPos += (int)relativeHorizontalAspectRatioStringSize.Y + padding / 2;
|
|
||||||
|
|
||||||
DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth - (int)relativeVerticalAspectRatioStringSize.X - padding, yPos), relativeVerticalAspectRatioString, Color.LightGreen, Color.Black, 0, SmallFont);
|
|
||||||
yPos += (int)relativeVerticalAspectRatioStringSize.Y + padding / 2;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -645,6 +646,8 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DrawSavingIndicator(spriteBatch);
|
||||||
|
|
||||||
if (GameMain.WindowActive && !HideCursor)
|
if (GameMain.WindowActive && !HideCursor)
|
||||||
{
|
{
|
||||||
spriteBatch.End();
|
spriteBatch.End();
|
||||||
@@ -855,6 +858,7 @@ namespace Barotrauma
|
|||||||
lock (mutex)
|
lock (mutex)
|
||||||
{
|
{
|
||||||
GUIMessageBox.AddActiveToGUIUpdateList();
|
GUIMessageBox.AddActiveToGUIUpdateList();
|
||||||
|
GUIContextMenu.AddActiveToGUIUpdateList();
|
||||||
|
|
||||||
if (pauseMenuOpen)
|
if (pauseMenuOpen)
|
||||||
{
|
{
|
||||||
@@ -921,6 +925,7 @@ namespace Barotrauma
|
|||||||
if ((!PlayerInput.PrimaryMouseButtonHeld() && !PlayerInput.PrimaryMouseButtonClicked()) || c == prevMouseOn)
|
if ((!PlayerInput.PrimaryMouseButtonHeld() && !PlayerInput.PrimaryMouseButtonClicked()) || c == prevMouseOn)
|
||||||
{
|
{
|
||||||
MouseOn = c;
|
MouseOn = c;
|
||||||
|
var sakdjfnsjkd = c.MouseRect;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1043,7 +1048,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parent != null)
|
if (parent != null && parent.CanBeFocused)
|
||||||
{
|
{
|
||||||
if (!parent.Rect.Equals(monitorRect)) { return parent.HoverCursor; }
|
if (!parent.Rect.Equals(monitorRect)) { return parent.HoverCursor; }
|
||||||
}
|
}
|
||||||
@@ -1222,6 +1227,7 @@ namespace Barotrauma
|
|||||||
Debug.Assert(updateList.Count == updateListSet.Count);
|
Debug.Assert(updateList.Count == updateListSet.Count);
|
||||||
updateList.ForEach(c => c.UpdateAuto(deltaTime));
|
updateList.ForEach(c => c.UpdateAuto(deltaTime));
|
||||||
UpdateMessages(deltaTime);
|
UpdateMessages(deltaTime);
|
||||||
|
UpdateSavingIndicator(deltaTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1266,6 +1272,58 @@ namespace Barotrauma
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void UpdateSavingIndicator(float deltaTime)
|
||||||
|
{
|
||||||
|
lock (mutex)
|
||||||
|
{
|
||||||
|
if (timeUntilSavingIndicatorDisabled.HasValue)
|
||||||
|
{
|
||||||
|
timeUntilSavingIndicatorDisabled -= deltaTime;
|
||||||
|
if (timeUntilSavingIndicatorDisabled <= 0.0f)
|
||||||
|
{
|
||||||
|
isSavingIndicatorEnabled = false;
|
||||||
|
timeUntilSavingIndicatorDisabled = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isSavingIndicatorEnabled)
|
||||||
|
{
|
||||||
|
if (savingIndicatorColor == Color.Transparent)
|
||||||
|
{
|
||||||
|
savingIndicatorState = SavingIndicatorState.FadingIn;
|
||||||
|
savingIndicatorColorLerpAmount = 0.0f;
|
||||||
|
}
|
||||||
|
else if (savingIndicatorColor == Color.White)
|
||||||
|
{
|
||||||
|
savingIndicatorState = SavingIndicatorState.None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (savingIndicatorColor == Color.White)
|
||||||
|
{
|
||||||
|
savingIndicatorState = SavingIndicatorState.FadingOut;
|
||||||
|
savingIndicatorColorLerpAmount = 0.0f;
|
||||||
|
}
|
||||||
|
else if (savingIndicatorColor == Color.Transparent)
|
||||||
|
{
|
||||||
|
savingIndicatorState = SavingIndicatorState.None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (savingIndicatorState != SavingIndicatorState.None)
|
||||||
|
{
|
||||||
|
bool isFadingIn = savingIndicatorState == SavingIndicatorState.FadingIn;
|
||||||
|
Color lerpStartColor = isFadingIn ? Color.Transparent : Color.White;
|
||||||
|
Color lerpTargetColor = isFadingIn ? Color.White : Color.Transparent;
|
||||||
|
savingIndicatorColorLerpAmount += (isFadingIn ? 2.0f : 0.5f) * deltaTime;
|
||||||
|
savingIndicatorColor = Color.Lerp(lerpStartColor, lerpTargetColor, savingIndicatorColorLerpAmount);
|
||||||
|
}
|
||||||
|
if (IsSavingIndicatorVisible)
|
||||||
|
{
|
||||||
|
savingIndicatorSpriteIndex = (savingIndicatorSpriteIndex + 15.0f * deltaTime) % (Style.SavingIndicator.FrameCount + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#region Element drawing
|
#region Element drawing
|
||||||
|
|
||||||
private static List<float> usedIndicatorAngles = new List<float>();
|
private static List<float> usedIndicatorAngles = new List<float>();
|
||||||
@@ -1278,7 +1336,7 @@ namespace Barotrauma
|
|||||||
Vector2 diff = worldPosition - cam.WorldViewCenter;
|
Vector2 diff = worldPosition - cam.WorldViewCenter;
|
||||||
float dist = diff.Length();
|
float dist = diff.Length();
|
||||||
|
|
||||||
float symbolScale = Math.Min(64.0f / sprite.size.X, 1.0f) * scaleMultiplier;
|
float symbolScale = Math.Min(64.0f / sprite.size.X, 1.0f) * scaleMultiplier * Scale;
|
||||||
|
|
||||||
if (overrideAlpha.HasValue || dist > hideDist)
|
if (overrideAlpha.HasValue || dist > hideDist)
|
||||||
{
|
{
|
||||||
@@ -1336,9 +1394,9 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void DrawLine(SpriteBatch sb, Vector2 start, Vector2 end, Color clr, float depth = 0.0f, int width = 1)
|
public static void DrawLine(SpriteBatch sb, Vector2 start, Vector2 end, Color clr, float depth = 0.0f, float width = 1)
|
||||||
{
|
{
|
||||||
DrawLine(sb, t, start, end, clr, depth, width);
|
DrawLine(sb, t, start, end, clr, depth, (int)width);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void DrawLine(SpriteBatch sb, Sprite sprite, Vector2 start, Vector2 end, Color clr, float depth = 0.0f, int width = 1)
|
public static void DrawLine(SpriteBatch sb, Sprite sprite, Vector2 start, Vector2 end, Color clr, float depth = 0.0f, int width = 1)
|
||||||
@@ -1405,7 +1463,7 @@ namespace Barotrauma
|
|||||||
font.DrawStringWithColors(sb, text, pos, color, 0.0f, Vector2.Zero, 1f, SpriteEffects.None, depth, richTextData);
|
font.DrawStringWithColors(sb, text, pos, color, 0.0f, Vector2.Zero, 1f, SpriteEffects.None, depth, richTextData);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void DrawRectangle(SpriteBatch sb, Vector2 start, Vector2 size, Color clr, bool isFilled = false, float depth = 0.0f, int thickness = 1)
|
public static void DrawRectangle(SpriteBatch sb, Vector2 start, Vector2 size, Color clr, bool isFilled = false, float depth = 0.0f, float thickness = 1)
|
||||||
{
|
{
|
||||||
if (size.X < 0)
|
if (size.X < 0)
|
||||||
{
|
{
|
||||||
@@ -1420,7 +1478,7 @@ namespace Barotrauma
|
|||||||
DrawRectangle(sb, new Rectangle((int)start.X, (int)start.Y, (int)size.X, (int)size.Y), clr, isFilled, depth, thickness);
|
DrawRectangle(sb, new Rectangle((int)start.X, (int)start.Y, (int)size.X, (int)size.Y), clr, isFilled, depth, thickness);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void DrawRectangle(SpriteBatch sb, Rectangle rect, Color clr, bool isFilled = false, float depth = 0.0f, int thickness = 1)
|
public static void DrawRectangle(SpriteBatch sb, Rectangle rect, Color clr, bool isFilled = false, float depth = 0.0f, float thickness = 1)
|
||||||
{
|
{
|
||||||
if (isFilled)
|
if (isFilled)
|
||||||
{
|
{
|
||||||
@@ -1428,15 +1486,15 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sb.Draw(t, new Rectangle(rect.X + thickness, rect.Y, rect.Width - thickness * 2, thickness), null, clr, 0.0f, Vector2.Zero, SpriteEffects.None, depth);
|
Rectangle srcRect = new Rectangle(0, 0, 1, 1);
|
||||||
sb.Draw(t, new Rectangle(rect.X + thickness, rect.Y + rect.Height - thickness, rect.Width - thickness * 2, thickness), null, clr, 0.0f, Vector2.Zero, SpriteEffects.None, depth);
|
sb.Draw(t, new Vector2(rect.X, rect.Y), srcRect, clr, 0.0f, Vector2.Zero, new Vector2(thickness, rect.Height), SpriteEffects.None, depth);
|
||||||
|
sb.Draw(t, new Vector2(rect.X + thickness, rect.Y), srcRect, clr, 0.0f, Vector2.Zero, new Vector2(rect.Width - thickness, thickness), SpriteEffects.None, depth);
|
||||||
sb.Draw(t, new Rectangle(rect.X, rect.Y, thickness, rect.Height), null, clr, 0.0f, Vector2.Zero, SpriteEffects.None, depth);
|
sb.Draw(t, new Vector2(rect.X + thickness, rect.Bottom - thickness), srcRect, clr, 0.0f, Vector2.Zero, new Vector2(rect.Width - thickness, thickness), SpriteEffects.None, depth);
|
||||||
sb.Draw(t, new Rectangle(rect.X + rect.Width - thickness, rect.Y, thickness, rect.Height), null, clr, 0.0f, Vector2.Zero, SpriteEffects.None, depth);
|
sb.Draw(t, new Vector2(rect.Right - thickness, rect.Y + thickness), srcRect, clr, 0.0f, Vector2.Zero, new Vector2(thickness, rect.Height - thickness * 2f), SpriteEffects.None, depth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void DrawRectangle(SpriteBatch sb, Vector2 center, float width, float height, float rotation, Color clr, float depth = 0.0f, int thickness = 1)
|
public static void DrawRectangle(SpriteBatch sb, Vector2 center, float width, float height, float rotation, Color clr, float depth = 0.0f, float thickness = 1)
|
||||||
{
|
{
|
||||||
Matrix rotate = Matrix.CreateRotationZ(rotation);
|
Matrix rotate = Matrix.CreateRotationZ(rotation);
|
||||||
|
|
||||||
@@ -1453,7 +1511,7 @@ namespace Barotrauma
|
|||||||
DrawLine(sb, bottomLeft, topLeft, clr, depth, thickness);
|
DrawLine(sb, bottomLeft, topLeft, clr, depth, thickness);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void DrawRectangle(SpriteBatch sb, Vector2[] corners, Color clr, float depth = 0.0f, int thickness = 1)
|
public static void DrawRectangle(SpriteBatch sb, Vector2[] corners, Color clr, float depth = 0.0f, float thickness = 1)
|
||||||
{
|
{
|
||||||
if (corners.Length != 4)
|
if (corners.Length != 4)
|
||||||
{
|
{
|
||||||
@@ -1590,6 +1648,14 @@ namespace Barotrauma
|
|||||||
ShapeExtensions.DrawPoint(spriteBatch, pos, color, dotSize);
|
ShapeExtensions.DrawPoint(spriteBatch, pos, color, dotSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void DrawSavingIndicator(SpriteBatch spriteBatch)
|
||||||
|
{
|
||||||
|
if (!IsSavingIndicatorVisible) { return; }
|
||||||
|
var sheet = Style.SavingIndicator;
|
||||||
|
Vector2 pos = new Vector2(GameMain.GraphicsWidth, GameMain.GraphicsHeight) - new Vector2(HUDLayoutSettings.Padding) - 2 * Scale * sheet.FrameSize.ToVector2();
|
||||||
|
sheet.Draw(spriteBatch, (int)Math.Floor(savingIndicatorSpriteIndex), pos, savingIndicatorColor, origin: Vector2.Zero, rotate: 0.0f, scale: new Vector2(Scale));
|
||||||
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Element creation
|
#region Element creation
|
||||||
@@ -2246,7 +2312,7 @@ namespace Barotrauma
|
|||||||
OnClicked = (btn, userdata) =>
|
OnClicked = (btn, userdata) =>
|
||||||
{
|
{
|
||||||
if (!GameMain.Client.HasPermission(ClientPermissions.ManageRound)) { return false; }
|
if (!GameMain.Client.HasPermission(ClientPermissions.ManageRound)) { return false; }
|
||||||
if (GameMain.GameSession.GameMode is CampaignMode || (!Submarine.MainSub.AtStartPosition && !Submarine.MainSub.AtEndPosition))
|
if (GameMain.GameSession.GameMode is CampaignMode || (!Submarine.MainSub.AtStartExit && !Submarine.MainSub.AtEndExit))
|
||||||
{
|
{
|
||||||
var msgBox = new GUIMessageBox("",
|
var msgBox = new GUIMessageBox("",
|
||||||
TextManager.Get(GameMain.GameSession.GameMode is CampaignMode ? "PauseMenuReturnToServerLobbyVerification" : "EndRoundSubNotAtLevelEnd"),
|
TextManager.Get(GameMain.GameSession.GameMode is CampaignMode ? "PauseMenuReturnToServerLobbyVerification" : "EndRoundSubNotAtLevelEnd"),
|
||||||
@@ -2343,6 +2409,21 @@ namespace Barotrauma
|
|||||||
float aspectRatio = HorizontalAspectRatio;
|
float aspectRatio = HorizontalAspectRatio;
|
||||||
return aspectRatio > 1.3f && aspectRatio < 1.4f;
|
return aspectRatio > 1.3f && aspectRatio < 1.4f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void SetSavingIndicatorState(bool enabled)
|
||||||
|
{
|
||||||
|
if (enabled)
|
||||||
|
{
|
||||||
|
timeUntilSavingIndicatorDisabled = null;
|
||||||
|
}
|
||||||
|
isSavingIndicatorEnabled = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void DisableSavingIndicatorDelayed(float delay = 3.0f)
|
||||||
|
{
|
||||||
|
if (!isSavingIndicatorEnabled) { return; }
|
||||||
|
timeUntilSavingIndicatorDisabled = delay;
|
||||||
|
}
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,6 +77,12 @@ namespace Barotrauma
|
|||||||
return RectTransform.IsParentOf(component.RectTransform, recursive);
|
return RectTransform.IsParentOf(component.RectTransform, recursive);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool IsChildOf(GUIComponent component, bool recursive = true)
|
||||||
|
{
|
||||||
|
if (component == null) { return false; }
|
||||||
|
return RectTransform.IsChildOf(component.RectTransform, recursive);
|
||||||
|
}
|
||||||
|
|
||||||
public virtual void RemoveChild(GUIComponent child)
|
public virtual void RemoveChild(GUIComponent child)
|
||||||
{
|
{
|
||||||
if (child == null) { return; }
|
if (child == null) { return; }
|
||||||
@@ -705,6 +711,29 @@ namespace Barotrauma
|
|||||||
if (!Visible) return;
|
if (!Visible) return;
|
||||||
DrawToolTip(spriteBatch, ToolTip, GUI.MouseOn.Rect, TooltipRichTextData);
|
DrawToolTip(spriteBatch, ToolTip, GUI.MouseOn.Rect, TooltipRichTextData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void DrawToolTip(SpriteBatch spriteBatch, string toolTip, Vector2 pos, List<RichTextData> richTextData = null)
|
||||||
|
{
|
||||||
|
if (Tutorials.Tutorial.ContentRunning) { return; }
|
||||||
|
|
||||||
|
int width = (int)(400 * GUI.Scale);
|
||||||
|
int height = (int)(18 * GUI.Scale);
|
||||||
|
Point padding = new Point((int)(10 * GUI.Scale));
|
||||||
|
|
||||||
|
if (toolTipBlock == null || (string)toolTipBlock.userData != toolTip)
|
||||||
|
{
|
||||||
|
toolTipBlock = new GUITextBlock(new RectTransform(new Point(width, height), null), richTextData, toolTip, font: GUI.SmallFont, wrap: true, style: "GUIToolTip");
|
||||||
|
toolTipBlock.RectTransform.NonScaledSize = new Point(
|
||||||
|
(int)(GUI.SmallFont.MeasureString(toolTipBlock.WrappedText).X + padding.X + toolTipBlock.Padding.X + toolTipBlock.Padding.Z),
|
||||||
|
(int)(GUI.SmallFont.MeasureString(toolTipBlock.WrappedText).Y + padding.Y + toolTipBlock.Padding.Y + toolTipBlock.Padding.W));
|
||||||
|
toolTipBlock.userData = toolTip;
|
||||||
|
}
|
||||||
|
|
||||||
|
toolTipBlock.RectTransform.AbsoluteOffset = pos.ToPoint();
|
||||||
|
toolTipBlock.SetTextPos();
|
||||||
|
|
||||||
|
toolTipBlock.DrawManually(spriteBatch);
|
||||||
|
}
|
||||||
|
|
||||||
public static void DrawToolTip(SpriteBatch spriteBatch, string toolTip, Rectangle targetElement, List<RichTextData> richTextData = null)
|
public static void DrawToolTip(SpriteBatch spriteBatch, string toolTip, Rectangle targetElement, List<RichTextData> richTextData = null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,292 @@
|
|||||||
|
#nullable enable
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Barotrauma.Extensions;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
|
||||||
|
namespace Barotrauma
|
||||||
|
{
|
||||||
|
struct ContextMenuOption
|
||||||
|
{
|
||||||
|
public string Label;
|
||||||
|
public Action OnSelected;
|
||||||
|
public ContextMenuOption[]? SubOptions;
|
||||||
|
public bool IsEnabled;
|
||||||
|
public string Tooltip;
|
||||||
|
|
||||||
|
// Creates a regular context menu
|
||||||
|
public ContextMenuOption(string label, bool isEnabled, Action onSelected)
|
||||||
|
{
|
||||||
|
Label = TextManager.Get(label, returnNull: true) ?? label;
|
||||||
|
OnSelected = onSelected;
|
||||||
|
IsEnabled = isEnabled;
|
||||||
|
SubOptions = null;
|
||||||
|
Tooltip = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a option with a sub context menu
|
||||||
|
public ContextMenuOption(string label, bool isEnabled, params ContextMenuOption[] options): this(label, isEnabled, () => { })
|
||||||
|
{
|
||||||
|
SubOptions = options;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class GUIContextMenu : GUIComponent
|
||||||
|
{
|
||||||
|
public static GUIContextMenu? CurrentContextMenu;
|
||||||
|
|
||||||
|
private readonly Dictionary<ContextMenuOption, GUITextBlock> Options = new Dictionary<ContextMenuOption, GUITextBlock>();
|
||||||
|
private GUIContextMenu? SubMenu;
|
||||||
|
public readonly GUITextBlock? HeaderLabel;
|
||||||
|
public GUITextBlock? ParentOption;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a context menu. This constructor does not make the context menu active.
|
||||||
|
/// Use <see cref="CreateContextMenu(Barotrauma.ContextMenuOption[])"/> to make right click context menus.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="position">Position at which to create the context menu</param>
|
||||||
|
/// <param name="header">Header text</param>
|
||||||
|
/// <param name="style">Background style</param>
|
||||||
|
/// <param name="options">list of context menu options</param>
|
||||||
|
public GUIContextMenu(Vector2? position, string header, string style, params ContextMenuOption[] options) : base(style, new RectTransform(Point.Zero, GUI.Canvas))
|
||||||
|
{
|
||||||
|
Vector2 pos = position ?? PlayerInput.MousePosition;
|
||||||
|
ScalableFont headerFont = GUI.SubHeadingFont;
|
||||||
|
ScalableFont font = GUI.SmallFont; // font the context menu options use
|
||||||
|
Vector4 padding = new Vector4(4), headerPadding = new Vector4(8);
|
||||||
|
int horizontalPadding = (int) (padding.X + padding.Z), verticalPadding = (int) (padding.Y + padding.W);
|
||||||
|
bool hasHeader = !string.IsNullOrWhiteSpace(header);
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Estimate the size of the context menu
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Dictionary<ContextMenuOption, Vector2> optionsAndSizes = new Dictionary<ContextMenuOption, Vector2>();
|
||||||
|
|
||||||
|
// estimate how big the context menu needs to be
|
||||||
|
Point estimatedSize = new Point(horizontalPadding, verticalPadding);
|
||||||
|
|
||||||
|
if (hasHeader)
|
||||||
|
{
|
||||||
|
InflateSize(ref estimatedSize, header, headerFont);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (ContextMenuOption option in options)
|
||||||
|
{
|
||||||
|
Vector2 optionSize = InflateSize(ref estimatedSize, option.Label, font);
|
||||||
|
optionsAndSizes.Add(option, optionSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
// it's better to overestimate the size since it's going to be cropped anyways
|
||||||
|
estimatedSize = estimatedSize.Multiply(1.2f);
|
||||||
|
|
||||||
|
RectTransform.NonScaledSize = estimatedSize;
|
||||||
|
RectTransform.AbsoluteOffset = pos.ToPoint();
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Construct the GUI elements
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
GUILayoutGroup background = new GUILayoutGroup(new RectTransform(Vector2.One, RectTransform, Anchor.Center));
|
||||||
|
|
||||||
|
if (hasHeader)
|
||||||
|
{
|
||||||
|
HeaderLabel = new GUITextBlock(new RectTransform(new Vector2(1f, 0.2f), background.RectTransform), header, font: headerFont) { Padding = headerPadding };
|
||||||
|
}
|
||||||
|
|
||||||
|
GUIListBox optionList = new GUIListBox(new RectTransform(new Vector2(1f, hasHeader ? 0.8f : 1f), background.RectTransform), style: null)
|
||||||
|
{
|
||||||
|
AutoHideScrollBar = false,
|
||||||
|
ScrollBarVisible = false,
|
||||||
|
Padding = hasHeader ? new Vector4(4, 0, 4, 4) : padding
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (var (option, size) in optionsAndSizes)
|
||||||
|
{
|
||||||
|
GUITextBlock optionElement = new GUITextBlock(new RectTransform(size.ToPoint(), optionList.Content.RectTransform), option.Label, font: font)
|
||||||
|
{
|
||||||
|
UserData = option,
|
||||||
|
Enabled = option.IsEnabled
|
||||||
|
};
|
||||||
|
Options.Add(option, optionElement);
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(option.Tooltip) && optionElement.Enabled)
|
||||||
|
{
|
||||||
|
optionElement.ToolTip = option.Tooltip;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!option.IsEnabled)
|
||||||
|
{
|
||||||
|
optionElement.TextColor *= 0.5f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Positioning and cropping the context menu
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
List<GUIComponent> children = optionList.Content.Children.ToList();
|
||||||
|
|
||||||
|
// Resize all children to the size of their text
|
||||||
|
foreach (GUITextBlock block in children.Where(c => c is GUITextBlock).Cast<GUITextBlock>())
|
||||||
|
{
|
||||||
|
block.RectTransform.NonScaledSize = new Point((int) (block.TextSize.X + (block.Padding.X + block.Padding.Z)), (int) (18 * GUI.Scale));
|
||||||
|
}
|
||||||
|
|
||||||
|
int largestWidth = children.Max(c => c.Rect.Width + horizontalPadding);
|
||||||
|
|
||||||
|
// if the header is bigger than any of the options then overwrite
|
||||||
|
if (HeaderLabel != null)
|
||||||
|
{
|
||||||
|
RectTransform headerTransform = HeaderLabel.RectTransform;
|
||||||
|
headerTransform.MinSize = new Point((int) (HeaderLabel.TextSize.X + (headerPadding.X + headerPadding.Z)), headerTransform.NonScaledSize.Y);
|
||||||
|
if (largestWidth < headerTransform.MinSize.X)
|
||||||
|
{
|
||||||
|
largestWidth = headerTransform.MinSize.X;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// resize all children to the size of the longest element
|
||||||
|
foreach (GUIComponent c in children)
|
||||||
|
{
|
||||||
|
c.RectTransform.MinSize = new Point(largestWidth, c.Rect.Height);
|
||||||
|
}
|
||||||
|
|
||||||
|
// the cropped size of the option list
|
||||||
|
Point newSize = new Point(largestWidth, children.Sum(c => c.Rect.Height) + verticalPadding);
|
||||||
|
// resize the menu itself taking into account the option menus relative Y size
|
||||||
|
RectTransform.NonScaledSize = new Point(newSize.X, (int) (newSize.Y / optionList.RectTransform.RelativeSize.Y));
|
||||||
|
optionList.RectTransform.NonScaledSize = newSize;
|
||||||
|
|
||||||
|
// move the context menu if it would go outside of screen
|
||||||
|
if (RectTransform.Rect.Bottom > GameMain.GraphicsHeight)
|
||||||
|
{
|
||||||
|
Rectangle rect = RectTransform.Rect;
|
||||||
|
RectTransform.AbsoluteOffset = new Point(rect.X, rect.Y - rect.Height);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RectTransform.Rect.Right > GameMain.GraphicsWidth)
|
||||||
|
{
|
||||||
|
Rectangle rect = RectTransform.Rect;
|
||||||
|
RectTransform.AbsoluteOffset = new Point(rect.X - rect.Width, rect.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
background.Recalculate();
|
||||||
|
|
||||||
|
optionList.OnSelected = OnSelected;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GUIContextMenu CreateContextMenu(params ContextMenuOption[] options) => CreateContextMenu(PlayerInput.MousePosition, string.Empty, null, options);
|
||||||
|
|
||||||
|
public static GUIContextMenu CreateContextMenu(Vector2? pos, string header, Color? headerColor, params ContextMenuOption[] options)
|
||||||
|
{
|
||||||
|
GUIContextMenu menu = new GUIContextMenu(pos,header, "GUIToolTip", options);
|
||||||
|
if (headerColor != null)
|
||||||
|
{
|
||||||
|
menu.HeaderLabel?.OverrideTextColor(headerColor.Value);
|
||||||
|
}
|
||||||
|
CurrentContextMenu = menu;
|
||||||
|
return menu;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool OnSelected(GUIComponent _, object data)
|
||||||
|
{
|
||||||
|
if (data is ContextMenuOption option && option.IsEnabled)
|
||||||
|
{
|
||||||
|
CurrentContextMenu = null;
|
||||||
|
option.OnSelected();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Inflates a point by the size of the text
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="size">Pint to resize</param>
|
||||||
|
/// <param name="label">String whose size to inflate by</param>
|
||||||
|
/// <param name="font">What font to use</param>
|
||||||
|
/// <returns>The size of the text</returns>
|
||||||
|
private Vector2 InflateSize(ref Point size, string label, ScalableFont font)
|
||||||
|
{
|
||||||
|
Vector2 textSize = font.MeasureString(label);
|
||||||
|
size.X = Math.Max((int) Math.Ceiling(textSize.X), size.X);
|
||||||
|
size.Y += (int) Math.Ceiling(textSize.Y);
|
||||||
|
return textSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Update(float deltaTime)
|
||||||
|
{
|
||||||
|
base.Update(deltaTime);
|
||||||
|
|
||||||
|
// keep the parent highlighted
|
||||||
|
if (ParentOption != null)
|
||||||
|
{
|
||||||
|
ParentOption.State = ComponentState.Hover;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SubMenu != null && !SubMenu.IsMouseOver())
|
||||||
|
{
|
||||||
|
SubMenu = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var (option, textBlock) in Options)
|
||||||
|
{
|
||||||
|
// Create a new sub context menu if hovering over an option with sub options
|
||||||
|
if (GUI.MouseOn != textBlock) { continue; }
|
||||||
|
if (option.IsEnabled && option.SubOptions is { } subOptions && subOptions.Any())
|
||||||
|
{
|
||||||
|
Vector2 subMenuPos = new Vector2(textBlock.MouseRect.Right + 4, textBlock.MouseRect.Y);
|
||||||
|
SubMenu = new GUIContextMenu(subMenuPos, "", "GUIToolTip", subOptions)
|
||||||
|
{
|
||||||
|
ParentOption = textBlock
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if the mouse cursor is over this context menu or any of its sub menus
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
private bool IsMouseOver()
|
||||||
|
{
|
||||||
|
Rectangle expandedRect = Rect;
|
||||||
|
expandedRect.Inflate(20, 20);
|
||||||
|
|
||||||
|
bool isMouseOn = expandedRect.Contains(PlayerInput.MousePosition);
|
||||||
|
|
||||||
|
if (ParentOption != null)
|
||||||
|
{
|
||||||
|
isMouseOn |= GUI.MouseOn == ParentOption;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recursively check sub context menus
|
||||||
|
if (!isMouseOn && SubMenu != null)
|
||||||
|
{
|
||||||
|
isMouseOn = SubMenu.IsMouseOver();
|
||||||
|
}
|
||||||
|
|
||||||
|
return isMouseOn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void AddToGUIUpdateList(bool ignoreChildren = false, int order = 0)
|
||||||
|
{
|
||||||
|
base.AddToGUIUpdateList(ignoreChildren, order);
|
||||||
|
SubMenu?.AddToGUIUpdateList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void AddActiveToGUIUpdateList()
|
||||||
|
{
|
||||||
|
if (CurrentContextMenu != null && !CurrentContextMenu.IsMouseOver())
|
||||||
|
{
|
||||||
|
CurrentContextMenu = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
CurrentContextMenu?.AddToGUIUpdateList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -194,6 +194,8 @@ namespace Barotrauma
|
|||||||
public bool ScrollBarEnabled { get; set; } = true;
|
public bool ScrollBarEnabled { get; set; } = true;
|
||||||
public bool KeepSpaceForScrollBar { get; set; }
|
public bool KeepSpaceForScrollBar { get; set; }
|
||||||
|
|
||||||
|
public bool CanTakeKeyBoardFocus { get; set; } = true;
|
||||||
|
|
||||||
public bool ScrollBarVisible
|
public bool ScrollBarVisible
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -214,7 +216,22 @@ namespace Barotrauma
|
|||||||
public bool AutoHideScrollBar { get; set; } = true;
|
public bool AutoHideScrollBar { get; set; } = true;
|
||||||
private bool IsScrollBarOnDefaultSide { get; set; }
|
private bool IsScrollBarOnDefaultSide { get; set; }
|
||||||
|
|
||||||
public bool CanDragElements { get; set; } = false;
|
public bool CanDragElements
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return canDragElements;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == false && canDragElements && draggedElement != null)
|
||||||
|
{
|
||||||
|
draggedElement = null;
|
||||||
|
}
|
||||||
|
canDragElements = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private bool canDragElements = false;
|
||||||
private GUIComponent draggedElement;
|
private GUIComponent draggedElement;
|
||||||
private Rectangle draggedReferenceRectangle;
|
private Rectangle draggedReferenceRectangle;
|
||||||
private Point draggedReferenceOffset;
|
private Point draggedReferenceOffset;
|
||||||
@@ -223,9 +240,12 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private bool scheduledScroll = false;
|
private bool scheduledScroll = false;
|
||||||
|
|
||||||
|
private readonly bool isHorizontal;
|
||||||
|
|
||||||
/// <param name="isScrollBarOnDefaultSide">For horizontal listbox, default side is on the bottom. For vertical, it's on the right.</param>
|
/// <param name="isScrollBarOnDefaultSide">For horizontal listbox, default side is on the bottom. For vertical, it's on the right.</param>
|
||||||
public GUIListBox(RectTransform rectT, bool isHorizontal = false, Color? color = null, string style = "", bool isScrollBarOnDefaultSide = true, bool useMouseDownToSelect = false) : base(style, rectT)
|
public GUIListBox(RectTransform rectT, bool isHorizontal = false, Color? color = null, string style = "", bool isScrollBarOnDefaultSide = true, bool useMouseDownToSelect = false) : base(style, rectT)
|
||||||
{
|
{
|
||||||
|
this.isHorizontal = isHorizontal;
|
||||||
HoverCursor = CursorState.Hand;
|
HoverCursor = CursorState.Hand;
|
||||||
CanBeFocused = true;
|
CanBeFocused = true;
|
||||||
selected = new List<GUIComponent>();
|
selected = new List<GUIComponent>();
|
||||||
@@ -454,22 +474,42 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
draggedElement.RectTransform.AbsoluteOffset = draggedReferenceOffset + new Point(0, (int)PlayerInput.MousePosition.Y - draggedReferenceRectangle.Center.Y);
|
draggedElement.RectTransform.AbsoluteOffset = isHorizontal ?
|
||||||
|
draggedReferenceOffset + new Point((int)PlayerInput.MousePosition.X - draggedReferenceRectangle.Center.X, 0) :
|
||||||
|
draggedReferenceOffset + new Point(0, (int)PlayerInput.MousePosition.Y - draggedReferenceRectangle.Center.Y);
|
||||||
|
|
||||||
int index = Content.RectTransform.GetChildIndex(draggedElement.RectTransform);
|
int index = Content.RectTransform.GetChildIndex(draggedElement.RectTransform);
|
||||||
int currIndex = index;
|
int currIndex = index;
|
||||||
|
|
||||||
while (currIndex > 0 && PlayerInput.MousePosition.Y < draggedReferenceRectangle.Top)
|
if (isHorizontal)
|
||||||
{
|
{
|
||||||
currIndex--;
|
while (currIndex > 0 && PlayerInput.MousePosition.X < draggedReferenceRectangle.Left)
|
||||||
draggedReferenceRectangle.Y -= draggedReferenceRectangle.Height;
|
{
|
||||||
draggedReferenceOffset.Y -= draggedReferenceRectangle.Height;
|
currIndex--;
|
||||||
|
draggedReferenceRectangle.X -= draggedReferenceRectangle.Width;
|
||||||
|
draggedReferenceOffset.X -= draggedReferenceRectangle.Width;
|
||||||
|
}
|
||||||
|
while (currIndex < Content.CountChildren - 1 && PlayerInput.MousePosition.X > draggedReferenceRectangle.Right)
|
||||||
|
{
|
||||||
|
currIndex++;
|
||||||
|
draggedReferenceRectangle.X += draggedReferenceRectangle.Width;
|
||||||
|
draggedReferenceOffset.X += draggedReferenceRectangle.Width;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
while (currIndex < Content.CountChildren - 1 && PlayerInput.MousePosition.Y > draggedReferenceRectangle.Bottom)
|
else
|
||||||
{
|
{
|
||||||
currIndex++;
|
while (currIndex > 0 && PlayerInput.MousePosition.Y < draggedReferenceRectangle.Top)
|
||||||
draggedReferenceRectangle.Y += draggedReferenceRectangle.Height;
|
{
|
||||||
draggedReferenceOffset.Y += draggedReferenceRectangle.Height;
|
currIndex--;
|
||||||
|
draggedReferenceRectangle.Y -= draggedReferenceRectangle.Height;
|
||||||
|
draggedReferenceOffset.Y -= draggedReferenceRectangle.Height;
|
||||||
|
}
|
||||||
|
while (currIndex < Content.CountChildren - 1 && PlayerInput.MousePosition.Y > draggedReferenceRectangle.Bottom)
|
||||||
|
{
|
||||||
|
currIndex++;
|
||||||
|
draggedReferenceRectangle.Y += draggedReferenceRectangle.Height;
|
||||||
|
draggedReferenceOffset.Y += draggedReferenceRectangle.Height;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currIndex != index)
|
if (currIndex != index)
|
||||||
@@ -853,7 +893,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If one of the children is the subscriber, we don't want to register, because it will unregister the child.
|
// If one of the children is the subscriber, we don't want to register, because it will unregister the child.
|
||||||
if (takeKeyBoardFocus && RectTransform.GetAllChildren().None(rt => rt.GUIComponent == GUI.KeyboardDispatcher.Subscriber))
|
if (takeKeyBoardFocus && CanTakeKeyBoardFocus && RectTransform.GetAllChildren().None(rt => rt.GUIComponent == GUI.KeyboardDispatcher.Subscriber))
|
||||||
{
|
{
|
||||||
Selected = true;
|
Selected = true;
|
||||||
GUI.KeyboardDispatcher.Subscriber = this;
|
GUI.KeyboardDispatcher.Subscriber = this;
|
||||||
@@ -943,9 +983,10 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public override void RemoveChild(GUIComponent child)
|
public override void RemoveChild(GUIComponent child)
|
||||||
{
|
{
|
||||||
if (child == null) { return; }
|
if (child == null) { return; }
|
||||||
child.RectTransform.Parent = null;
|
child.RectTransform.Parent = null;
|
||||||
if (selected.Contains(child)) selected.Remove(child);
|
if (selected.Contains(child)) { selected.Remove(child); }
|
||||||
|
if (draggedElement == child) { draggedElement = null; }
|
||||||
UpdateScrollBarSize();
|
UpdateScrollBarSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Barotrauma.Networking;
|
using Barotrauma.Networking;
|
||||||
|
using Barotrauma.Extensions;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
@@ -22,11 +23,11 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
Default,
|
Default,
|
||||||
InGame,
|
InGame,
|
||||||
Vote
|
Vote,
|
||||||
|
Hint
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<GUIButton> Buttons { get; private set; } = new List<GUIButton>();
|
public List<GUIButton> Buttons { get; private set; } = new List<GUIButton>();
|
||||||
//public GUIFrame BackgroundFrame { get; private set; }
|
|
||||||
public GUILayoutGroup Content { get; private set; }
|
public GUILayoutGroup Content { get; private set; }
|
||||||
public GUIFrame InnerFrame { get; private set; }
|
public GUIFrame InnerFrame { get; private set; }
|
||||||
public GUITextBlock Header { get; private set; }
|
public GUITextBlock Header { get; private set; }
|
||||||
@@ -58,8 +59,6 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public bool AutoClose;
|
public bool AutoClose;
|
||||||
|
|
||||||
private readonly bool alwaysVisible;
|
|
||||||
|
|
||||||
private float openState;
|
private float openState;
|
||||||
private float iconState;
|
private float iconState;
|
||||||
private bool iconSwitching;
|
private bool iconSwitching;
|
||||||
@@ -77,10 +76,17 @@ namespace Barotrauma
|
|||||||
this.Buttons[0].OnClicked = Close;
|
this.Buttons[0].OnClicked = Close;
|
||||||
}
|
}
|
||||||
|
|
||||||
public GUIMessageBox(string headerText, string text, string[] buttons, Vector2? relativeSize = null, Point? minSize = null, Alignment textAlignment = Alignment.TopLeft, Type type = Type.Default, string tag = "", Sprite icon = null, string iconStyle = "", Sprite backgroundIcon = null)
|
public GUIMessageBox(string headerText, string text, string[] buttons, Vector2? relativeSize = null, Point? minSize = null, Alignment textAlignment = Alignment.TopLeft, Type type = Type.Default, string tag = "", Sprite icon = null, string iconStyle = "", Sprite backgroundIcon = null, bool parseRichText = false)
|
||||||
: base(new RectTransform(GUI.Canvas.RelativeSize, GUI.Canvas, Anchor.Center), style: GUI.Style.GetComponentStyle("GUIMessageBox." + type) != null ? "GUIMessageBox." + type : "GUIMessageBox")
|
: base(new RectTransform(GUI.Canvas.RelativeSize, GUI.Canvas, Anchor.Center), style: GUI.Style.GetComponentStyle("GUIMessageBox." + type) != null ? "GUIMessageBox." + type : "GUIMessageBox")
|
||||||
{
|
{
|
||||||
int width = (int)(DefaultWidth * (type == Type.Default ? 1.0f : 1.5f)), height = 0;
|
int width = (int)(DefaultWidth * type switch
|
||||||
|
{
|
||||||
|
Type.Default => 1.0f,
|
||||||
|
Type.Hint => 1.25f,
|
||||||
|
_ => 1.5f
|
||||||
|
});
|
||||||
|
int height = 0;
|
||||||
|
|
||||||
if (relativeSize.HasValue)
|
if (relativeSize.HasValue)
|
||||||
{
|
{
|
||||||
width = (int)(GameMain.GraphicsWidth * relativeSize.Value.X);
|
width = (int)(GameMain.GraphicsWidth * relativeSize.Value.X);
|
||||||
@@ -107,6 +113,7 @@ namespace Barotrauma
|
|||||||
Anchor anchor = type switch
|
Anchor anchor = type switch
|
||||||
{
|
{
|
||||||
Type.InGame => Anchor.TopCenter,
|
Type.InGame => Anchor.TopCenter,
|
||||||
|
Type.Hint => Anchor.TopRight,
|
||||||
Type.Vote => Anchor.TopRight,
|
Type.Vote => Anchor.TopRight,
|
||||||
_ => Anchor.Center
|
_ => Anchor.Center
|
||||||
};
|
};
|
||||||
@@ -127,13 +134,13 @@ namespace Barotrauma
|
|||||||
Content = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.85f), InnerFrame.RectTransform, Anchor.Center)) { AbsoluteSpacing = 5 };
|
Content = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.85f), InnerFrame.RectTransform, Anchor.Center)) { AbsoluteSpacing = 5 };
|
||||||
|
|
||||||
Header = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), Content.RectTransform),
|
Header = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), Content.RectTransform),
|
||||||
headerText, font: GUI.SubHeadingFont, textAlignment: Alignment.Center, wrap: true);
|
headerText, font: GUI.SubHeadingFont, textAlignment: Alignment.Center, wrap: true, parseRichText: parseRichText);
|
||||||
GUI.Style.Apply(Header, "", this);
|
GUI.Style.Apply(Header, "", this);
|
||||||
Header.RectTransform.MinSize = new Point(0, Header.Rect.Height);
|
Header.RectTransform.MinSize = new Point(0, Header.Rect.Height);
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(text))
|
if (!string.IsNullOrWhiteSpace(text))
|
||||||
{
|
{
|
||||||
Text = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), Content.RectTransform), text, textAlignment: textAlignment, wrap: true);
|
Text = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), Content.RectTransform), text, textAlignment: textAlignment, wrap: true, parseRichText: parseRichText);
|
||||||
GUI.Style.Apply(Text, "", this);
|
GUI.Style.Apply(Text, "", this);
|
||||||
Text.RectTransform.NonScaledSize = Text.RectTransform.MinSize = Text.RectTransform.MaxSize =
|
Text.RectTransform.NonScaledSize = Text.RectTransform.MinSize = Text.RectTransform.MaxSize =
|
||||||
new Point(Text.Rect.Width, Text.Rect.Height);
|
new Point(Text.Rect.Width, Text.Rect.Height);
|
||||||
@@ -180,7 +187,6 @@ namespace Barotrauma
|
|||||||
else if (type == Type.InGame)
|
else if (type == Type.InGame)
|
||||||
{
|
{
|
||||||
InnerFrame.RectTransform.AbsoluteOffset = new Point(0, GameMain.GraphicsHeight);
|
InnerFrame.RectTransform.AbsoluteOffset = new Point(0, GameMain.GraphicsHeight);
|
||||||
alwaysVisible = true;
|
|
||||||
CanBeFocused = false;
|
CanBeFocused = false;
|
||||||
AutoClose = true;
|
AutoClose = true;
|
||||||
GUI.Style.Apply(InnerFrame, "", this);
|
GUI.Style.Apply(InnerFrame, "", this);
|
||||||
@@ -235,13 +241,13 @@ namespace Barotrauma
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Header = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), Content.RectTransform), headerText, wrap: true);
|
Header = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), Content.RectTransform), headerText, wrap: true, parseRichText: parseRichText);
|
||||||
GUI.Style.Apply(Header, "", this);
|
GUI.Style.Apply(Header, "", this);
|
||||||
Header.RectTransform.MinSize = new Point(0, Header.Rect.Height);
|
Header.RectTransform.MinSize = new Point(0, Header.Rect.Height);
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(text))
|
if (!string.IsNullOrWhiteSpace(text))
|
||||||
{
|
{
|
||||||
Text = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), Content.RectTransform), text, textAlignment: textAlignment, wrap: true);
|
Text = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), Content.RectTransform), text, textAlignment: textAlignment, wrap: true, parseRichText: parseRichText);
|
||||||
GUI.Style.Apply(Text, "", this);
|
GUI.Style.Apply(Text, "", this);
|
||||||
Content.Recalculate();
|
Content.Recalculate();
|
||||||
Text.RectTransform.NonScaledSize = Text.RectTransform.MinSize = Text.RectTransform.MaxSize =
|
Text.RectTransform.NonScaledSize = Text.RectTransform.MinSize = Text.RectTransform.MaxSize =
|
||||||
@@ -266,30 +272,184 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
Buttons[0].RectTransform.MaxSize = new Point((int)(0.4f * Buttons[0].Rect.Y), Buttons[0].Rect.Y);
|
Buttons[0].RectTransform.MaxSize = new Point((int)(0.4f * Buttons[0].Rect.Y), Buttons[0].Rect.Y);
|
||||||
}
|
}
|
||||||
|
else if (type == Type.Hint)
|
||||||
|
{
|
||||||
|
CanBeFocused = false;
|
||||||
|
GUI.Style.Apply(InnerFrame, "", this);
|
||||||
|
|
||||||
|
Point absoluteSpacing = GUIStyle.ItemFrameMargin.Multiply(1.0f / 5.0f);
|
||||||
|
var verticalLayoutGroup = new GUILayoutGroup(new RectTransform(GetVerticalLayoutGroupSize(), parent: InnerFrame.RectTransform, anchor: Anchor.Center), childAnchor: Anchor.TopCenter)
|
||||||
|
{
|
||||||
|
AbsoluteSpacing = absoluteSpacing.Y,
|
||||||
|
Stretch = true
|
||||||
|
};
|
||||||
|
|
||||||
|
var topHorizontalLayoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.7f), verticalLayoutGroup.RectTransform),
|
||||||
|
isHorizontal: true, childAnchor: Anchor.CenterLeft)
|
||||||
|
{
|
||||||
|
Stretch = true,
|
||||||
|
RelativeSpacing = 0.02f
|
||||||
|
};
|
||||||
|
|
||||||
|
int iconMaxHeight = 0;
|
||||||
|
if (icon != null)
|
||||||
|
{
|
||||||
|
Icon = new GUIImage(new RectTransform(new Vector2(0.15f, 0.95f), topHorizontalLayoutGroup.RectTransform), icon, scaleToFit: true);
|
||||||
|
iconMaxHeight = (int)Icon.Sprite.size.Y;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bool iconStyleDefined = !string.IsNullOrEmpty(iconStyle);
|
||||||
|
Icon = new GUIImage(new RectTransform(new Vector2(0.15f, 0.95f), topHorizontalLayoutGroup.RectTransform),
|
||||||
|
iconStyleDefined ? iconStyle : "GUIButtonInfo", scaleToFit: true);
|
||||||
|
if (!iconStyleDefined)
|
||||||
|
{
|
||||||
|
Icon.Color = Color.Orange;
|
||||||
|
}
|
||||||
|
iconMaxHeight = (int)(Icon.Style.GetDefaultSprite()?.size.Y ?? GUI.yScale * 40);
|
||||||
|
}
|
||||||
|
|
||||||
|
iconMaxHeight = Math.Min((int)(GUI.yScale * 40), iconMaxHeight);
|
||||||
|
int iconMinHeight = Math.Min((int)(GUI.yScale * 40), iconMaxHeight);
|
||||||
|
Icon.RectTransform.MinSize = new Point(Icon.Rect.Width, iconMinHeight);
|
||||||
|
Icon.RectTransform.MaxSize = new Point(Icon.Rect.Width, iconMaxHeight);
|
||||||
|
|
||||||
|
Content = new GUILayoutGroup(new RectTransform(new Vector2(Icon != null ? 0.85f : 1.0f, 1.0f), topHorizontalLayoutGroup.RectTransform))
|
||||||
|
{
|
||||||
|
AbsoluteSpacing = absoluteSpacing.Y,
|
||||||
|
};
|
||||||
|
|
||||||
|
var bottomContainer = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.3f), verticalLayoutGroup.RectTransform), style: null);
|
||||||
|
|
||||||
|
var tickBoxLayoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.67f, 1.0f), bottomContainer.RectTransform, anchor: Anchor.CenterLeft),
|
||||||
|
isHorizontal: true, childAnchor: Anchor.CenterLeft)
|
||||||
|
{
|
||||||
|
Stretch = true,
|
||||||
|
RelativeSpacing = 0.02f
|
||||||
|
};
|
||||||
|
|
||||||
|
var dontShowAgainTickBox = new GUITickBox(new RectTransform(new Vector2(0.5f, 1.0f), tickBoxLayoutGroup.RectTransform),
|
||||||
|
TextManager.Get("hintmessagebox.dontshowagain"))
|
||||||
|
{
|
||||||
|
ToolTip = TextManager.Get("hintmessagebox.dontshowagaintooltip"),
|
||||||
|
UserData = "dontshowagain"
|
||||||
|
};
|
||||||
|
|
||||||
|
//var disableHintsTickBox = new GUITickBox(new RectTransform(new Vector2(0.33f, 1.0f), tickBoxLayoutGroup.RectTransform),
|
||||||
|
// TextManager.Get("hintmessagebox.disablehints"))
|
||||||
|
//{
|
||||||
|
// ToolTip = TextManager.Get("hintmessagebox.disablehintstooltip"),
|
||||||
|
// UserData = "disablehints"
|
||||||
|
//};
|
||||||
|
|
||||||
|
Buttons = new List<GUIButton>(1)
|
||||||
|
{
|
||||||
|
new GUIButton(new RectTransform(new Vector2(0.33f, 1.0f), bottomContainer.RectTransform, Anchor.CenterRight),
|
||||||
|
text: TextManager.Get("hintmessagebox.dismiss"), style: "GUIButtonSmall")
|
||||||
|
{
|
||||||
|
OnClicked = Close
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Header = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), Content.RectTransform), headerText, wrap: true);
|
||||||
|
GUI.Style.Apply(Header, "", this);
|
||||||
|
Header.RectTransform.MinSize = new Point(0, Header.Rect.Height);
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(text))
|
||||||
|
{
|
||||||
|
Text = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), Content.RectTransform), text, textAlignment: textAlignment, wrap: true);
|
||||||
|
GUI.Style.Apply(Text, "", this);
|
||||||
|
Content.Recalculate();
|
||||||
|
Text.RectTransform.NonScaledSize = Text.RectTransform.MinSize = Text.RectTransform.MaxSize =
|
||||||
|
new Point(Text.Rect.Width, Text.Rect.Height);
|
||||||
|
Text.RectTransform.IsFixedSize = true;
|
||||||
|
if (string.IsNullOrWhiteSpace(headerText))
|
||||||
|
{
|
||||||
|
Header.RectTransform.Parent = null;
|
||||||
|
Content.ChildAnchor = Anchor.Center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (height == 0)
|
||||||
|
{
|
||||||
|
height = absoluteSpacing.Y;
|
||||||
|
int upperContainerHeight = absoluteSpacing.Y;
|
||||||
|
if (Header.Rect.Height > 0) { upperContainerHeight += Header.Rect.Height + Content.AbsoluteSpacing; }
|
||||||
|
if (Text != null) { upperContainerHeight += Text.Rect.Height + Content.AbsoluteSpacing; }
|
||||||
|
upperContainerHeight = Math.Max(upperContainerHeight, Icon.Rect.Height);
|
||||||
|
height += upperContainerHeight;
|
||||||
|
height += absoluteSpacing.Y;
|
||||||
|
height += (int)((bottomContainer.RectTransform.RelativeSize.Y / topHorizontalLayoutGroup.RectTransform.RelativeSize.Y) * upperContainerHeight);
|
||||||
|
height += absoluteSpacing.Y;
|
||||||
|
if (minSize.HasValue) { height = Math.Max(height, minSize.Value.Y); }
|
||||||
|
|
||||||
|
InnerFrame.RectTransform.NonScaledSize = new Point(InnerFrame.Rect.Width, height);
|
||||||
|
verticalLayoutGroup.RectTransform.NonScaledSize = GetVerticalLayoutGroupSize();
|
||||||
|
verticalLayoutGroup.Recalculate();
|
||||||
|
topHorizontalLayoutGroup.Recalculate();
|
||||||
|
Content.Recalculate();
|
||||||
|
tickBoxLayoutGroup.Recalculate();
|
||||||
|
}
|
||||||
|
|
||||||
|
InnerFrame.RectTransform.AbsoluteOffset = new Point(GUI.IntScale(64), -InnerFrame.Rect.Height);
|
||||||
|
|
||||||
|
Point GetVerticalLayoutGroupSize()
|
||||||
|
{
|
||||||
|
return InnerFrame.Rect.Size - absoluteSpacing.Multiply(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MessageBoxes.Add(this);
|
MessageBoxes.Add(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use to create a message box of Hint type
|
||||||
|
/// </summary>
|
||||||
|
public GUIMessageBox(string hintIdentifier, string text, Sprite icon) : this("", text, new string[0], textAlignment: Alignment.CenterLeft, type: Type.Hint, icon: icon)
|
||||||
|
{
|
||||||
|
if (InnerFrame.FindChild("dontshowagain", recursive: true) is GUITickBox dontShowAgainTickBox)
|
||||||
|
{
|
||||||
|
dontShowAgainTickBox.OnSelected = HintManager.OnDontShowAgain;
|
||||||
|
dontShowAgainTickBox.UserData = hintIdentifier;
|
||||||
|
}
|
||||||
|
if (InnerFrame.FindChild("disablehints", recursive: true) is GUITickBox disableHintsTickBox)
|
||||||
|
{
|
||||||
|
disableHintsTickBox.OnSelected = HintManager.OnDisableHints;
|
||||||
|
disableHintsTickBox.UserData = hintIdentifier;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Type[] messageBoxTypes;
|
||||||
|
|
||||||
public static void AddActiveToGUIUpdateList()
|
public static void AddActiveToGUIUpdateList()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < MessageBoxes.Count; i++)
|
messageBoxTypes ??= (Type[])Enum.GetValues(typeof(Type));
|
||||||
|
|
||||||
|
foreach (var type in messageBoxTypes)
|
||||||
{
|
{
|
||||||
if (MessageBoxes[i] is GUIMessageBox alwaysVisibleMsgBox && alwaysVisibleMsgBox.alwaysVisible)
|
// Don't display hints when HUD is disabled
|
||||||
|
if (type == Type.Hint && GUI.DisableHUD) { continue; }
|
||||||
|
|
||||||
|
for (int i = 0; i < MessageBoxes.Count; i++)
|
||||||
{
|
{
|
||||||
alwaysVisibleMsgBox.AddToGUIUpdateList();
|
if (MessageBoxes[i] == null) { continue; }
|
||||||
break;
|
if (!(MessageBoxes[i] is GUIMessageBox messageBox))
|
||||||
}
|
{
|
||||||
}
|
if (type == Type.Default)
|
||||||
for (int i = MessageBoxes.Count - 1; i >= 0; i--)
|
{
|
||||||
{
|
// Message box not of type GUIMessageBox is likely the round summary
|
||||||
if (MessageBoxes[i].UserData as string == "verificationprompt" ||
|
MessageBoxes[i].AddToGUIUpdateList();
|
||||||
MessageBoxes[i].UserData as string == "bugreporter")
|
break;
|
||||||
{
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!(MessageBoxes[i] is GUIMessageBox msgBox) || !msgBox.alwaysVisible)
|
if (messageBox.type != type) { continue; }
|
||||||
{
|
|
||||||
MessageBoxes[i].AddToGUIUpdateList();
|
// These are handled separately in GUI.HandlePersistingElements()
|
||||||
|
if (MessageBoxes[i].UserData as string == "verificationprompt") { continue; }
|
||||||
|
if (MessageBoxes[i].UserData as string == "bugreporter") { continue; }
|
||||||
|
|
||||||
|
messageBox.AddToGUIUpdateList();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -337,11 +497,21 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == Type.InGame)
|
if (type == Type.InGame || type == Type.Hint)
|
||||||
{
|
{
|
||||||
Vector2 initialPos = new Vector2(0.0f, GameMain.GraphicsHeight);
|
Vector2 initialPos, defaultPos, endPos;
|
||||||
Vector2 defaultPos = new Vector2(0.0f, HUDLayoutSettings.InventoryAreaLower.Y - InnerFrame.Rect.Height - 20 * GUI.Scale);
|
if (type == Type.InGame)
|
||||||
Vector2 endPos = new Vector2(GameMain.GraphicsWidth, defaultPos.Y);
|
{
|
||||||
|
initialPos = new Vector2(0.0f, GameMain.GraphicsHeight);
|
||||||
|
defaultPos = new Vector2(0.0f, HUDLayoutSettings.InventoryAreaLower.Y - InnerFrame.Rect.Height - 20 * GUI.Scale);
|
||||||
|
endPos = new Vector2(GameMain.GraphicsWidth, defaultPos.Y);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
initialPos = new Vector2(GUI.IntScale(64), -InnerFrame.Rect.Height);
|
||||||
|
defaultPos = new Vector2(initialPos.X, HUDLayoutSettings.ButtonAreaTop.Height + GUI.IntScale(64));
|
||||||
|
endPos = new Vector2(-InnerFrame.Rect.Width, defaultPos.Y);
|
||||||
|
}
|
||||||
|
|
||||||
if (!closing)
|
if (!closing)
|
||||||
{
|
{
|
||||||
@@ -428,7 +598,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public void Close()
|
public void Close()
|
||||||
{
|
{
|
||||||
if (type == Type.InGame)
|
if (type == Type.InGame || type == Type.Hint)
|
||||||
{
|
{
|
||||||
closing = true;
|
closing = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,11 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public readonly Sprite[] CursorSprite = new Sprite[7];
|
public readonly Sprite[] CursorSprite = new Sprite[7];
|
||||||
|
|
||||||
|
public UISprite RadiationSprite { get; private set; }
|
||||||
|
public SpriteSheet RadiationAnimSpriteSheet { get; private set; }
|
||||||
|
|
||||||
|
public SpriteSheet SavingIndicator { get; private set; }
|
||||||
|
|
||||||
public UISprite UIGlow { get; private set; }
|
public UISprite UIGlow { get; private set; }
|
||||||
public UISprite UIGlowCircular { get; private set; }
|
public UISprite UIGlowCircular { get; private set; }
|
||||||
|
|
||||||
@@ -77,6 +82,12 @@ namespace Barotrauma
|
|||||||
public Color TextColorDark { get; private set; } = Color.Black * 0.9f;
|
public Color TextColorDark { get; private set; } = Color.Black * 0.9f;
|
||||||
public Color TextColorDim { get; private set; } = Color.White * 0.6f;
|
public Color TextColorDim { get; private set; } = Color.White * 0.6f;
|
||||||
|
|
||||||
|
public Color ColorReputationVeryLow { get; private set; } = Color.Red;
|
||||||
|
public Color ColorReputationLow { get; private set; } = Color.Orange;
|
||||||
|
public Color ColorReputationNeutral { get; private set; } = Color.White * 0.8f;
|
||||||
|
public Color ColorReputationHigh { get; private set; } = Color.LightBlue;
|
||||||
|
public Color ColorReputationVeryHigh { get; private set; } = Color.Blue;
|
||||||
|
|
||||||
// Inventory
|
// Inventory
|
||||||
public Color EquipmentSlotIconColor { get; private set; } = new Color(99, 70, 64);
|
public Color EquipmentSlotIconColor { get; private set; } = new Color(99, 70, 64);
|
||||||
|
|
||||||
@@ -167,6 +178,21 @@ namespace Barotrauma
|
|||||||
case "textcolor":
|
case "textcolor":
|
||||||
TextColor = subElement.GetAttributeColor("color", TextColor);
|
TextColor = subElement.GetAttributeColor("color", TextColor);
|
||||||
break;
|
break;
|
||||||
|
case "colorreputationverylow":
|
||||||
|
ColorReputationVeryLow = subElement.GetAttributeColor("color", TextColor);
|
||||||
|
break;
|
||||||
|
case "colorreputationlow":
|
||||||
|
ColorReputationLow = subElement.GetAttributeColor("color", TextColor);
|
||||||
|
break;
|
||||||
|
case "colorreputationneutral":
|
||||||
|
ColorReputationNeutral = subElement.GetAttributeColor("color", TextColor);
|
||||||
|
break;
|
||||||
|
case "colorreputationhigh":
|
||||||
|
ColorReputationHigh = subElement.GetAttributeColor("color", TextColor);
|
||||||
|
break;
|
||||||
|
case "colorreputationveryhigh":
|
||||||
|
ColorReputationVeryHigh = subElement.GetAttributeColor("color", TextColor);
|
||||||
|
break;
|
||||||
case "equipmentsloticoncolor":
|
case "equipmentsloticoncolor":
|
||||||
EquipmentSlotIconColor = subElement.GetAttributeColor("color", EquipmentSlotIconColor);
|
EquipmentSlotIconColor = subElement.GetAttributeColor("color", EquipmentSlotIconColor);
|
||||||
break;
|
break;
|
||||||
@@ -209,6 +235,12 @@ namespace Barotrauma
|
|||||||
case "uiglow":
|
case "uiglow":
|
||||||
UIGlow = new UISprite(subElement);
|
UIGlow = new UISprite(subElement);
|
||||||
break;
|
break;
|
||||||
|
case "radiation":
|
||||||
|
RadiationSprite = new UISprite(subElement);
|
||||||
|
break;
|
||||||
|
case "radiationanimspritesheet":
|
||||||
|
RadiationAnimSpriteSheet = new SpriteSheet(subElement);
|
||||||
|
break;
|
||||||
case "uiglowcircular":
|
case "uiglowcircular":
|
||||||
UIGlowCircular = new UISprite(subElement);
|
UIGlowCircular = new UISprite(subElement);
|
||||||
break;
|
break;
|
||||||
@@ -218,6 +250,9 @@ namespace Barotrauma
|
|||||||
case "focusindicator":
|
case "focusindicator":
|
||||||
FocusIndicator = new SpriteSheet(subElement);
|
FocusIndicator = new SpriteSheet(subElement);
|
||||||
break;
|
break;
|
||||||
|
case "savingindicator":
|
||||||
|
SavingIndicator = new SpriteSheet(subElement);
|
||||||
|
break;
|
||||||
case "font":
|
case "font":
|
||||||
Font = LoadFont(subElement, graphicsDevice);
|
Font = LoadFont(subElement, graphicsDevice);
|
||||||
ForceFontUpperCase[Font] = subElement.GetAttributeBool("forceuppercase", false);
|
ForceFontUpperCase[Font] = subElement.GetAttributeBool("forceuppercase", false);
|
||||||
|
|||||||
@@ -259,9 +259,11 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public StrikethroughSettings Strikethrough = null;
|
public StrikethroughSettings Strikethrough = null;
|
||||||
|
|
||||||
private readonly List<RichTextData> richTextData = null;
|
public readonly List<RichTextData> RichTextData = null;
|
||||||
|
|
||||||
private readonly bool hasColorHighlight = false;
|
public bool HasColorHighlight => RichTextData != null;
|
||||||
|
|
||||||
|
public bool OverrideRichTextDataAlpha = true;
|
||||||
|
|
||||||
public struct ClickableArea
|
public struct ClickableArea
|
||||||
{
|
{
|
||||||
@@ -279,7 +281,8 @@ namespace Barotrauma
|
|||||||
/// If the rectT height is set 0, the height is calculated from the text.
|
/// If the rectT height is set 0, the height is calculated from the text.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public GUITextBlock(RectTransform rectT, string text, Color? textColor = null, ScalableFont font = null,
|
public GUITextBlock(RectTransform rectT, string text, Color? textColor = null, ScalableFont font = null,
|
||||||
Alignment textAlignment = Alignment.Left, bool wrap = false, string style = "", Color? color = null, bool playerInput = false)
|
Alignment textAlignment = Alignment.Left, bool wrap = false, string style = "", Color? color = null,
|
||||||
|
bool playerInput = false, bool parseRichText = false)
|
||||||
: base(style, rectT)
|
: base(style, rectT)
|
||||||
{
|
{
|
||||||
if (color.HasValue)
|
if (color.HasValue)
|
||||||
@@ -289,7 +292,12 @@ namespace Barotrauma
|
|||||||
if (textColor.HasValue)
|
if (textColor.HasValue)
|
||||||
{
|
{
|
||||||
OverrideTextColor(textColor.Value);
|
OverrideTextColor(textColor.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (parseRichText)
|
||||||
|
{
|
||||||
|
RichTextData = Barotrauma.RichTextData.GetRichTextData(text, out text);
|
||||||
|
}
|
||||||
|
|
||||||
//if the text is in chinese/korean/japanese and we're not using a CJK-compatible font,
|
//if the text is in chinese/korean/japanese and we're not using a CJK-compatible font,
|
||||||
//use the default CJK font as a fallback
|
//use the default CJK font as a fallback
|
||||||
@@ -318,8 +326,7 @@ namespace Barotrauma
|
|||||||
public GUITextBlock(RectTransform rectT, List<RichTextData> richTextData, string text, Color? textColor = null, ScalableFont font = null, Alignment textAlignment = Alignment.Left, bool wrap = false, string style = "", Color? color = null, bool playerInput = false)
|
public GUITextBlock(RectTransform rectT, List<RichTextData> richTextData, string text, Color? textColor = null, ScalableFont font = null, Alignment textAlignment = Alignment.Left, bool wrap = false, string style = "", Color? color = null, bool playerInput = false)
|
||||||
: this(rectT, text, textColor, font, textAlignment, wrap, style, color, playerInput)
|
: this(rectT, text, textColor, font, textAlignment, wrap, style, color, playerInput)
|
||||||
{
|
{
|
||||||
this.richTextData = richTextData;
|
this.RichTextData = richTextData;
|
||||||
hasColorHighlight = richTextData != null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CalculateHeightFromText(int padding = 0, bool removeExtraSpacing = false)
|
public void CalculateHeightFromText(int padding = 0, bool removeExtraSpacing = false)
|
||||||
@@ -568,8 +575,9 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
base.Update(deltaTime);
|
base.Update(deltaTime);
|
||||||
|
|
||||||
if (ClickableAreas.Any() && (GUI.MouseOn?.IsParentOf(this) ?? true) && Rect.Contains(PlayerInput.MousePosition))
|
if (ClickableAreas.Any() && (GUI.MouseOn?.IsParentOf(this) ?? true))
|
||||||
{
|
{
|
||||||
|
if (!Rect.Contains(PlayerInput.MousePosition)) { return; }
|
||||||
int index = GetCaretIndexFromScreenPos(PlayerInput.MousePosition);
|
int index = GetCaretIndexFromScreenPos(PlayerInput.MousePosition);
|
||||||
foreach (ClickableArea clickableArea in ClickableAreas)
|
foreach (ClickableArea clickableArea in ClickableAreas)
|
||||||
{
|
{
|
||||||
@@ -627,7 +635,7 @@ namespace Barotrauma
|
|||||||
currentTextColor = selectedTextColor;
|
currentTextColor = selectedTextColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hasColorHighlight)
|
if (!HasColorHighlight)
|
||||||
{
|
{
|
||||||
string textToShow = Censor ? censoredText : (Wrap ? wrappedText : text);
|
string textToShow = Censor ? censoredText : (Wrap ? wrappedText : text);
|
||||||
Color colorToShow = currentTextColor * (currentTextColor.A / 255.0f);
|
Color colorToShow = currentTextColor * (currentTextColor.A / 255.0f);
|
||||||
@@ -639,12 +647,15 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
Font.DrawString(spriteBatch, textToShow, pos, colorToShow, 0.0f, origin, TextScale, SpriteEffects.None, textDepth);
|
Font.DrawString(spriteBatch, textToShow, pos, colorToShow, 0.0f, origin, TextScale, SpriteEffects.None, textDepth);
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (OverrideRichTextDataAlpha)
|
||||||
|
{
|
||||||
|
RichTextData.ForEach(rt => rt.Alpha = currentTextColor.A / 255.0f);
|
||||||
|
}
|
||||||
Font.DrawStringWithColors(spriteBatch, Censor ? censoredText : (Wrap ? wrappedText : text), pos,
|
Font.DrawStringWithColors(spriteBatch, Censor ? censoredText : (Wrap ? wrappedText : text), pos,
|
||||||
currentTextColor * (currentTextColor.A / 255.0f), 0.0f, origin, TextScale, SpriteEffects.None, textDepth, richTextData);
|
currentTextColor * (currentTextColor.A / 255.0f), 0.0f, origin, TextScale, SpriteEffects.None, textDepth, RichTextData);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Strikethrough != null)
|
if (Strikethrough != null)
|
||||||
|
|||||||
@@ -626,6 +626,9 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (Text == null) Text = "";
|
if (Text == null) Text = "";
|
||||||
|
|
||||||
|
// Prevent alt gr from triggering any of these as that combination is often needed for special characters
|
||||||
|
if (PlayerInput.IsAltDown()) return;
|
||||||
|
|
||||||
switch (command)
|
switch (command)
|
||||||
{
|
{
|
||||||
case '\b' when !Readonly: //backspace
|
case '\b' when !Readonly: //backspace
|
||||||
@@ -667,7 +670,10 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case (char)0x1: // ctrl-a
|
case (char)0x1: // ctrl-a
|
||||||
SelectAll();
|
if (PlayerInput.IsCtrlDown())
|
||||||
|
{
|
||||||
|
SelectAll();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case (char)0x1A when !Readonly && !SubEditorScreen.IsSubEditor(): // ctrl-z
|
case (char)0x1A when !Readonly && !SubEditorScreen.IsSubEditor(): // ctrl-z
|
||||||
text = memento.Undo();
|
text = memento.Undo();
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
|
|
||||||
int messageAreaWidth = GameMain.GraphicsWidth / 3;
|
int messageAreaWidth = GameMain.GraphicsWidth / 3;
|
||||||
MessageAreaTop = new Rectangle((GameMain.GraphicsWidth - messageAreaWidth) / 2, ButtonAreaTop.Bottom, messageAreaWidth, ButtonAreaTop.Height);
|
MessageAreaTop = new Rectangle((GameMain.GraphicsWidth - messageAreaWidth) / 2, ButtonAreaTop.Bottom + ButtonAreaTop.Height, messageAreaWidth, ButtonAreaTop.Height);
|
||||||
|
|
||||||
bool isFourByThree = GUI.IsFourByThree();
|
bool isFourByThree = GUI.IsFourByThree();
|
||||||
int chatBoxWidth = !isFourByThree ? (int)(475 * GUI.Scale) : (int)(375 * GUI.Scale);
|
int chatBoxWidth = !isFourByThree ? (int)(475 * GUI.Scale) : (int)(375 * GUI.Scale);
|
||||||
@@ -139,7 +139,9 @@ namespace Barotrauma
|
|||||||
int objectiveAnchorOffsetY = (int)(150 * GUI.Scale);
|
int objectiveAnchorOffsetY = (int)(150 * GUI.Scale);
|
||||||
ObjectiveAnchor = new Rectangle(Padding, ChatBoxArea.Y - objectiveAnchorOffsetY, objectiveAnchorWidth, 0);
|
ObjectiveAnchor = new Rectangle(Padding, ChatBoxArea.Y - objectiveAnchorOffsetY, objectiveAnchorWidth, 0);
|
||||||
|
|
||||||
CrewArea = new Rectangle(Padding, Padding, (int)Math.Max(400 * GUI.Scale, 220), ObjectiveAnchor.Top - Padding * 2);
|
int crewAreaY = ButtonAreaTop.Bottom + Padding;
|
||||||
|
int crewAreaHeight = ObjectiveAnchor.Top - Padding - crewAreaY;
|
||||||
|
CrewArea = new Rectangle(Padding, crewAreaY, (int)Math.Max(400 * GUI.Scale, 220), crewAreaHeight);
|
||||||
|
|
||||||
InventoryAreaLower = new Rectangle(ChatBoxArea.Right + Padding * 7, inventoryTopY, GameMain.GraphicsWidth - Padding * 9 - ChatBoxArea.Width, GameMain.GraphicsHeight - inventoryTopY);
|
InventoryAreaLower = new Rectangle(ChatBoxArea.Right + Padding * 7, inventoryTopY, GameMain.GraphicsWidth - Padding * 9 - ChatBoxArea.Width, GameMain.GraphicsHeight - inventoryTopY);
|
||||||
|
|
||||||
|
|||||||
@@ -70,6 +70,14 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
private string selectedTip;
|
private string selectedTip;
|
||||||
|
private List<RichTextData> selectedTipRichTextData;
|
||||||
|
private bool selectedTipRichTextUnparsed;
|
||||||
|
private void SetSelectedTip(string tip)
|
||||||
|
{
|
||||||
|
selectedTip = tip;
|
||||||
|
selectedTipRichTextData = null;
|
||||||
|
selectedTipRichTextUnparsed = true;
|
||||||
|
}
|
||||||
|
|
||||||
private readonly object loadMutex = new object();
|
private readonly object loadMutex = new object();
|
||||||
private float? loadState;
|
private float? loadState;
|
||||||
@@ -115,7 +123,7 @@ namespace Barotrauma
|
|||||||
overlay = TextureLoader.FromFile("Content/UI/LoadingScreenOverlay.png");
|
overlay = TextureLoader.FromFile("Content/UI/LoadingScreenOverlay.png");
|
||||||
noiseSprite = new Sprite("Content/UI/noise.png", Vector2.Zero);
|
noiseSprite = new Sprite("Content/UI/noise.png", Vector2.Zero);
|
||||||
DrawLoadingText = true;
|
DrawLoadingText = true;
|
||||||
selectedTip = TextManager.Get("LoadingScreenTip", true);
|
SetSelectedTip(TextManager.Get("LoadingScreenTip", true));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Draw(SpriteBatch spriteBatch, GraphicsDevice graphics, float deltaTime)
|
public void Draw(SpriteBatch spriteBatch, GraphicsDevice graphics, float deltaTime)
|
||||||
@@ -215,14 +223,34 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (GUI.Font != null && selectedTip != null)
|
if (GUI.Font != null && selectedTip != null)
|
||||||
{
|
{
|
||||||
|
if (selectedTipRichTextUnparsed)
|
||||||
|
{
|
||||||
|
selectedTipRichTextData = RichTextData.GetRichTextData(selectedTip, out selectedTip);
|
||||||
|
selectedTipRichTextUnparsed = false;
|
||||||
|
}
|
||||||
|
|
||||||
string wrappedTip = ToolBox.WrapText(selectedTip, GameMain.GraphicsWidth * 0.5f, GUI.Font);
|
string wrappedTip = ToolBox.WrapText(selectedTip, GameMain.GraphicsWidth * 0.5f, GUI.Font);
|
||||||
string[] lines = wrappedTip.Split('\n');
|
string[] lines = wrappedTip.Split('\n');
|
||||||
float lineHeight = GUI.Font.MeasureString(selectedTip).Y;
|
float lineHeight = GUI.Font.MeasureString(selectedTip).Y;
|
||||||
|
|
||||||
for (int i = 0; i < lines.Length; i++)
|
if (selectedTipRichTextData != null)
|
||||||
{
|
{
|
||||||
GUI.Font.DrawString(spriteBatch, lines[i],
|
int rtdOffset = 0;
|
||||||
new Vector2((int)(GameMain.GraphicsWidth / 2.0f - GUI.Font.MeasureString(lines[i]).X / 2.0f), (int)(GameMain.GraphicsHeight * 0.8f + i * lineHeight)), Color.White);
|
for (int i = 0; i < lines.Length; i++)
|
||||||
|
{
|
||||||
|
GUI.Font.DrawStringWithColors(spriteBatch, lines[i],
|
||||||
|
new Vector2((int)(GameMain.GraphicsWidth / 2.0f - GUI.Font.MeasureString(lines[i]).X / 2.0f), (int)(GameMain.GraphicsHeight * 0.8f + i * lineHeight)), Color.White,
|
||||||
|
0f, Vector2.Zero, 1f, SpriteEffects.None, 0f, selectedTipRichTextData, rtdOffset);
|
||||||
|
rtdOffset += lines[i].Length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int i = 0; i < lines.Length; i++)
|
||||||
|
{
|
||||||
|
GUI.Font.DrawString(spriteBatch, lines[i],
|
||||||
|
new Vector2((int)(GameMain.GraphicsWidth / 2.0f - GUI.Font.MeasureString(lines[i]).X / 2.0f), (int)(GameMain.GraphicsHeight * 0.8f + i * lineHeight)), Color.White);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -302,7 +330,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
GameMain.Config.Language = language;
|
GameMain.Config.Language = language;
|
||||||
//reload tip in the selected language
|
//reload tip in the selected language
|
||||||
selectedTip = TextManager.Get("LoadingScreenTip", true);
|
SetSelectedTip(TextManager.Get("LoadingScreenTip", true));
|
||||||
GameMain.Config.SetDefaultBindings(legacy: false);
|
GameMain.Config.SetDefaultBindings(legacy: false);
|
||||||
GameMain.Config.CheckBindings(useDefaults: true);
|
GameMain.Config.CheckBindings(useDefaults: true);
|
||||||
WaitForLanguageSelection = false;
|
WaitForLanguageSelection = false;
|
||||||
@@ -364,7 +392,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
drawn = false;
|
drawn = false;
|
||||||
LoadState = null;
|
LoadState = null;
|
||||||
selectedTip = TextManager.Get("LoadingScreenTip", true);
|
SetSelectedTip(TextManager.Get("LoadingScreenTip", true));
|
||||||
currentBackgroundTexture = LocationType.List.GetRandom()?.GetPortrait(Rand.Int(int.MaxValue))?.Texture;
|
currentBackgroundTexture = LocationType.List.GetRandom()?.GetPortrait(Rand.Int(int.MaxValue))?.Texture;
|
||||||
|
|
||||||
while (!drawn)
|
while (!drawn)
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Point maxPoint = new Point(int.MaxValue, int.MaxValue);
|
public readonly static Point MaxPoint = new Point(int.MaxValue, int.MaxValue);
|
||||||
private Point? maxSize;
|
private Point? maxSize;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -103,7 +103,7 @@ namespace Barotrauma
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public Point MaxSize
|
public Point MaxSize
|
||||||
{
|
{
|
||||||
get { return maxSize ?? maxPoint; }
|
get { return maxSize ?? MaxPoint; }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (maxSize == value) { return; }
|
if (maxSize == value) { return; }
|
||||||
@@ -640,6 +640,12 @@ namespace Barotrauma
|
|||||||
return children.Contains(rectT) || (recursive && children.Any(c => c.IsParentOf(rectT)));
|
return children.Contains(rectT) || (recursive && children.Any(c => c.IsParentOf(rectT)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool IsChildOf(RectTransform rectT, bool recursive = true)
|
||||||
|
{
|
||||||
|
if (Parent == null) { return false; }
|
||||||
|
return Parent == rectT || (recursive && Parent.IsChildOf(rectT));
|
||||||
|
}
|
||||||
|
|
||||||
public void ClearChildren()
|
public void ClearChildren()
|
||||||
{
|
{
|
||||||
children.ForEachMod(c => c.Parent = null);
|
children.ForEachMod(c => c.Parent = null);
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ namespace Barotrauma
|
|||||||
private int buyTotal, sellTotal;
|
private int buyTotal, sellTotal;
|
||||||
|
|
||||||
private GUITextBlock merchantBalanceBlock;
|
private GUITextBlock merchantBalanceBlock;
|
||||||
private GUILayoutGroup valueChangeGroup;
|
|
||||||
private GUITextBlock currentSellValueBlock, newSellValueBlock;
|
private GUITextBlock currentSellValueBlock, newSellValueBlock;
|
||||||
private GUIImage sellValueChangeArrow;
|
private GUIImage sellValueChangeArrow;
|
||||||
private GUIDropDown sortingDropDown;
|
private GUIDropDown sortingDropDown;
|
||||||
@@ -158,7 +157,7 @@ namespace Barotrauma
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Store header ------------------------------------------------
|
// Store header ------------------------------------------------
|
||||||
var headerGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.75f / 14.0f), storeContent.RectTransform), isHorizontal: true)
|
var headerGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.95f / 14.0f), storeContent.RectTransform), isHorizontal: true)
|
||||||
{
|
{
|
||||||
RelativeSpacing = 0.005f
|
RelativeSpacing = 0.005f
|
||||||
};
|
};
|
||||||
@@ -209,7 +208,7 @@ namespace Barotrauma
|
|||||||
// Item sell value ------------------------------------------------
|
// Item sell value ------------------------------------------------
|
||||||
var sellValueContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.5f, 1.0f), balanceAndValueGroup.RectTransform))
|
var sellValueContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.5f, 1.0f), balanceAndValueGroup.RectTransform))
|
||||||
{
|
{
|
||||||
CanBeFocused = false,
|
CanBeFocused = true,
|
||||||
RelativeSpacing = 0.005f
|
RelativeSpacing = 0.005f
|
||||||
};
|
};
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), sellValueContainer.RectTransform),
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), sellValueContainer.RectTransform),
|
||||||
@@ -220,9 +219,9 @@ namespace Barotrauma
|
|||||||
ForceUpperCase = true
|
ForceUpperCase = true
|
||||||
};
|
};
|
||||||
|
|
||||||
valueChangeGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.5f), sellValueContainer.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft)
|
var valueChangeGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.5f), sellValueContainer.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft)
|
||||||
{
|
{
|
||||||
CanBeFocused = true,
|
CanBeFocused = false,
|
||||||
RelativeSpacing = 0.02f
|
RelativeSpacing = 0.02f
|
||||||
};
|
};
|
||||||
float blockWidth = GUI.IsFourByThree() ? 0.32f : 0.28f;
|
float blockWidth = GUI.IsFourByThree() ? 0.32f : 0.28f;
|
||||||
@@ -247,7 +246,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
string tooltipTag = newStatus.SellPriceModifier > CurrentLocation.ActiveStoreBalanceStatus.SellPriceModifier ?
|
string tooltipTag = newStatus.SellPriceModifier > CurrentLocation.ActiveStoreBalanceStatus.SellPriceModifier ?
|
||||||
"campaingstore.valueincreasetooltip" : "campaingstore.valuedecreasetooltip";
|
"campaingstore.valueincreasetooltip" : "campaingstore.valuedecreasetooltip";
|
||||||
valueChangeGroup.ToolTip = TextManager.Get(tooltipTag);
|
sellValueContainer.ToolTip = TextManager.Get(tooltipTag);
|
||||||
currentSellValueBlock.TextColor = newStatus.Color;
|
currentSellValueBlock.TextColor = newStatus.Color;
|
||||||
sellValueChangeArrow.Color = newStatus.Color;
|
sellValueChangeArrow.Color = newStatus.Color;
|
||||||
sellValueChangeArrow.Visible = true;
|
sellValueChangeArrow.Visible = true;
|
||||||
@@ -256,7 +255,7 @@ namespace Barotrauma
|
|||||||
return $"{(CurrentLocation.ActiveStoreBalanceStatus.SellPriceModifier * 100).FormatZeroDecimal()} %";
|
return $"{(CurrentLocation.ActiveStoreBalanceStatus.SellPriceModifier * 100).FormatZeroDecimal()} %";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
valueChangeGroup.ToolTip = null;
|
sellValueContainer.ToolTip = TextManager.Get("campaignstore.sellvaluetooltip");
|
||||||
currentSellValueBlock.TextColor = CurrentLocation.BalanceColor;
|
currentSellValueBlock.TextColor = CurrentLocation.BalanceColor;
|
||||||
sellValueChangeArrow.Visible = false;
|
sellValueChangeArrow.Visible = false;
|
||||||
newSellValueBlock.Text = null;
|
newSellValueBlock.Text = null;
|
||||||
@@ -264,7 +263,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
valueChangeGroup.ToolTip = null;
|
sellValueContainer.ToolTip = null;
|
||||||
sellValueChangeArrow.Visible = false;
|
sellValueChangeArrow.Visible = false;
|
||||||
newSellValueBlock.Text = null;
|
newSellValueBlock.Text = null;
|
||||||
return null;
|
return null;
|
||||||
@@ -293,7 +292,7 @@ namespace Barotrauma
|
|||||||
newSellValueBlock.Padding = newPadding;
|
newSellValueBlock.Padding = newPadding;
|
||||||
|
|
||||||
// Store mode buttons ------------------------------------------------
|
// Store mode buttons ------------------------------------------------
|
||||||
var modeButtonFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.6f / 14.0f), storeContent.RectTransform), style: null);
|
var modeButtonFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.4f / 14.0f), storeContent.RectTransform), style: null);
|
||||||
var modeButtonContainer = new GUILayoutGroup(new RectTransform(Vector2.One, modeButtonFrame.RectTransform), isHorizontal: true);
|
var modeButtonContainer = new GUILayoutGroup(new RectTransform(Vector2.One, modeButtonFrame.RectTransform), isHorizontal: true);
|
||||||
|
|
||||||
var tabs = Enum.GetValues(typeof(StoreTab));
|
var tabs = Enum.GetValues(typeof(StoreTab));
|
||||||
@@ -676,6 +675,7 @@ namespace Barotrauma
|
|||||||
(itemFrame.UserData as PurchasedItem).Quantity = quantity;
|
(itemFrame.UserData as PurchasedItem).Quantity = quantity;
|
||||||
SetQuantityLabelText(StoreTab.Buy, itemFrame);
|
SetQuantityLabelText(StoreTab.Buy, itemFrame);
|
||||||
SetOwnedLabelText(itemFrame);
|
SetOwnedLabelText(itemFrame);
|
||||||
|
SetPriceGetters(itemFrame, true);
|
||||||
}
|
}
|
||||||
SetItemFrameStatus(itemFrame, hasPermissions && quantity > 0);
|
SetItemFrameStatus(itemFrame, hasPermissions && quantity > 0);
|
||||||
existingItemFrames.Add(itemFrame);
|
existingItemFrames.Add(itemFrame);
|
||||||
@@ -750,6 +750,7 @@ namespace Barotrauma
|
|||||||
(itemFrame.UserData as PurchasedItem).Quantity = itemQuantity;
|
(itemFrame.UserData as PurchasedItem).Quantity = itemQuantity;
|
||||||
SetQuantityLabelText(StoreTab.Sell, itemFrame);
|
SetQuantityLabelText(StoreTab.Sell, itemFrame);
|
||||||
SetOwnedLabelText(itemFrame);
|
SetOwnedLabelText(itemFrame);
|
||||||
|
SetPriceGetters(itemFrame, false);
|
||||||
}
|
}
|
||||||
SetItemFrameStatus(itemFrame, hasPermissions && itemQuantity > 0);
|
SetItemFrameStatus(itemFrame, hasPermissions && itemQuantity > 0);
|
||||||
if (itemQuantity < 1 && !isRequestedGood)
|
if (itemQuantity < 1 && !isRequestedGood)
|
||||||
@@ -772,6 +773,37 @@ namespace Barotrauma
|
|||||||
shoppingCrateSellList.BarScroll = prevShoppingCrateScroll;
|
shoppingCrateSellList.BarScroll = prevShoppingCrateScroll;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void SetPriceGetters(GUIComponent itemFrame, bool buying)
|
||||||
|
{
|
||||||
|
if (itemFrame == null || !(itemFrame.UserData is PurchasedItem pi)) { return; }
|
||||||
|
|
||||||
|
if (itemFrame.FindChild("undiscountedprice", recursive: true) is GUITextBlock undiscountedPriceBlock)
|
||||||
|
{
|
||||||
|
if (buying)
|
||||||
|
{
|
||||||
|
undiscountedPriceBlock.TextGetter = () => GetCurrencyFormatted(
|
||||||
|
CurrentLocation?.GetAdjustedItemBuyPrice(pi.ItemPrefab, considerDailySpecials: false) ?? 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
undiscountedPriceBlock.TextGetter = () => GetCurrencyFormatted(
|
||||||
|
CurrentLocation?.GetAdjustedItemSellPrice(pi.ItemPrefab, considerRequestedGoods: false) ?? 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (itemFrame.FindChild("price", recursive: true) is GUITextBlock priceBlock)
|
||||||
|
{
|
||||||
|
if (buying)
|
||||||
|
{
|
||||||
|
priceBlock.TextGetter = () => GetCurrencyFormatted(CurrentLocation?.GetAdjustedItemBuyPrice(pi.ItemPrefab) ?? 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
priceBlock.TextGetter = () => GetCurrencyFormatted(CurrentLocation?.GetAdjustedItemSellPrice(pi.ItemPrefab) ?? 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void RefreshItemsToSell()
|
public void RefreshItemsToSell()
|
||||||
{
|
{
|
||||||
itemsToSell.Clear();
|
itemsToSell.Clear();
|
||||||
@@ -1188,14 +1220,6 @@ namespace Barotrauma
|
|||||||
};
|
};
|
||||||
priceBlock.Color *= (forceDisable ? 0.5f : 1.0f);
|
priceBlock.Color *= (forceDisable ? 0.5f : 1.0f);
|
||||||
priceBlock.CalculateHeightFromText();
|
priceBlock.CalculateHeightFromText();
|
||||||
if (isSellingRelatedList)
|
|
||||||
{
|
|
||||||
priceBlock.TextGetter = () => GetCurrencyFormatted(CurrentLocation?.GetAdjustedItemSellPrice(pi.ItemPrefab, priceInfo: priceInfo) ?? 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
priceBlock.TextGetter = () => GetCurrencyFormatted(CurrentLocation?.GetAdjustedItemBuyPrice(pi.ItemPrefab, priceInfo: priceInfo) ?? 0);
|
|
||||||
}
|
|
||||||
if (locationHasDealOnItem)
|
if (locationHasDealOnItem)
|
||||||
{
|
{
|
||||||
var undiscounterPriceBlock = new GUITextBlock(
|
var undiscounterPriceBlock = new GUITextBlock(
|
||||||
@@ -1209,17 +1233,8 @@ namespace Barotrauma
|
|||||||
TextColor = priceBlock.TextColor,
|
TextColor = priceBlock.TextColor,
|
||||||
UserData = "undiscountedprice"
|
UserData = "undiscountedprice"
|
||||||
};
|
};
|
||||||
if (isSellingRelatedList)
|
|
||||||
{
|
|
||||||
undiscounterPriceBlock.TextGetter = () => GetCurrencyFormatted(
|
|
||||||
CurrentLocation?.GetAdjustedItemSellPrice(pi.ItemPrefab, priceInfo: priceInfo, considerRequestedGoods: false) ?? 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
undiscounterPriceBlock.TextGetter = () => GetCurrencyFormatted(
|
|
||||||
CurrentLocation?.GetAdjustedItemBuyPrice(pi.ItemPrefab, priceInfo: priceInfo, considerDailySpecials: false) ?? 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
SetPriceGetters(frame, !isSellingRelatedList);
|
||||||
|
|
||||||
if (isParentOnLeftSideOfInterface)
|
if (isParentOnLeftSideOfInterface)
|
||||||
{
|
{
|
||||||
@@ -1268,7 +1283,8 @@ namespace Barotrauma
|
|||||||
// Add items on the sub(s)
|
// Add items on the sub(s)
|
||||||
Submarine.MainSub?.GetItems(true)
|
Submarine.MainSub?.GetItems(true)
|
||||||
.Where(i => i.Components.All(c => !(c is Holdable h) || !h.Attachable || !h.Attached) &&
|
.Where(i => i.Components.All(c => !(c is Holdable h) || !h.Attachable || !h.Attached) &&
|
||||||
i.Components.All(c => !(c is Wire w) || w.Connections.All(c => c == null)))
|
i.Components.All(c => !(c is Wire w) || w.Connections.All(c => c == null)) &&
|
||||||
|
ItemAndAllContainersInteractable(i))
|
||||||
.ForEach(i => AddToOwnedItems(i.Prefab));
|
.ForEach(i => AddToOwnedItems(i.Prefab));
|
||||||
|
|
||||||
// Add items in character inventories
|
// Add items in character inventories
|
||||||
@@ -1286,6 +1302,16 @@ namespace Barotrauma
|
|||||||
|
|
||||||
ownedItemsUpdateTimer = 0.0f;
|
ownedItemsUpdateTimer = 0.0f;
|
||||||
|
|
||||||
|
static bool ItemAndAllContainersInteractable(Item item)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (!item.IsPlayerTeamInteractable) { return false; }
|
||||||
|
item = item.Container;
|
||||||
|
} while (item != null);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void AddToOwnedItems(ItemPrefab itemPrefab, int amount = 1)
|
void AddToOwnedItems(ItemPrefab itemPrefab, int amount = 1)
|
||||||
{
|
{
|
||||||
if (OwnedItems.ContainsKey(itemPrefab))
|
if (OwnedItems.ContainsKey(itemPrefab))
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ namespace Barotrauma
|
|||||||
public GUITextBlock submarineFee;
|
public GUITextBlock submarineFee;
|
||||||
public GUIButton selectSubmarineButton;
|
public GUIButton selectSubmarineButton;
|
||||||
public GUITextBlock middleTextBlock;
|
public GUITextBlock middleTextBlock;
|
||||||
|
public GUIButton previewButton;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SubmarineSelection(bool transfer, Action closeAction, RectTransform parent)
|
public SubmarineSelection(bool transfer, Action closeAction, RectTransform parent)
|
||||||
@@ -191,6 +192,12 @@ namespace Barotrauma
|
|||||||
submarineDisplayElement.submarineClass = new GUITextBlock(new RectTransform(new Vector2(1f, 0.1f), submarineDisplayElement.background.RectTransform, Anchor.TopCenter, Pivot.TopCenter) { AbsoluteOffset = new Point(0, HUDLayoutSettings.Padding + (int)GUI.Font.MeasureString(submarineDisplayElement.submarineName.Text).Y) }, string.Empty, textAlignment: Alignment.Center);
|
submarineDisplayElement.submarineClass = new GUITextBlock(new RectTransform(new Vector2(1f, 0.1f), submarineDisplayElement.background.RectTransform, Anchor.TopCenter, Pivot.TopCenter) { AbsoluteOffset = new Point(0, HUDLayoutSettings.Padding + (int)GUI.Font.MeasureString(submarineDisplayElement.submarineName.Text).Y) }, string.Empty, textAlignment: Alignment.Center);
|
||||||
submarineDisplayElement.submarineFee = new GUITextBlock(new RectTransform(new Vector2(1f, 0.1f), submarineDisplayElement.background.RectTransform, Anchor.BottomCenter, Pivot.BottomCenter) { AbsoluteOffset = new Point(0, HUDLayoutSettings.Padding) }, string.Empty, textAlignment: Alignment.Center, font: GUI.SubHeadingFont);
|
submarineDisplayElement.submarineFee = new GUITextBlock(new RectTransform(new Vector2(1f, 0.1f), submarineDisplayElement.background.RectTransform, Anchor.BottomCenter, Pivot.BottomCenter) { AbsoluteOffset = new Point(0, HUDLayoutSettings.Padding) }, string.Empty, textAlignment: Alignment.Center, font: GUI.SubHeadingFont);
|
||||||
submarineDisplayElement.selectSubmarineButton = new GUIButton(new RectTransform(Vector2.One, submarineDisplayElement.background.RectTransform), style: null);
|
submarineDisplayElement.selectSubmarineButton = new GUIButton(new RectTransform(Vector2.One, submarineDisplayElement.background.RectTransform), style: null);
|
||||||
|
submarineDisplayElement.previewButton = new GUIButton(new RectTransform(Vector2.One * 0.12f, submarineDisplayElement.background.RectTransform, anchor: Anchor.BottomRight, pivot: Pivot.BottomRight, scaleBasis: ScaleBasis.BothHeight) { AbsoluteOffset = new Point((int)(0.03f * background.Rect.Height)) }, style: "ExpandButton")
|
||||||
|
{
|
||||||
|
Color = Color.White,
|
||||||
|
HoverColor = Color.White,
|
||||||
|
PressedColor = Color.White
|
||||||
|
};
|
||||||
submarineDisplays[i] = submarineDisplayElement;
|
submarineDisplays[i] = submarineDisplayElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -299,6 +306,7 @@ namespace Barotrauma
|
|||||||
submarineDisplays[i].selectSubmarineButton.OnClicked = null;
|
submarineDisplays[i].selectSubmarineButton.OnClicked = null;
|
||||||
submarineDisplays[i].displayedSubmarine = null;
|
submarineDisplays[i].displayedSubmarine = null;
|
||||||
submarineDisplays[i].middleTextBlock.AutoDraw = false;
|
submarineDisplays[i].middleTextBlock.AutoDraw = false;
|
||||||
|
submarineDisplays[i].previewButton.Visible = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -369,6 +377,13 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
SelectSubmarine(subToDisplay, submarineDisplays[i].background.Rect);
|
SelectSubmarine(subToDisplay, submarineDisplays[i].background.Rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
submarineDisplays[i].previewButton.Visible = true;
|
||||||
|
submarineDisplays[i].previewButton.OnClicked = (btn, obj) =>
|
||||||
|
{
|
||||||
|
SubmarinePreview.Create(subToDisplay);
|
||||||
|
return false;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
submarineIndex++;
|
submarineIndex++;
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using Microsoft.Xna.Framework.Graphics;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Barotrauma.Networking;
|
using Barotrauma.Networking;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
using Barotrauma.Extensions;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
@@ -17,7 +18,7 @@ namespace Barotrauma
|
|||||||
private static UISprite spectateIcon, disconnectedIcon;
|
private static UISprite spectateIcon, disconnectedIcon;
|
||||||
private static Sprite ownerIcon, moderatorIcon;
|
private static Sprite ownerIcon, moderatorIcon;
|
||||||
|
|
||||||
private enum InfoFrameTab { Crew, Mission, MyCharacter, Traitor };
|
private enum InfoFrameTab { Crew, Mission, Reputation, MyCharacter, Traitor, Submarine };
|
||||||
private static InfoFrameTab selectedTab;
|
private static InfoFrameTab selectedTab;
|
||||||
private GUIFrame infoFrame, contentFrame;
|
private GUIFrame infoFrame, contentFrame;
|
||||||
|
|
||||||
@@ -40,11 +41,11 @@ namespace Barotrauma
|
|||||||
private const ushort mediumPingThreshold = 200;
|
private const ushort mediumPingThreshold = 200;
|
||||||
|
|
||||||
private ushort currentPing;
|
private ushort currentPing;
|
||||||
private Client client;
|
private readonly Client client;
|
||||||
private Character character;
|
private readonly Character character;
|
||||||
private bool hasCharacter;
|
private readonly bool hasCharacter;
|
||||||
private GUITextBlock textBlock;
|
private readonly GUITextBlock textBlock;
|
||||||
private GUIFrame frame;
|
private readonly GUIFrame frame;
|
||||||
|
|
||||||
public LinkedGUI(Client client, GUIFrame frame, bool hasCharacter, GUITextBlock textBlock)
|
public LinkedGUI(Client client, GUIFrame frame, bool hasCharacter, GUITextBlock textBlock)
|
||||||
{
|
{
|
||||||
@@ -180,60 +181,79 @@ namespace Barotrauma
|
|||||||
infoFrame = new GUIFrame(new RectTransform(Vector2.One, GUI.Canvas, Anchor.Center), style: null);
|
infoFrame = new GUIFrame(new RectTransform(Vector2.One, GUI.Canvas, Anchor.Center), style: null);
|
||||||
new GUIFrame(new RectTransform(GUI.Canvas.RelativeSize, infoFrame.RectTransform, Anchor.Center), style: "GUIBackgroundBlocker");
|
new GUIFrame(new RectTransform(GUI.Canvas.RelativeSize, infoFrame.RectTransform, Anchor.Center), style: "GUIBackgroundBlocker");
|
||||||
|
|
||||||
|
//this used to be a switch expression but i changed it because it killed enc :(
|
||||||
|
Vector2 contentFrameSize;
|
||||||
switch (selectedTab)
|
switch (selectedTab)
|
||||||
{
|
{
|
||||||
case InfoFrameTab.Crew:
|
|
||||||
case InfoFrameTab.Mission:
|
|
||||||
case InfoFrameTab.Traitor:
|
|
||||||
default:
|
|
||||||
contentFrame = new GUIFrame(new RectTransform(new Vector2(0.33f, 0.667f), infoFrame.RectTransform, Anchor.TopCenter, Pivot.TopCenter) { /*MinSize = new Point(width, height),*/ RelativeOffset = new Vector2(0.025f, 0.12f) });
|
|
||||||
break;
|
|
||||||
case InfoFrameTab.MyCharacter:
|
case InfoFrameTab.MyCharacter:
|
||||||
contentFrame = new GUIFrame(new RectTransform(new Vector2(0.33f, 0.5f), infoFrame.RectTransform, Anchor.TopCenter, Pivot.TopCenter) { /*MinSize = new Point(width, height),*/ RelativeOffset = new Vector2(0.025f, 0.12f) });
|
contentFrameSize = new Vector2(0.45f, 0.5f);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
contentFrameSize = new Vector2(0.45f, 0.667f);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
contentFrame = new GUIFrame(new RectTransform(contentFrameSize, infoFrame.RectTransform, Anchor.TopCenter, Pivot.TopCenter) { RelativeOffset = new Vector2(0.0f, 0.12f) });
|
||||||
|
|
||||||
var innerFrame = new GUIFrame(new RectTransform(new Vector2(0.958f, 0.943f), contentFrame.RectTransform, Anchor.TopCenter, Pivot.TopCenter) { AbsoluteOffset = new Point(0, GUI.IntScale(17.5f)) }, style: null);
|
var horizontalLayoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.958f, 0.943f), contentFrame.RectTransform, Anchor.TopCenter, Pivot.TopCenter) { AbsoluteOffset = new Point(0, GUI.IntScale(25f)) }, isHorizontal: true)
|
||||||
var buttonArea = new GUILayoutGroup(new RectTransform(new Point(innerFrame.Rect.Width, GUI.IntScale(25f)), innerFrame.RectTransform) { AbsoluteOffset = new Point(2, 0) }, isHorizontal: true)
|
|
||||||
{
|
{
|
||||||
RelativeSpacing = 0.01f
|
RelativeSpacing = 0.01f
|
||||||
};
|
};
|
||||||
|
|
||||||
infoFrameHolder = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.926f), innerFrame.RectTransform, Anchor.BottomCenter, Pivot.BottomCenter), style: null);
|
var buttonArea = new GUILayoutGroup(new RectTransform(new Vector2(0.07f, 1f), parent: horizontalLayoutGroup.RectTransform), isHorizontal: false)
|
||||||
|
|
||||||
var crewButton = new GUIButton(new RectTransform(new Vector2(0.245f, 1.0f), buttonArea.RectTransform), TextManager.Get("Crew"), style: "GUITabButton")
|
|
||||||
{
|
{
|
||||||
UserData = InfoFrameTab.Crew,
|
AbsoluteSpacing = GUI.IntScale(5f)
|
||||||
OnClicked = SelectInfoFrameTab
|
|
||||||
};
|
};
|
||||||
tabButtons.Add(crewButton);
|
var innerLayoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.92f, 1f), horizontalLayoutGroup.RectTransform))
|
||||||
|
|
||||||
var missionButton = new GUIButton(new RectTransform(new Vector2(0.245f, 1.0f), buttonArea.RectTransform), TextManager.Get("Mission"), style: "GUITabButton")
|
|
||||||
{
|
{
|
||||||
UserData = InfoFrameTab.Mission,
|
RelativeSpacing = 0.01f,
|
||||||
OnClicked = SelectInfoFrameTab
|
Stretch = true
|
||||||
};
|
};
|
||||||
tabButtons.Add(missionButton);
|
|
||||||
|
|
||||||
bool isTraitor = GameMain.Client?.Character?.IsTraitor ?? false;
|
float absoluteSpacing = innerLayoutGroup.RelativeSpacing * innerLayoutGroup.Rect.Height;
|
||||||
if (isTraitor && GameMain.Client.TraitorMission != null)
|
int multiplier = GameMain.GameSession?.GameMode is CampaignMode ? 2 : 1;
|
||||||
|
int infoFrameHolderHeight = Math.Min((int)(0.97f * innerLayoutGroup.Rect.Height), (int)(innerLayoutGroup.Rect.Height - multiplier * (GUI.IntScale(15f) + absoluteSpacing)));
|
||||||
|
infoFrameHolder = new GUIFrame(new RectTransform(new Point(innerLayoutGroup.Rect.Width, infoFrameHolderHeight), parent: innerLayoutGroup.RectTransform), style: null);
|
||||||
|
|
||||||
|
GUIButton createTabButton(InfoFrameTab tab, string textTag)
|
||||||
{
|
{
|
||||||
var traitorButton = new GUIButton(new RectTransform(new Vector2(0.245f, 1.0f), buttonArea.RectTransform), TextManager.Get("tabmenu.traitor"), style: "GUITabButton")
|
var newButton = new GUIButton(new RectTransform(Vector2.One, buttonArea.RectTransform, scaleBasis: ScaleBasis.BothWidth), style: $"InfoFrameTabButton.{tab}")
|
||||||
{
|
{
|
||||||
UserData = InfoFrameTab.Traitor,
|
UserData = tab,
|
||||||
|
ToolTip = TextManager.Get(textTag),
|
||||||
OnClicked = SelectInfoFrameTab
|
OnClicked = SelectInfoFrameTab
|
||||||
};
|
};
|
||||||
tabButtons.Add(traitorButton);
|
tabButtons.Add(newButton);
|
||||||
|
return newButton;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var crewButton = createTabButton(InfoFrameTab.Crew, "crew");
|
||||||
|
|
||||||
|
var missionButton = createTabButton(InfoFrameTab.Mission, "mission");
|
||||||
|
|
||||||
|
if (GameMain.GameSession?.GameMode is CampaignMode campaignMode)
|
||||||
|
{
|
||||||
|
var reputationButton = createTabButton(InfoFrameTab.Reputation, "reputation");
|
||||||
|
|
||||||
|
var balanceFrame = new GUIFrame(new RectTransform(new Point(innerLayoutGroup.Rect.Width, innerLayoutGroup.Rect.Height - infoFrameHolderHeight), parent: innerLayoutGroup.RectTransform), style: "InnerFrame");
|
||||||
|
new GUITextBlock(new RectTransform(Vector2.One, balanceFrame.RectTransform), "", textAlignment: Alignment.Right, parseRichText: true)
|
||||||
|
{
|
||||||
|
TextGetter = () => TextManager.GetWithVariable("campaignmoney", "[money]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", campaignMode.Money))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bool isTraitor = GameMain.Client?.Character?.IsTraitor ?? false;
|
||||||
|
if (isTraitor && GameMain.Client.TraitorMission != null)
|
||||||
|
{
|
||||||
|
var traitorButton = createTabButton(InfoFrameTab.Traitor, "tabmenu.traitor");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var submarineButton = createTabButton(InfoFrameTab.Submarine, "submarine");
|
||||||
|
|
||||||
if (GameMain.NetworkMember != null)
|
if (GameMain.NetworkMember != null)
|
||||||
{
|
{
|
||||||
var myCharacterButton = new GUIButton(new RectTransform(new Vector2(0.245f, 1.0f), buttonArea.RectTransform), TextManager.Get("tabmenu.character"), style: "GUITabButton")
|
var myCharacterButton = createTabButton(InfoFrameTab.MyCharacter, "tabmenu.character");
|
||||||
{
|
|
||||||
UserData = InfoFrameTab.MyCharacter,
|
|
||||||
OnClicked = SelectInfoFrameTab
|
|
||||||
};
|
|
||||||
tabButtons.Add(myCharacterButton);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -252,6 +272,14 @@ namespace Barotrauma
|
|||||||
case InfoFrameTab.Mission:
|
case InfoFrameTab.Mission:
|
||||||
CreateMissionInfo(infoFrameHolder);
|
CreateMissionInfo(infoFrameHolder);
|
||||||
break;
|
break;
|
||||||
|
case InfoFrameTab.Reputation:
|
||||||
|
if (GameMain.GameSession.RoundSummary != null && GameMain.GameSession.GameMode is CampaignMode campaignMode)
|
||||||
|
{
|
||||||
|
infoFrameHolder.ClearChildren();
|
||||||
|
GUIFrame reputationFrame = new GUIFrame(new RectTransform(Vector2.One, infoFrameHolder.RectTransform, Anchor.TopCenter), style: "GUIFrameListBox");
|
||||||
|
GameMain.GameSession.RoundSummary.CreateReputationInfoPanel(reputationFrame, campaignMode);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case InfoFrameTab.Traitor:
|
case InfoFrameTab.Traitor:
|
||||||
TraitorMissionPrefab traitorMission = GameMain.Client.TraitorMission;
|
TraitorMissionPrefab traitorMission = GameMain.Client.TraitorMission;
|
||||||
Character traitor = GameMain.Client.Character;
|
Character traitor = GameMain.Client.Character;
|
||||||
@@ -262,6 +290,9 @@ namespace Barotrauma
|
|||||||
if (GameMain.NetworkMember == null) { return false; }
|
if (GameMain.NetworkMember == null) { return false; }
|
||||||
GameMain.NetLobbyScreen.CreatePlayerFrame(infoFrameHolder);
|
GameMain.NetLobbyScreen.CreatePlayerFrame(infoFrameHolder);
|
||||||
break;
|
break;
|
||||||
|
case InfoFrameTab.Submarine:
|
||||||
|
CreateSubmarineInfo(infoFrameHolder, Submarine.MainSub);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -356,6 +387,21 @@ namespace Barotrauma
|
|||||||
|
|
||||||
crewFrame.RectTransform.AbsoluteOffset = new Point(0, (int)(headerFrames[0].Rect.Height * headerFrames.Length) - (teamIDs.Count > 1 ? GUI.IntScale(10f) : 0));
|
crewFrame.RectTransform.AbsoluteOffset = new Point(0, (int)(headerFrames[0].Rect.Height * headerFrames.Length) - (teamIDs.Count > 1 ? GUI.IntScale(10f) : 0));
|
||||||
|
|
||||||
|
float totalRelativeHeight = 0.0f;
|
||||||
|
if (teamIDs.Count > 1) { totalRelativeHeight += teamIDs.Count * nameHeight; }
|
||||||
|
headerFrames.ForEach(f => totalRelativeHeight += f.RectTransform.RelativeSize.Y);
|
||||||
|
crewListArray.ForEach(f => totalRelativeHeight += f.RectTransform.RelativeSize.Y);
|
||||||
|
if (totalRelativeHeight > 1.0f)
|
||||||
|
{
|
||||||
|
float heightOverflow = totalRelativeHeight - 1.0f;
|
||||||
|
float heightToReduce = heightOverflow / crewListArray.Length;
|
||||||
|
crewListArray.ForEach(l =>
|
||||||
|
{
|
||||||
|
l.RectTransform.Resize(l.RectTransform.RelativeSize - new Vector2(0.0f, heightToReduce));
|
||||||
|
l.UpdateDimensions();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (GameMain.IsMultiplayer)
|
if (GameMain.IsMultiplayer)
|
||||||
{
|
{
|
||||||
CreateMultiPlayerList(false);
|
CreateMultiPlayerList(false);
|
||||||
@@ -676,7 +722,7 @@ namespace Barotrauma
|
|||||||
GUIComponent existingPreview = infoFrameHolder.FindChild("SelectedCharacter");
|
GUIComponent existingPreview = infoFrameHolder.FindChild("SelectedCharacter");
|
||||||
if (existingPreview != null) infoFrameHolder.RemoveChild(existingPreview);
|
if (existingPreview != null) infoFrameHolder.RemoveChild(existingPreview);
|
||||||
|
|
||||||
GUIFrame background = new GUIFrame(new RectTransform(new Vector2(0.543f, 0.717f), infoFrameHolder.RectTransform, Anchor.TopLeft, Pivot.TopRight) { RelativeOffset = new Vector2(-0.061f, 0) })
|
GUIFrame background = new GUIFrame(new RectTransform(new Vector2(0.543f, 0.717f), infoFrameHolder.RectTransform, Anchor.TopLeft, Pivot.TopRight) { RelativeOffset = new Vector2(-0.145f, 0) })
|
||||||
{
|
{
|
||||||
UserData = "SelectedCharacter"
|
UserData = "SelectedCharacter"
|
||||||
};
|
};
|
||||||
@@ -831,12 +877,24 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (logList != null)
|
if (logList != null)
|
||||||
{
|
{
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), logList.Content.RectTransform), line, wrap: true, font: GUI.SmallFont)
|
var textBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), logList.Content.RectTransform), line, wrap: true, font: GUI.SmallFont, parseRichText: true)
|
||||||
{
|
{
|
||||||
TextColor = textColor,
|
TextColor = textColor,
|
||||||
CanBeFocused = false,
|
CanBeFocused = false,
|
||||||
UserData = line
|
UserData = line
|
||||||
}.CalculateHeightFromText();
|
};
|
||||||
|
textBlock.CalculateHeightFromText();
|
||||||
|
if (textBlock.HasColorHighlight)
|
||||||
|
{
|
||||||
|
foreach (var data in textBlock.RichTextData)
|
||||||
|
{
|
||||||
|
textBlock.ClickableAreas.Add(new GUITextBlock.ClickableArea()
|
||||||
|
{
|
||||||
|
Data = data,
|
||||||
|
OnClick = GameMain.NetLobbyScreen.SelectPlayer
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -857,54 +915,109 @@ namespace Barotrauma
|
|||||||
|
|
||||||
int locationInfoYOffset = locationNameText.Rect.Height + locationTypeText.Rect.Height + padding * 2;
|
int locationInfoYOffset = locationNameText.Rect.Height + locationTypeText.Rect.Height + padding * 2;
|
||||||
|
|
||||||
GUIFrame missionDescriptionHolder;
|
GUIListBox missionList;
|
||||||
|
|
||||||
if (hasPortrait)
|
if (hasPortrait)
|
||||||
{
|
{
|
||||||
GUIFrame missionImageHolder = new GUIFrame(new RectTransform(new Point(contentWidth, (int)(missionFrame.Rect.Height * 0.588f)), missionFrame.RectTransform, Anchor.TopCenter) { AbsoluteOffset = new Point(0, locationInfoYOffset) });
|
GUIFrame portraitHolder = new GUIFrame(new RectTransform(new Point(contentWidth, (int)(missionFrame.Rect.Height * 0.588f)), missionFrame.RectTransform, Anchor.TopCenter) { AbsoluteOffset = new Point(0, locationInfoYOffset) });
|
||||||
float portraitAspectRatio = portrait.SourceRect.Width / portrait.SourceRect.Height;
|
float portraitAspectRatio = portrait.SourceRect.Width / portrait.SourceRect.Height;
|
||||||
GUIImage portraitImage = new GUIImage(new RectTransform(new Vector2(1.0f, 1f), missionImageHolder.RectTransform), portrait, scaleToFit: true);
|
GUIImage portraitImage = new GUIImage(new RectTransform(new Vector2(1.0f, 1f), portraitHolder.RectTransform), portrait, scaleToFit: true);
|
||||||
missionImageHolder.RectTransform.NonScaledSize = new Point(portraitImage.Rect.Size.X, (int)(portraitImage.Rect.Size.X / portraitAspectRatio));
|
portraitHolder.RectTransform.NonScaledSize = new Point(portraitImage.Rect.Size.X, (int)(portraitImage.Rect.Size.X / portraitAspectRatio));
|
||||||
missionDescriptionHolder = new GUIFrame(new RectTransform(new Point(contentWidth, 0), missionFrame.RectTransform, Anchor.TopCenter) { AbsoluteOffset = new Point(0, missionImageHolder.RectTransform.AbsoluteOffset.Y + missionImageHolder.Rect.Height + padding) }, style: null);
|
|
||||||
|
missionList = new GUIListBox(new RectTransform(new Point(contentWidth, missionFrame.Rect.Bottom - portraitHolder.Rect.Bottom - padding), missionFrame.RectTransform, Anchor.TopCenter) { AbsoluteOffset = new Point(0, portraitHolder.RectTransform.AbsoluteOffset.Y + portraitHolder.Rect.Height + padding) });
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
missionDescriptionHolder = new GUIFrame(new RectTransform(new Point(contentWidth, 0), missionFrame.RectTransform, Anchor.TopCenter) { AbsoluteOffset = new Point(0, locationInfoYOffset) }, style: null);
|
missionList = new GUIListBox(new RectTransform(new Point(contentWidth, missionFrame.Rect.Height - locationInfoYOffset - padding), missionFrame.RectTransform, Anchor.TopCenter) { AbsoluteOffset = new Point(0, locationInfoYOffset) });
|
||||||
}
|
}
|
||||||
|
missionList.ContentBackground.Color = Color.Transparent;
|
||||||
|
missionList.Spacing = GUI.IntScale(15);
|
||||||
|
|
||||||
Mission mission = GameMain.GameSession?.Mission;
|
if (GameMain.GameSession?.Missions != null)
|
||||||
if (mission != null)
|
|
||||||
{
|
{
|
||||||
GUILayoutGroup missionTextGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.744f, 0f), missionDescriptionHolder.RectTransform, Anchor.CenterLeft) { RelativeOffset = new Vector2(0.225f, 0f) }, false, childAnchor: Anchor.TopLeft);
|
foreach (Mission mission in GameMain.GameSession.Missions)
|
||||||
|
|
||||||
string missionNameString = ToolBox.WrapText(mission.Name, missionTextGroup.Rect.Width, GUI.LargeFont);
|
|
||||||
string missionDescriptionString = ToolBox.WrapText(mission.Description, missionTextGroup.Rect.Width, GUI.Font);
|
|
||||||
string rewardText = TextManager.GetWithVariable("currencyformat", "[credits]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", mission.Reward));
|
|
||||||
string missionRewardString = ToolBox.WrapText(TextManager.GetWithVariable("MissionReward", "[reward]", rewardText), missionTextGroup.Rect.Width, GUI.Font);
|
|
||||||
|
|
||||||
Vector2 missionNameSize = GUI.LargeFont.MeasureString(missionNameString);
|
|
||||||
Vector2 missionDescriptionSize = GUI.Font.MeasureString(missionDescriptionString);
|
|
||||||
Vector2 missionRewardSize = GUI.Font.MeasureString(missionRewardString);
|
|
||||||
|
|
||||||
missionDescriptionHolder.RectTransform.NonScaledSize = new Point(missionDescriptionHolder.RectTransform.NonScaledSize.X, (int)(missionNameSize.Y + missionDescriptionSize.Y + missionRewardSize.Y));
|
|
||||||
missionTextGroup.RectTransform.NonScaledSize = new Point(missionTextGroup.RectTransform.NonScaledSize.X, missionDescriptionHolder.RectTransform.NonScaledSize.Y);
|
|
||||||
|
|
||||||
if (mission.Prefab.Icon != null)
|
|
||||||
{
|
{
|
||||||
float iconAspectRatio = mission.Prefab.Icon.SourceRect.Width / mission.Prefab.Icon.SourceRect.Height;
|
GUIFrame missionDescriptionHolder = new GUIFrame(new RectTransform(Vector2.One, missionList.Content.RectTransform), style: null);
|
||||||
int iconWidth = (int)(0.225f * missionDescriptionHolder.RectTransform.NonScaledSize.X);
|
GUILayoutGroup missionTextGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.744f, 0f), missionDescriptionHolder.RectTransform, Anchor.CenterLeft) { RelativeOffset = new Vector2(0.225f, 0f) }, false, childAnchor: Anchor.TopLeft)
|
||||||
int iconHeight = Math.Max(missionTextGroup.RectTransform.NonScaledSize.Y, (int)(iconWidth * iconAspectRatio));
|
{
|
||||||
Point iconSize = new Point(iconWidth, iconHeight);
|
AbsoluteSpacing = GUI.IntScale(5)
|
||||||
|
};
|
||||||
|
string descriptionText = mission.Description;
|
||||||
|
foreach (string missionMessage in mission.ShownMessages)
|
||||||
|
{
|
||||||
|
descriptionText += "\n\n" + missionMessage;
|
||||||
|
}
|
||||||
|
string rewardText = mission.GetMissionRewardText();
|
||||||
|
string reputationText = mission.GetReputationRewardText(mission.Locations[0]);
|
||||||
|
|
||||||
new GUIImage(new RectTransform(iconSize, missionDescriptionHolder.RectTransform), mission.Prefab.Icon, null, true) { Color = mission.Prefab.IconColor };
|
var missionNameRichTextData = RichTextData.GetRichTextData(mission.Name, out string missionNameString);
|
||||||
|
var missionRewardRichTextData = RichTextData.GetRichTextData(rewardText, out string missionRewardString);
|
||||||
|
var missionReputationRichTextData = RichTextData.GetRichTextData(reputationText, out string missionReputationString);
|
||||||
|
var missionDescriptionRichTextData = RichTextData.GetRichTextData(descriptionText, out string missionDescriptionString);
|
||||||
|
|
||||||
|
missionNameString = ToolBox.WrapText(missionNameString, missionTextGroup.Rect.Width, GUI.LargeFont);
|
||||||
|
missionRewardString = ToolBox.WrapText(missionRewardString, missionTextGroup.Rect.Width, GUI.Font);
|
||||||
|
missionReputationString = ToolBox.WrapText(missionReputationString, missionTextGroup.Rect.Width, GUI.Font);
|
||||||
|
missionDescriptionString = ToolBox.WrapText(missionDescriptionString, missionTextGroup.Rect.Width, GUI.Font);
|
||||||
|
|
||||||
|
Vector2 missionNameSize = GUI.LargeFont.MeasureString(missionNameString);
|
||||||
|
Vector2 missionDescriptionSize = GUI.Font.MeasureString(missionDescriptionString);
|
||||||
|
Vector2 missionRewardSize = GUI.Font.MeasureString(missionRewardString);
|
||||||
|
Vector2 missionReputationSize = GUI.Font.MeasureString(missionReputationString);
|
||||||
|
|
||||||
|
float ySize = missionNameSize.Y + missionDescriptionSize.Y + missionRewardSize.Y + missionReputationSize.Y + missionTextGroup.AbsoluteSpacing * 4;
|
||||||
|
bool displayDifficulty = mission.Difficulty.HasValue;
|
||||||
|
if (displayDifficulty) { ySize += missionRewardSize.Y; }
|
||||||
|
|
||||||
|
missionDescriptionHolder.RectTransform.NonScaledSize = new Point(missionDescriptionHolder.RectTransform.NonScaledSize.X, (int)ySize);
|
||||||
|
missionTextGroup.RectTransform.NonScaledSize = new Point(missionTextGroup.RectTransform.NonScaledSize.X, missionDescriptionHolder.RectTransform.NonScaledSize.Y);
|
||||||
|
|
||||||
|
if (mission.Prefab.Icon != null)
|
||||||
|
{
|
||||||
|
float iconAspectRatio = mission.Prefab.Icon.SourceRect.Width / mission.Prefab.Icon.SourceRect.Height;
|
||||||
|
int iconWidth = (int)(0.225f * missionDescriptionHolder.RectTransform.NonScaledSize.X);
|
||||||
|
int iconHeight = Math.Max(missionTextGroup.RectTransform.NonScaledSize.Y, (int)(iconWidth * iconAspectRatio));
|
||||||
|
Point iconSize = new Point(iconWidth, iconHeight);
|
||||||
|
|
||||||
|
new GUIImage(new RectTransform(iconSize, missionDescriptionHolder.RectTransform), mission.Prefab.Icon, null, true)
|
||||||
|
{
|
||||||
|
Color = mission.Prefab.IconColor,
|
||||||
|
HoverColor = mission.Prefab.IconColor,
|
||||||
|
SelectedColor = mission.Prefab.IconColor,
|
||||||
|
CanBeFocused = false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextGroup.RectTransform), missionNameRichTextData, missionNameString, font: GUI.LargeFont);
|
||||||
|
GUILayoutGroup difficultyIndicatorGroup = null;
|
||||||
|
if (displayDifficulty)
|
||||||
|
{
|
||||||
|
difficultyIndicatorGroup = new GUILayoutGroup(new RectTransform(new Point(missionTextGroup.Rect.Width, (int)missionRewardSize.Y), parent: missionTextGroup.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft)
|
||||||
|
{
|
||||||
|
AbsoluteSpacing = 1
|
||||||
|
};
|
||||||
|
var difficultyColor = mission.GetDifficultyColor();
|
||||||
|
for (int i = 0; i < mission.Difficulty.Value; i++)
|
||||||
|
{
|
||||||
|
new GUIImage(new RectTransform(Vector2.One, difficultyIndicatorGroup.RectTransform, scaleBasis: ScaleBasis.Smallest), "DifficultyIndicator", scaleToFit: true)
|
||||||
|
{
|
||||||
|
CanBeFocused = false,
|
||||||
|
Color = difficultyColor
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var rewardTextBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextGroup.RectTransform), missionRewardRichTextData, missionRewardString);
|
||||||
|
if (difficultyIndicatorGroup != null)
|
||||||
|
{
|
||||||
|
difficultyIndicatorGroup.RectTransform.Resize(new Point((int)(difficultyIndicatorGroup.Rect.Width - rewardTextBlock.Padding.X - rewardTextBlock.Padding.Z), difficultyIndicatorGroup.Rect.Height));
|
||||||
|
difficultyIndicatorGroup.RectTransform.AbsoluteOffset = new Point((int)rewardTextBlock.Padding.X, 0);
|
||||||
|
}
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextGroup.RectTransform), missionReputationRichTextData, missionReputationString);
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextGroup.RectTransform), missionDescriptionRichTextData, missionDescriptionString);
|
||||||
}
|
}
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextGroup.RectTransform), missionNameString, font: GUI.LargeFont);
|
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextGroup.RectTransform), missionRewardString);
|
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextGroup.RectTransform), missionDescriptionString);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GUILayoutGroup missionTextGroup = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0f), missionDescriptionHolder.RectTransform, Anchor.CenterLeft), false, childAnchor: Anchor.TopLeft);
|
GUILayoutGroup missionTextGroup = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0f), missionList.RectTransform, Anchor.CenterLeft), false, childAnchor: Anchor.TopLeft);
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextGroup.RectTransform), TextManager.Get("NoMission"), font: GUI.LargeFont);
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextGroup.RectTransform), TextManager.Get("NoMission"), font: GUI.LargeFont);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -938,5 +1051,93 @@ namespace Barotrauma
|
|||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextGroup.RectTransform), missionNameString, font: GUI.LargeFont);
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextGroup.RectTransform), missionNameString, font: GUI.LargeFont);
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextGroup.RectTransform), missionDescriptionString);
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextGroup.RectTransform), missionDescriptionString);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void CreateSubmarineInfo(GUIFrame infoFrame, Submarine sub)
|
||||||
|
{
|
||||||
|
GUIFrame subInfoFrame = new GUIFrame(new RectTransform(Vector2.One, infoFrame.RectTransform, Anchor.TopCenter), style: "GUIFrameListBox");
|
||||||
|
GUIFrame paddedFrame = new GUIFrame(new RectTransform(Vector2.One * 0.97f, subInfoFrame.RectTransform, Anchor.Center), style: null);
|
||||||
|
|
||||||
|
var previewButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.43f), paddedFrame.RectTransform), style: null)
|
||||||
|
{
|
||||||
|
OnClicked = (btn, obj) => { SubmarinePreview.Create(sub.Info); return false; },
|
||||||
|
};
|
||||||
|
|
||||||
|
var previewImage = sub.Info.PreviewImage ?? SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.Name.Equals(sub.Info.Name, StringComparison.OrdinalIgnoreCase))?.PreviewImage;
|
||||||
|
if (previewImage == null)
|
||||||
|
{
|
||||||
|
new GUITextBlock(new RectTransform(Vector2.One, previewButton.RectTransform), TextManager.Get("SubPreviewImageNotFound"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var submarinePreviewBackground = new GUIFrame(new RectTransform(Vector2.One, previewButton.RectTransform), style: null)
|
||||||
|
{
|
||||||
|
Color = Color.Black,
|
||||||
|
HoverColor = Color.Black,
|
||||||
|
SelectedColor = Color.Black,
|
||||||
|
PressedColor = Color.Black,
|
||||||
|
CanBeFocused = false,
|
||||||
|
};
|
||||||
|
new GUIImage(new RectTransform(new Vector2(0.98f), submarinePreviewBackground.RectTransform, Anchor.Center), previewImage, scaleToFit: true) { CanBeFocused = false };
|
||||||
|
new GUIFrame(new RectTransform(Vector2.One, submarinePreviewBackground.RectTransform), "InnerGlow", color: Color.Black) { CanBeFocused = false };
|
||||||
|
}
|
||||||
|
|
||||||
|
new GUIFrame(new RectTransform(Vector2.One * 0.12f, previewButton.RectTransform, anchor: Anchor.BottomRight, pivot: Pivot.BottomRight, scaleBasis: ScaleBasis.BothHeight)
|
||||||
|
{
|
||||||
|
AbsoluteOffset = new Point((int)(0.03f * previewButton.Rect.Height))
|
||||||
|
},
|
||||||
|
"ExpandButton", Color.White)
|
||||||
|
{
|
||||||
|
Color = Color.White,
|
||||||
|
HoverColor = Color.White,
|
||||||
|
PressedColor = Color.White
|
||||||
|
};
|
||||||
|
|
||||||
|
var subInfoTextLayout = new GUILayoutGroup(new RectTransform(Vector2.One, paddedFrame.RectTransform));
|
||||||
|
|
||||||
|
string className = !sub.Info.HasTag(SubmarineTag.Shuttle) ? TextManager.Get($"submarineclass.{sub.Info.SubmarineClass}") : TextManager.Get("shuttle");
|
||||||
|
|
||||||
|
int nameHeight = (int)GUI.LargeFont.MeasureString(sub.Info.DisplayName, true).Y;
|
||||||
|
int classHeight = (int)GUI.SubHeadingFont.MeasureString(className).Y;
|
||||||
|
|
||||||
|
var submarineNameText = new GUITextBlock(new RectTransform(new Point(subInfoTextLayout.Rect.Width, nameHeight + HUDLayoutSettings.Padding / 2), subInfoTextLayout.RectTransform), sub.Info.DisplayName, textAlignment: Alignment.CenterLeft, font: GUI.LargeFont) { CanBeFocused = false };
|
||||||
|
submarineNameText.RectTransform.MinSize = new Point(0, (int)submarineNameText.TextSize.Y);
|
||||||
|
var submarineClassText = new GUITextBlock(new RectTransform(new Point(subInfoTextLayout.Rect.Width, classHeight), subInfoTextLayout.RectTransform), className, textAlignment: Alignment.CenterLeft, font: GUI.SubHeadingFont) { CanBeFocused = false };
|
||||||
|
submarineClassText.RectTransform.MinSize = new Point(0, (int)submarineClassText.TextSize.Y);
|
||||||
|
|
||||||
|
if (GameMain.GameSession?.GameMode is CampaignMode campaign)
|
||||||
|
{
|
||||||
|
GUILayoutGroup headerLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.09f), paddedFrame.RectTransform) { RelativeOffset = new Vector2(0f, 0.43f) }, isHorizontal: true) { Stretch = true };
|
||||||
|
GUIImage headerIcon = new GUIImage(new RectTransform(Vector2.One, headerLayout.RectTransform, scaleBasis: ScaleBasis.BothHeight), style: "SubmarineIcon");
|
||||||
|
new GUITextBlock(new RectTransform(Vector2.One, headerLayout.RectTransform), TextManager.Get("uicategory.upgrades"), font: GUI.LargeFont);
|
||||||
|
|
||||||
|
var upgradeRootLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.48f), paddedFrame.RectTransform, Anchor.BottomLeft, Pivot.BottomLeft), isHorizontal: true);
|
||||||
|
|
||||||
|
var upgradeCategoryPanel = UpgradeStore.CreateUpgradeCategoryList(new RectTransform(new Vector2(0.4f, 1f), upgradeRootLayout.RectTransform));
|
||||||
|
upgradeCategoryPanel.HideChildrenOutsideFrame = true;
|
||||||
|
UpgradeStore.UpdateCategoryList(upgradeCategoryPanel, campaign, sub, UpgradeStore.GetApplicableCategories(sub).ToArray());
|
||||||
|
GUIComponent[] toRemove = upgradeCategoryPanel.Content.FindChildren(c => !c.Enabled).ToArray();
|
||||||
|
toRemove.ForEach(c => upgradeCategoryPanel.RemoveChild(c));
|
||||||
|
|
||||||
|
var upgradePanel = new GUIListBox(new RectTransform(new Vector2(0.6f, 1f), upgradeRootLayout.RectTransform));
|
||||||
|
upgradeCategoryPanel.OnSelected = (component, userData) =>
|
||||||
|
{
|
||||||
|
upgradePanel.ClearChildren();
|
||||||
|
if (userData is UpgradeStore.CategoryData categoryData && Submarine.MainSub != null)
|
||||||
|
{
|
||||||
|
foreach (UpgradePrefab prefab in categoryData.Prefabs)
|
||||||
|
{
|
||||||
|
var frame = UpgradeStore.CreateUpgradeFrame(prefab, categoryData.Category, campaign, new RectTransform(new Vector2(1f, 0.3f), upgradePanel.Content.RectTransform), addBuyButton: false);
|
||||||
|
UpgradeStore.UpdateUpgradeEntry(frame, prefab, categoryData.Category, campaign);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var specsListBox = new GUIListBox(new RectTransform(new Vector2(1f, 0.57f), paddedFrame.RectTransform, Anchor.BottomLeft, Pivot.BottomLeft));
|
||||||
|
sub.Info.CreateSpecsWindow(specsListBox, GUI.Font, includeTitle: false, includeClass: false, includeDescription: true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
internal class UpgradeStore
|
internal class UpgradeStore
|
||||||
{
|
{
|
||||||
private readonly struct CategoryData
|
public readonly struct CategoryData
|
||||||
{
|
{
|
||||||
public readonly UpgradeCategory Category;
|
public readonly UpgradeCategory Category;
|
||||||
public readonly List<UpgradePrefab> Prefabs;
|
public readonly List<UpgradePrefab> Prefabs;
|
||||||
@@ -125,7 +125,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (component.UserData is CategoryData data)
|
if (component.UserData is CategoryData data)
|
||||||
{
|
{
|
||||||
UpdateUpgradeEntry(component, data.SinglePrefab, data.Category);
|
UpdateUpgradeEntry(component, data.SinglePrefab, data.Category, Campaign);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -133,29 +133,35 @@ namespace Barotrauma
|
|||||||
// update the small indicator icons on the list
|
// update the small indicator icons on the list
|
||||||
if (currentStoreLayout?.Parent != null)
|
if (currentStoreLayout?.Parent != null)
|
||||||
{
|
{
|
||||||
foreach (GUIComponent component in currentStoreLayout.Content.Children)
|
UpdateCategoryList(currentStoreLayout, Campaign, drawnSubmarine, applicableCategories);
|
||||||
{
|
}
|
||||||
if (!(component.UserData is CategoryData data)) { continue; }
|
}
|
||||||
if (component.FindChild("indicators", true) is { } indicators)
|
|
||||||
{
|
|
||||||
UpdateCategoryIndicators(indicators, component, data.Prefabs, data.Category);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// reset the order first
|
//TODO: move this somewhere else
|
||||||
foreach (UpgradeCategory category in UpgradeCategory.Categories)
|
public static void UpdateCategoryList(GUIListBox categoryList, CampaignMode campaign, Submarine drawnSubmarine, IEnumerable<UpgradeCategory> applicableCategories)
|
||||||
|
{
|
||||||
|
foreach (GUIComponent component in categoryList.Content.Children)
|
||||||
|
{
|
||||||
|
if (!(component.UserData is CategoryData data)) { continue; }
|
||||||
|
if (component.FindChild("indicators", true) is { } indicators)
|
||||||
{
|
{
|
||||||
GUIComponent component = currentStoreLayout.Content.FindChild(c => c.UserData is CategoryData categoryData && categoryData.Category == category);
|
UpdateCategoryIndicators(indicators, component, data.Prefabs, data.Category, campaign, drawnSubmarine, applicableCategories);
|
||||||
component?.SetAsLastChild();
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// send the disabled components to the bottom
|
// reset the order first
|
||||||
List<GUIComponent> lastChilds = currentStoreLayout.Content.Children.Where(component => !component.Enabled).ToList();
|
foreach (UpgradeCategory category in UpgradeCategory.Categories)
|
||||||
|
{
|
||||||
|
GUIComponent component = categoryList.Content.FindChild(c => c.UserData is CategoryData categoryData && categoryData.Category == category);
|
||||||
|
component?.SetAsLastChild();
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var lastChild in lastChilds)
|
// send the disabled components to the bottom
|
||||||
{
|
List<GUIComponent> lastChilds = categoryList.Content.Children.Where(component => !component.Enabled).ToList();
|
||||||
lastChild.SetAsLastChild();
|
|
||||||
}
|
foreach (var lastChild in lastChilds)
|
||||||
|
{
|
||||||
|
lastChild.SetAsLastChild();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -511,9 +517,10 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CreateUpgradeTab()
|
//TODO: put this somewhere else
|
||||||
|
public static GUIListBox CreateUpgradeCategoryList(RectTransform rectTransform)
|
||||||
{
|
{
|
||||||
currentStoreLayout = new GUIListBox(rectT(1.0f, 1.5f, storeLayout), style: null)
|
var upgradeCategoryList = new GUIListBox(rectTransform, style: null)
|
||||||
{
|
{
|
||||||
AutoHideScrollBar = false,
|
AutoHideScrollBar = false,
|
||||||
ScrollBarVisible = false,
|
ScrollBarVisible = false,
|
||||||
@@ -548,7 +555,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
foreach (var (category, prefabs) in upgrades)
|
foreach (var (category, prefabs) in upgrades)
|
||||||
{
|
{
|
||||||
var frameChild = new GUIFrame(rectT(1, 0.15f, currentStoreLayout.Content), style: "UpgradeUIFrame")
|
var frameChild = new GUIFrame(rectT(1, 0.15f, upgradeCategoryList.Content), style: "UpgradeUIFrame")
|
||||||
{
|
{
|
||||||
UserData = new CategoryData(category, prefabs),
|
UserData = new CategoryData(category, prefabs),
|
||||||
GlowOnSelect = true
|
GlowOnSelect = true
|
||||||
@@ -565,9 +572,9 @@ namespace Barotrauma
|
|||||||
* |-----------------------------|--------------------------|
|
* |-----------------------------|--------------------------|
|
||||||
*/
|
*/
|
||||||
GUILayoutGroup contentLayout = new GUILayoutGroup(rectT(0.9f, 0.85f, frameChild, Anchor.Center));
|
GUILayoutGroup contentLayout = new GUILayoutGroup(rectT(0.9f, 0.85f, frameChild, Anchor.Center));
|
||||||
var itemCategoryLabel = new GUITextBlock(rectT(1, 1, contentLayout), category.Name, font: GUI.SubHeadingFont) { CanBeFocused = false };
|
var itemCategoryLabel = new GUITextBlock(rectT(1, 1, contentLayout), category.Name, font: GUI.SubHeadingFont) { CanBeFocused = false };
|
||||||
GUILayoutGroup indicatorLayout = new GUILayoutGroup(rectT(0.5f, 0.25f, contentLayout, Anchor.BottomRight), isHorizontal: true, childAnchor: Anchor.TopRight) { UserData = "indicators", IgnoreLayoutGroups = true, RelativeSpacing = 0.01f };
|
GUILayoutGroup indicatorLayout = new GUILayoutGroup(rectT(0.5f, 0.25f, contentLayout, Anchor.BottomRight), isHorizontal: true, childAnchor: Anchor.TopRight) { UserData = "indicators", IgnoreLayoutGroups = true, RelativeSpacing = 0.01f };
|
||||||
|
|
||||||
foreach (var prefab in prefabs)
|
foreach (var prefab in prefabs)
|
||||||
{
|
{
|
||||||
GUIImage upgradeIndicator = new GUIImage(rectT(0.1f, 1f, indicatorLayout), style: "UpgradeIndicator", scaleToFit: true) { UserData = prefab, CanBeFocused = false };
|
GUIImage upgradeIndicator = new GUIImage(rectT(0.1f, 1f, indicatorLayout), style: "UpgradeIndicator", scaleToFit: true) { UserData = prefab, CanBeFocused = false };
|
||||||
@@ -582,6 +589,13 @@ namespace Barotrauma
|
|||||||
indicatorLayout.Recalculate();
|
indicatorLayout.Recalculate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return upgradeCategoryList;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateUpgradeTab()
|
||||||
|
{
|
||||||
|
currentStoreLayout = CreateUpgradeCategoryList(rectT(1.0f, 1.5f, storeLayout));
|
||||||
|
|
||||||
selectedUpgradeCategoryLayout = new GUIFrame(rectT(GUI.IsFourByThree() ? 0.3f : 0.25f, 1, mainStoreLayout), style: null) { CanBeFocused = false };
|
selectedUpgradeCategoryLayout = new GUIFrame(rectT(GUI.IsFourByThree() ? 0.3f : 0.25f, 1, mainStoreLayout), style: null) { CanBeFocused = false };
|
||||||
|
|
||||||
RefreshUpgradeList();
|
RefreshUpgradeList();
|
||||||
@@ -637,7 +651,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CreateUpgradeEntry(UpgradePrefab prefab, UpgradeCategory category, GUIComponent parent, List<Item> itemsOnSubmarine)
|
public static GUIFrame CreateUpgradeFrame(UpgradePrefab prefab, UpgradeCategory category, CampaignMode campaign, RectTransform rectTransform, bool addBuyButton = true)
|
||||||
{
|
{
|
||||||
/* UPGRADE PREFAB ENTRY
|
/* UPGRADE PREFAB ENTRY
|
||||||
* |------------------------------------------------------------------|
|
* |------------------------------------------------------------------|
|
||||||
@@ -648,8 +662,8 @@ namespace Barotrauma
|
|||||||
* | | progress bar | x / y | |
|
* | | progress bar | x / y | |
|
||||||
* |------------------------------------------------------------------|
|
* |------------------------------------------------------------------|
|
||||||
*/
|
*/
|
||||||
GUIFrame prefabFrame = new GUIFrame(rectT(1f, 0.25f, parent), style: "ListBoxElement") { SelectedColor = Color.Transparent, UserData = new CategoryData(category, prefab) };
|
GUIFrame prefabFrame = new GUIFrame(rectTransform, style: "ListBoxElement") { SelectedColor = Color.Transparent, UserData = new CategoryData(category, prefab) };
|
||||||
GUILayoutGroup prefabLayout = new GUILayoutGroup(rectT(0.98f,0.95f, prefabFrame, Anchor.Center), isHorizontal: true);
|
GUILayoutGroup prefabLayout = new GUILayoutGroup(rectT(0.98f, 0.95f, prefabFrame, Anchor.Center), isHorizontal: true) { Stretch = true };
|
||||||
GUILayoutGroup imageLayout = new GUILayoutGroup(rectT(new Point(prefabLayout.Rect.Height, prefabLayout.Rect.Height), prefabLayout), childAnchor: Anchor.Center);
|
GUILayoutGroup imageLayout = new GUILayoutGroup(rectT(new Point(prefabLayout.Rect.Height, prefabLayout.Rect.Height), prefabLayout), childAnchor: Anchor.Center);
|
||||||
var icon = new GUIImage(rectT(0.9f, 0.9f, imageLayout), prefab.Sprite, scaleToFit: true) { CanBeFocused = false };
|
var icon = new GUIImage(rectT(0.9f, 0.9f, imageLayout), prefab.Sprite, scaleToFit: true) { CanBeFocused = false };
|
||||||
GUILayoutGroup textLayout = new GUILayoutGroup(rectT(0.8f - imageLayout.RectTransform.RelativeSize.X, 1, prefabLayout));
|
GUILayoutGroup textLayout = new GUILayoutGroup(rectT(0.8f - imageLayout.RectTransform.RelativeSize.X, 1, prefabLayout));
|
||||||
@@ -659,9 +673,13 @@ namespace Barotrauma
|
|||||||
GUILayoutGroup progressLayout = new GUILayoutGroup(rectT(1, 0.25f, textLayout), isHorizontal: true, childAnchor: Anchor.CenterLeft) { UserData = "progressbar" };
|
GUILayoutGroup progressLayout = new GUILayoutGroup(rectT(1, 0.25f, textLayout), isHorizontal: true, childAnchor: Anchor.CenterLeft) { UserData = "progressbar" };
|
||||||
new GUIProgressBar(rectT(0.8f, 0.75f, progressLayout), 0.0f, GUI.Style.Orange);
|
new GUIProgressBar(rectT(0.8f, 0.75f, progressLayout), 0.0f, GUI.Style.Orange);
|
||||||
new GUITextBlock(rectT(0.2f, 1, progressLayout), string.Empty, font: GUI.SmallFont, textAlignment: Alignment.Center) { Padding = Vector4.Zero };
|
new GUITextBlock(rectT(0.2f, 1, progressLayout), string.Empty, font: GUI.SmallFont, textAlignment: Alignment.Center) { Padding = Vector4.Zero };
|
||||||
GUILayoutGroup buyButtonLayout = new GUILayoutGroup(rectT(0.2f, 1, prefabLayout), childAnchor: Anchor.TopCenter) { UserData = "buybutton" };
|
GUILayoutGroup buyButtonLayout = null;
|
||||||
new GUITextBlock(rectT(1, 0.4f, buyButtonLayout), FormatCurrency(prefab.Price.GetBuyprice(Campaign.UpgradeManager.GetUpgradeLevel(prefab, category), Campaign.Map?.CurrentLocation)), textAlignment: Alignment.Center) { Padding = Vector4.Zero };
|
if (addBuyButton)
|
||||||
|
{
|
||||||
|
buyButtonLayout = new GUILayoutGroup(rectT(0.2f, 1, prefabLayout), childAnchor: Anchor.TopCenter) { UserData = "buybutton" };
|
||||||
|
new GUITextBlock(rectT(1, 0.4f, buyButtonLayout), FormatCurrency(prefab.Price.GetBuyprice(campaign.UpgradeManager.GetUpgradeLevel(prefab, category), campaign.Map?.CurrentLocation)), textAlignment: Alignment.Center) { Padding = Vector4.Zero };
|
||||||
var buyButton = new GUIButton(rectT(0.7f, 0.5f, buyButtonLayout), string.Empty, style: "UpgradeBuyButton") { Enabled = false };
|
var buyButton = new GUIButton(rectT(0.7f, 0.5f, buyButtonLayout), string.Empty, style: "UpgradeBuyButton") { Enabled = false };
|
||||||
|
}
|
||||||
|
|
||||||
description.CalculateHeightFromText();
|
description.CalculateHeightFromText();
|
||||||
// cut the description if it overflows and add a tooltip to it
|
// cut the description if it overflows and add a tooltip to it
|
||||||
@@ -677,14 +695,33 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Recalculate everything to prevent jumping
|
// Recalculate everything to prevent jumping
|
||||||
if (parent is GUILayoutGroup group) { group.Recalculate(); }
|
if (rectTransform.Parent.GUIComponent is GUILayoutGroup group) { group.Recalculate(); }
|
||||||
|
|
||||||
descriptionLayout.Recalculate();
|
descriptionLayout.Recalculate();
|
||||||
prefabLayout.Recalculate();
|
prefabLayout.Recalculate();
|
||||||
imageLayout.Recalculate();
|
imageLayout.Recalculate();
|
||||||
textLayout.Recalculate();
|
textLayout.Recalculate();
|
||||||
progressLayout.Recalculate();
|
progressLayout.Recalculate();
|
||||||
buyButtonLayout.Recalculate();
|
buyButtonLayout?.Recalculate();
|
||||||
|
|
||||||
|
return prefabFrame;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateUpgradeEntry(UpgradePrefab prefab, UpgradeCategory category, GUIComponent parent, List<Item> itemsOnSubmarine)
|
||||||
|
{
|
||||||
|
GUIFrame prefabFrame = CreateUpgradeFrame(prefab, category, Campaign, rectT(1f, 0.25f, parent));
|
||||||
|
var prefabLayout = prefabFrame.GetChild<GUILayoutGroup>();
|
||||||
|
GUILayoutGroup[] childLayouts = prefabLayout.GetAllChildren<GUILayoutGroup>().ToArray();
|
||||||
|
var imageLayout = childLayouts[0];
|
||||||
|
var icon = imageLayout.GetChild<GUIImage>();
|
||||||
|
var textLayout = childLayouts[1];
|
||||||
|
var name = textLayout.GetChild<GUITextBlock>();
|
||||||
|
GUILayoutGroup[] textChildLayouts = textLayout.GetAllChildren<GUILayoutGroup>().ToArray();
|
||||||
|
var descriptionLayout = textChildLayouts[0];
|
||||||
|
var description = descriptionLayout.GetChild<GUITextBlock>();
|
||||||
|
var progressLayout = textChildLayouts[1];
|
||||||
|
var buyButtonLayout = childLayouts[2];
|
||||||
|
var buyButton = buyButtonLayout.GetChild<GUIButton>();
|
||||||
|
|
||||||
if (!HasPermission || itemsOnSubmarine != null && !itemsOnSubmarine.Any(it => category.CanBeApplied(it, prefab)))
|
if (!HasPermission || itemsOnSubmarine != null && !itemsOnSubmarine.Any(it => category.CanBeApplied(it, prefab)))
|
||||||
{
|
{
|
||||||
@@ -713,7 +750,7 @@ namespace Barotrauma
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
UpdateUpgradeEntry(prefabFrame, prefab, category);
|
UpdateUpgradeEntry(prefabFrame, prefab, category, Campaign);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CreateItemTooltip(MapEntity entity)
|
private void CreateItemTooltip(MapEntity entity)
|
||||||
@@ -778,6 +815,18 @@ namespace Barotrauma
|
|||||||
static string CreateListEntry(string name, int level) => TextManager.GetWithVariables("upgradeuitooltip.upgradelistelement", new[] { "[upgradename]", "[level]" }, new[] { name, $"{level}" });
|
static string CreateListEntry(string name, int level) => TextManager.GetWithVariables("upgradeuitooltip.upgradelistelement", new[] { "[upgradename]", "[level]" }, new[] { name, $"{level}" });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<UpgradeCategory> GetApplicableCategories(Submarine drawnSubmarine)
|
||||||
|
{
|
||||||
|
Item[] entitiesOnSub = drawnSubmarine.GetItems(true).Where(i => drawnSubmarine.IsEntityFoundOnThisSub(i, true)).ToArray();
|
||||||
|
foreach (UpgradeCategory category in UpgradeCategory.Categories)
|
||||||
|
{
|
||||||
|
if (entitiesOnSub.Any(item => category.CanBeApplied(item, null)))
|
||||||
|
{
|
||||||
|
yield return category;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void UpdateSubmarinePreview(float deltaTime, GUICustomComponent parent)
|
private void UpdateSubmarinePreview(float deltaTime, GUICustomComponent parent)
|
||||||
{
|
{
|
||||||
if (!parent.Children.Any() || Submarine.MainSub != null && Submarine.MainSub != drawnSubmarine || GameMain.GraphicsWidth != screenResolution.X || GameMain.GraphicsHeight != screenResolution.Y)
|
if (!parent.Children.Any() || Submarine.MainSub != null && Submarine.MainSub != drawnSubmarine || GameMain.GraphicsWidth != screenResolution.X || GameMain.GraphicsHeight != screenResolution.Y)
|
||||||
@@ -789,16 +838,8 @@ namespace Barotrauma
|
|||||||
CreateSubmarinePreview(drawnSubmarine, parent);
|
CreateSubmarinePreview(drawnSubmarine, parent);
|
||||||
CreateHullBorderVerticies(drawnSubmarine, parent);
|
CreateHullBorderVerticies(drawnSubmarine, parent);
|
||||||
|
|
||||||
List<Item> entitiesOnSub = drawnSubmarine.GetItems(true).Where(i => drawnSubmarine.IsEntityFoundOnThisSub(i, true)).ToList();
|
|
||||||
applicableCategories.Clear();
|
applicableCategories.Clear();
|
||||||
|
applicableCategories.AddRange(GetApplicableCategories(drawnSubmarine));
|
||||||
foreach (UpgradeCategory category in UpgradeCategory.Categories)
|
|
||||||
{
|
|
||||||
if (entitiesOnSub.Any(item => category.CanBeApplied(item, null)))
|
|
||||||
{
|
|
||||||
applicableCategories.Add(category);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
screenResolution = new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
|
screenResolution = new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
|
||||||
@@ -1002,9 +1043,9 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateUpgradeEntry(GUIComponent prefabFrame, UpgradePrefab prefab, UpgradeCategory category)
|
public static void UpdateUpgradeEntry(GUIComponent prefabFrame, UpgradePrefab prefab, UpgradeCategory category, CampaignMode campaign)
|
||||||
{
|
{
|
||||||
int currentLevel = Campaign.UpgradeManager.GetUpgradeLevel(prefab, category);
|
int currentLevel = campaign.UpgradeManager.GetUpgradeLevel(prefab, category);
|
||||||
|
|
||||||
string progressText = TextManager.GetWithVariables("upgrades.progressformat", new[] { "[level]", "[maxlevel]" }, new[] { currentLevel.ToString(), prefab.MaxLevel.ToString() });
|
string progressText = TextManager.GetWithVariables("upgrades.progressformat", new[] { "[level]", "[maxlevel]" }, new[] { currentLevel.ToString(), prefab.MaxLevel.ToString() });
|
||||||
if (prefabFrame.FindChild("progressbar", true) is { } progressParent)
|
if (prefabFrame.FindChild("progressbar", true) is { } progressParent)
|
||||||
@@ -1023,7 +1064,7 @@ namespace Barotrauma
|
|||||||
if (prefabFrame.FindChild("buybutton", true) is { } buttonParent)
|
if (prefabFrame.FindChild("buybutton", true) is { } buttonParent)
|
||||||
{
|
{
|
||||||
GUITextBlock priceLabel = buttonParent.GetChild<GUITextBlock>();
|
GUITextBlock priceLabel = buttonParent.GetChild<GUITextBlock>();
|
||||||
int price = prefab.Price.GetBuyprice(Campaign.UpgradeManager.GetUpgradeLevel(prefab, category), Campaign.Map?.CurrentLocation);
|
int price = prefab.Price.GetBuyprice(campaign.UpgradeManager.GetUpgradeLevel(prefab, category), campaign.Map?.CurrentLocation);
|
||||||
|
|
||||||
if (priceLabel != null && !WaitForServerUpdate)
|
if (priceLabel != null && !WaitForServerUpdate)
|
||||||
{
|
{
|
||||||
@@ -1038,7 +1079,7 @@ namespace Barotrauma
|
|||||||
if (button != null)
|
if (button != null)
|
||||||
{
|
{
|
||||||
button.Enabled = currentLevel < prefab.MaxLevel;
|
button.Enabled = currentLevel < prefab.MaxLevel;
|
||||||
if (WaitForServerUpdate || !HasPermission || price > Campaign.Money)
|
if (WaitForServerUpdate || !campaign.AllowedToManageCampaign() || price > campaign.Money)
|
||||||
{
|
{
|
||||||
button.Enabled = false;
|
button.Enabled = false;
|
||||||
}
|
}
|
||||||
@@ -1046,7 +1087,14 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateCategoryIndicators(GUIComponent indicators, GUIComponent parent, List<UpgradePrefab> prefabs, UpgradeCategory category)
|
private static void UpdateCategoryIndicators(
|
||||||
|
GUIComponent indicators,
|
||||||
|
GUIComponent parent,
|
||||||
|
List<UpgradePrefab> prefabs,
|
||||||
|
UpgradeCategory category,
|
||||||
|
CampaignMode campaign,
|
||||||
|
Submarine drawnSubmarine,
|
||||||
|
IEnumerable<UpgradeCategory> applicableCategories)
|
||||||
{
|
{
|
||||||
// Disables the parent and only re-enables if the submarine contains valid items
|
// Disables the parent and only re-enables if the submarine contains valid items
|
||||||
if (!category.IsWallUpgrade && drawnSubmarine != null)
|
if (!category.IsWallUpgrade && drawnSubmarine != null)
|
||||||
@@ -1078,13 +1126,13 @@ namespace Barotrauma
|
|||||||
GUIComponentStyle dimStyle = styles["upgradeindicatordim"];
|
GUIComponentStyle dimStyle = styles["upgradeindicatordim"];
|
||||||
GUIComponentStyle offStyle = styles["upgradeindicatoroff"];
|
GUIComponentStyle offStyle = styles["upgradeindicatoroff"];
|
||||||
|
|
||||||
if (Campaign.UpgradeManager.GetUpgradeLevel(prefab, category) >= prefab.MaxLevel)
|
if (campaign.UpgradeManager.GetUpgradeLevel(prefab, category) >= prefab.MaxLevel)
|
||||||
{
|
{
|
||||||
// we check this to avoid flickering from re-applying the same style
|
// we check this to avoid flickering from re-applying the same style
|
||||||
if (image.Style == onStyle) { continue; }
|
if (image.Style == onStyle) { continue; }
|
||||||
image.ApplyStyle(onStyle);
|
image.ApplyStyle(onStyle);
|
||||||
}
|
}
|
||||||
else if (Campaign.UpgradeManager.GetUpgradeLevel(prefab, category) > 0)
|
else if (campaign.UpgradeManager.GetUpgradeLevel(prefab, category) > 0)
|
||||||
{
|
{
|
||||||
if (image.Style == dimStyle) { continue; }
|
if (image.Style == dimStyle) { continue; }
|
||||||
image.ApplyStyle(dimStyle);
|
image.ApplyStyle(dimStyle);
|
||||||
|
|||||||
@@ -77,10 +77,6 @@ namespace Barotrauma
|
|||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (gameSession == value) { return; }
|
if (gameSession == value) { return; }
|
||||||
if (value == null && Screen.Selected == GameScreen && gameSession.GameMode is CampaignMode)
|
|
||||||
{
|
|
||||||
DebugConsole.AddWarning("GameSession set to null while in the game screen\n" + Environment.StackTrace.CleanupStackTrace());
|
|
||||||
}
|
|
||||||
if (gameSession?.GameMode != null && gameSession.GameMode != value?.GameMode)
|
if (gameSession?.GameMode != null && gameSession.GameMode != value?.GameMode)
|
||||||
{
|
{
|
||||||
gameSession.GameMode.Remove();
|
gameSession.GameMode.Remove();
|
||||||
@@ -465,7 +461,28 @@ namespace Barotrauma
|
|||||||
|
|
||||||
while (Config.WaitingForAutoUpdate) { yield return CoroutineStatus.Running; }
|
while (Config.WaitingForAutoUpdate) { yield return CoroutineStatus.Running; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
if (Config.ModBreakerMode)
|
||||||
|
{
|
||||||
|
Config.SelectCorePackage(ContentPackage.CorePackages.GetRandom());
|
||||||
|
foreach (var regularPackage in ContentPackage.RegularPackages)
|
||||||
|
{
|
||||||
|
if (Rand.Range(0.0, 1.0) <= 0.5)
|
||||||
|
{
|
||||||
|
Config.EnableRegularPackage(regularPackage);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Config.DisableRegularPackage(regularPackage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ContentPackage.SortContentPackages(p =>
|
||||||
|
{
|
||||||
|
return Rand.Int(int.MaxValue);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (Config.AllEnabledPackages.None())
|
if (Config.AllEnabledPackages.None())
|
||||||
{
|
{
|
||||||
@@ -535,6 +552,7 @@ namespace Barotrauma
|
|||||||
Order.Init();
|
Order.Init();
|
||||||
EventManagerSettings.Init();
|
EventManagerSettings.Init();
|
||||||
BallastFloraPrefab.LoadAll(GetFilesOfType(ContentType.MapCreature));
|
BallastFloraPrefab.LoadAll(GetFilesOfType(ContentType.MapCreature));
|
||||||
|
HintManager.Init();
|
||||||
TitleScreen.LoadState = 50.0f;
|
TitleScreen.LoadState = 50.0f;
|
||||||
yield return CoroutineStatus.Running;
|
yield return CoroutineStatus.Running;
|
||||||
|
|
||||||
@@ -904,7 +922,9 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if !DEBUG
|
#if !DEBUG
|
||||||
if (NetworkMember == null && !WindowActive && !Paused && true && Screen.Selected != MainMenuScreen && Config.PauseOnFocusLost)
|
if (NetworkMember == null && !WindowActive && !Paused && true && Config.PauseOnFocusLost &&
|
||||||
|
Screen.Selected != MainMenuScreen && Screen.Selected != ServerListScreen && Screen.Selected != NetLobbyScreen &&
|
||||||
|
Screen.Selected != SubEditorScreen && Screen.Selected != LevelEditorScreen)
|
||||||
{
|
{
|
||||||
GUI.TogglePauseMenu();
|
GUI.TogglePauseMenu();
|
||||||
Paused = true;
|
Paused = true;
|
||||||
@@ -918,6 +938,8 @@ namespace Barotrauma
|
|||||||
Client.AddToGUIUpdateList();
|
Client.AddToGUIUpdateList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SubmarinePreview.AddToGUIUpdateList();
|
||||||
|
|
||||||
FileSelection.AddToGUIUpdateList();
|
FileSelection.AddToGUIUpdateList();
|
||||||
|
|
||||||
DebugConsole.AddToGUIUpdateList();
|
DebugConsole.AddToGUIUpdateList();
|
||||||
@@ -1044,6 +1066,8 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (save)
|
if (save)
|
||||||
{
|
{
|
||||||
|
GUI.SetSavingIndicatorState(true);
|
||||||
|
|
||||||
if (GameSession.Submarine != null && !GameSession.Submarine.Removed)
|
if (GameSession.Submarine != null && !GameSession.Submarine.Removed)
|
||||||
{
|
{
|
||||||
GameSession.SubmarineInfo = new SubmarineInfo(GameSession.Submarine);
|
GameSession.SubmarineInfo = new SubmarineInfo(GameSession.Submarine);
|
||||||
@@ -1074,13 +1098,6 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
((TutorialMode)GameSession.GameMode).Tutorial?.Stop();
|
((TutorialMode)GameSession.GameMode).Tutorial?.Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GameSettings.SendUserStatistics)
|
|
||||||
{
|
|
||||||
Mission mission = GameSession.Mission;
|
|
||||||
GameAnalyticsManager.AddDesignEvent("QuitRound:" + (save ? "Save" : "NoSave"));
|
|
||||||
GameAnalyticsManager.AddDesignEvent("EndRound:" + (mission == null ? "NoMission" : (mission.Completed ? "MissionCompleted" : "MissionFailed")));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
GUIMessageBox.CloseAll();
|
GUIMessageBox.CloseAll();
|
||||||
MainMenuScreen.Select();
|
MainMenuScreen.Select();
|
||||||
@@ -1214,13 +1231,19 @@ namespace Barotrauma
|
|||||||
base.OnExiting(sender, args);
|
base.OnExiting(sender, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ShowOpenUrlInWebBrowserPrompt(string url)
|
public void ShowOpenUrlInWebBrowserPrompt(string url, string promptExtensionTag = null)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(url)) { return; }
|
if (string.IsNullOrEmpty(url)) { return; }
|
||||||
if (GUIMessageBox.VisibleBox?.UserData as string == "verificationprompt") { return; }
|
if (GUIMessageBox.VisibleBox?.UserData as string == "verificationprompt") { return; }
|
||||||
|
|
||||||
var msgBox = new GUIMessageBox("", TextManager.GetWithVariable("openlinkinbrowserprompt", "[link]", url),
|
string text = TextManager.GetWithVariable("openlinkinbrowserprompt", "[link]", url);
|
||||||
new string[] { TextManager.Get("Yes"), TextManager.Get("No") })
|
string extensionText = TextManager.Get(promptExtensionTag, returnNull: true, useEnglishAsFallBack: false);
|
||||||
|
if (!string.IsNullOrEmpty(extensionText))
|
||||||
|
{
|
||||||
|
text += $"\n\n{extensionText}";
|
||||||
|
}
|
||||||
|
|
||||||
|
var msgBox = new GUIMessageBox("", text, new string[] { TextManager.Get("Yes"), TextManager.Get("No") })
|
||||||
{
|
{
|
||||||
UserData = "verificationprompt"
|
UserData = "verificationprompt"
|
||||||
};
|
};
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -18,6 +18,8 @@ namespace Barotrauma
|
|||||||
protected Color overlayTextColor;
|
protected Color overlayTextColor;
|
||||||
protected Sprite overlaySprite;
|
protected Sprite overlaySprite;
|
||||||
|
|
||||||
|
private TransitionType prevCampaignUIAutoOpenType;
|
||||||
|
|
||||||
protected GUIButton endRoundButton;
|
protected GUIButton endRoundButton;
|
||||||
|
|
||||||
public GUIButton ReadyCheckButton;
|
public GUIButton ReadyCheckButton;
|
||||||
@@ -53,19 +55,26 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
chatBox.ToggleOpen = wasChatBoxOpen;
|
chatBox.ToggleOpen = wasChatBoxOpen;
|
||||||
}
|
}
|
||||||
|
if (!value && CampaignUI?.SelectedTab == InteractionType.PurchaseSub)
|
||||||
|
{
|
||||||
|
SubmarinePreview.Close();
|
||||||
|
}
|
||||||
showCampaignUI = value;
|
showCampaignUI = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void ShowStartMessage()
|
public override void ShowStartMessage()
|
||||||
{
|
{
|
||||||
if (Mission == null) return;
|
foreach (Mission mission in Missions)
|
||||||
|
|
||||||
new GUIMessageBox(Mission.Name, Mission.Description, new string[0], type: GUIMessageBox.Type.InGame, icon: Mission.Prefab.Icon)
|
|
||||||
{
|
{
|
||||||
IconColor = Mission.Prefab.IconColor,
|
new GUIMessageBox(
|
||||||
UserData = "missionstartmessage"
|
mission.Prefab.IsSideObjective ? TextManager.AddPunctuation(':', TextManager.Get("sideobjective"), mission.Name) : mission.Name,
|
||||||
};
|
mission.Description, new string[0], type: GUIMessageBox.Type.InGame, icon: mission.Prefab.Icon, parseRichText: true)
|
||||||
|
{
|
||||||
|
IconColor = mission.Prefab.IconColor,
|
||||||
|
UserData = "missionstartmessage"
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -119,22 +128,22 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
var backgroundSprite = GUI.Style.GetComponentStyle("CommandBackground").GetDefaultSprite();
|
var backgroundSprite = GUI.Style.GetComponentStyle("CommandBackground").GetDefaultSprite();
|
||||||
Vector2 centerPos = new Vector2(GameMain.GraphicsWidth, GameMain.GraphicsHeight) / 2;
|
Vector2 centerPos = new Vector2(GameMain.GraphicsWidth, GameMain.GraphicsHeight) / 2;
|
||||||
|
string wrappedText = ToolBox.WrapText(overlayText, GameMain.GraphicsWidth / 3, GUI.Font);
|
||||||
|
Vector2 textSize = GUI.Font.MeasureString(wrappedText);
|
||||||
|
Vector2 textPos = centerPos - textSize / 2;
|
||||||
backgroundSprite.Draw(spriteBatch,
|
backgroundSprite.Draw(spriteBatch,
|
||||||
centerPos,
|
centerPos,
|
||||||
Color.White * (overlayTextColor.A / 255.0f),
|
Color.White * (overlayTextColor.A / 255.0f),
|
||||||
origin: backgroundSprite.size / 2,
|
origin: backgroundSprite.size / 2,
|
||||||
rotate: 0.0f,
|
rotate: 0.0f,
|
||||||
scale: new Vector2(1.5f, 0.7f) * (GameMain.GraphicsWidth / 3 / backgroundSprite.size.X));
|
scale: new Vector2(GameMain.GraphicsWidth / 2 / backgroundSprite.size.X, textSize.Y / backgroundSprite.size.Y * 1.5f));
|
||||||
|
|
||||||
string wrappedText = ToolBox.WrapText(overlayText, GameMain.GraphicsWidth / 3, GUI.Font);
|
|
||||||
Vector2 textSize = GUI.Font.MeasureString(wrappedText);
|
|
||||||
Vector2 textPos = centerPos - textSize / 2;
|
|
||||||
GUI.DrawString(spriteBatch, textPos + Vector2.One, wrappedText, Color.Black * (overlayTextColor.A / 255.0f));
|
GUI.DrawString(spriteBatch, textPos + Vector2.One, wrappedText, Color.Black * (overlayTextColor.A / 255.0f));
|
||||||
GUI.DrawString(spriteBatch, textPos, wrappedText, overlayTextColor);
|
GUI.DrawString(spriteBatch, textPos, wrappedText, overlayTextColor);
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(overlayTextBottom))
|
if (!string.IsNullOrEmpty(overlayTextBottom))
|
||||||
{
|
{
|
||||||
Vector2 bottomTextPos = centerPos + new Vector2(0.0f, textSize.Y + 30 * GUI.Scale) - GUI.Font.MeasureString(overlayTextBottom) / 2;
|
Vector2 bottomTextPos = centerPos + new Vector2(0.0f, textSize.Y / 2 + 40 * GUI.Scale) - GUI.Font.MeasureString(overlayTextBottom) / 2;
|
||||||
GUI.DrawString(spriteBatch, bottomTextPos + Vector2.One, overlayTextBottom, Color.Black * (overlayTextColor.A / 255.0f));
|
GUI.DrawString(spriteBatch, bottomTextPos + Vector2.One, overlayTextBottom, Color.Black * (overlayTextColor.A / 255.0f));
|
||||||
GUI.DrawString(spriteBatch, bottomTextPos, overlayTextBottom, overlayTextColor);
|
GUI.DrawString(spriteBatch, bottomTextPos, overlayTextBottom, overlayTextColor);
|
||||||
}
|
}
|
||||||
@@ -147,7 +156,7 @@ namespace Barotrauma
|
|||||||
if (ReadyCheckButton != null) { ReadyCheckButton.Visible = false; }
|
if (ReadyCheckButton != null) { ReadyCheckButton.Visible = false; }
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (Submarine.MainSub == null) { return; }
|
if (Submarine.MainSub == null || Level.Loaded == null) { return; }
|
||||||
|
|
||||||
endRoundButton.Visible = false;
|
endRoundButton.Visible = false;
|
||||||
var availableTransition = GetAvailableTransition(out _, out Submarine leavingSub);
|
var availableTransition = GetAvailableTransition(out _, out Submarine leavingSub);
|
||||||
@@ -158,7 +167,8 @@ namespace Barotrauma
|
|||||||
case TransitionType.ProgressToNextEmptyLocation:
|
case TransitionType.ProgressToNextEmptyLocation:
|
||||||
if (Level.Loaded.EndOutpost == null || !Level.Loaded.EndOutpost.DockedTo.Contains(leavingSub))
|
if (Level.Loaded.EndOutpost == null || !Level.Loaded.EndOutpost.DockedTo.Contains(leavingSub))
|
||||||
{
|
{
|
||||||
buttonText = TextManager.GetWithVariable("EnterLocation", "[locationname]", Level.Loaded.EndLocation?.Name ?? "[ERROR]");
|
string textTag = availableTransition == TransitionType.ProgressToNextLocation ? "EnterLocation" : "EnterEmptyLocation";
|
||||||
|
buttonText = TextManager.GetWithVariable(textTag, "[locationname]", Level.Loaded.EndLocation?.Name ?? "[ERROR]");
|
||||||
endRoundButton.Visible = !ForceMapUI && !ShowCampaignUI;
|
endRoundButton.Visible = !ForceMapUI && !ShowCampaignUI;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -170,7 +180,8 @@ namespace Barotrauma
|
|||||||
case TransitionType.ReturnToPreviousEmptyLocation:
|
case TransitionType.ReturnToPreviousEmptyLocation:
|
||||||
if (Level.Loaded.StartOutpost == null || !Level.Loaded.StartOutpost.DockedTo.Contains(leavingSub))
|
if (Level.Loaded.StartOutpost == null || !Level.Loaded.StartOutpost.DockedTo.Contains(leavingSub))
|
||||||
{
|
{
|
||||||
buttonText = TextManager.GetWithVariable("EnterLocation", "[locationname]", Level.Loaded.StartLocation?.Name ?? "[ERROR]");
|
string textTag = availableTransition == TransitionType.ReturnToPreviousLocation ? "EnterLocation" : "EnterEmptyLocation";
|
||||||
|
buttonText = TextManager.GetWithVariable(textTag, "[locationname]", Level.Loaded.StartLocation?.Name ?? "[ERROR]");
|
||||||
endRoundButton.Visible = !ForceMapUI && !ShowCampaignUI;
|
endRoundButton.Visible = !ForceMapUI && !ShowCampaignUI;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -194,7 +205,20 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (endRoundButton.Visible)
|
if (endRoundButton.Visible)
|
||||||
{
|
{
|
||||||
if (!AllowedToEndRound()) { buttonText = TextManager.Get("map"); }
|
if (!AllowedToEndRound())
|
||||||
|
{
|
||||||
|
buttonText = TextManager.Get("map");
|
||||||
|
}
|
||||||
|
else if (prevCampaignUIAutoOpenType != availableTransition &&
|
||||||
|
(availableTransition == TransitionType.ProgressToNextEmptyLocation || availableTransition == TransitionType.ReturnToPreviousEmptyLocation))
|
||||||
|
{
|
||||||
|
HintManager.OnAvailableTransition(availableTransition);
|
||||||
|
//opening the campaign map pauses the game and prevents HintManager from running -> update it manually to get the hint to show up immediately
|
||||||
|
HintManager.Update();
|
||||||
|
Map.SelectLocation(-1);
|
||||||
|
endRoundButton.OnClicked(EndRoundButton, null);
|
||||||
|
prevCampaignUIAutoOpenType = availableTransition;
|
||||||
|
}
|
||||||
endRoundButton.Text = ToolBox.LimitString(buttonText, endRoundButton.Font, endRoundButton.Rect.Width - 5);
|
endRoundButton.Text = ToolBox.LimitString(buttonText, endRoundButton.Font, endRoundButton.Rect.Width - 5);
|
||||||
if (endRoundButton.Text != buttonText)
|
if (endRoundButton.Text != buttonText)
|
||||||
{
|
{
|
||||||
@@ -209,15 +233,20 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
endRoundButton.RectTransform.ScreenSpaceOffset = new Point(0, Character.Controlled.CharacterHealth.SuicideButton.Rect.Height);
|
endRoundButton.RectTransform.ScreenSpaceOffset = new Point(0, Character.Controlled.CharacterHealth.SuicideButton.Rect.Height);
|
||||||
}
|
}
|
||||||
|
else if (GameMain.Client != null && GameMain.Client.IsFollowSubTickBoxVisible)
|
||||||
|
{
|
||||||
|
endRoundButton.RectTransform.ScreenSpaceOffset = new Point(0, HUDLayoutSettings.Padding + GameMain.Client.FollowSubTickBox.Rect.Height);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
endRoundButton.RectTransform.ScreenSpaceOffset = Point.Zero;
|
endRoundButton.RectTransform.ScreenSpaceOffset = Point.Zero;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
endRoundButton.DrawManually(spriteBatch);
|
endRoundButton.DrawManually(spriteBatch);
|
||||||
if (this is MultiPlayerCampaign)
|
if (this is MultiPlayerCampaign && ReadyCheckButton != null)
|
||||||
{
|
{
|
||||||
ReadyCheckButton?.DrawManually(spriteBatch);
|
ReadyCheckButton.RectTransform.ScreenSpaceOffset = endRoundButton.RectTransform.ScreenSpaceOffset;
|
||||||
|
ReadyCheckButton.DrawManually(spriteBatch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+62
-23
@@ -227,6 +227,11 @@ namespace Barotrauma
|
|||||||
float timer = 0.0f;
|
float timer = 0.0f;
|
||||||
while (timer < textDuration)
|
while (timer < textDuration)
|
||||||
{
|
{
|
||||||
|
if (GameMain.GameSession == null || Screen.Selected != GameMain.GameScreen)
|
||||||
|
{
|
||||||
|
GUI.DisableHUD = false;
|
||||||
|
yield return CoroutineStatus.Success;
|
||||||
|
}
|
||||||
// Try to grab the controlled here to prevent inputs, assigned late on multiplayer
|
// Try to grab the controlled here to prevent inputs, assigned late on multiplayer
|
||||||
if (Character.Controlled != null)
|
if (Character.Controlled != null)
|
||||||
{
|
{
|
||||||
@@ -239,11 +244,20 @@ namespace Barotrauma
|
|||||||
timer = Math.Min(timer + CoroutineManager.DeltaTime, textDuration);
|
timer = Math.Min(timer + CoroutineManager.DeltaTime, textDuration);
|
||||||
yield return CoroutineStatus.Running;
|
yield return CoroutineStatus.Running;
|
||||||
}
|
}
|
||||||
|
var outpost = GameMain.GameSession.Level.StartOutpost;
|
||||||
|
var borders = outpost.GetDockedBorders();
|
||||||
|
borders.Location += outpost.WorldPosition.ToPoint();
|
||||||
|
GameMain.GameScreen.Cam.Position = new Vector2(borders.X + borders.Width / 2, borders.Y - borders.Height / 2);
|
||||||
|
float startZoom = 0.8f /
|
||||||
|
((float)Math.Max(borders.Width, borders.Height) / (float)GameMain.GameScreen.Cam.Resolution.X);
|
||||||
|
GameMain.GameScreen.Cam.MinZoom = Math.Min(startZoom, GameMain.GameScreen.Cam.MinZoom);
|
||||||
var transition = new CameraTransition(prevControlled, GameMain.GameScreen.Cam,
|
var transition = new CameraTransition(prevControlled, GameMain.GameScreen.Cam,
|
||||||
null, null,
|
null, null,
|
||||||
fadeOut: false,
|
fadeOut: false,
|
||||||
duration: 5,
|
losFadeIn: true,
|
||||||
startZoom: 1.5f, endZoom: 1.0f)
|
waitDuration: 1,
|
||||||
|
panDuration: 5,
|
||||||
|
startZoom: startZoom, endZoom: 1.0f)
|
||||||
{
|
{
|
||||||
AllowInterrupt = true,
|
AllowInterrupt = true,
|
||||||
RemoveControlFromCharacter = false
|
RemoveControlFromCharacter = false
|
||||||
@@ -274,7 +288,8 @@ namespace Barotrauma
|
|||||||
var transition = new CameraTransition(Submarine.MainSub, GameMain.GameScreen.Cam,
|
var transition = new CameraTransition(Submarine.MainSub, GameMain.GameScreen.Cam,
|
||||||
null, null,
|
null, null,
|
||||||
fadeOut: false,
|
fadeOut: false,
|
||||||
duration: 5,
|
losFadeIn: true,
|
||||||
|
panDuration: 5,
|
||||||
startZoom: 0.5f, endZoom: 1.0f)
|
startZoom: 0.5f, endZoom: 1.0f)
|
||||||
{
|
{
|
||||||
AllowInterrupt = true,
|
AllowInterrupt = true,
|
||||||
@@ -311,6 +326,7 @@ namespace Barotrauma
|
|||||||
Level prevLevel = Level.Loaded;
|
Level prevLevel = Level.Loaded;
|
||||||
|
|
||||||
bool success = CrewManager.GetCharacters().Any(c => !c.IsDead);
|
bool success = CrewManager.GetCharacters().Any(c => !c.IsDead);
|
||||||
|
GUI.SetSavingIndicatorState(success);
|
||||||
crewDead = false;
|
crewDead = false;
|
||||||
|
|
||||||
var continueButton = GameMain.GameSession.RoundSummary?.ContinueButton;
|
var continueButton = GameMain.GameSession.RoundSummary?.ContinueButton;
|
||||||
@@ -327,7 +343,7 @@ namespace Barotrauma
|
|||||||
var endTransition = new CameraTransition(Submarine.MainSub, GameMain.GameScreen.Cam, null,
|
var endTransition = new CameraTransition(Submarine.MainSub, GameMain.GameScreen.Cam, null,
|
||||||
Alignment.Center,
|
Alignment.Center,
|
||||||
fadeOut: false,
|
fadeOut: false,
|
||||||
duration: EndTransitionDuration);
|
panDuration: EndTransitionDuration);
|
||||||
GameMain.Client.EndCinematic = endTransition;
|
GameMain.Client.EndCinematic = endTransition;
|
||||||
|
|
||||||
Location portraitLocation = Map?.SelectedLocation ?? Map?.CurrentLocation ?? Level.Loaded?.StartLocation;
|
Location portraitLocation = Map?.SelectedLocation ?? Map?.CurrentLocation ?? Level.Loaded?.StartLocation;
|
||||||
@@ -335,7 +351,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
overlaySprite = portraitLocation.Type.GetPortrait(portraitLocation.PortraitId);
|
overlaySprite = portraitLocation.Type.GetPortrait(portraitLocation.PortraitId);
|
||||||
}
|
}
|
||||||
float fadeOutDuration = endTransition.Duration;
|
float fadeOutDuration = endTransition.PanDuration;
|
||||||
float t = 0.0f;
|
float t = 0.0f;
|
||||||
while (t < fadeOutDuration || endTransition.Running)
|
while (t < fadeOutDuration || endTransition.Running)
|
||||||
{
|
{
|
||||||
@@ -368,6 +384,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GUI.SetSavingIndicatorState(false);
|
||||||
yield return CoroutineStatus.Success;
|
yield return CoroutineStatus.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -420,7 +437,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
//wasn't initially docked (sub doesn't have a docking port?)
|
//wasn't initially docked (sub doesn't have a docking port?)
|
||||||
// -> choose a destination when the sub is far enough from the start outpost
|
// -> choose a destination when the sub is far enough from the start outpost
|
||||||
if (!Submarine.MainSub.AtStartPosition)
|
if (!Submarine.MainSub.AtStartExit)
|
||||||
{
|
{
|
||||||
ForceMapUI = true;
|
ForceMapUI = true;
|
||||||
if (CampaignUI == null) { InitCampaignUI(); }
|
if (CampaignUI == null) { InitCampaignUI(); }
|
||||||
@@ -437,8 +454,10 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
ShowCampaignUI = false;
|
ShowCampaignUI = false;
|
||||||
}
|
}
|
||||||
|
HintManager.OnAvailableTransition(transitionType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void End(TransitionType transitionType = TransitionType.None)
|
public override void End(TransitionType transitionType = TransitionType.None)
|
||||||
{
|
{
|
||||||
base.End(transitionType);
|
base.End(transitionType);
|
||||||
@@ -496,7 +515,7 @@ namespace Barotrauma
|
|||||||
var transition = new CameraTransition(endObject ?? Submarine.MainSub, GameMain.GameScreen.Cam,
|
var transition = new CameraTransition(endObject ?? Submarine.MainSub, GameMain.GameScreen.Cam,
|
||||||
null, Alignment.Center,
|
null, Alignment.Center,
|
||||||
fadeOut: true,
|
fadeOut: true,
|
||||||
duration: 10,
|
panDuration: 10,
|
||||||
startZoom: null, endZoom: 0.2f);
|
startZoom: null, endZoom: 0.2f);
|
||||||
|
|
||||||
while (transition.Running)
|
while (transition.Running)
|
||||||
@@ -649,7 +668,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
string savePath = SaveUtil.CreateSavePath(SaveUtil.SaveType.Multiplayer);
|
string savePath = SaveUtil.CreateSavePath(SaveUtil.SaveType.Multiplayer);
|
||||||
|
|
||||||
GameMain.GameSession = new GameSession(null, savePath, GameModePreset.MultiPlayerCampaign, mapSeed);
|
GameMain.GameSession = new GameSession(null, savePath, GameModePreset.MultiPlayerCampaign, CampaignSettings.Unsure, mapSeed);
|
||||||
campaign = (MultiPlayerCampaign)GameMain.GameSession.GameMode;
|
campaign = (MultiPlayerCampaign)GameMain.GameSession.GameMode;
|
||||||
campaign.CampaignID = campaignID;
|
campaign.CampaignID = campaignID;
|
||||||
GameMain.NetLobbyScreen.ToggleCampaignMode(true);
|
GameMain.NetLobbyScreen.ToggleCampaignMode(true);
|
||||||
@@ -711,13 +730,20 @@ namespace Barotrauma
|
|||||||
DebugConsole.ThrowError($"Error when receiving campaign data from the server: mission prefab \"{availableMission.First}\" not found.");
|
DebugConsole.ThrowError($"Error when receiving campaign data from the server: mission prefab \"{availableMission.First}\" not found.");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (availableMission.Second < 0 || availableMission.Second >= campaign.Map.CurrentLocation.Connections.Count)
|
if (availableMission.Second == 255)
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError($"Error when receiving campaign data from the server: connection index for mission \"{availableMission.First}\" out of range (index: {availableMission.Second}, current location: {campaign.Map.CurrentLocation.Name}, connections: {campaign.Map.CurrentLocation.Connections.Count}).");
|
campaign.Map.CurrentLocation.UnlockMission(missionPrefab);
|
||||||
continue;
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (availableMission.Second < 0 || availableMission.Second >= campaign.Map.CurrentLocation.Connections.Count)
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError($"Error when receiving campaign data from the server: connection index for mission \"{availableMission.First}\" out of range (index: {availableMission.Second}, current location: {campaign.Map.CurrentLocation.Name}, connections: {campaign.Map.CurrentLocation.Connections.Count}).");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
LocationConnection connection = campaign.Map.CurrentLocation.Connections[availableMission.Second];
|
||||||
|
campaign.Map.CurrentLocation.UnlockMission(missionPrefab, connection);
|
||||||
}
|
}
|
||||||
LocationConnection connection = campaign.Map.CurrentLocation.Connections[availableMission.Second];
|
|
||||||
campaign.Map.CurrentLocation.UnlockMission(missionPrefab, connection);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GameMain.NetLobbyScreen.ToggleCampaignMode(true);
|
GameMain.NetLobbyScreen.ToggleCampaignMode(true);
|
||||||
@@ -770,16 +796,29 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
pendingHires.Add(msg.ReadInt32());
|
pendingHires.Add(msg.ReadInt32());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool validateHires = msg.ReadBoolean();
|
ushort hiredLength = msg.ReadUInt16();
|
||||||
|
List<CharacterInfo> hiredCharacters = new List<CharacterInfo>();
|
||||||
|
for (int i = 0; i < hiredLength; i++)
|
||||||
|
{
|
||||||
|
CharacterInfo hired = CharacterInfo.ClientRead("human", msg);
|
||||||
|
hired.Salary = msg.ReadInt32();
|
||||||
|
hiredCharacters.Add(hired);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool renameCrewMember = msg.ReadBoolean();
|
||||||
|
if (renameCrewMember)
|
||||||
|
{
|
||||||
|
int renamedIdentifier = msg.ReadInt32();
|
||||||
|
string newName = msg.ReadString();
|
||||||
|
CharacterInfo renamedCharacter = CrewManager.CharacterInfos.FirstOrDefault(info => info.GetIdentifierUsingOriginalName() == renamedIdentifier);
|
||||||
|
if (renamedCharacter != null) { CrewManager.RenameCharacter(renamedCharacter, newName); }
|
||||||
|
}
|
||||||
|
|
||||||
bool fireCharacter = msg.ReadBoolean();
|
bool fireCharacter = msg.ReadBoolean();
|
||||||
|
|
||||||
int firedIdentifier = -1;
|
|
||||||
if (fireCharacter) { firedIdentifier = msg.ReadInt32(); }
|
|
||||||
|
|
||||||
if (fireCharacter)
|
if (fireCharacter)
|
||||||
{
|
{
|
||||||
|
int firedIdentifier = msg.ReadInt32();
|
||||||
CharacterInfo firedCharacter = CrewManager.CharacterInfos.FirstOrDefault(info => info.GetIdentifier() == firedIdentifier);
|
CharacterInfo firedCharacter = CrewManager.CharacterInfos.FirstOrDefault(info => info.GetIdentifier() == firedIdentifier);
|
||||||
// this one might and is allowed to be null since the character is already fired on the original sender's game
|
// this one might and is allowed to be null since the character is already fired on the original sender's game
|
||||||
if (firedCharacter != null) { CrewManager.FireCharacter(firedCharacter); }
|
if (firedCharacter != null) { CrewManager.FireCharacter(firedCharacter); }
|
||||||
@@ -787,10 +826,10 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (map?.CurrentLocation?.HireManager != null && CampaignUI?.CrewManagement != null)
|
if (map?.CurrentLocation?.HireManager != null && CampaignUI?.CrewManagement != null)
|
||||||
{
|
{
|
||||||
CampaignUI?.CrewManagement?.SetHireables(map.CurrentLocation, availableHires);
|
CampaignUI.CrewManagement.SetHireables(map.CurrentLocation, availableHires);
|
||||||
if (validateHires) { CampaignUI?.CrewManagement.ValidatePendingHires(); }
|
if (hiredCharacters.Any()) { CampaignUI.CrewManagement.ValidateHires(hiredCharacters); }
|
||||||
CampaignUI?.CrewManagement?.SetPendingHires(pendingHires, map?.CurrentLocation);
|
CampaignUI.CrewManagement.SetPendingHires(pendingHires, map.CurrentLocation);
|
||||||
if (fireCharacter) { CampaignUI?.CrewManagement.UpdateCrew(); }
|
if (renameCrewMember || fireCharacter) { CampaignUI.CrewManagement.UpdateCrew(); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+43
-27
@@ -22,7 +22,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (CoroutineManager.IsCoroutineRunning("LevelTransition") || CoroutineManager.IsCoroutineRunning("SubmarineTransition") || gameOver) { return; }
|
if (CoroutineManager.IsCoroutineRunning("LevelTransition") || CoroutineManager.IsCoroutineRunning("SubmarineTransition") || gameOver) { return; }
|
||||||
|
|
||||||
if (PlayerInput.RightButtonClicked() ||
|
if (PlayerInput.SecondaryMouseButtonClicked() ||
|
||||||
PlayerInput.KeyHit(Microsoft.Xna.Framework.Input.Keys.Escape))
|
PlayerInput.KeyHit(Microsoft.Xna.Framework.Input.Keys.Escape))
|
||||||
{
|
{
|
||||||
ShowCampaignUI = false;
|
ShowCampaignUI = false;
|
||||||
@@ -57,11 +57,12 @@ namespace Barotrauma
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Instantiates a new single player campaign
|
/// Instantiates a new single player campaign
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private SinglePlayerCampaign(string mapSeed) : base(GameModePreset.SinglePlayerCampaign)
|
private SinglePlayerCampaign(string mapSeed, CampaignSettings settings) : base(GameModePreset.SinglePlayerCampaign)
|
||||||
{
|
{
|
||||||
CampaignMetadata = new CampaignMetadata(this);
|
CampaignMetadata = new CampaignMetadata(this);
|
||||||
UpgradeManager = new UpgradeManager(this);
|
UpgradeManager = new UpgradeManager(this);
|
||||||
map = new Map(this, mapSeed);
|
map = new Map(this, mapSeed, settings);
|
||||||
|
Settings = settings;
|
||||||
foreach (JobPrefab jobPrefab in JobPrefab.Prefabs)
|
foreach (JobPrefab jobPrefab in JobPrefab.Prefabs)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < jobPrefab.InitialCount; i++)
|
for (int i = 0; i < jobPrefab.InitialCount; i++)
|
||||||
@@ -85,11 +86,14 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||||
{
|
{
|
||||||
|
case "campaignsettings":
|
||||||
|
Settings = new CampaignSettings(subElement);
|
||||||
|
break;
|
||||||
case "crew":
|
case "crew":
|
||||||
GameMain.GameSession.CrewManager = new CrewManager(subElement, true);
|
GameMain.GameSession.CrewManager = new CrewManager(subElement, true);
|
||||||
break;
|
break;
|
||||||
case "map":
|
case "map":
|
||||||
map = Map.Load(this, subElement);
|
map = Map.Load(this, subElement, Settings);
|
||||||
break;
|
break;
|
||||||
case "metadata":
|
case "metadata":
|
||||||
CampaignMetadata = new CampaignMetadata(this, subElement);
|
CampaignMetadata = new CampaignMetadata(this, subElement);
|
||||||
@@ -141,9 +145,9 @@ namespace Barotrauma
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Start a completely new single player campaign
|
/// Start a completely new single player campaign
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static SinglePlayerCampaign StartNew(string mapSeed, SubmarineInfo selectedSub)
|
public static SinglePlayerCampaign StartNew(string mapSeed, SubmarineInfo selectedSub, CampaignSettings settings)
|
||||||
{
|
{
|
||||||
var campaign = new SinglePlayerCampaign(mapSeed);
|
var campaign = new SinglePlayerCampaign(mapSeed, settings);
|
||||||
return campaign;
|
return campaign;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,6 +217,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (!savedOnStart)
|
if (!savedOnStart)
|
||||||
{
|
{
|
||||||
|
GUI.SetSavingIndicatorState(true);
|
||||||
SaveUtil.SaveGame(GameMain.GameSession.SavePath);
|
SaveUtil.SaveGame(GameMain.GameSession.SavePath);
|
||||||
savedOnStart = true;
|
savedOnStart = true;
|
||||||
}
|
}
|
||||||
@@ -224,6 +229,8 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
PetBehavior.LoadPets(petsElement);
|
PetBehavior.LoadPets(petsElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GUI.DisableSavingIndicatorDelayed();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void LoadInitialLevel()
|
protected override void LoadInitialLevel()
|
||||||
@@ -290,15 +297,29 @@ namespace Barotrauma
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (GameMain.GameSession == null)
|
||||||
|
{
|
||||||
|
GUI.DisableHUD = false;
|
||||||
|
yield return CoroutineStatus.Success;
|
||||||
|
}
|
||||||
overlayTextColor = Color.Lerp(Color.Transparent, Color.White, (timer - 1.0f) / fadeInDuration);
|
overlayTextColor = Color.Lerp(Color.Transparent, Color.White, (timer - 1.0f) / fadeInDuration);
|
||||||
timer = Math.Min(timer + CoroutineManager.DeltaTime, textDuration);
|
timer = Math.Min(timer + CoroutineManager.DeltaTime, textDuration);
|
||||||
yield return CoroutineStatus.Running;
|
yield return CoroutineStatus.Running;
|
||||||
}
|
}
|
||||||
|
var outpost = GameMain.GameSession.Level.StartOutpost;
|
||||||
|
var borders = outpost.GetDockedBorders();
|
||||||
|
borders.Location += outpost.WorldPosition.ToPoint();
|
||||||
|
GameMain.GameScreen.Cam.Position = new Vector2(borders.X + borders.Width / 2, borders.Y - borders.Height / 2);
|
||||||
|
float startZoom = 0.8f /
|
||||||
|
((float)Math.Max(borders.Width, borders.Height) / (float)GameMain.GameScreen.Cam.Resolution.X);
|
||||||
|
GameMain.GameScreen.Cam.MinZoom = Math.Min(startZoom, GameMain.GameScreen.Cam.MinZoom);
|
||||||
var transition = new CameraTransition(prevControlled, GameMain.GameScreen.Cam,
|
var transition = new CameraTransition(prevControlled, GameMain.GameScreen.Cam,
|
||||||
null, null,
|
null, null,
|
||||||
fadeOut: false,
|
fadeOut: false,
|
||||||
duration: 5,
|
losFadeIn: true,
|
||||||
startZoom: 1.5f, endZoom: 1.0f)
|
waitDuration: 1,
|
||||||
|
panDuration: 5,
|
||||||
|
startZoom: startZoom, endZoom: 1.0f)
|
||||||
{
|
{
|
||||||
AllowInterrupt = true,
|
AllowInterrupt = true,
|
||||||
RemoveControlFromCharacter = false
|
RemoveControlFromCharacter = false
|
||||||
@@ -323,19 +344,13 @@ namespace Barotrauma
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
ISpatialEntity transitionTarget;
|
ISpatialEntity transitionTarget;
|
||||||
if (prevControlled != null)
|
transitionTarget = (ISpatialEntity)prevControlled ?? Submarine.MainSub;
|
||||||
{
|
|
||||||
transitionTarget = prevControlled;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
transitionTarget = Submarine.MainSub;
|
|
||||||
}
|
|
||||||
|
|
||||||
var transition = new CameraTransition(transitionTarget, GameMain.GameScreen.Cam,
|
var transition = new CameraTransition(transitionTarget, GameMain.GameScreen.Cam,
|
||||||
null, null,
|
null, null,
|
||||||
fadeOut: false,
|
fadeOut: false,
|
||||||
duration: 5,
|
losFadeIn: prevControlled != null,
|
||||||
|
panDuration: 5,
|
||||||
startZoom: 0.5f, endZoom: 1.0f)
|
startZoom: 0.5f, endZoom: 1.0f)
|
||||||
{
|
{
|
||||||
AllowInterrupt = true,
|
AllowInterrupt = true,
|
||||||
@@ -370,11 +385,9 @@ namespace Barotrauma
|
|||||||
bool success = CrewManager.GetCharacters().Any(c => !c.IsDead);
|
bool success = CrewManager.GetCharacters().Any(c => !c.IsDead);
|
||||||
SoundPlayer.OverrideMusicType = success ? "endround" : "crewdead";
|
SoundPlayer.OverrideMusicType = success ? "endround" : "crewdead";
|
||||||
SoundPlayer.OverrideMusicDuration = 18.0f;
|
SoundPlayer.OverrideMusicDuration = 18.0f;
|
||||||
|
GUI.SetSavingIndicatorState(success);
|
||||||
crewDead = false;
|
crewDead = false;
|
||||||
|
|
||||||
LevelData lvlData = GameMain.GameSession.LevelData;
|
|
||||||
bool beaconActive = GameMain.GameSession.Level.CheckBeaconActive();
|
|
||||||
|
|
||||||
GameMain.GameSession.EndRound("", traitorResults, transitionType);
|
GameMain.GameSession.EndRound("", traitorResults, transitionType);
|
||||||
var continueButton = GameMain.GameSession.RoundSummary?.ContinueButton;
|
var continueButton = GameMain.GameSession.RoundSummary?.ContinueButton;
|
||||||
RoundSummary roundSummary = null;
|
RoundSummary roundSummary = null;
|
||||||
@@ -408,13 +421,13 @@ namespace Barotrauma
|
|||||||
var endTransition = new CameraTransition(Submarine.MainSub, GameMain.GameScreen.Cam, null,
|
var endTransition = new CameraTransition(Submarine.MainSub, GameMain.GameScreen.Cam, null,
|
||||||
transitionType == TransitionType.LeaveLocation ? Alignment.BottomCenter : Alignment.Center,
|
transitionType == TransitionType.LeaveLocation ? Alignment.BottomCenter : Alignment.Center,
|
||||||
fadeOut: false,
|
fadeOut: false,
|
||||||
duration: EndTransitionDuration);
|
panDuration: EndTransitionDuration);
|
||||||
|
|
||||||
GUI.ClearMessages();
|
GUI.ClearMessages();
|
||||||
|
|
||||||
Location portraitLocation = Map.SelectedLocation ?? Map.CurrentLocation;
|
Location portraitLocation = Map.SelectedLocation ?? Map.CurrentLocation;
|
||||||
overlaySprite = portraitLocation.Type.GetPortrait(portraitLocation.PortraitId);
|
overlaySprite = portraitLocation.Type.GetPortrait(portraitLocation.PortraitId);
|
||||||
float fadeOutDuration = endTransition.Duration;
|
float fadeOutDuration = endTransition.PanDuration;
|
||||||
float t = 0.0f;
|
float t = 0.0f;
|
||||||
while (t < fadeOutDuration || endTransition.Running)
|
while (t < fadeOutDuration || endTransition.Running)
|
||||||
{
|
{
|
||||||
@@ -459,8 +472,6 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lvlData.IsBeaconActive = beaconActive;
|
|
||||||
|
|
||||||
SaveUtil.SaveGame(GameMain.GameSession.SavePath);
|
SaveUtil.SaveGame(GameMain.GameSession.SavePath);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -484,6 +495,7 @@ namespace Barotrauma
|
|||||||
overlayColor = Color.Transparent;
|
overlayColor = Color.Transparent;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
GUI.SetSavingIndicatorState(false);
|
||||||
yield return CoroutineStatus.Success;
|
yield return CoroutineStatus.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -510,7 +522,7 @@ namespace Barotrauma
|
|||||||
var transition = new CameraTransition(endObject ?? Submarine.MainSub, GameMain.GameScreen.Cam,
|
var transition = new CameraTransition(endObject ?? Submarine.MainSub, GameMain.GameScreen.Cam,
|
||||||
null, Alignment.Center,
|
null, Alignment.Center,
|
||||||
fadeOut: true,
|
fadeOut: true,
|
||||||
duration: 10,
|
panDuration: 10,
|
||||||
startZoom: null, endZoom: 0.2f);
|
startZoom: null, endZoom: 0.2f);
|
||||||
|
|
||||||
while (transition.Running)
|
while (transition.Running)
|
||||||
@@ -530,6 +542,8 @@ namespace Barotrauma
|
|||||||
if (CoroutineManager.IsCoroutineRunning("LevelTransition") || CoroutineManager.IsCoroutineRunning("SubmarineTransition") || gameOver) { return; }
|
if (CoroutineManager.IsCoroutineRunning("LevelTransition") || CoroutineManager.IsCoroutineRunning("SubmarineTransition") || gameOver) { return; }
|
||||||
|
|
||||||
base.Update(deltaTime);
|
base.Update(deltaTime);
|
||||||
|
|
||||||
|
Map?.Radiation?.UpdateRadiation(deltaTime);
|
||||||
|
|
||||||
if (PlayerInput.SecondaryMouseButtonClicked() ||
|
if (PlayerInput.SecondaryMouseButtonClicked() ||
|
||||||
PlayerInput.KeyHit(Microsoft.Xna.Framework.Input.Keys.Escape))
|
PlayerInput.KeyHit(Microsoft.Xna.Framework.Input.Keys.Escape))
|
||||||
@@ -583,7 +597,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
//wasn't initially docked (sub doesn't have a docking port?)
|
//wasn't initially docked (sub doesn't have a docking port?)
|
||||||
// -> choose a destination when the sub is far enough from the start outpost
|
// -> choose a destination when the sub is far enough from the start outpost
|
||||||
if (!Submarine.MainSub.AtStartPosition)
|
if (!Submarine.MainSub.AtStartExit)
|
||||||
{
|
{
|
||||||
ForceMapUI = true;
|
ForceMapUI = true;
|
||||||
CampaignUI.SelectTab(InteractionType.Map);
|
CampaignUI.SelectTab(InteractionType.Map);
|
||||||
@@ -611,6 +625,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
ShowCampaignUI = false;
|
ShowCampaignUI = false;
|
||||||
}
|
}
|
||||||
|
HintManager.OnAvailableTransition(transitionType);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!crewDead)
|
if (!crewDead)
|
||||||
@@ -632,9 +647,9 @@ namespace Barotrauma
|
|||||||
if (nextLevel == null)
|
if (nextLevel == null)
|
||||||
{
|
{
|
||||||
//no level selected -> force the player to select one
|
//no level selected -> force the player to select one
|
||||||
|
ForceMapUI = true;
|
||||||
CampaignUI.SelectTab(InteractionType.Map);
|
CampaignUI.SelectTab(InteractionType.Map);
|
||||||
map.SelectLocation(-1);
|
map.SelectLocation(-1);
|
||||||
ForceMapUI = true;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (transitionType == TransitionType.ProgressToNextEmptyLocation)
|
else if (transitionType == TransitionType.ProgressToNextEmptyLocation)
|
||||||
@@ -707,6 +722,7 @@ namespace Barotrauma
|
|||||||
new XAttribute("purchasedhullrepairs", PurchasedHullRepairs),
|
new XAttribute("purchasedhullrepairs", PurchasedHullRepairs),
|
||||||
new XAttribute("purchaseditemrepairs", PurchasedItemRepairs),
|
new XAttribute("purchaseditemrepairs", PurchasedItemRepairs),
|
||||||
new XAttribute("cheatsenabled", CheatsEnabled));
|
new XAttribute("cheatsenabled", CheatsEnabled));
|
||||||
|
modeElement.Add(Settings.Save());
|
||||||
|
|
||||||
//save and remove all items that are in someone's inventory so they don't get included in the sub file as well
|
//save and remove all items that are in someone's inventory so they don't get included in the sub file as well
|
||||||
foreach (Character c in Character.CharacterList)
|
foreach (Character c in Character.CharacterList)
|
||||||
|
|||||||
+1
-1
@@ -614,7 +614,7 @@ namespace Barotrauma.Tutorials
|
|||||||
GameMain.GameScreen.Cam.TargetPos = Vector2.Zero;
|
GameMain.GameScreen.Cam.TargetPos = Vector2.Zero;
|
||||||
GameMain.LightManager.LosEnabled = false;
|
GameMain.LightManager.LosEnabled = false;
|
||||||
|
|
||||||
var cinematic = new CameraTransition(Submarine.MainSub, GameMain.GameScreen.Cam, Alignment.CenterLeft, Alignment.CenterRight, duration: 5.0f);
|
var cinematic = new CameraTransition(Submarine.MainSub, GameMain.GameScreen.Cam, Alignment.CenterLeft, Alignment.CenterRight, panDuration: 5.0f);
|
||||||
|
|
||||||
while (cinematic.Running)
|
while (cinematic.Running)
|
||||||
{
|
{
|
||||||
|
|||||||
+5
-5
@@ -99,7 +99,7 @@ namespace Barotrauma.Tutorials
|
|||||||
captain_medicSpawnPos = Item.ItemList.Find(i => i.HasTag("captain_medicspawnpos")).WorldPosition;
|
captain_medicSpawnPos = Item.ItemList.Find(i => i.HasTag("captain_medicspawnpos")).WorldPosition;
|
||||||
tutorial_submarineDoor = Item.ItemList.Find(i => i.HasTag("tutorial_submarinedoor")).GetComponent<Door>();
|
tutorial_submarineDoor = Item.ItemList.Find(i => i.HasTag("tutorial_submarinedoor")).GetComponent<Door>();
|
||||||
tutorial_submarineDoorLight = Item.ItemList.Find(i => i.HasTag("tutorial_submarinedoorlight")).GetComponent<LightComponent>();
|
tutorial_submarineDoorLight = Item.ItemList.Find(i => i.HasTag("tutorial_submarinedoorlight")).GetComponent<LightComponent>();
|
||||||
var medicInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, "", JobPrefab.Get("medicaldoctor"));
|
var medicInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobPrefab: JobPrefab.Get("medicaldoctor"));
|
||||||
captain_medic = Character.Create(medicInfo, captain_medicSpawnPos, "medicaldoctor");
|
captain_medic = Character.Create(medicInfo, captain_medicSpawnPos, "medicaldoctor");
|
||||||
captain_medic.TeamID = CharacterTeamType.Team1;
|
captain_medic.TeamID = CharacterTeamType.Team1;
|
||||||
captain_medic.GiveJobItems(null);
|
captain_medic.GiveJobItems(null);
|
||||||
@@ -122,17 +122,17 @@ namespace Barotrauma.Tutorials
|
|||||||
SetDoorAccess(tutorial_lockedDoor_1, null, false);
|
SetDoorAccess(tutorial_lockedDoor_1, null, false);
|
||||||
SetDoorAccess(tutorial_lockedDoor_2, null, false);
|
SetDoorAccess(tutorial_lockedDoor_2, null, false);
|
||||||
|
|
||||||
var mechanicInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, "", JobPrefab.Get("mechanic"));
|
var mechanicInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobPrefab: JobPrefab.Get("mechanic"));
|
||||||
captain_mechanic = Character.Create(mechanicInfo, WayPoint.GetRandom(SpawnType.Human, mechanicInfo.Job, Submarine.MainSub).WorldPosition, "mechanic");
|
captain_mechanic = Character.Create(mechanicInfo, WayPoint.GetRandom(SpawnType.Human, mechanicInfo.Job, Submarine.MainSub).WorldPosition, "mechanic");
|
||||||
captain_mechanic.TeamID = CharacterTeamType.Team1;
|
captain_mechanic.TeamID = CharacterTeamType.Team1;
|
||||||
captain_mechanic.GiveJobItems();
|
captain_mechanic.GiveJobItems();
|
||||||
|
|
||||||
var securityInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, "", JobPrefab.Get("securityofficer"));
|
var securityInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobPrefab: JobPrefab.Get("securityofficer"));
|
||||||
captain_security = Character.Create(securityInfo, WayPoint.GetRandom(SpawnType.Human, securityInfo.Job, Submarine.MainSub).WorldPosition, "securityofficer");
|
captain_security = Character.Create(securityInfo, WayPoint.GetRandom(SpawnType.Human, securityInfo.Job, Submarine.MainSub).WorldPosition, "securityofficer");
|
||||||
captain_security.TeamID = CharacterTeamType.Team1;
|
captain_security.TeamID = CharacterTeamType.Team1;
|
||||||
captain_security.GiveJobItems();
|
captain_security.GiveJobItems();
|
||||||
|
|
||||||
var engineerInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, "", JobPrefab.Get("engineer"));
|
var engineerInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobPrefab: JobPrefab.Get("engineer"));
|
||||||
captain_engineer = Character.Create(engineerInfo, WayPoint.GetRandom(SpawnType.Human, engineerInfo.Job, Submarine.MainSub).WorldPosition, "engineer");
|
captain_engineer = Character.Create(engineerInfo, WayPoint.GetRandom(SpawnType.Human, engineerInfo.Job, Submarine.MainSub).WorldPosition, "engineer");
|
||||||
captain_engineer.TeamID = CharacterTeamType.Team1;
|
captain_engineer.TeamID = CharacterTeamType.Team1;
|
||||||
captain_engineer.GiveJobItems();
|
captain_engineer.GiveJobItems();
|
||||||
@@ -249,7 +249,7 @@ namespace Barotrauma.Tutorials
|
|||||||
{
|
{
|
||||||
//captain_navConsoleCustomInterface.HighlightElement(0, uiHighlightColor, duration: 1.0f, pulsateAmount: 0.0f);
|
//captain_navConsoleCustomInterface.HighlightElement(0, uiHighlightColor, duration: 1.0f, pulsateAmount: 0.0f);
|
||||||
yield return new WaitForSeconds(1.0f, false);
|
yield return new WaitForSeconds(1.0f, false);
|
||||||
} while (!Submarine.MainSub.AtEndPosition || !Submarine.MainSub.DockedTo.Any());
|
} while (!Submarine.MainSub.AtEndExit || !Submarine.MainSub.DockedTo.Any());
|
||||||
RemoveCompletedObjective(segments[6]);
|
RemoveCompletedObjective(segments[6]);
|
||||||
yield return new WaitForSeconds(3f, false);
|
yield return new WaitForSeconds(3f, false);
|
||||||
GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.GetWithVariable("Captain.Radio.Complete", "[OUTPOSTNAME]", GameMain.GameSession.EndLocation.Name), ChatMessageType.Radio, null);
|
GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.GetWithVariable("Captain.Radio.Complete", "[OUTPOSTNAME]", GameMain.GameSession.EndLocation.Name), ChatMessageType.Radio, null);
|
||||||
|
|||||||
+6
-6
@@ -78,7 +78,7 @@ namespace Barotrauma.Tutorials
|
|||||||
var patientHull2 = WayPoint.WayPointList.Find(wp => wp.IdCardDesc == "airlock").CurrentHull;
|
var patientHull2 = WayPoint.WayPointList.Find(wp => wp.IdCardDesc == "airlock").CurrentHull;
|
||||||
medBay = WayPoint.WayPointList.Find(wp => wp.IdCardDesc == "medbay").CurrentHull;
|
medBay = WayPoint.WayPointList.Find(wp => wp.IdCardDesc == "medbay").CurrentHull;
|
||||||
|
|
||||||
var assistantInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, "", JobPrefab.Get("assistant"));
|
var assistantInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobPrefab: JobPrefab.Get("assistant"));
|
||||||
patient1 = Character.Create(assistantInfo, patientHull1.WorldPosition, "1");
|
patient1 = Character.Create(assistantInfo, patientHull1.WorldPosition, "1");
|
||||||
patient1.TeamID = CharacterTeamType.Team1;
|
patient1.TeamID = CharacterTeamType.Team1;
|
||||||
patient1.GiveJobItems(null);
|
patient1.GiveJobItems(null);
|
||||||
@@ -86,26 +86,26 @@ namespace Barotrauma.Tutorials
|
|||||||
patient1.AddDamage(patient1.WorldPosition, new List<Affliction>() { new Affliction(AfflictionPrefab.Burn, 15.0f) }, stun: 0, playSound: false);
|
patient1.AddDamage(patient1.WorldPosition, new List<Affliction>() { new Affliction(AfflictionPrefab.Burn, 15.0f) }, stun: 0, playSound: false);
|
||||||
patient1.AIController.Enabled = false;
|
patient1.AIController.Enabled = false;
|
||||||
|
|
||||||
assistantInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, "", JobPrefab.Get("assistant"));
|
assistantInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobPrefab: JobPrefab.Get("assistant"));
|
||||||
patient2 = Character.Create(assistantInfo, patientHull2.WorldPosition, "2");
|
patient2 = Character.Create(assistantInfo, patientHull2.WorldPosition, "2");
|
||||||
patient2.TeamID = CharacterTeamType.Team1;
|
patient2.TeamID = CharacterTeamType.Team1;
|
||||||
patient2.GiveJobItems(null);
|
patient2.GiveJobItems(null);
|
||||||
patient2.CanSpeak = false;
|
patient2.CanSpeak = false;
|
||||||
patient2.AIController.Enabled = false;
|
patient2.AIController.Enabled = false;
|
||||||
|
|
||||||
var mechanicInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, "", JobPrefab.Get("engineer"));
|
var mechanicInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobPrefab: JobPrefab.Get("engineer"));
|
||||||
var subPatient1 = Character.Create(mechanicInfo, WayPoint.GetRandom(SpawnType.Human, mechanicInfo.Job, Submarine.MainSub).WorldPosition, "3");
|
var subPatient1 = Character.Create(mechanicInfo, WayPoint.GetRandom(SpawnType.Human, mechanicInfo.Job, Submarine.MainSub).WorldPosition, "3");
|
||||||
subPatient1.TeamID = CharacterTeamType.Team1;
|
subPatient1.TeamID = CharacterTeamType.Team1;
|
||||||
subPatient1.AddDamage(patient1.WorldPosition, new List<Affliction>() { new Affliction(AfflictionPrefab.Burn, 40.0f) }, stun: 0, playSound: false);
|
subPatient1.AddDamage(patient1.WorldPosition, new List<Affliction>() { new Affliction(AfflictionPrefab.Burn, 40.0f) }, stun: 0, playSound: false);
|
||||||
subPatients.Add(subPatient1);
|
subPatients.Add(subPatient1);
|
||||||
|
|
||||||
var securityInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, "", JobPrefab.Get("securityofficer"));
|
var securityInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobPrefab: JobPrefab.Get("securityofficer"));
|
||||||
var subPatient2 = Character.Create(securityInfo, WayPoint.GetRandom(SpawnType.Human, securityInfo.Job, Submarine.MainSub).WorldPosition, "3");
|
var subPatient2 = Character.Create(securityInfo, WayPoint.GetRandom(SpawnType.Human, securityInfo.Job, Submarine.MainSub).WorldPosition, "3");
|
||||||
subPatient2.TeamID = CharacterTeamType.Team1;
|
subPatient2.TeamID = CharacterTeamType.Team1;
|
||||||
subPatient2.AddDamage(patient1.WorldPosition, new List<Affliction>() { new Affliction(AfflictionPrefab.InternalDamage, 40.0f) }, stun: 0, playSound: false);
|
subPatient2.AddDamage(patient1.WorldPosition, new List<Affliction>() { new Affliction(AfflictionPrefab.InternalDamage, 40.0f) }, stun: 0, playSound: false);
|
||||||
subPatients.Add(subPatient2);
|
subPatients.Add(subPatient2);
|
||||||
|
|
||||||
var engineerInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, "", JobPrefab.Get("engineer"));
|
var engineerInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobPrefab: JobPrefab.Get("engineer"));
|
||||||
var subPatient3 = Character.Create(securityInfo, WayPoint.GetRandom(SpawnType.Human, engineerInfo.Job, Submarine.MainSub).WorldPosition, "3");
|
var subPatient3 = Character.Create(securityInfo, WayPoint.GetRandom(SpawnType.Human, engineerInfo.Job, Submarine.MainSub).WorldPosition, "3");
|
||||||
subPatient3.TeamID = CharacterTeamType.Team1;
|
subPatient3.TeamID = CharacterTeamType.Team1;
|
||||||
subPatient3.AddDamage(patient1.WorldPosition, new List<Affliction>() { new Affliction(AfflictionPrefab.Burn, 20.0f) }, stun: 0, playSound: false);
|
subPatient3.AddDamage(patient1.WorldPosition, new List<Affliction>() { new Affliction(AfflictionPrefab.Burn, 20.0f) }, stun: 0, playSound: false);
|
||||||
@@ -283,7 +283,7 @@ namespace Barotrauma.Tutorials
|
|||||||
doctor.RemoveActiveObjectiveEntity(patient1);
|
doctor.RemoveActiveObjectiveEntity(patient1);
|
||||||
TriggerTutorialSegment(3, GameMain.Config.KeyBindText(InputType.Command)); // Get the patient to medbay
|
TriggerTutorialSegment(3, GameMain.Config.KeyBindText(InputType.Command)); // Get the patient to medbay
|
||||||
|
|
||||||
while (patient1.CurrentOrder == null || patient1.CurrentOrder.Identifier != "follow")
|
while (patient1.GetCurrentOrderWithTopPriority()?.Order?.Identifier != "follow")
|
||||||
{
|
{
|
||||||
// TODO: Rework order highlighting for new command UI
|
// TODO: Rework order highlighting for new command UI
|
||||||
// GameMain.GameSession.CrewManager.HighlightOrderButton(patient1, "follow", highlightColor, new Vector2(5, 5));
|
// GameMain.GameSession.CrewManager.HighlightOrderButton(patient1, "follow", highlightColor, new Vector2(5, 5));
|
||||||
|
|||||||
+2
-1
@@ -317,7 +317,8 @@ namespace Barotrauma.Tutorials
|
|||||||
yield return new WaitForSeconds(2f, false);
|
yield return new WaitForSeconds(2f, false);
|
||||||
TriggerTutorialSegment(4, GameMain.Config.KeyBindText(InputType.Select), GameMain.Config.KeyBindText(InputType.Shoot), GameMain.Config.KeyBindText(InputType.Deselect)); // Kill hammerhead
|
TriggerTutorialSegment(4, GameMain.Config.KeyBindText(InputType.Select), GameMain.Config.KeyBindText(InputType.Shoot), GameMain.Config.KeyBindText(InputType.Deselect)); // Kill hammerhead
|
||||||
officer_hammerhead = SpawnMonster("hammerhead", officer_hammerheadSpawnPos);
|
officer_hammerhead = SpawnMonster("hammerhead", officer_hammerheadSpawnPos);
|
||||||
((EnemyAIController)officer_hammerhead.AIController).StayInsideLevel = false;
|
officer_hammerhead.Params.AI.AvoidAbyss = false;
|
||||||
|
officer_hammerhead.Params.AI.StayInAbyss = false;
|
||||||
officer_hammerhead.AIController.SelectTarget(officer.AiTarget);
|
officer_hammerhead.AIController.SelectTarget(officer.AiTarget);
|
||||||
SetHighlight(officer_coilgunPeriscope, true);
|
SetHighlight(officer_coilgunPeriscope, true);
|
||||||
float originalDistance = Vector2.Distance(officer_coilgunPeriscope.WorldPosition, officer_hammerheadSpawnPos);
|
float originalDistance = Vector2.Distance(officer_coilgunPeriscope.WorldPosition, officer_hammerheadSpawnPos);
|
||||||
|
|||||||
+6
-6
@@ -62,7 +62,7 @@ namespace Barotrauma.Tutorials
|
|||||||
|
|
||||||
yield return CoroutineStatus.Running;
|
yield return CoroutineStatus.Running;
|
||||||
|
|
||||||
GameMain.GameSession = new GameSession(subInfo, GameModePreset.Tutorial, missionPrefab: null);
|
GameMain.GameSession = new GameSession(subInfo, GameModePreset.Tutorial, missionPrefabs: null);
|
||||||
(GameMain.GameSession.GameMode as TutorialMode).Tutorial = this;
|
(GameMain.GameSession.GameMode as TutorialMode).Tutorial = this;
|
||||||
|
|
||||||
if (generationParams != null)
|
if (generationParams != null)
|
||||||
@@ -110,7 +110,7 @@ namespace Barotrauma.Tutorials
|
|||||||
}
|
}
|
||||||
|
|
||||||
CharacterInfo charInfo = configElement.Element("Character") == null ?
|
CharacterInfo charInfo = configElement.Element("Character") == null ?
|
||||||
new CharacterInfo(CharacterPrefab.HumanSpeciesName, "", JobPrefab.Get("engineer")) :
|
new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobPrefab: JobPrefab.Get("engineer")) :
|
||||||
new CharacterInfo(configElement.Element("Character"));
|
new CharacterInfo(configElement.Element("Character"));
|
||||||
|
|
||||||
WayPoint wayPoint = GetSpawnPoint(charInfo);
|
WayPoint wayPoint = GetSpawnPoint(charInfo);
|
||||||
@@ -182,7 +182,8 @@ namespace Barotrauma.Tutorials
|
|||||||
|
|
||||||
protected bool HasOrder(Character character, string identifier, string option = null)
|
protected bool HasOrder(Character character, string identifier, string option = null)
|
||||||
{
|
{
|
||||||
if (character.CurrentOrder?.Identifier == identifier)
|
var currentOrderInfo = character.GetCurrentOrderWithTopPriority();
|
||||||
|
if (currentOrderInfo?.Order?.Identifier == identifier)
|
||||||
{
|
{
|
||||||
if (option == null)
|
if (option == null)
|
||||||
{
|
{
|
||||||
@@ -190,8 +191,7 @@ namespace Barotrauma.Tutorials
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
HumanAIController humanAI = character.AIController as HumanAIController;
|
return currentOrderInfo?.OrderOption == option;
|
||||||
return humanAI.CurrentOrderOption == option;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -288,7 +288,7 @@ namespace Barotrauma.Tutorials
|
|||||||
|
|
||||||
yield return new WaitForSeconds(waitBeforeFade);
|
yield return new WaitForSeconds(waitBeforeFade);
|
||||||
|
|
||||||
var endCinematic = new CameraTransition(Submarine.MainSub, GameMain.GameScreen.Cam, null, Alignment.Center, duration: fadeOutTime);
|
var endCinematic = new CameraTransition(Submarine.MainSub, GameMain.GameScreen.Cam, null, Alignment.Center, panDuration: fadeOutTime);
|
||||||
currentTutorialCompleted = Completed = true;
|
currentTutorialCompleted = Completed = true;
|
||||||
while (endCinematic.Running) yield return null;
|
while (endCinematic.Running) yield return null;
|
||||||
Stop();
|
Stop();
|
||||||
|
|||||||
+3
-3
@@ -535,15 +535,15 @@ namespace Barotrauma.Tutorials
|
|||||||
titleBlock.RectTransform.IsFixedSize = true;
|
titleBlock.RectTransform.IsFixedSize = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<RichTextData> richTextData = RichTextData.GetRichTextData(text, out text);
|
List<RichTextData> richTextData = RichTextData.GetRichTextData(" " + text, out text);
|
||||||
GUITextBlock textBlock;
|
GUITextBlock textBlock;
|
||||||
if (richTextData == null)
|
if (richTextData == null)
|
||||||
{
|
{
|
||||||
textBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), infoContent.RectTransform), " " + text, wrap: true);
|
textBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), infoContent.RectTransform), text, wrap: true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
textBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), infoContent.RectTransform), richTextData, " " + text, wrap: true);
|
textBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), infoContent.RectTransform), richTextData, text, wrap: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
textBlock.RectTransform.IsFixedSize = true;
|
textBlock.RectTransform.IsFixedSize = true;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework;
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
@@ -26,6 +27,7 @@ namespace Barotrauma
|
|||||||
if (tabMenu == null && GameMode is TutorialMode == false)
|
if (tabMenu == null && GameMode is TutorialMode == false)
|
||||||
{
|
{
|
||||||
tabMenu = new TabMenu();
|
tabMenu = new TabMenu();
|
||||||
|
HintManager.OnShowTabMenu();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -36,12 +38,106 @@ namespace Barotrauma
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private GUILayoutGroup topLeftButtonGroup;
|
||||||
|
private GUIButton crewListButton, commandButton, tabMenuButton;
|
||||||
|
|
||||||
|
private GUIComponent respawnInfoFrame, respawnButtonContainer;
|
||||||
|
private GUITextBlock respawnInfoText;
|
||||||
|
private GUITickBox respawnTickBox;
|
||||||
|
private GUILayoutGroup TopLeftButtonGroup;
|
||||||
|
private void CreateTopLeftButtons()
|
||||||
|
{
|
||||||
|
if (topLeftButtonGroup != null)
|
||||||
|
{
|
||||||
|
topLeftButtonGroup.RectTransform.Parent = null;
|
||||||
|
topLeftButtonGroup = null;
|
||||||
|
crewListButton = commandButton = tabMenuButton = null;
|
||||||
|
}
|
||||||
|
topLeftButtonGroup = new GUILayoutGroup(HUDLayoutSettings.ToRectTransform(HUDLayoutSettings.ButtonAreaTop, GUI.Canvas), isHorizontal: true, childAnchor: Anchor.CenterLeft)
|
||||||
|
{
|
||||||
|
AbsoluteSpacing = HUDLayoutSettings.Padding,
|
||||||
|
CanBeFocused = false
|
||||||
|
};
|
||||||
|
topLeftButtonGroup.RectTransform.ParentChanged += (_) =>
|
||||||
|
{
|
||||||
|
GameMain.Instance.ResolutionChanged -= CreateTopLeftButtons;
|
||||||
|
};
|
||||||
|
int buttonHeight = GUI.IntScale(40);
|
||||||
|
Vector2 buttonSpriteSize = GUI.Style.GetComponentStyle("CrewListToggleButton").GetDefaultSprite().size;
|
||||||
|
int buttonWidth = (int)((buttonHeight / buttonSpriteSize.Y) * buttonSpriteSize.X);
|
||||||
|
Point buttonSize = new Point(buttonWidth, buttonHeight);
|
||||||
|
crewListButton = new GUIButton(new RectTransform(buttonSize, parent: topLeftButtonGroup.RectTransform), style: "CrewListToggleButton")
|
||||||
|
{
|
||||||
|
ToolTip = TextManager.GetWithVariable("hudbutton.crewlist", "[key]", GameMain.Config.KeyBindText(InputType.CrewOrders)),
|
||||||
|
OnClicked = (GUIButton btn, object userdata) =>
|
||||||
|
{
|
||||||
|
if (CrewManager == null) { return false; }
|
||||||
|
CrewManager.IsCrewMenuOpen = !CrewManager.IsCrewMenuOpen;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
commandButton = new GUIButton(new RectTransform(buttonSize, parent: topLeftButtonGroup.RectTransform), style: "CommandButton")
|
||||||
|
{
|
||||||
|
ToolTip = TextManager.GetWithVariable("hudbutton.commandinterface", "[key]", GameMain.Config.KeyBindText(InputType.Command)),
|
||||||
|
OnClicked = (button, userData) =>
|
||||||
|
{
|
||||||
|
if (CrewManager == null) { return false; }
|
||||||
|
CrewManager.ToggleCommandUI();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
tabMenuButton = new GUIButton(new RectTransform(buttonSize, parent: topLeftButtonGroup.RectTransform), style: "TabMenuButton")
|
||||||
|
{
|
||||||
|
ToolTip = TextManager.GetWithVariable("hudbutton.tabmenu", "[key]", GameMain.Config.KeyBindText(InputType.InfoTab)),
|
||||||
|
OnClicked = (button, userData) =>
|
||||||
|
{
|
||||||
|
return ToggleTabMenu();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
GameMain.Instance.ResolutionChanged += CreateTopLeftButtons;
|
||||||
|
|
||||||
|
respawnInfoFrame = new GUIFrame(new RectTransform(new Vector2(0.5f, 1.0f), parent: topLeftButtonGroup.RectTransform)
|
||||||
|
{ MaxSize = new Point(HUDLayoutSettings.ButtonAreaTop.Width / 3, int.MaxValue) }, style: null)
|
||||||
|
{
|
||||||
|
Visible = false
|
||||||
|
};
|
||||||
|
respawnInfoText = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), respawnInfoFrame.RectTransform), "", wrap: true);
|
||||||
|
respawnButtonContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.5f, 1.0f), respawnInfoFrame.RectTransform, Anchor.CenterRight), isHorizontal: true, childAnchor: Anchor.CenterLeft)
|
||||||
|
{
|
||||||
|
AbsoluteSpacing = HUDLayoutSettings.Padding,
|
||||||
|
Stretch = true
|
||||||
|
};
|
||||||
|
respawnTickBox = new GUITickBox(new RectTransform(Vector2.One * 0.9f, respawnButtonContainer.RectTransform, Anchor.Center), TextManager.Get("respawnquestionpromptrespawn"))
|
||||||
|
{
|
||||||
|
ToolTip = TextManager.Get("respawnquestionprompt"),
|
||||||
|
OnSelected = (tickbox) =>
|
||||||
|
{
|
||||||
|
GameMain.Client?.SendRespawnPromptResponse(waitForNextRoundRespawn: !tickbox.Selected);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
public void AddToGUIUpdateList()
|
public void AddToGUIUpdateList()
|
||||||
{
|
{
|
||||||
if (GUI.DisableHUD) return;
|
if (GUI.DisableHUD) { return; }
|
||||||
GameMode?.AddToGUIUpdateList();
|
GameMode?.AddToGUIUpdateList();
|
||||||
tabMenu?.AddToGUIUpdateList();
|
tabMenu?.AddToGUIUpdateList();
|
||||||
|
|
||||||
|
if ((!(GameMode is CampaignMode campaign) || (!campaign.ForceMapUI && !campaign.ShowCampaignUI)) &&
|
||||||
|
!CoroutineManager.IsCoroutineRunning("LevelTransition") && !CoroutineManager.IsCoroutineRunning("SubmarineTransition"))
|
||||||
|
{
|
||||||
|
if (topLeftButtonGroup == null)
|
||||||
|
{
|
||||||
|
CreateTopLeftButtons();
|
||||||
|
}
|
||||||
|
crewListButton.Selected = CrewManager != null && CrewManager.IsCrewMenuOpen;
|
||||||
|
commandButton.Selected = CrewManager.IsCommandInterfaceOpen;
|
||||||
|
commandButton.Enabled = CrewManager.CanIssueOrders;
|
||||||
|
tabMenuButton.Selected = IsTabMenuOpen;
|
||||||
|
topLeftButtonGroup.AddToGUIUpdateList();
|
||||||
|
}
|
||||||
|
|
||||||
if (GameMain.NetworkMember != null)
|
if (GameMain.NetworkMember != null)
|
||||||
{
|
{
|
||||||
GameMain.NetLobbyScreen?.HeadSelectionList?.AddToGUIUpdateList();
|
GameMain.NetLobbyScreen?.HeadSelectionList?.AddToGUIUpdateList();
|
||||||
@@ -55,7 +151,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (tabMenu == null)
|
if (tabMenu == null)
|
||||||
{
|
{
|
||||||
if (PlayerInput.KeyHit(InputType.InfoTab) && GUI.KeyboardDispatcher.Subscriber is GUITextBox == false)
|
if (PlayerInput.KeyHit(InputType.InfoTab) && !(GUI.KeyboardDispatcher.Subscriber is GUITextBox))
|
||||||
{
|
{
|
||||||
ToggleTabMenu();
|
ToggleTabMenu();
|
||||||
}
|
}
|
||||||
@@ -63,8 +159,8 @@ namespace Barotrauma
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
tabMenu.Update();
|
tabMenu.Update();
|
||||||
|
if ((PlayerInput.KeyHit(InputType.InfoTab) || PlayerInput.KeyHit(Microsoft.Xna.Framework.Input.Keys.Escape)) &&
|
||||||
if (PlayerInput.KeyHit(InputType.InfoTab) && GUI.KeyboardDispatcher.Subscriber is GUITextBox == false)
|
!(GUI.KeyboardDispatcher.Subscriber is GUITextBox))
|
||||||
{
|
{
|
||||||
ToggleTabMenu();
|
ToggleTabMenu();
|
||||||
}
|
}
|
||||||
@@ -88,6 +184,19 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HintManager.Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetRespawnInfo(bool visible, string text, Color textColor, bool buttonsVisible, bool waitForNextRoundRespawn)
|
||||||
|
{
|
||||||
|
if (topLeftButtonGroup == null) { return; }
|
||||||
|
respawnInfoFrame.Visible = visible;
|
||||||
|
if (!visible) { return; }
|
||||||
|
respawnInfoText.Text = text;
|
||||||
|
respawnInfoText.TextColor = textColor;
|
||||||
|
respawnButtonContainer.Visible = buttonsVisible;
|
||||||
|
respawnTickBox.Selected = !waitForNextRoundRespawn;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Draw(SpriteBatch spriteBatch)
|
public void Draw(SpriteBatch spriteBatch)
|
||||||
|
|||||||
@@ -0,0 +1,731 @@
|
|||||||
|
using Barotrauma.Extensions;
|
||||||
|
using Barotrauma.IO;
|
||||||
|
using Barotrauma.Items.Components;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Xml.Linq;
|
||||||
|
|
||||||
|
namespace Barotrauma
|
||||||
|
{
|
||||||
|
static class HintManager
|
||||||
|
{
|
||||||
|
private const string HintManagerFile = "hintmanager.xml";
|
||||||
|
private static HashSet<string> HintIdentifiers { get; set; }
|
||||||
|
private static Dictionary<string, HashSet<string>> HintTags { get; } = new Dictionary<string, HashSet<string>>();
|
||||||
|
private static Dictionary<string, (string identifier, string option)> HintOrders { get; } = new Dictionary<string, (string orderIdentifier, string orderOption)>();
|
||||||
|
/// <summary>
|
||||||
|
/// Hints that have already been shown this round and shouldn't be shown shown again until the next round
|
||||||
|
/// </summary>
|
||||||
|
private static HashSet<string> HintsIgnoredThisRound { get; } = new HashSet<string>();
|
||||||
|
private static GUIMessageBox ActiveHintMessageBox { get; set; }
|
||||||
|
private static Action OnUpdate { get; set; }
|
||||||
|
private static double TimeStoppedInteracting { get; set; }
|
||||||
|
private static double TimeRoundStarted { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Seconds before any reminders can be shown
|
||||||
|
/// </summary>
|
||||||
|
private static int TimeBeforeReminders { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Seconds before another reminder can be shown
|
||||||
|
/// </summary>
|
||||||
|
private static int ReminderCooldown { get; set; }
|
||||||
|
private static double TimeReminderLastDisplayed { get; set; }
|
||||||
|
private static HashSet<Hull> BallastHulls { get; } = new HashSet<Hull>();
|
||||||
|
|
||||||
|
public static void Init()
|
||||||
|
{
|
||||||
|
if (File.Exists(HintManagerFile))
|
||||||
|
{
|
||||||
|
var doc = XMLExtensions.TryLoadXml(HintManagerFile);
|
||||||
|
if (doc?.Root != null)
|
||||||
|
{
|
||||||
|
HintIdentifiers = new HashSet<string>();
|
||||||
|
foreach (var element in doc.Root.Elements())
|
||||||
|
{
|
||||||
|
GetHintsRecursive(element, element.Name.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError($"File \"{HintManagerFile}\" is empty - cannot initialize the HintManager!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError($"File \"{HintManagerFile}\" is missing - cannot initialize the HintManager!");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void GetHintsRecursive(XElement element, string identifier)
|
||||||
|
{
|
||||||
|
if (!element.HasElements)
|
||||||
|
{
|
||||||
|
HintIdentifiers.Add(identifier);
|
||||||
|
if (element.GetAttributeStringArray("tags", null, convertToLowerInvariant: true) is string[] tags)
|
||||||
|
{
|
||||||
|
HintTags.TryAdd(identifier, tags.ToHashSet());
|
||||||
|
}
|
||||||
|
if (element.GetAttributeString("order", null) is string orderIdentifier && !string.IsNullOrEmpty(orderIdentifier))
|
||||||
|
{
|
||||||
|
string orderOption = element.GetAttributeString("orderoption", "");
|
||||||
|
HintOrders.Add(identifier, (orderIdentifier, orderOption));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (element.Name.ToString().Equals("reminder"))
|
||||||
|
{
|
||||||
|
TimeBeforeReminders = element.GetAttributeInt("timebeforereminders", TimeBeforeReminders);
|
||||||
|
ReminderCooldown = element.GetAttributeInt("remindercooldown", ReminderCooldown);
|
||||||
|
}
|
||||||
|
foreach (var childElement in element.Elements())
|
||||||
|
{
|
||||||
|
GetHintsRecursive(childElement, $"{identifier}.{childElement.Name}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Update()
|
||||||
|
{
|
||||||
|
if (HintIdentifiers == null || GameMain.Config.DisableInGameHints) { return; }
|
||||||
|
if (GameMain.GameSession == null || !GameMain.GameSession.IsRunning) { return; }
|
||||||
|
|
||||||
|
if (ActiveHintMessageBox != null)
|
||||||
|
{
|
||||||
|
if (ActiveHintMessageBox.Closed)
|
||||||
|
{
|
||||||
|
ActiveHintMessageBox = null;
|
||||||
|
OnUpdate = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
OnUpdate?.Invoke();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CheckIsInteracting();
|
||||||
|
CheckIfDivingGearOutOfOxygen();
|
||||||
|
CheckHulls();
|
||||||
|
CheckReminders();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void OnSetSelectedConstruction(Character character, Item oldConstruction, Item newConstruction)
|
||||||
|
{
|
||||||
|
if (oldConstruction == newConstruction) { return; }
|
||||||
|
|
||||||
|
if (Character.Controlled != null && Character.Controlled == character && oldConstruction != null && oldConstruction.GetComponent<Ladder>() == null)
|
||||||
|
{
|
||||||
|
TimeStoppedInteracting = Timing.TotalTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newConstruction == null) { return; }
|
||||||
|
if (newConstruction.GetComponent<Ladder>() != null) { return; }
|
||||||
|
if (newConstruction.GetComponent<ConnectionPanel>() is ConnectionPanel cp && cp.User == character) { return; }
|
||||||
|
OnStartedInteracting(character, newConstruction);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void OnStartedInteracting(Character character, Item item)
|
||||||
|
{
|
||||||
|
if (!CanDisplayHints()) { return; }
|
||||||
|
if (character != Character.Controlled || item == null) { return; }
|
||||||
|
|
||||||
|
string hintIdentifierBase = "onstartedinteracting";
|
||||||
|
|
||||||
|
// onstartedinteracting.brokenitem
|
||||||
|
if (item.Repairables.Any(r => item.ConditionPercentage < r.RepairThreshold))
|
||||||
|
{
|
||||||
|
if (DisplayHint($"{hintIdentifierBase}.brokenitem")) { return; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't display other item-related hints if the repair interface is displayed
|
||||||
|
if (item.Repairables.Any(r => r.ShouldDrawHUD(character))) { return; }
|
||||||
|
|
||||||
|
// onstartedinteracting.lootingisstealing
|
||||||
|
if (item.Submarine?.Info?.Type == SubmarineType.Outpost &&
|
||||||
|
item.ContainedItems.Any(i => !i.AllowStealing))
|
||||||
|
{
|
||||||
|
if (DisplayHint($"{hintIdentifierBase}.lootingisstealing")) { return; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// onstartedinteracting.turretperiscope
|
||||||
|
if (item.HasTag("periscope") &&
|
||||||
|
item.GetConnectedComponents<Turret>().FirstOrDefault(t => t.Item.HasTag("turret")) is Turret)
|
||||||
|
{
|
||||||
|
if (DisplayHint($"{hintIdentifierBase}.turretperiscope",
|
||||||
|
variableTags: new string[] { "[shootkey]", "[deselectkey]", },
|
||||||
|
variableValues: new string[] { GameMain.Config.KeyBindText(InputType.Shoot), GameMain.Config.KeyBindText(InputType.Deselect) }))
|
||||||
|
{ return; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// onstartedinteracting.item...
|
||||||
|
hintIdentifierBase += ".item";
|
||||||
|
foreach (string hintIdentifier in HintIdentifiers)
|
||||||
|
{
|
||||||
|
if (!hintIdentifier.StartsWith(hintIdentifierBase)) { continue; }
|
||||||
|
if (!HintTags.TryGetValue(hintIdentifier, out var hintTags)) { continue; }
|
||||||
|
if (!item.HasTag(hintTags)) { continue; }
|
||||||
|
if (DisplayHint(hintIdentifier)) { return; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CheckIsInteracting()
|
||||||
|
{
|
||||||
|
if (!CanDisplayHints()) { return; }
|
||||||
|
if (Character.Controlled?.SelectedConstruction == null) { return; }
|
||||||
|
|
||||||
|
if (Character.Controlled.SelectedConstruction.GetComponent<Reactor>() is Reactor reactor && reactor.PowerOn &&
|
||||||
|
Character.Controlled.SelectedConstruction.OwnInventory?.AllItems is IEnumerable<Item> containedItems &&
|
||||||
|
containedItems.Count(i => i.HasTag("reactorfuel")) > 1)
|
||||||
|
{
|
||||||
|
if (DisplayHint("onisinteracting.reactorwithextrarods")) { return; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void OnRoundStarted()
|
||||||
|
{
|
||||||
|
// Make sure everything's been reset properly, OnRoundEnded() isn't always called when exiting a game
|
||||||
|
Reset();
|
||||||
|
TimeRoundStarted = GameMain.GameScreen.GameTime;
|
||||||
|
|
||||||
|
var initRoundHandle = CoroutineManager.StartCoroutine(InitRound(), "HintManager.InitRound");
|
||||||
|
if (!CanDisplayHints(requireGameScreen: false, requireControllingCharacter: false)) { return; }
|
||||||
|
CoroutineManager.StartCoroutine(DisplayRoundStartedHints(initRoundHandle), "HintManager.DisplayRoundStartedHints");
|
||||||
|
|
||||||
|
static IEnumerable<object> InitRound()
|
||||||
|
{
|
||||||
|
while (Character.Controlled == null) { yield return CoroutineStatus.Running; }
|
||||||
|
// Get the ballast hulls on round start not to find them again and again later
|
||||||
|
BallastHulls.Clear();
|
||||||
|
var sub = Submarine.MainSubs.FirstOrDefault(s => s != null && s.TeamID == Character.Controlled.TeamID);
|
||||||
|
if (sub != null)
|
||||||
|
{
|
||||||
|
foreach (var item in sub.GetItems(true))
|
||||||
|
{
|
||||||
|
if (item.CurrentHull == null) { continue; }
|
||||||
|
if (item.GetComponent<Pump>() == null) { continue; }
|
||||||
|
if (!item.HasTag("ballast")) { continue; }
|
||||||
|
BallastHulls.Add(item.CurrentHull);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
yield return CoroutineStatus.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
static IEnumerable<object> DisplayRoundStartedHints(CoroutineHandle initRoundHandle)
|
||||||
|
{
|
||||||
|
while (GameMain.Instance.LoadingScreenOpen || Screen.Selected != GameMain.GameScreen ||
|
||||||
|
CoroutineManager.IsCoroutineRunning(initRoundHandle) ||
|
||||||
|
CoroutineManager.IsCoroutineRunning("LevelTransition") ||
|
||||||
|
CoroutineManager.IsCoroutineRunning("SinglePlayerCampaign.DoInitialCameraTransition") ||
|
||||||
|
CoroutineManager.IsCoroutineRunning("MultiPlayerCampaign.DoInitialCameraTransition") ||
|
||||||
|
GUIMessageBox.VisibleBox != null || Character.Controlled == null)
|
||||||
|
{
|
||||||
|
yield return CoroutineStatus.Running;
|
||||||
|
}
|
||||||
|
|
||||||
|
OnStartedControlling();
|
||||||
|
|
||||||
|
while (ActiveHintMessageBox != null)
|
||||||
|
{
|
||||||
|
yield return CoroutineStatus.Running;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!GameMain.GameSession.GameMode.IsSinglePlayer &&
|
||||||
|
GameMain.Config.VoiceSetting == GameSettings.VoiceMode.Disabled)
|
||||||
|
{
|
||||||
|
DisplayHint("onroundstarted.voipdisabled", onUpdate: () =>
|
||||||
|
{
|
||||||
|
if (GameMain.Config.VoiceSetting == GameSettings.VoiceMode.Disabled) { return; }
|
||||||
|
ActiveHintMessageBox.Close();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
yield return CoroutineStatus.Success;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void OnRoundEnded()
|
||||||
|
{
|
||||||
|
Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void Reset()
|
||||||
|
{
|
||||||
|
CoroutineManager.StopCoroutines("HintManager.InitRound");
|
||||||
|
CoroutineManager.StopCoroutines("HintManager.DisplayRoundStartedHints");
|
||||||
|
if (ActiveHintMessageBox != null)
|
||||||
|
{
|
||||||
|
GUIMessageBox.MessageBoxes.Remove(ActiveHintMessageBox);
|
||||||
|
ActiveHintMessageBox = null;
|
||||||
|
}
|
||||||
|
OnUpdate = null;
|
||||||
|
HintsIgnoredThisRound.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void OnSonarSpottedCharacter(Item sonar, Character spottedCharacter)
|
||||||
|
{
|
||||||
|
if (!CanDisplayHints()) { return; }
|
||||||
|
if (sonar == null || sonar.Removed) { return; }
|
||||||
|
if (spottedCharacter == null || spottedCharacter.Removed || spottedCharacter.IsDead) { return; }
|
||||||
|
if (Character.Controlled.SelectedConstruction != sonar) { return; }
|
||||||
|
if (HumanAIController.IsFriendly(Character.Controlled, spottedCharacter)) { return; }
|
||||||
|
DisplayHint("onsonarspottedenemy");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void OnAfflictionDisplayed(Character character, List<Affliction> displayedAfflictions)
|
||||||
|
{
|
||||||
|
if (!CanDisplayHints()) { return; }
|
||||||
|
if (character != Character.Controlled || displayedAfflictions == null) { return; }
|
||||||
|
foreach (var affliction in displayedAfflictions)
|
||||||
|
{
|
||||||
|
if (affliction?.Prefab == null) { continue; }
|
||||||
|
if (affliction.Prefab.IsBuff) { continue; }
|
||||||
|
if (affliction.Prefab == AfflictionPrefab.OxygenLow) { continue; }
|
||||||
|
if (affliction.Prefab == AfflictionPrefab.RadiationSickness && (GameMain.GameSession.Map?.Radiation?.IsEntityRadiated(character) ?? false)) { continue; }
|
||||||
|
if (affliction.Strength < affliction.Prefab.ShowIconThreshold) { continue; }
|
||||||
|
DisplayHint("onafflictiondisplayed",
|
||||||
|
variableTags: new string[1] { "[key]" },
|
||||||
|
variableValues: new string[1] { GameMain.Config.KeyBindText(InputType.Health) },
|
||||||
|
icon: affliction.Prefab.Icon,
|
||||||
|
iconColor: CharacterHealth.GetAfflictionIconColor(affliction),
|
||||||
|
onUpdate: () =>
|
||||||
|
{
|
||||||
|
if (CharacterHealth.OpenHealthWindow == null) { return; }
|
||||||
|
ActiveHintMessageBox.Close();
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void OnShootWithoutAiming(Character character, Item item)
|
||||||
|
{
|
||||||
|
if (!CanDisplayHints()) { return; }
|
||||||
|
if (character != Character.Controlled) { return; }
|
||||||
|
if (character.SelectedConstruction != null || character.FocusedItem != null) { return; }
|
||||||
|
if (item == null || !item.IsShootable || !item.RequireAimToUse) { return; }
|
||||||
|
if (TimeStoppedInteracting + 1 > Timing.TotalTime) { return; }
|
||||||
|
if (GUI.MouseOn != null) { return; }
|
||||||
|
if (Character.Controlled.Inventory?.visualSlots != null && Character.Controlled.Inventory.visualSlots.Any(s => s.InteractRect.Contains(PlayerInput.MousePosition))) { return; }
|
||||||
|
string hintIdentifier = "onshootwithoutaiming";
|
||||||
|
if (!HintTags.TryGetValue(hintIdentifier, out var tags)) { return; }
|
||||||
|
if (!item.HasTag(tags)) { return; }
|
||||||
|
DisplayHint(hintIdentifier,
|
||||||
|
variableTags: new string[1] { "[key]" },
|
||||||
|
variableValues: new string[1] { GameMain.Config.KeyBindText(InputType.Aim) },
|
||||||
|
onUpdate: () =>
|
||||||
|
{
|
||||||
|
if (character.SelectedConstruction == null && GUI.MouseOn == null && PlayerInput.KeyDown(InputType.Aim))
|
||||||
|
{
|
||||||
|
ActiveHintMessageBox.Close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void OnWeldingDoor(Character character, Door door)
|
||||||
|
{
|
||||||
|
if (!CanDisplayHints()) { return; }
|
||||||
|
if (character != Character.Controlled) { return; }
|
||||||
|
if (door == null || door.Stuck < 20.0f) { return; }
|
||||||
|
DisplayHint("onweldingdoor");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void OnTryOpenStuckDoor(Character character)
|
||||||
|
{
|
||||||
|
if (!CanDisplayHints()) { return; }
|
||||||
|
if (character != Character.Controlled) { return; }
|
||||||
|
DisplayHint("ontryopenstuckdoor");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void OnShowCampaignInterface(CampaignMode.InteractionType interactionType)
|
||||||
|
{
|
||||||
|
if (!CanDisplayHints()) { return; }
|
||||||
|
if (interactionType == CampaignMode.InteractionType.None) { return; }
|
||||||
|
string hintIdentifier = $"onshowcampaigninterface.{interactionType.ToString().ToLowerInvariant()}";
|
||||||
|
DisplayHint(hintIdentifier, onUpdate: () =>
|
||||||
|
{
|
||||||
|
|
||||||
|
if (!(GameMain.GameSession?.Campaign is CampaignMode campaign) ||
|
||||||
|
(!campaign.ShowCampaignUI && !campaign.ForceMapUI) ||
|
||||||
|
campaign.CampaignUI?.SelectedTab != CampaignMode.InteractionType.Map)
|
||||||
|
{
|
||||||
|
ActiveHintMessageBox.Close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void OnShowCommandInterface()
|
||||||
|
{
|
||||||
|
IgnoreReminder("commandinterface");
|
||||||
|
if (!CanDisplayHints()) { return; }
|
||||||
|
DisplayHint("onshowcommandinterface", onUpdate: () =>
|
||||||
|
{
|
||||||
|
if (CrewManager.IsCommandInterfaceOpen) { return; }
|
||||||
|
ActiveHintMessageBox.Close();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void OnShowHealthInterface()
|
||||||
|
{
|
||||||
|
if (!CanDisplayHints()) { return; }
|
||||||
|
if (CharacterHealth.OpenHealthWindow == null) { return; }
|
||||||
|
DisplayHint("onshowhealthinterface", onUpdate: () =>
|
||||||
|
{
|
||||||
|
if (CharacterHealth.OpenHealthWindow != null) { return; }
|
||||||
|
ActiveHintMessageBox.Close();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void OnShowTabMenu()
|
||||||
|
{
|
||||||
|
IgnoreReminder("tabmenu");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void OnStoleItem(Character character, Item item)
|
||||||
|
{
|
||||||
|
if (!CanDisplayHints()) { return; }
|
||||||
|
if (character != Character.Controlled) { return; }
|
||||||
|
if (item == null || item.AllowStealing || !item.StolenDuringRound) { return; }
|
||||||
|
DisplayHint("onstoleitem", onUpdate: () =>
|
||||||
|
{
|
||||||
|
if (item == null || item.Removed || item.GetRootInventoryOwner() != character)
|
||||||
|
{
|
||||||
|
ActiveHintMessageBox.Close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void OnHandcuffed(Character character)
|
||||||
|
{
|
||||||
|
if (!CanDisplayHints()) { return; }
|
||||||
|
if (character != Character.Controlled || !character.LockHands) { return; }
|
||||||
|
DisplayHint("onhandcuffed", onUpdate: () =>
|
||||||
|
{
|
||||||
|
if (character != null && !character.Removed && character.LockHands) { return; }
|
||||||
|
ActiveHintMessageBox.Close();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void OnReactorOutOfFuel(Reactor reactor)
|
||||||
|
{
|
||||||
|
if (!CanDisplayHints()) { return; }
|
||||||
|
if (reactor == null) { return; }
|
||||||
|
if (reactor.Item.Submarine?.Info?.Type != SubmarineType.Player || reactor.Item.Submarine.TeamID != Character.Controlled.TeamID) { return; }
|
||||||
|
if (!HasValidJob("engineer")) { return; }
|
||||||
|
DisplayHint("onreactoroutoffuel", onUpdate: () =>
|
||||||
|
{
|
||||||
|
if (reactor?.Item != null && !reactor.Item.Removed && reactor.AvailableFuel < 1) { return; }
|
||||||
|
ActiveHintMessageBox.Close();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void OnAvailableTransition(CampaignMode.TransitionType transitionType)
|
||||||
|
{
|
||||||
|
if (!CanDisplayHints()) { return; }
|
||||||
|
if (transitionType == CampaignMode.TransitionType.None) { return; }
|
||||||
|
DisplayHint($"onavailabletransition.{transitionType.ToString().ToLowerInvariant()}");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void OnShowSubInventory(Item item)
|
||||||
|
{
|
||||||
|
if (item?.Prefab == null) { return; }
|
||||||
|
if (item.Prefab.Identifier.Equals("toolbelt", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
IgnoreReminder("toolbelt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void OnChangeCharacter()
|
||||||
|
{
|
||||||
|
IgnoreReminder("characterchange");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void OnCharacterUnconscious(Character character)
|
||||||
|
{
|
||||||
|
if (!CanDisplayHints()) { return; }
|
||||||
|
if (character != Character.Controlled) { return; }
|
||||||
|
if (character.IsDead) { return; }
|
||||||
|
if (character.CharacterHealth != null && character.Vitality < character.CharacterHealth.MinVitality) { return; }
|
||||||
|
DisplayHint("oncharacterunconscious");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void OnCharacterKilled(Character character)
|
||||||
|
{
|
||||||
|
if (!CanDisplayHints()) { return; }
|
||||||
|
if (character != Character.Controlled) { return; }
|
||||||
|
if (GameMain.IsMultiplayer) { return; }
|
||||||
|
if (GameMain.GameSession?.CrewManager == null) { return; }
|
||||||
|
if (GameMain.GameSession.CrewManager.GetCharacters().None(c => !c.IsDead)) { return; }
|
||||||
|
DisplayHint("oncharacterkilled");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void OnStartedControlling()
|
||||||
|
{
|
||||||
|
if (Level.IsLoadedOutpost) { return; }
|
||||||
|
if (Character.Controlled?.Info?.Job?.Prefab == null) { return; }
|
||||||
|
string hintIdentifier = $"onstartedcontrolling.job.{Character.Controlled.Info.Job.Prefab.Identifier}";
|
||||||
|
DisplayHint(hintIdentifier,
|
||||||
|
icon: Character.Controlled.Info.Job.Prefab.Icon,
|
||||||
|
iconColor: Character.Controlled.Info.Job.Prefab.UIColor,
|
||||||
|
onDisplay: () =>
|
||||||
|
{
|
||||||
|
if (!HintOrders.TryGetValue(hintIdentifier, out var orderInfo)) { return; }
|
||||||
|
var orderPrefab = Order.GetPrefab(orderInfo.identifier);
|
||||||
|
if (orderPrefab == null) { return; }
|
||||||
|
Item targetEntity = null;
|
||||||
|
ItemComponent targetItem = null;
|
||||||
|
if (orderPrefab.MustSetTarget)
|
||||||
|
{
|
||||||
|
targetEntity = orderPrefab.GetMatchingItems(true, interactableFor: Character.Controlled).FirstOrDefault();
|
||||||
|
if (targetEntity == null) { return; }
|
||||||
|
targetItem = orderPrefab.GetTargetItemComponent(targetEntity);
|
||||||
|
}
|
||||||
|
var order = new Order(orderPrefab, targetEntity as Entity, targetItem, orderGiver: Character.Controlled);
|
||||||
|
GameMain.GameSession.CrewManager.SetCharacterOrder(Character.Controlled, order, orderInfo.option, CharacterInfo.HighestManualOrderPriority, Character.Controlled);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void OnAutoPilotPathUpdated(Steering steering)
|
||||||
|
{
|
||||||
|
if (!CanDisplayHints()) { return; }
|
||||||
|
if (!HasValidJob("captain")) { return; }
|
||||||
|
if (steering?.Item?.Submarine?.Info == null) { return; }
|
||||||
|
if (steering.Item.Submarine.Info.Type != SubmarineType.Player) { return; }
|
||||||
|
if (steering.Item.Submarine.TeamID != Character.Controlled.TeamID) { return; }
|
||||||
|
if (!steering.AutoPilot || steering.MaintainPos) { return; }
|
||||||
|
if (steering.SteeringPath?.CurrentNode?.Tunnel?.Type != Level.TunnelType.MainPath) { return; }
|
||||||
|
if (!steering.SteeringPath.Finished && steering.SteeringPath.NextNode != null) { return; }
|
||||||
|
if (steering.LevelStartSelected && (Level.Loaded.StartOutpost == null || !steering.Item.Submarine.AtStartExit)) { return; }
|
||||||
|
if (steering.LevelEndSelected && (Level.Loaded.EndOutpost == null || !steering.Item.Submarine.AtEndExit)) { return; }
|
||||||
|
DisplayHint("onautopilotreachedoutpost");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void OnStatusEffectApplied(ItemComponent component, ActionType actionType, Character character)
|
||||||
|
{
|
||||||
|
if (!CanDisplayHints()) { return; }
|
||||||
|
if (character != Character.Controlled) { return; }
|
||||||
|
// Could make this more generic if there will ever be any other status effect related hints
|
||||||
|
if (!(component is Repairable) || actionType != ActionType.OnFailure) { return; }
|
||||||
|
DisplayHint("onrepairfailed");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void OnActiveOrderAdded(Order order)
|
||||||
|
{
|
||||||
|
if (!CanDisplayHints()) { return; }
|
||||||
|
if (order == null) { return; }
|
||||||
|
|
||||||
|
if (order.Identifier == "reportballastflora" &&
|
||||||
|
order.TargetEntity is Hull h &&
|
||||||
|
h.Submarine?.TeamID == Character.Controlled.TeamID)
|
||||||
|
{
|
||||||
|
DisplayHint("onballastflorainfected");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CheckIfDivingGearOutOfOxygen()
|
||||||
|
{
|
||||||
|
if (!CanDisplayHints()) { return; }
|
||||||
|
var divingGear = Character.Controlled.GetEquippedItem("diving");
|
||||||
|
if (divingGear?.OwnInventory == null) { return; }
|
||||||
|
if (divingGear.GetContainedItemConditionPercentage() > 0.0f) { return; }
|
||||||
|
DisplayHint("ondivinggearoutofoxygen", onUpdate: () =>
|
||||||
|
{
|
||||||
|
if (divingGear == null || divingGear.Removed ||
|
||||||
|
Character.Controlled == null || !Character.Controlled.HasEquippedItem(divingGear) ||
|
||||||
|
divingGear.GetContainedItemConditionPercentage() > 0.0f)
|
||||||
|
{
|
||||||
|
ActiveHintMessageBox.Close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CheckHulls()
|
||||||
|
{
|
||||||
|
if (!CanDisplayHints()) { return; }
|
||||||
|
if (Character.Controlled.CurrentHull == null) { return; }
|
||||||
|
if (HumanAIController.IsBallastFloraNoticeable(Character.Controlled, Character.Controlled.CurrentHull))
|
||||||
|
{
|
||||||
|
if (DisplayHint("onballastflorainfected")) { return; }
|
||||||
|
}
|
||||||
|
foreach (var gap in Character.Controlled.CurrentHull.ConnectedGaps)
|
||||||
|
{
|
||||||
|
if (gap.ConnectedDoor == null || gap.ConnectedDoor.Impassable) { continue; }
|
||||||
|
if (Vector2.DistanceSquared(Character.Controlled.WorldPosition, gap.ConnectedDoor.Item.WorldPosition) > 400 * 400) { continue; }
|
||||||
|
if (!gap.IsRoomToRoom)
|
||||||
|
{
|
||||||
|
if (!(Character.Controlled.GetEquippedItem("deepdiving") is Item)) { continue; }
|
||||||
|
if (Character.Controlled.IsProtectedFromPressure()) { continue; }
|
||||||
|
if (DisplayHint("divingsuitwarning", extendTextTag: false)) { return; }
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
foreach (var me in gap.linkedTo)
|
||||||
|
{
|
||||||
|
if (me == Character.Controlled.CurrentHull) { continue; }
|
||||||
|
if (!(me is Hull adjacentHull)) { continue; }
|
||||||
|
if (adjacentHull.LethalPressure > 5.0f && DisplayHint("onadjacenthull.highpressure")) { return; }
|
||||||
|
if (adjacentHull.WaterPercentage > 75 && !BallastHulls.Contains(adjacentHull) && DisplayHint("onadjacenthull.highwaterpercentage")) { return; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CheckReminders()
|
||||||
|
{
|
||||||
|
if (!CanDisplayHints()) { return; }
|
||||||
|
if (Level.Loaded == null) { return; }
|
||||||
|
if (GameMain.GameScreen.GameTime < TimeRoundStarted + TimeBeforeReminders) { return; }
|
||||||
|
if (GameMain.GameScreen.GameTime < TimeReminderLastDisplayed + ReminderCooldown) { return; }
|
||||||
|
|
||||||
|
string hintIdentifierBase = "reminder";
|
||||||
|
|
||||||
|
if (GameMain.GameSession.GameMode.IsSinglePlayer)
|
||||||
|
{
|
||||||
|
if (DisplayHint($"{hintIdentifierBase}.characterchange"))
|
||||||
|
{
|
||||||
|
TimeReminderLastDisplayed = GameMain.GameScreen.GameTime;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Level.Loaded.Type != LevelData.LevelType.Outpost)
|
||||||
|
{
|
||||||
|
if (DisplayHint($"{hintIdentifierBase}.commandinterface",
|
||||||
|
variableTags: new string[] { "[commandkey]" },
|
||||||
|
variableValues: new string[] { GameMain.Config.KeyBindText(InputType.Command) },
|
||||||
|
onUpdate: () =>
|
||||||
|
{
|
||||||
|
if (!CrewManager.IsCommandInterfaceOpen) { return; }
|
||||||
|
ActiveHintMessageBox.Close();
|
||||||
|
}))
|
||||||
|
{
|
||||||
|
TimeReminderLastDisplayed = GameMain.GameScreen.GameTime;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DisplayHint($"{hintIdentifierBase}.tabmenu",
|
||||||
|
variableTags: new string[] { "[infotabkey]" },
|
||||||
|
variableValues: new string[] { GameMain.Config.KeyBindText(InputType.InfoTab) },
|
||||||
|
onUpdate: () =>
|
||||||
|
{
|
||||||
|
if (!GameSession.IsTabMenuOpen) { return; }
|
||||||
|
ActiveHintMessageBox.Close();
|
||||||
|
}))
|
||||||
|
{
|
||||||
|
TimeReminderLastDisplayed = GameMain.GameScreen.GameTime;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Character.Controlled.Inventory?.GetItemInLimbSlot(InvSlotType.Bag)?.Prefab?.Identifier == "toolbelt")
|
||||||
|
{
|
||||||
|
if (DisplayHint($"{hintIdentifierBase}.toolbelt"))
|
||||||
|
{
|
||||||
|
TimeReminderLastDisplayed = GameMain.GameScreen.GameTime;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool DisplayHint(string hintIdentifier, bool extendTextTag = true, string[] variableTags = null, string[] variableValues = null, Sprite icon = null, Color? iconColor = null, Action onDisplay = null, Action onUpdate = null)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(hintIdentifier)) { return false; }
|
||||||
|
if (!HintIdentifiers.Contains(hintIdentifier)) { return false; }
|
||||||
|
if (GameMain.Config.IgnoredHints.Contains(hintIdentifier)) { return false; }
|
||||||
|
if (HintsIgnoredThisRound.Contains(hintIdentifier)) { return false; }
|
||||||
|
|
||||||
|
string text;
|
||||||
|
string textTag = extendTextTag ? $"hint.{hintIdentifier}" : hintIdentifier;
|
||||||
|
if (variableTags != null && variableTags != null && variableTags.Length > 0 && variableTags.Length == variableValues.Length)
|
||||||
|
{
|
||||||
|
text = TextManager.GetWithVariables(textTag, variableTags, variableValues, returnNull: true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
text = TextManager.Get(textTag, returnNull: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(text))
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
DebugConsole.ThrowError($"No hint text found for text tag \"{textTag}\"");
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
HintsIgnoredThisRound.Add(hintIdentifier);
|
||||||
|
|
||||||
|
ActiveHintMessageBox = new GUIMessageBox(hintIdentifier, text, icon);
|
||||||
|
if (iconColor.HasValue) { ActiveHintMessageBox.IconColor = iconColor.Value; }
|
||||||
|
OnUpdate = onUpdate;
|
||||||
|
|
||||||
|
SoundPlayer.PlayUISound(GUISoundType.UIMessage);
|
||||||
|
ActiveHintMessageBox.InnerFrame.Flash(color: iconColor ?? Color.Orange, flashDuration: 0.75f);
|
||||||
|
onDisplay?.Invoke();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool OnDontShowAgain(GUITickBox tickBox)
|
||||||
|
{
|
||||||
|
IgnoreHint((string)tickBox.UserData, ignore: tickBox.Selected);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void IgnoreHint(string hintIdentifier, bool ignore = true)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(hintIdentifier)) { return; }
|
||||||
|
if (!HintIdentifiers.Contains(hintIdentifier))
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
DebugConsole.ThrowError($"Tried to ignore a hint not defined in {HintManagerFile}: {hintIdentifier}");
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ignore)
|
||||||
|
{
|
||||||
|
GameMain.Config.IgnoredHints.Add(hintIdentifier);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GameMain.Config.IgnoredHints.Remove(hintIdentifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void IgnoreReminder(string reminderIdentifier)
|
||||||
|
{
|
||||||
|
HintsIgnoredThisRound.Add($"reminder.{reminderIdentifier}");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool OnDisableHints(GUITickBox tickBox)
|
||||||
|
{
|
||||||
|
GameMain.Config.DisableInGameHints = tickBox.Selected;
|
||||||
|
return GameMain.Config.SaveNewPlayerConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool CanDisplayHints(bool requireGameScreen = true, bool requireControllingCharacter = true)
|
||||||
|
{
|
||||||
|
if (HintIdentifiers == null) { return false; }
|
||||||
|
if (GameMain.Config.DisableInGameHints) { return false; }
|
||||||
|
if (ActiveHintMessageBox != null) { return false; }
|
||||||
|
if (requireControllingCharacter && Character.Controlled == null) { return false; }
|
||||||
|
var gameMode = GameMain.GameSession?.GameMode;
|
||||||
|
if (!(gameMode is CampaignMode || gameMode is MissionMode)) { return false; }
|
||||||
|
if (requireGameScreen && Screen.Selected != GameMain.GameScreen) { return false; }
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool HasValidJob(string jobIdentifier)
|
||||||
|
{
|
||||||
|
// In singleplayer, we can control all character so we don't care about job restrictions
|
||||||
|
if (GameMain.GameSession.GameMode.IsSinglePlayer) { return true; }
|
||||||
|
if (Character.Controlled.HasJob(jobIdentifier)) { return true; }
|
||||||
|
// In multiplayer, if there are players with the job, display the hint to all players
|
||||||
|
foreach (var c in GameMain.GameSession.CrewManager.GetCharacters())
|
||||||
|
{
|
||||||
|
if (c == null || !c.IsRemotePlayer) { continue; }
|
||||||
|
if (c.IsUnconscious || c.IsDead || c.Removed) { continue; }
|
||||||
|
if (!c.HasJob(jobIdentifier)) { continue; }
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -48,6 +48,7 @@ namespace Barotrauma
|
|||||||
msgBox.Buttons[0].OnClicked = delegate
|
msgBox.Buttons[0].OnClicked = delegate
|
||||||
{
|
{
|
||||||
msgBox.Close();
|
msgBox.Close();
|
||||||
|
if (GameMain.Client == null) { return true; }
|
||||||
SendState(ReadyStatus.Yes);
|
SendState(ReadyStatus.Yes);
|
||||||
CreateResultsMessage();
|
CreateResultsMessage();
|
||||||
return true;
|
return true;
|
||||||
@@ -57,6 +58,7 @@ namespace Barotrauma
|
|||||||
msgBox.Buttons[1].OnClicked = delegate
|
msgBox.Buttons[1].OnClicked = delegate
|
||||||
{
|
{
|
||||||
msgBox.Close();
|
msgBox.Close();
|
||||||
|
if (GameMain.Client == null) { return true; }
|
||||||
SendState(ReadyStatus.No);
|
SendState(ReadyStatus.No);
|
||||||
CreateResultsMessage();
|
CreateResultsMessage();
|
||||||
return true;
|
return true;
|
||||||
@@ -65,6 +67,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private void CreateResultsMessage()
|
private void CreateResultsMessage()
|
||||||
{
|
{
|
||||||
|
if (GameMain.Client == null) { return; }
|
||||||
|
|
||||||
Vector2 relativeSize = new Vector2(0.2f, 0.3f);
|
Vector2 relativeSize = new Vector2(0.2f, 0.3f);
|
||||||
Point minSize = new Point(300, 400);
|
Point minSize = new Point(300, 400);
|
||||||
resultsBox = new GUIMessageBox(readyCheckHeader, string.Empty, new[] { closeButton }, relativeSize, minSize, type: GUIMessageBox.Type.Vote) { UserData = ResultData, Draggable = true };
|
resultsBox = new GUIMessageBox(readyCheckHeader, string.Empty, new[] { closeButton }, relativeSize, minSize, type: GUIMessageBox.Type.Vote) { UserData = ResultData, Draggable = true };
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ namespace Barotrauma
|
|||||||
private int jobColumnWidth, characterColumnWidth, statusColumnWidth;
|
private int jobColumnWidth, characterColumnWidth, statusColumnWidth;
|
||||||
|
|
||||||
private readonly SubmarineInfo sub;
|
private readonly SubmarineInfo sub;
|
||||||
private readonly Mission selectedMission;
|
private readonly List<Mission> selectedMissions;
|
||||||
private readonly Location startLocation, endLocation;
|
private readonly Location startLocation, endLocation;
|
||||||
|
|
||||||
private readonly GameMode gameMode;
|
private readonly GameMode gameMode;
|
||||||
@@ -32,11 +32,11 @@ namespace Barotrauma
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
public RoundSummary(SubmarineInfo sub, GameMode gameMode, Mission selectedMission, Location startLocation, Location endLocation)
|
public RoundSummary(SubmarineInfo sub, GameMode gameMode, IEnumerable<Mission> selectedMissions, Location startLocation, Location endLocation)
|
||||||
{
|
{
|
||||||
this.sub = sub;
|
this.sub = sub;
|
||||||
this.gameMode = gameMode;
|
this.gameMode = gameMode;
|
||||||
this.selectedMission = selectedMission;
|
this.selectedMissions = selectedMissions.ToList();
|
||||||
this.startLocation = startLocation;
|
this.startLocation = startLocation;
|
||||||
this.endLocation = endLocation;
|
this.endLocation = endLocation;
|
||||||
initialLocationReputation = startLocation?.Reputation?.Value ?? 0.0f;
|
initialLocationReputation = startLocation?.Reputation?.Value ?? 0.0f;
|
||||||
@@ -75,7 +75,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
//crew panel -------------------------------------------------------------------------------
|
//crew panel -------------------------------------------------------------------------------
|
||||||
|
|
||||||
GUIFrame crewFrame = new GUIFrame(new RectTransform(new Vector2(0.35f, 0.55f), background.RectTransform, Anchor.TopCenter, minSize: new Point(minWidth, minHeight)));
|
GUIFrame crewFrame = new GUIFrame(new RectTransform(new Vector2(0.35f, 0.45f), background.RectTransform, Anchor.TopCenter, minSize: new Point(minWidth, minHeight)));
|
||||||
GUIFrame crewFrameInner = new GUIFrame(new RectTransform(new Point(crewFrame.Rect.Width - padding * 2, crewFrame.Rect.Height - padding * 2), crewFrame.RectTransform, Anchor.Center), style: "InnerFrame");
|
GUIFrame crewFrameInner = new GUIFrame(new RectTransform(new Point(crewFrame.Rect.Width - padding * 2, crewFrame.Rect.Height - padding * 2), crewFrame.RectTransform, Anchor.Center), style: "InnerFrame");
|
||||||
|
|
||||||
var crewContent = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), crewFrameInner.RectTransform, Anchor.Center))
|
var crewContent = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), crewFrameInner.RectTransform, Anchor.Center))
|
||||||
@@ -90,10 +90,10 @@ namespace Barotrauma
|
|||||||
CreateCrewList(crewContent, gameSession.CrewManager.GetCharacterInfos().Where(c => c.TeamID != CharacterTeamType.Team2));
|
CreateCrewList(crewContent, gameSession.CrewManager.GetCharacterInfos().Where(c => c.TeamID != CharacterTeamType.Team2));
|
||||||
|
|
||||||
//another crew frame for the 2nd team in combat missions
|
//another crew frame for the 2nd team in combat missions
|
||||||
if (gameSession.Mission is CombatMission)
|
if (gameSession.Missions.Any(m => m is CombatMission))
|
||||||
{
|
{
|
||||||
crewHeader.Text = CombatMission.GetTeamName(CharacterTeamType.Team1);
|
crewHeader.Text = CombatMission.GetTeamName(CharacterTeamType.Team1);
|
||||||
GUIFrame crewFrame2 = new GUIFrame(new RectTransform(new Vector2(0.35f, 0.55f), background.RectTransform, Anchor.TopCenter, minSize: new Point(minWidth, minHeight)));
|
GUIFrame crewFrame2 = new GUIFrame(new RectTransform(new Vector2(0.35f, 0.45f), background.RectTransform, Anchor.TopCenter, minSize: new Point(minWidth, minHeight)));
|
||||||
rightPanels.Add(crewFrame2);
|
rightPanels.Add(crewFrame2);
|
||||||
GUIFrame crewFrameInner2 = new GUIFrame(new RectTransform(new Point(crewFrame2.Rect.Width - padding * 2, crewFrame2.Rect.Height - padding * 2), crewFrame2.RectTransform, Anchor.Center), style: "InnerFrame");
|
GUIFrame crewFrameInner2 = new GUIFrame(new RectTransform(new Point(crewFrame2.Rect.Width - padding * 2, crewFrame2.Rect.Height - padding * 2), crewFrame2.RectTransform, Anchor.Center), style: "InnerFrame");
|
||||||
var crewContent2 = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), crewFrameInner2.RectTransform, Anchor.Center))
|
var crewContent2 = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), crewFrameInner2.RectTransform, Anchor.Center))
|
||||||
@@ -183,7 +183,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
//reputation panel -------------------------------------------------------------------------------
|
//reputation panel -------------------------------------------------------------------------------
|
||||||
|
|
||||||
if (gameMode is CampaignMode campaignMode)
|
var campaignMode = gameMode as CampaignMode;
|
||||||
|
if (campaignMode != null)
|
||||||
{
|
{
|
||||||
GUIFrame reputationframe = new GUIFrame(new RectTransform(crewFrame.RectTransform.RelativeSize, background.RectTransform, Anchor.TopCenter, minSize: crewFrame.RectTransform.MinSize));
|
GUIFrame reputationframe = new GUIFrame(new RectTransform(crewFrame.RectTransform.RelativeSize, background.RectTransform, Anchor.TopCenter, minSize: crewFrame.RectTransform.MinSize));
|
||||||
rightPanels.Add(reputationframe);
|
rightPanels.Add(reputationframe);
|
||||||
@@ -198,158 +199,154 @@ namespace Barotrauma
|
|||||||
TextManager.Get("reputation"), textAlignment: Alignment.TopLeft, font: GUI.SubHeadingFont);
|
TextManager.Get("reputation"), textAlignment: Alignment.TopLeft, font: GUI.SubHeadingFont);
|
||||||
reputationHeader.RectTransform.MinSize = new Point(0, GUI.IntScale(reputationHeader.Rect.Height * 2.0f));
|
reputationHeader.RectTransform.MinSize = new Point(0, GUI.IntScale(reputationHeader.Rect.Height * 2.0f));
|
||||||
|
|
||||||
GUIListBox reputationList = new GUIListBox(new RectTransform(Vector2.One, reputationContent.RectTransform))
|
CreateReputationInfoPanel(reputationContent, campaignMode);
|
||||||
{
|
|
||||||
Padding = new Vector4(2, 5, 0, 0)
|
|
||||||
};
|
|
||||||
reputationList.ContentBackground.Color = Color.Transparent;
|
|
||||||
|
|
||||||
if (startLocation.Type.HasOutpost && startLocation.Reputation != null)
|
|
||||||
{
|
|
||||||
var iconStyle = GUI.Style.GetComponentStyle("LocationReputationIcon");
|
|
||||||
CreateReputationElement(
|
|
||||||
reputationList.Content,
|
|
||||||
startLocation.Name,
|
|
||||||
startLocation.Reputation.Value, startLocation.Reputation.NormalizedValue, initialLocationReputation,
|
|
||||||
startLocation.Type.Name, "",
|
|
||||||
iconStyle?.GetDefaultSprite(), startLocation.Type.GetPortrait(0), iconStyle?.Color ?? Color.White);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (Faction faction in campaignMode.Factions)
|
|
||||||
{
|
|
||||||
float initialReputation = faction.Reputation.Value;
|
|
||||||
if (initialFactionReputations.ContainsKey(faction))
|
|
||||||
{
|
|
||||||
initialReputation = initialFactionReputations[faction];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DebugConsole.AddWarning($"Could not determine reputation change for faction \"{faction.Prefab.Name}\" (faction was not present at the start of the round).");
|
|
||||||
}
|
|
||||||
CreateReputationElement(
|
|
||||||
reputationList.Content,
|
|
||||||
faction.Prefab.Name,
|
|
||||||
faction.Reputation.Value, faction.Reputation.NormalizedValue, initialReputation,
|
|
||||||
faction.Prefab.ShortDescription, faction.Prefab.Description,
|
|
||||||
faction.Prefab.Icon, faction.Prefab.BackgroundPortrait, faction.Prefab.IconColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
float otherElementHeight = 0.0f;
|
|
||||||
float maxDescriptionHeight = 0.0f;
|
|
||||||
foreach (GUIComponent child in reputationList.Content.Children)
|
|
||||||
{
|
|
||||||
var descriptionElement = child.FindChild("description", recursive: true) as GUITextBlock;
|
|
||||||
maxDescriptionHeight = Math.Max(maxDescriptionHeight, descriptionElement.TextSize.Y * 1.1f);
|
|
||||||
otherElementHeight = Math.Max(otherElementHeight, descriptionElement.Parent.Rect.Height - descriptionElement.TextSize.Y);
|
|
||||||
}
|
|
||||||
foreach (GUIComponent child in reputationList.Content.Children)
|
|
||||||
{
|
|
||||||
var descriptionElement = child.FindChild("description", recursive: true) as GUITextBlock;
|
|
||||||
descriptionElement.RectTransform.MaxSize = new Point(int.MaxValue, (int)(maxDescriptionHeight));
|
|
||||||
child.RectTransform.MaxSize = new Point(int.MaxValue, (int)((maxDescriptionHeight + otherElementHeight) * 1.2f));
|
|
||||||
(descriptionElement?.Parent as GUILayoutGroup).Recalculate();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//mission panel -------------------------------------------------------------------------------
|
//mission panel -------------------------------------------------------------------------------
|
||||||
|
|
||||||
GUIFrame missionframe = new GUIFrame(new RectTransform(new Vector2(0.39f, 0.22f), background.RectTransform, Anchor.TopCenter, minSize: new Point(minWidth, minHeight / 4)));
|
GUIFrame missionframe = new GUIFrame(new RectTransform(new Vector2(0.39f, 0.3f), background.RectTransform, Anchor.TopCenter, minSize: new Point(minWidth, minHeight / 4)));
|
||||||
GUIFrame missionframeInner = new GUIFrame(new RectTransform(new Point(missionframe.Rect.Width - padding * 2, missionframe.Rect.Height - padding * 2), missionframe.RectTransform, Anchor.Center), style: "InnerFrame");
|
GUILayoutGroup missionFrameContent = new GUILayoutGroup(new RectTransform(new Point(missionframe.Rect.Width - padding * 2, missionframe.Rect.Height - padding * 2), missionframe.RectTransform, Anchor.Center))
|
||||||
|
{
|
||||||
var missionContent = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), missionframeInner.RectTransform, Anchor.Center))
|
Stretch = true,
|
||||||
|
RelativeSpacing = 0.05f
|
||||||
|
};
|
||||||
|
GUIFrame missionframeInner = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.9f), missionFrameContent.RectTransform, Anchor.Center), style: "InnerFrame");
|
||||||
|
|
||||||
|
var missionContent = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.93f), missionframeInner.RectTransform, Anchor.Center))
|
||||||
{
|
{
|
||||||
RelativeSpacing = 0.05f,
|
|
||||||
Stretch = true
|
Stretch = true
|
||||||
};
|
};
|
||||||
|
|
||||||
|
List<Mission> missionsToDisplay = new List<Mission>(selectedMissions);
|
||||||
|
if (!selectedMissions.Any() && startLocation?.SelectedMission != null)
|
||||||
|
{
|
||||||
|
if (startLocation.SelectedMission.Locations[0] == startLocation.SelectedMission.Locations[1] ||
|
||||||
|
startLocation.SelectedMission.Locations.Contains(campaignMode?.Map.SelectedLocation))
|
||||||
|
{
|
||||||
|
missionsToDisplay.Add(startLocation.SelectedMission);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (missionsToDisplay.Any())
|
||||||
|
{
|
||||||
|
var missionHeader = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionContent.RectTransform),
|
||||||
|
TextManager.Get(missionsToDisplay.Count > 1 ? "Missions" : "Mission"), textAlignment: Alignment.TopLeft, font: GUI.SubHeadingFont);
|
||||||
|
missionHeader.RectTransform.MinSize = new Point(0, (int)(missionHeader.Rect.Height * 1.2f));
|
||||||
|
}
|
||||||
|
|
||||||
|
GUIListBox missionList = new GUIListBox(new RectTransform(Vector2.One, missionContent.RectTransform, Anchor.Center))
|
||||||
|
{
|
||||||
|
Padding = new Vector4(4, 10, 0, 0) * GUI.Scale
|
||||||
|
};
|
||||||
|
missionList.ContentBackground.Color = Color.Transparent;
|
||||||
|
|
||||||
|
ButtonArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.1f), missionFrameContent.RectTransform, Anchor.BottomCenter), isHorizontal: true, childAnchor: Anchor.BottomRight)
|
||||||
|
{
|
||||||
|
RelativeSpacing = 0.025f
|
||||||
|
};
|
||||||
|
|
||||||
|
missionFrameContent.Recalculate();
|
||||||
|
missionContent.Recalculate();
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(endMessage))
|
if (!string.IsNullOrWhiteSpace(endMessage))
|
||||||
{
|
{
|
||||||
var endText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionContent.RectTransform),
|
var endText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionList.Content.RectTransform),
|
||||||
TextManager.GetServerMessage(endMessage), wrap: true);
|
TextManager.GetServerMessage(endMessage), wrap: true)
|
||||||
|
{
|
||||||
|
CanBeFocused = false
|
||||||
|
};
|
||||||
endText.RectTransform.MinSize = new Point(0, endText.Rect.Height);
|
endText.RectTransform.MinSize = new Point(0, endText.Rect.Height);
|
||||||
var line = new GUIFrame(new RectTransform(new Vector2(0.5f, 0.1f), missionContent.RectTransform), style: "HorizontalLine");
|
var line = new GUIFrame(new RectTransform(new Vector2(0.5f, 0.1f), missionList.Content.RectTransform), style: "HorizontalLine");
|
||||||
line.RectTransform.NonScaledSize = new Point(line.Rect.Width, GUI.IntScale(5.0f));
|
line.RectTransform.NonScaledSize = new Point(line.Rect.Width, GUI.IntScale(5.0f));
|
||||||
}
|
}
|
||||||
|
|
||||||
var missionContentHorizontal = new GUILayoutGroup(new RectTransform(Vector2.One, missionContent.RectTransform), childAnchor: Anchor.TopLeft, isHorizontal: true)
|
foreach (Mission displayedMission in missionsToDisplay)
|
||||||
{
|
{
|
||||||
RelativeSpacing = 0.025f,
|
var missionContentHorizontal = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.8f), missionList.Content.RectTransform), childAnchor: Anchor.CenterLeft, isHorizontal: true)
|
||||||
Stretch = true
|
|
||||||
};
|
|
||||||
|
|
||||||
Mission displayedMission = selectedMission ?? startLocation.SelectedMission;
|
|
||||||
string missionMessage = "";
|
|
||||||
GUIImage missionIcon;
|
|
||||||
if (displayedMission != null)
|
|
||||||
{
|
|
||||||
missionMessage =
|
|
||||||
displayedMission == selectedMission ?
|
|
||||||
displayedMission.Completed ? displayedMission.SuccessMessage : displayedMission.FailureMessage :
|
|
||||||
displayedMission.Description;
|
|
||||||
missionIcon = new GUIImage(new RectTransform(new Point(missionContentHorizontal.Rect.Height), missionContentHorizontal.RectTransform), displayedMission.Prefab.Icon, scaleToFit: true)
|
|
||||||
{
|
{
|
||||||
Color = displayedMission.Prefab.IconColor
|
RelativeSpacing = 0.025f,
|
||||||
|
Stretch = true
|
||||||
};
|
};
|
||||||
if (displayedMission == selectedMission)
|
|
||||||
{
|
|
||||||
new GUIImage(new RectTransform(Vector2.One, missionIcon.RectTransform), displayedMission.Completed ? "MissionCompletedIcon" : "MissionFailedIcon", scaleToFit: true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
missionIcon = new GUIImage(new RectTransform(new Point(missionContentHorizontal.Rect.Height), missionContentHorizontal.RectTransform), style: "NoMissionIcon", scaleToFit: true);
|
|
||||||
}
|
|
||||||
var missionTextContent = new GUILayoutGroup(new RectTransform(Vector2.One, missionContentHorizontal.RectTransform))
|
|
||||||
{
|
|
||||||
RelativeSpacing = 0.05f
|
|
||||||
};
|
|
||||||
missionContentHorizontal.Recalculate();
|
|
||||||
missionContent.Recalculate();
|
|
||||||
missionIcon.RectTransform.MinSize = new Point(0, missionContentHorizontal.Rect.Height);
|
|
||||||
missionTextContent.RectTransform.MaxSize = new Point(int.MaxValue, missionIcon.Rect.Width);
|
|
||||||
|
|
||||||
GUITextBlock missionDescription = null;
|
string missionMessage =
|
||||||
if (displayedMission == null)
|
selectedMissions.Contains(displayedMission) ?
|
||||||
{
|
displayedMission.Completed ? displayedMission.SuccessMessage : displayedMission.FailureMessage :
|
||||||
|
displayedMission.Description;
|
||||||
|
GUIImage missionIcon = new GUIImage(new RectTransform(new Point((int)(missionContentHorizontal.Rect.Height)), missionContentHorizontal.RectTransform), displayedMission.Prefab.Icon, scaleToFit: true)
|
||||||
|
{
|
||||||
|
Color = displayedMission.Prefab.IconColor,
|
||||||
|
HoverColor = displayedMission.Prefab.IconColor,
|
||||||
|
SelectedColor = displayedMission.Prefab.IconColor
|
||||||
|
};
|
||||||
|
missionIcon.RectTransform.MinSize = new Point((int)(missionContentHorizontal.Rect.Height * 0.9f));
|
||||||
|
if (selectedMissions.Contains(displayedMission))
|
||||||
|
{
|
||||||
|
new GUIImage(new RectTransform(Vector2.One, missionIcon.RectTransform), displayedMission.Completed ? "MissionCompletedIcon" : "MissionFailedIcon", scaleToFit: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
var missionTextContent = new GUILayoutGroup(new RectTransform(new Vector2(0.8f, 0.8f), missionContentHorizontal.RectTransform))
|
||||||
|
{
|
||||||
|
RelativeSpacing = 0.05f
|
||||||
|
};
|
||||||
|
var missionNameTextBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform),
|
||||||
|
displayedMission.Name, font: GUI.SubHeadingFont);
|
||||||
|
if (displayedMission.Difficulty.HasValue)
|
||||||
|
{
|
||||||
|
var groupSize = missionNameTextBlock.Rect.Size;
|
||||||
|
groupSize.X -= (int)(missionNameTextBlock.Padding.X + missionNameTextBlock.Padding.Z);
|
||||||
|
var indicatorGroup = new GUILayoutGroup(new RectTransform(groupSize, missionTextContent.RectTransform) { AbsoluteOffset = new Point((int)missionNameTextBlock.Padding.X, 0) },
|
||||||
|
isHorizontal: true, childAnchor: Anchor.CenterLeft)
|
||||||
|
{
|
||||||
|
AbsoluteSpacing = 1
|
||||||
|
};
|
||||||
|
var difficultyColor = displayedMission.GetDifficultyColor();
|
||||||
|
for (int i = 0; i < displayedMission.Difficulty; i++)
|
||||||
|
{
|
||||||
|
new GUIImage(new RectTransform(Vector2.One, indicatorGroup.RectTransform, scaleBasis: ScaleBasis.Smallest) { IsFixedSize = true }, "DifficultyIndicator", scaleToFit: true)
|
||||||
|
{
|
||||||
|
CanBeFocused = false,
|
||||||
|
Color = difficultyColor
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform),
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform),
|
||||||
TextManager.Get("nomission"), font: GUI.LargeFont);
|
missionMessage, wrap: true, parseRichText: true);
|
||||||
}
|
if (selectedMissions.Contains(displayedMission) && displayedMission.Completed && displayedMission.Reward > 0)
|
||||||
else
|
|
||||||
{
|
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform),
|
|
||||||
TextManager.AddPunctuation(':', TextManager.Get("Mission"), displayedMission.Name), font: GUI.SubHeadingFont);
|
|
||||||
missionDescription = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform),
|
|
||||||
missionMessage, wrap: true);
|
|
||||||
if (displayedMission == selectedMission && displayedMission.Completed)
|
|
||||||
{
|
{
|
||||||
string rewardText = TextManager.GetWithVariable("currencyformat", "[credits]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", displayedMission.Reward));
|
string rewardText = TextManager.GetWithVariable("currencyformat", "[credits]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", displayedMission.Reward));
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform),
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform), displayedMission.GetMissionRewardText(), parseRichText: true);
|
||||||
TextManager.GetWithVariable("MissionReward", "[reward]", rewardText));
|
}
|
||||||
|
|
||||||
|
if (displayedMission != missionsToDisplay.Last())
|
||||||
|
{
|
||||||
|
var spacing = new GUIFrame(new RectTransform(new Vector2(1.0f, 1.0f), missionList.Content.RectTransform) { MaxSize = new Point(int.MaxValue, GUI.IntScale(15)) }, style: null);
|
||||||
|
new GUIFrame(new RectTransform(new Vector2(0.8f, 1.0f), spacing.RectTransform, Anchor.Center) { RelativeOffset = new Vector2(0.1f, 0.0f) }, "HorizontalLine");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ButtonArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.1f), missionContent.RectTransform, Anchor.BottomCenter), isHorizontal: true, childAnchor: Anchor.BottomRight)
|
if (!missionsToDisplay.Any())
|
||||||
{
|
{
|
||||||
IgnoreLayoutGroups = true,
|
var missionContentHorizontal = new GUILayoutGroup(new RectTransform(Vector2.One, missionList.Content.RectTransform), childAnchor: Anchor.TopLeft, isHorizontal: true)
|
||||||
RelativeSpacing = 0.025f
|
{
|
||||||
};
|
RelativeSpacing = 0.025f,
|
||||||
|
Stretch = true
|
||||||
|
};
|
||||||
|
GUIImage missionIcon = new GUIImage(new RectTransform(new Point((int)(missionContentHorizontal.Rect.Height * 0.7f)), missionContentHorizontal.RectTransform), style: "NoMissionIcon", scaleToFit: true);
|
||||||
|
missionIcon.RectTransform.MinSize = new Point((int)(missionContentHorizontal.Rect.Height * 0.7f));
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionContentHorizontal.RectTransform),
|
||||||
|
TextManager.Get("nomission"), font: GUI.LargeFont);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*missionContentHorizontal.Recalculate();
|
||||||
|
missionContent.Recalculate();
|
||||||
|
missionIcon.RectTransform.MinSize = new Point(0, missionContentHorizontal.Rect.Height);
|
||||||
|
missionTextContent.RectTransform.MaxSize = new Point(int.MaxValue, missionIcon.Rect.Width);*/
|
||||||
|
|
||||||
ContinueButton = new GUIButton(new RectTransform(new Vector2(0.25f, 1.0f), ButtonArea.RectTransform), TextManager.Get("Close"));
|
ContinueButton = new GUIButton(new RectTransform(new Vector2(0.25f, 1.0f), ButtonArea.RectTransform), TextManager.Get("Close"));
|
||||||
ButtonArea.RectTransform.NonScaledSize = new Point(ButtonArea.Rect.Width, ContinueButton.Rect.Height);
|
ButtonArea.RectTransform.NonScaledSize = new Point(ButtonArea.Rect.Width, ContinueButton.Rect.Height);
|
||||||
ButtonArea.RectTransform.IsFixedSize = true;
|
ButtonArea.RectTransform.IsFixedSize = true;
|
||||||
|
|
||||||
missionContent.Recalculate();
|
missionFrameContent.Recalculate();
|
||||||
//description overlapping with the buttons -> switch to small font
|
|
||||||
if (missionDescription != null && missionDescription.Rect.Y + missionDescription.TextSize.Y > ButtonArea.Rect.Y)
|
|
||||||
{
|
|
||||||
missionDescription.Font = GUI.Style.SmallFont;
|
|
||||||
//still overlapping -> shorten the text
|
|
||||||
if (missionDescription.Rect.Y + missionDescription.TextSize.Y > ButtonArea.Rect.Y && missionDescription.WrappedText.Contains('\n'))
|
|
||||||
{
|
|
||||||
missionDescription.ToolTip = missionDescription.Text;
|
|
||||||
missionDescription.Text = missionDescription.WrappedText.Split('\n').First() + "...";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// set layout -------------------------------------------------------------------
|
// set layout -------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -378,9 +375,114 @@ namespace Barotrauma
|
|||||||
return background;
|
return background;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void CreateReputationInfoPanel(GUIComponent parent, CampaignMode campaignMode)
|
||||||
|
{
|
||||||
|
GUIListBox reputationList = new GUIListBox(new RectTransform(Vector2.One, parent.RectTransform))
|
||||||
|
{
|
||||||
|
Padding = new Vector4(4, 10, 0, 0) * GUI.Scale
|
||||||
|
};
|
||||||
|
reputationList.ContentBackground.Color = Color.Transparent;
|
||||||
|
|
||||||
|
if (startLocation.Type.HasOutpost && startLocation.Reputation != null)
|
||||||
|
{
|
||||||
|
var iconStyle = GUI.Style.GetComponentStyle("LocationReputationIcon");
|
||||||
|
var locationFrame = CreateReputationElement(
|
||||||
|
reputationList.Content,
|
||||||
|
startLocation.Name,
|
||||||
|
startLocation.Reputation.Value, startLocation.Reputation.NormalizedValue, initialLocationReputation,
|
||||||
|
startLocation.Type.Name, "",
|
||||||
|
iconStyle?.GetDefaultSprite(), startLocation.Type.GetPortrait(0), iconStyle?.Color ?? Color.White);
|
||||||
|
CreatePathUnlockElement(locationFrame, null, startLocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (Faction faction in campaignMode.Factions)
|
||||||
|
{
|
||||||
|
float initialReputation = faction.Reputation.Value;
|
||||||
|
if (initialFactionReputations.ContainsKey(faction))
|
||||||
|
{
|
||||||
|
initialReputation = initialFactionReputations[faction];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DebugConsole.AddWarning($"Could not determine reputation change for faction \"{faction.Prefab.Name}\" (faction was not present at the start of the round).");
|
||||||
|
}
|
||||||
|
var factionFrame = CreateReputationElement(
|
||||||
|
reputationList.Content,
|
||||||
|
faction.Prefab.Name,
|
||||||
|
faction.Reputation.Value, faction.Reputation.NormalizedValue, initialReputation,
|
||||||
|
faction.Prefab.ShortDescription, faction.Prefab.Description,
|
||||||
|
faction.Prefab.Icon, faction.Prefab.BackgroundPortrait, faction.Prefab.IconColor);
|
||||||
|
CreatePathUnlockElement(factionFrame, faction, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
float maxDescriptionHeight = 0.0f;
|
||||||
|
foreach (GUIComponent child in reputationList.Content.Children)
|
||||||
|
{
|
||||||
|
var descriptionElement = child.FindChild("description", recursive: true) as GUITextBlock;
|
||||||
|
maxDescriptionHeight = Math.Max(maxDescriptionHeight, descriptionElement.TextSize.Y * 1.1f);
|
||||||
|
}
|
||||||
|
foreach (GUIComponent child in reputationList.Content.Children)
|
||||||
|
{
|
||||||
|
var headerElement = child.FindChild("header", recursive: true) as GUITextBlock;
|
||||||
|
var descriptionElement = child.FindChild("description", recursive: true) as GUITextBlock;
|
||||||
|
descriptionElement.RectTransform.NonScaledSize = new Point(descriptionElement.Rect.Width, (int)maxDescriptionHeight);
|
||||||
|
descriptionElement.RectTransform.IsFixedSize = true;
|
||||||
|
child.RectTransform.NonScaledSize = new Point(child.Rect.Width, headerElement.Rect.Height + descriptionElement.RectTransform.Parent.Children.Sum(c => c.Rect.Height + ((GUILayoutGroup)descriptionElement.Parent).AbsoluteSpacing));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CreatePathUnlockElement(GUIComponent reputationFrame, Faction faction, Location location)
|
||||||
|
{
|
||||||
|
if (GameMain.GameSession?.Campaign?.Map != null)
|
||||||
|
{
|
||||||
|
foreach (LocationConnection connection in GameMain.GameSession.Campaign.Map.Connections)
|
||||||
|
{
|
||||||
|
if (!connection.Locked || (!connection.Locations[0].Discovered && !connection.Locations[1].Discovered)) { continue; }
|
||||||
|
|
||||||
|
var gateLocation = connection.Locations[0].IsGateBetweenBiomes ? connection.Locations[0] : connection.Locations[1];
|
||||||
|
var unlockEvent =
|
||||||
|
EventSet.PrefabList.Find(ep => ep.UnlockPathEvent && ep.BiomeIdentifier == gateLocation.LevelData.Biome.Identifier) ??
|
||||||
|
EventSet.PrefabList.Find(ep => ep.UnlockPathEvent && string.IsNullOrEmpty(ep.BiomeIdentifier));
|
||||||
|
|
||||||
|
if (unlockEvent == null) { continue; }
|
||||||
|
if (string.IsNullOrEmpty(unlockEvent.UnlockPathFaction) || unlockEvent.UnlockPathFaction.Equals("location", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
if (location == null || gateLocation != location) { continue; }
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (faction == null || !faction.Prefab.Identifier.Equals(unlockEvent.UnlockPathFaction, StringComparison.OrdinalIgnoreCase)) { continue; }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unlockEvent != null)
|
||||||
|
{
|
||||||
|
Reputation unlockReputation = gateLocation.Reputation;
|
||||||
|
Faction unlockFaction = null;
|
||||||
|
if (!string.IsNullOrEmpty(unlockEvent.UnlockPathFaction))
|
||||||
|
{
|
||||||
|
unlockFaction = GameMain.GameSession.Campaign.Factions.Find(f => f.Prefab.Identifier.Equals(unlockEvent.UnlockPathFaction, StringComparison.OrdinalIgnoreCase));
|
||||||
|
unlockReputation = unlockFaction?.Reputation;
|
||||||
|
}
|
||||||
|
float normalizedUnlockReputation = MathUtils.InverseLerp(unlockReputation.MinReputation, unlockReputation.MaxReputation, unlockEvent.UnlockPathReputation);
|
||||||
|
string unlockText = TextManager.GetWithVariables(
|
||||||
|
"lockedpathreputationrequirement",
|
||||||
|
new string[] { "[reputation]", "[biomename]" },
|
||||||
|
new string[] { Reputation.GetFormattedReputationText(normalizedUnlockReputation, unlockEvent.UnlockPathReputation, addColorTags: true), $"‖color:gui.orange‖{connection.LevelData.Biome.DisplayName}‖end‖" });
|
||||||
|
var unlockInfoPanel = new GUITextBlock(new RectTransform(new Vector2(0.8f, 0.0f), reputationFrame.RectTransform, Anchor.BottomCenter) { MinSize = new Point(0, GUI.IntScale(30)), AbsoluteOffset = new Point(0, GUI.IntScale(3)) },
|
||||||
|
unlockText, style: "GUIButtonRound", textAlignment: Alignment.Center, textColor: GUI.Style.TextColor, parseRichText: true);
|
||||||
|
unlockInfoPanel.Color = Color.Lerp(unlockInfoPanel.Color, Color.Black, 0.8f);
|
||||||
|
if (unlockInfoPanel.TextSize.X > unlockInfoPanel.Rect.Width * 0.7f)
|
||||||
|
{
|
||||||
|
unlockInfoPanel.Font = GUI.SmallFont;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private string GetHeaderText(bool gameOver, CampaignMode.TransitionType transitionType)
|
private string GetHeaderText(bool gameOver, CampaignMode.TransitionType transitionType)
|
||||||
{
|
{
|
||||||
string locationName = Submarine.MainSub.AtEndPosition ? endLocation?.Name : startLocation?.Name;
|
string locationName = Submarine.MainSub.AtEndExit ? endLocation?.Name : startLocation?.Name;
|
||||||
|
|
||||||
string textTag;
|
string textTag;
|
||||||
if (gameOver)
|
if (gameOver)
|
||||||
@@ -396,17 +498,23 @@ namespace Barotrauma
|
|||||||
textTag = "RoundSummaryLeaving";
|
textTag = "RoundSummaryLeaving";
|
||||||
break;
|
break;
|
||||||
case CampaignMode.TransitionType.ProgressToNextLocation:
|
case CampaignMode.TransitionType.ProgressToNextLocation:
|
||||||
case CampaignMode.TransitionType.ProgressToNextEmptyLocation:
|
|
||||||
locationName = endLocation?.Name;
|
locationName = endLocation?.Name;
|
||||||
textTag = "RoundSummaryProgress";
|
textTag = "RoundSummaryProgress";
|
||||||
break;
|
break;
|
||||||
|
case CampaignMode.TransitionType.ProgressToNextEmptyLocation:
|
||||||
|
locationName = endLocation?.Name;
|
||||||
|
textTag = "RoundSummaryProgressToEmptyLocation";
|
||||||
|
break;
|
||||||
case CampaignMode.TransitionType.ReturnToPreviousLocation:
|
case CampaignMode.TransitionType.ReturnToPreviousLocation:
|
||||||
case CampaignMode.TransitionType.ReturnToPreviousEmptyLocation:
|
|
||||||
locationName = startLocation?.Name;
|
locationName = startLocation?.Name;
|
||||||
textTag = "RoundSummaryReturn";
|
textTag = "RoundSummaryReturn";
|
||||||
break;
|
break;
|
||||||
|
case CampaignMode.TransitionType.ReturnToPreviousEmptyLocation:
|
||||||
|
locationName = startLocation?.Name;
|
||||||
|
textTag = "RoundSummaryReturnToEmptyLocation";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
textTag = Submarine.MainSub.AtEndPosition ? "RoundSummaryProgress" : "RoundSummaryReturn";
|
textTag = Submarine.MainSub.AtEndExit ? "RoundSummaryProgress" : "RoundSummaryReturn";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -456,7 +564,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
GUIListBox crewList = new GUIListBox(new RectTransform(Vector2.One, parent.RectTransform))
|
GUIListBox crewList = new GUIListBox(new RectTransform(Vector2.One, parent.RectTransform))
|
||||||
{
|
{
|
||||||
Padding = new Vector4(2, 5, 0, 0),
|
Padding = new Vector4(4, 10, 0, 0) * GUI.Scale,
|
||||||
AutoHideScrollBar = false
|
AutoHideScrollBar = false
|
||||||
};
|
};
|
||||||
crewList.ContentBackground.Color = Color.Transparent;
|
crewList.ContentBackground.Color = Color.Transparent;
|
||||||
@@ -547,11 +655,11 @@ namespace Barotrauma
|
|||||||
ToolBox.LimitString(statusText, GUI.Font, characterColumnWidth), textAlignment: Alignment.Center, textColor: statusColor);
|
ToolBox.LimitString(statusText, GUI.Font, characterColumnWidth), textAlignment: Alignment.Center, textColor: statusColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CreateReputationElement(GUIComponent parent,
|
private GUIFrame CreateReputationElement(GUIComponent parent,
|
||||||
string name, float reputation, float normalizedReputation, float initialReputation,
|
string name, float reputation, float normalizedReputation, float initialReputation,
|
||||||
string shortDescription, string fullDescription, Sprite icon, Sprite backgroundPortrait, Color iconColor)
|
string shortDescription, string fullDescription, Sprite icon, Sprite backgroundPortrait, Color iconColor)
|
||||||
{
|
{
|
||||||
var factionFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.3f), parent.RectTransform), style: null);
|
var factionFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.1f), parent.RectTransform), style: null);
|
||||||
|
|
||||||
if (backgroundPortrait != null)
|
if (backgroundPortrait != null)
|
||||||
{
|
{
|
||||||
@@ -568,13 +676,13 @@ namespace Barotrauma
|
|||||||
|
|
||||||
var factionInfoHorizontal = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), factionFrame.RectTransform, Anchor.Center), childAnchor: Anchor.CenterLeft, isHorizontal: true)
|
var factionInfoHorizontal = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), factionFrame.RectTransform, Anchor.Center), childAnchor: Anchor.CenterLeft, isHorizontal: true)
|
||||||
{
|
{
|
||||||
RelativeSpacing = 0.02f,
|
AbsoluteSpacing = GUI.IntScale(5),
|
||||||
Stretch = true
|
Stretch = true
|
||||||
};
|
};
|
||||||
|
|
||||||
var factionTextContent = new GUILayoutGroup(new RectTransform(Vector2.One, factionInfoHorizontal.RectTransform))
|
var factionTextContent = new GUILayoutGroup(new RectTransform(Vector2.One, factionInfoHorizontal.RectTransform))
|
||||||
{
|
{
|
||||||
RelativeSpacing = 0.05f,
|
AbsoluteSpacing = GUI.IntScale(10),
|
||||||
Stretch = true
|
Stretch = true
|
||||||
};
|
};
|
||||||
var factionIcon = new GUIImage(new RectTransform(new Point((int)(factionInfoHorizontal.Rect.Height * 0.7f)), factionInfoHorizontal.RectTransform, scaleBasis: ScaleBasis.Smallest), icon, scaleToFit: true)
|
var factionIcon = new GUIImage(new RectTransform(new Point((int)(factionInfoHorizontal.Rect.Height * 0.7f)), factionInfoHorizontal.RectTransform, scaleBasis: ScaleBasis.Smallest), icon, scaleToFit: true)
|
||||||
@@ -583,12 +691,48 @@ namespace Barotrauma
|
|||||||
};
|
};
|
||||||
factionInfoHorizontal.Recalculate();
|
factionInfoHorizontal.Recalculate();
|
||||||
|
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), factionTextContent.RectTransform),
|
var header = new GUITextBlock(new RectTransform(new Point(factionTextContent.Rect.Width, GUI.IntScale(40)), factionTextContent.RectTransform),
|
||||||
name, font: GUI.SubHeadingFont)
|
name, font: GUI.SubHeadingFont)
|
||||||
{
|
{
|
||||||
Padding = Vector4.Zero
|
Padding = Vector4.Zero,
|
||||||
|
UserData = "header"
|
||||||
};
|
};
|
||||||
var factionDescription = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.6f), factionTextContent.RectTransform),
|
header.RectTransform.IsFixedSize = true;
|
||||||
|
|
||||||
|
var sliderHolder = new GUILayoutGroup(new RectTransform(new Point((int)(factionTextContent.Rect.Width * 0.8f), GUI.IntScale(20.0f)), factionTextContent.RectTransform),
|
||||||
|
childAnchor: Anchor.CenterLeft, isHorizontal: true)
|
||||||
|
{
|
||||||
|
RelativeSpacing = 0.05f,
|
||||||
|
Stretch = true
|
||||||
|
};
|
||||||
|
sliderHolder.RectTransform.IsFixedSize = true;
|
||||||
|
factionTextContent.Recalculate();
|
||||||
|
|
||||||
|
new GUICustomComponent(new RectTransform(new Vector2(0.8f, 1.0f), sliderHolder.RectTransform),
|
||||||
|
onDraw: (sb, customComponent) => DrawReputationBar(sb, customComponent.Rect, normalizedReputation));
|
||||||
|
|
||||||
|
string reputationText = Reputation.GetFormattedReputationText(normalizedReputation, reputation, addColorTags: true);
|
||||||
|
int reputationChange = (int)Math.Round(reputation - initialReputation);
|
||||||
|
if (Math.Abs(reputationChange) > 0)
|
||||||
|
{
|
||||||
|
string changeText = $"{(reputationChange > 0 ? "+" : "") + reputationChange}";
|
||||||
|
string colorStr = XMLExtensions.ColorToString(reputationChange > 0 ? GUI.Style.Green : GUI.Style.Red);
|
||||||
|
var rtData = RichTextData.GetRichTextData($"{reputationText} (‖color:{colorStr}‖{changeText}‖color:end‖)", out string sanitizedText);
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), sliderHolder.RectTransform),
|
||||||
|
rtData, sanitizedText,
|
||||||
|
textAlignment: Alignment.CenterLeft, font: GUI.SubHeadingFont);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), sliderHolder.RectTransform),
|
||||||
|
reputationText,
|
||||||
|
textAlignment: Alignment.CenterLeft, font: GUI.SubHeadingFont, parseRichText: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
//spacing
|
||||||
|
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.0f), factionTextContent.RectTransform) { MinSize = new Point(0, GUI.IntScale(5)) }, style: null);
|
||||||
|
|
||||||
|
var factionDescription = new GUITextBlock(new RectTransform(new Vector2(0.8f, 0.6f), factionTextContent.RectTransform),
|
||||||
shortDescription, font: GUI.SmallFont, wrap: true)
|
shortDescription, font: GUI.SmallFont, wrap: true)
|
||||||
{
|
{
|
||||||
UserData = "description",
|
UserData = "description",
|
||||||
@@ -599,51 +743,32 @@ namespace Barotrauma
|
|||||||
factionDescription.ToolTip = fullDescription;
|
factionDescription.ToolTip = fullDescription;
|
||||||
}
|
}
|
||||||
|
|
||||||
var sliderHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.1f), factionTextContent.RectTransform),
|
//spacing
|
||||||
childAnchor: Anchor.CenterLeft, isHorizontal: true)
|
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.0f), factionTextContent.RectTransform) { MinSize = new Point(0, GUI.IntScale(5)) }, style: null);
|
||||||
{
|
|
||||||
RelativeSpacing = 0.05f,
|
factionInfoHorizontal.Recalculate();
|
||||||
Stretch = true
|
|
||||||
};
|
|
||||||
sliderHolder.RectTransform.MaxSize = new Point(int.MaxValue, GUI.IntScale(25.0f));
|
|
||||||
factionTextContent.Recalculate();
|
factionTextContent.Recalculate();
|
||||||
|
|
||||||
new GUICustomComponent(new RectTransform(new Vector2(0.8f, 1.0f), sliderHolder.RectTransform),
|
return factionFrame;
|
||||||
onDraw: (sb, customComponent) => DrawReputationBar(sb, customComponent.Rect, normalizedReputation));
|
|
||||||
|
|
||||||
string reputationText = ((int)Math.Round(reputation)).ToString();
|
|
||||||
int reputationChange = (int)Math.Round( reputation - initialReputation);
|
|
||||||
if (Math.Abs(reputationChange) > 0)
|
|
||||||
{
|
|
||||||
string changeText = $"{(reputationChange > 0 ? "+" : "") + reputationChange}";
|
|
||||||
string colorStr = XMLExtensions.ColorToString(reputationChange > 0 ? GUI.Style.Green : GUI.Style.Red);
|
|
||||||
var rtData = RichTextData.GetRichTextData($"{reputationText} (‖color:{colorStr}‖{changeText}‖color:end‖)", out string sanitizedText);
|
|
||||||
new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), sliderHolder.RectTransform),
|
|
||||||
rtData, sanitizedText,
|
|
||||||
textAlignment: Alignment.CenterLeft, font: GUI.SubHeadingFont);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), sliderHolder.RectTransform),
|
|
||||||
reputationText,
|
|
||||||
textAlignment: Alignment.CenterLeft, font: GUI.SubHeadingFont);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void DrawReputationBar(SpriteBatch sb, Rectangle rect, float normalizedReputation)
|
public static void DrawReputationBar(SpriteBatch sb, Rectangle rect, float normalizedReputation)
|
||||||
{
|
{
|
||||||
GUI.DrawRectangle(sb, rect, GUI.Style.ColorInventoryBackground, isFilled: true);
|
int segmentWidth = rect.Width / 5;
|
||||||
if (normalizedReputation < 0.5f)
|
rect.Width = segmentWidth * 5;
|
||||||
|
for (int i = 0; i < 5; i++)
|
||||||
{
|
{
|
||||||
int barWidth = (int)((0.5f - normalizedReputation) * rect.Width);
|
GUI.DrawRectangle(sb, new Rectangle(rect.X + (segmentWidth * i), rect.Y, segmentWidth, rect.Height), Reputation.GetReputationColor(i / 5.0f), isFilled: true);
|
||||||
GUI.DrawRectangle(sb, new Rectangle(rect.Center.X - barWidth, rect.Y, barWidth, rect.Height), GUI.Style.Red, isFilled: true);
|
GUI.DrawRectangle(sb, new Rectangle(rect.X + (segmentWidth * i), rect.Y, segmentWidth, rect.Height), GUI.Style.ColorInventoryBackground, isFilled: false);
|
||||||
}
|
}
|
||||||
else if (normalizedReputation > 0.5f)
|
GUI.DrawRectangle(sb, rect, GUI.Style.ColorInventoryBackground, isFilled: false);
|
||||||
{
|
|
||||||
int barWidth = (int)((normalizedReputation - 0.5f) * rect.Width);
|
GUI.Arrow.Draw(sb, new Vector2(rect.X + rect.Width * normalizedReputation, rect.Y), GUI.Style.ColorInventoryBackground, scale: GUI.Scale, spriteEffect: SpriteEffects.FlipVertically);
|
||||||
GUI.DrawRectangle(sb, new Rectangle(rect.Center.X, rect.Y, barWidth, rect.Height), GUI.Style.Green, isFilled: true);
|
GUI.Arrow.Draw(sb, new Vector2(rect.X + rect.Width * normalizedReputation, rect.Y), GUI.Style.TextColor, scale: GUI.Scale * 0.8f, spriteEffect: SpriteEffects.FlipVertically);
|
||||||
}
|
|
||||||
GUI.DrawLine(sb, new Vector2(rect.Center.X, rect.Y - 2), new Vector2(rect.Center.X, rect.Bottom + 2), GUI.Style.TextColor);
|
GUI.DrawString(sb, new Vector2(rect.X, rect.Bottom), "-100", GUI.Style.TextColor, font: GUI.SmallFont);
|
||||||
|
Vector2 textSize = GUI.SmallFont.MeasureString("100");
|
||||||
|
GUI.DrawString(sb, new Vector2(rect.Right - textSize.X, rect.Bottom), "100", GUI.Style.TextColor, font: GUI.SmallFont);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ namespace Barotrauma
|
|||||||
Audio,
|
Audio,
|
||||||
VoiceChat,
|
VoiceChat,
|
||||||
Controls,
|
Controls,
|
||||||
|
Gameplay,
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
Debug
|
Debug
|
||||||
#endif
|
#endif
|
||||||
@@ -532,29 +533,19 @@ namespace Barotrauma
|
|||||||
UserData = tab
|
UserData = tab
|
||||||
};
|
};
|
||||||
|
|
||||||
float tabWidth = 0.25f;
|
float tabWidth = 1.0f / tabs.Length;
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
tabWidth = 0.2f;
|
string buttonText = tab != Tab.Debug ? TextManager.Get("SettingsTab." + tab.ToString()) : "Debug";
|
||||||
if (tab != Tab.Debug)
|
#else
|
||||||
{
|
string buttonText = TextManager.Get("SettingsTab." + tab.ToString());
|
||||||
#endif
|
#endif
|
||||||
tabButtons[(int)tab] = new GUIButton(new RectTransform(new Vector2(tabWidth, 1.0f), tabButtonHolder.RectTransform),
|
|
||||||
TextManager.Get("SettingsTab." + tab.ToString()), style: "GUITabButton")
|
tabButtons[(int)tab] = new GUIButton(new RectTransform(new Vector2(tabWidth, 1.0f), tabButtonHolder.RectTransform), style: "GUITabButton")
|
||||||
{
|
|
||||||
UserData = tab,
|
|
||||||
OnClicked = (bt, userdata) => { SelectTab((Tab)userdata); return true; }
|
|
||||||
};
|
|
||||||
#if DEBUG
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
tabButtons[(int)tab] = new GUIButton(new RectTransform(new Vector2(tabWidth, 1.0f), tabButtonHolder.RectTransform), "Debug", style: "GUITabButton")
|
UserData = tab,
|
||||||
{
|
OnClicked = (bt, userdata) => { SelectTab((Tab)userdata); return true; }
|
||||||
UserData = tab,
|
};
|
||||||
OnClicked = (bt, userdata) => { SelectTab((Tab)userdata); return true; }
|
tabButtons[(int)tab].Text = ToolBox.LimitString(buttonText, tabButtons[(int)tab].Font, (int)(0.75f * tabWidth * tabButtonHolder.Rect.Width));
|
||||||
};
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
new GUIButton(new RectTransform(new Vector2(0.05f, 0.75f), tabButtonHolder.RectTransform, Anchor.BottomRight) { RelativeOffset = new Vector2(0.0f, 0.2f) }, style: "GUIBugButton")
|
new GUIButton(new RectTransform(new Vector2(0.05f, 0.75f), tabButtonHolder.RectTransform, Anchor.BottomRight) { RelativeOffset = new Vector2(0.0f, 0.2f) }, style: "GUIBugButton")
|
||||||
@@ -669,19 +660,6 @@ namespace Barotrauma
|
|||||||
Selected = TextureCompressionEnabled
|
Selected = TextureCompressionEnabled
|
||||||
};
|
};
|
||||||
|
|
||||||
GUITickBox pauseOnFocusLostBox = new GUITickBox(new RectTransform(tickBoxScale, leftColumn.RectTransform),
|
|
||||||
TextManager.Get("PauseOnFocusLost"))
|
|
||||||
{
|
|
||||||
Selected = PauseOnFocusLost,
|
|
||||||
ToolTip = TextManager.Get("PauseOnFocusLostToolTip"),
|
|
||||||
OnSelected = (tickBox) =>
|
|
||||||
{
|
|
||||||
PauseOnFocusLost = tickBox.Selected;
|
|
||||||
UnsavedSettings = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
GUITextBlock particleLimitText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), TextManager.Get("ParticleLimit"), font: GUI.SubHeadingFont, wrap: true);
|
GUITextBlock particleLimitText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), TextManager.Get("ParticleLimit"), font: GUI.SubHeadingFont, wrap: true);
|
||||||
GUIScrollBar particleScrollBar = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), style: "GUISlider",
|
GUIScrollBar particleScrollBar = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), style: "GUISlider",
|
||||||
barSize: 0.1f)
|
barSize: 0.1f)
|
||||||
@@ -773,56 +751,6 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
GUITextBlock HUDScaleText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), TextManager.Get("HUDScale"), font: GUI.SubHeadingFont, wrap: true);
|
|
||||||
GUIScrollBar HUDScaleScrollBar = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform),
|
|
||||||
style: "GUISlider", barSize: 0.1f)
|
|
||||||
{
|
|
||||||
UserData = HUDScaleText,
|
|
||||||
BarScroll = (HUDScale - MinHUDScale) / (MaxHUDScale - MinHUDScale),
|
|
||||||
OnMoved = (scrollBar, scroll) =>
|
|
||||||
{
|
|
||||||
HUDScale = MathHelper.Lerp(MinHUDScale, MaxHUDScale, scroll);
|
|
||||||
ChangeSliderText(scrollBar, HUDScale);
|
|
||||||
OnHUDScaleChanged?.Invoke();
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
Step = 0.02f
|
|
||||||
};
|
|
||||||
HUDScaleScrollBar.OnMoved(HUDScaleScrollBar, HUDScaleScrollBar.BarScroll);
|
|
||||||
|
|
||||||
GUITextBlock inventoryScaleText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), TextManager.Get("InventoryScale"), font: GUI.SubHeadingFont);
|
|
||||||
GUIScrollBar inventoryScaleScrollBar = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform),
|
|
||||||
style: "GUISlider", barSize: 0.1f)
|
|
||||||
{
|
|
||||||
UserData = inventoryScaleText,
|
|
||||||
BarScroll = (InventoryScale - MinInventoryScale) / (MaxInventoryScale - MinInventoryScale),
|
|
||||||
OnMoved = (scrollBar, scroll) =>
|
|
||||||
{
|
|
||||||
InventoryScale = MathHelper.Lerp(MinInventoryScale, MaxInventoryScale, scroll);
|
|
||||||
ChangeSliderText(scrollBar, InventoryScale);
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
Step = 0.02f
|
|
||||||
};
|
|
||||||
inventoryScaleScrollBar.OnMoved(inventoryScaleScrollBar, inventoryScaleScrollBar.BarScroll);
|
|
||||||
|
|
||||||
GUITextBlock textScaleText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), TextManager.Get("TextScale"), font: GUI.SubHeadingFont);
|
|
||||||
GUIScrollBar textScaleScrollBar = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform),
|
|
||||||
style: "GUISlider", barSize: 0.1f)
|
|
||||||
{
|
|
||||||
UserData = textScaleText,
|
|
||||||
BarScroll = (TextScale - MinTextScale) / (MaxTextScale - MinTextScale),
|
|
||||||
OnMoved = (scrollBar, scroll) =>
|
|
||||||
{
|
|
||||||
TextScale = MathHelper.Lerp(MinTextScale, MaxTextScale, scroll);
|
|
||||||
textScaleDirty = true;
|
|
||||||
ChangeSliderText(scrollBar, TextScale);
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
Step = 0.01f
|
|
||||||
};
|
|
||||||
textScaleScrollBar.OnMoved(textScaleScrollBar, textScaleScrollBar.BarScroll);
|
|
||||||
|
|
||||||
/// Audio tab ----------------------------------------------------------------
|
/// Audio tab ----------------------------------------------------------------
|
||||||
|
|
||||||
var audioContent = new GUILayoutGroup(new RectTransform(new Vector2(0.97f, 0.97f), tabs[(int)Tab.Audio].RectTransform, Anchor.Center), childAnchor: Anchor.TopCenter)
|
var audioContent = new GUILayoutGroup(new RectTransform(new Vector2(0.97f, 0.97f), tabs[(int)Tab.Audio].RectTransform, Anchor.Center), childAnchor: Anchor.TopCenter)
|
||||||
@@ -1177,13 +1105,14 @@ namespace Barotrauma
|
|||||||
style: "GUISlider", barSize: 0.05f)
|
style: "GUISlider", barSize: 0.05f)
|
||||||
{
|
{
|
||||||
UserData = micVolumeText,
|
UserData = micVolumeText,
|
||||||
Range = new Vector2(0,540),
|
Range = new Vector2(0, ((float)VoipConfig.BUFFER_SIZE / (float)VoipConfig.FREQUENCY) * 1000.0f * 25.0f),
|
||||||
Step = 1.0f / 9.0f
|
Step = 1.0f / 25.0f
|
||||||
};
|
};
|
||||||
cutoffPreventionSlider.BarScrollValue = VoiceChatCutoffPrevention;
|
cutoffPreventionSlider.BarScrollValue = VoiceChatCutoffPrevention;
|
||||||
cutoffPreventionSlider.OnMoved = (scrollBar, scroll) =>
|
cutoffPreventionSlider.OnMoved = (scrollBar, scroll) =>
|
||||||
{
|
{
|
||||||
VoiceChatCutoffPrevention = (int)scrollBar.BarScrollValue;
|
int bufferMsLength = (int)(((float)VoipConfig.BUFFER_SIZE / (float)VoipConfig.FREQUENCY) * 1000.0f);
|
||||||
|
VoiceChatCutoffPrevention = (int)Math.Round(scrollBar.BarScrollValue / bufferMsLength) * bufferMsLength;
|
||||||
cutoffPreventionText.Text = TextManager.Get("CutoffPrevention") +
|
cutoffPreventionText.Text = TextManager.Get("CutoffPrevention") +
|
||||||
" " + TextManager.GetWithVariable("timeformatmilliseconds", "[milliseconds]", VoiceChatCutoffPrevention.ToString());
|
" " + TextManager.GetWithVariable("timeformatmilliseconds", "[milliseconds]", VoiceChatCutoffPrevention.ToString());
|
||||||
return true;
|
return true;
|
||||||
@@ -1379,6 +1308,93 @@ namespace Barotrauma
|
|||||||
GUITextBlock.AutoScaleAndNormalize(defaultBindingsButton.TextBlock, legacyBindingsButton.TextBlock);
|
GUITextBlock.AutoScaleAndNormalize(defaultBindingsButton.TextBlock, legacyBindingsButton.TextBlock);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Gameplay tab -------------------------------------------------------------
|
||||||
|
var gameplaySettingsGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.46f, 0.95f), tabs[(int)Tab.Gameplay].RectTransform, Anchor.TopLeft)
|
||||||
|
{ RelativeOffset = new Vector2(0.025f, 0.02f) })
|
||||||
|
{ RelativeSpacing = 0.01f };
|
||||||
|
|
||||||
|
GUITickBox pauseOnFocusLostBox = new GUITickBox(new RectTransform(tickBoxScale, gameplaySettingsGroup.RectTransform),
|
||||||
|
TextManager.Get("PauseOnFocusLost"))
|
||||||
|
{
|
||||||
|
Selected = PauseOnFocusLost,
|
||||||
|
ToolTip = TextManager.Get("PauseOnFocusLostToolTip"),
|
||||||
|
OnSelected = (tickBox) =>
|
||||||
|
{
|
||||||
|
PauseOnFocusLost = tickBox.Selected;
|
||||||
|
UnsavedSettings = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
GUITickBox disableInGameHintsBox = new GUITickBox(new RectTransform(tickBoxScale, gameplaySettingsGroup.RectTransform),
|
||||||
|
TextManager.Get("DisableInGameHints"))
|
||||||
|
{
|
||||||
|
Selected = DisableInGameHints,
|
||||||
|
ToolTip = TextManager.Get("DisableInGameHintsToolTip"),
|
||||||
|
OnSelected = (tickBox) =>
|
||||||
|
{
|
||||||
|
DisableInGameHints = tickBox.Selected;
|
||||||
|
if (!DisableInGameHints && GameMain.Config?.IgnoredHints != null)
|
||||||
|
{
|
||||||
|
// Reset the ignored hints when the hints are re-enabled (to-be-replaced by a separate button)
|
||||||
|
GameMain.Config.IgnoredHints.Clear();
|
||||||
|
}
|
||||||
|
UnsavedSettings = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
GUITextBlock HUDScaleText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), gameplaySettingsGroup.RectTransform), TextManager.Get("HUDScale"), font: GUI.SubHeadingFont, wrap: true);
|
||||||
|
GUIScrollBar HUDScaleScrollBar = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.05f), gameplaySettingsGroup.RectTransform),
|
||||||
|
style: "GUISlider", barSize: 0.1f)
|
||||||
|
{
|
||||||
|
UserData = HUDScaleText,
|
||||||
|
BarScroll = (HUDScale - MinHUDScale) / (MaxHUDScale - MinHUDScale),
|
||||||
|
OnMoved = (scrollBar, scroll) =>
|
||||||
|
{
|
||||||
|
HUDScale = MathHelper.Lerp(MinHUDScale, MaxHUDScale, scroll);
|
||||||
|
ChangeSliderText(scrollBar, HUDScale);
|
||||||
|
OnHUDScaleChanged?.Invoke();
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
Step = 0.02f
|
||||||
|
};
|
||||||
|
HUDScaleScrollBar.OnMoved(HUDScaleScrollBar, HUDScaleScrollBar.BarScroll);
|
||||||
|
|
||||||
|
GUITextBlock inventoryScaleText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), gameplaySettingsGroup.RectTransform), TextManager.Get("InventoryScale"), font: GUI.SubHeadingFont);
|
||||||
|
GUIScrollBar inventoryScaleScrollBar = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.05f), gameplaySettingsGroup.RectTransform),
|
||||||
|
style: "GUISlider", barSize: 0.1f)
|
||||||
|
{
|
||||||
|
UserData = inventoryScaleText,
|
||||||
|
BarScroll = (InventoryScale - MinInventoryScale) / (MaxInventoryScale - MinInventoryScale),
|
||||||
|
OnMoved = (scrollBar, scroll) =>
|
||||||
|
{
|
||||||
|
InventoryScale = MathHelper.Lerp(MinInventoryScale, MaxInventoryScale, scroll);
|
||||||
|
ChangeSliderText(scrollBar, InventoryScale);
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
Step = 0.02f
|
||||||
|
};
|
||||||
|
inventoryScaleScrollBar.OnMoved(inventoryScaleScrollBar, inventoryScaleScrollBar.BarScroll);
|
||||||
|
|
||||||
|
GUITextBlock textScaleText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), gameplaySettingsGroup.RectTransform), TextManager.Get("TextScale"), font: GUI.SubHeadingFont);
|
||||||
|
GUIScrollBar textScaleScrollBar = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.05f), gameplaySettingsGroup.RectTransform),
|
||||||
|
style: "GUISlider", barSize: 0.1f)
|
||||||
|
{
|
||||||
|
UserData = textScaleText,
|
||||||
|
BarScroll = (TextScale - MinTextScale) / (MaxTextScale - MinTextScale),
|
||||||
|
OnMoved = (scrollBar, scroll) =>
|
||||||
|
{
|
||||||
|
TextScale = MathHelper.Lerp(MinTextScale, MaxTextScale, scroll);
|
||||||
|
textScaleDirty = true;
|
||||||
|
ChangeSliderText(scrollBar, TextScale);
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
Step = 0.01f
|
||||||
|
};
|
||||||
|
textScaleScrollBar.OnMoved(textScaleScrollBar, textScaleScrollBar.BarScroll);
|
||||||
|
|
||||||
|
/// Bottom buttons -------------------------------------------------------------
|
||||||
new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), buttonArea.RectTransform, Anchor.BottomLeft),
|
new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), buttonArea.RectTransform, Anchor.BottomLeft),
|
||||||
TextManager.Get("Cancel"))
|
TextManager.Get("Cancel"))
|
||||||
{
|
{
|
||||||
@@ -1464,55 +1480,54 @@ namespace Barotrauma
|
|||||||
{ RelativeOffset = new Vector2(0.02f, 0.02f) })
|
{ RelativeOffset = new Vector2(0.02f, 0.02f) })
|
||||||
{ RelativeSpacing = 0.01f };
|
{ RelativeSpacing = 0.01f };
|
||||||
|
|
||||||
var automaticQuickStartTickBox = new GUITickBox(new RectTransform(tickBoxScale / 0.18f, debugTickBoxes.RectTransform, scaleBasis: ScaleBasis.BothHeight), "Automatic quickstart enabled", style: "GUITickBox");
|
void addDebugTickBox(bool initialValue, Action<bool> set, string label, string tooltip)
|
||||||
automaticQuickStartTickBox.Selected = AutomaticQuickStartEnabled;
|
|
||||||
automaticQuickStartTickBox.ToolTip = "Will the game automatically move on to Quickstart when the game is launched";
|
|
||||||
automaticQuickStartTickBox.OnSelected = (tickBox) =>
|
|
||||||
{
|
{
|
||||||
AutomaticQuickStartEnabled = tickBox.Selected;
|
var tickBox = new GUITickBox(new RectTransform(tickBoxScale / 0.18f, debugTickBoxes.RectTransform, scaleBasis: ScaleBasis.BothHeight), label, style: "GUITickBox");
|
||||||
UnsavedSettings = true;
|
tickBox.Selected = initialValue;
|
||||||
return true;
|
tickBox.ToolTip = tooltip;
|
||||||
};
|
tickBox.OnSelected = (tickBox) =>
|
||||||
|
{
|
||||||
|
set(tickBox.Selected);
|
||||||
|
UnsavedSettings = true;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
var automaticCampaignLoadTickBox = new GUITickBox(new RectTransform(tickBoxScale / 0.18f, debugTickBoxes.RectTransform, scaleBasis: ScaleBasis.BothHeight), "Automatic campaign load enabled", style: "GUITickBox");
|
addDebugTickBox(
|
||||||
automaticCampaignLoadTickBox.Selected = AutomaticCampaignLoadEnabled;
|
AutomaticQuickStartEnabled,
|
||||||
automaticCampaignLoadTickBox.ToolTip = "Will the game automatically load the latest campaign save when the game is launched";
|
(b) => AutomaticQuickStartEnabled = b,
|
||||||
automaticCampaignLoadTickBox.OnSelected = (tickBox) =>
|
"Automatic quickstart enabled",
|
||||||
{
|
"Will the game automatically move on to Quickstart when the game is launched");
|
||||||
AutomaticCampaignLoadEnabled = tickBox.Selected;
|
|
||||||
UnsavedSettings = true;
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
var showSplashScreenTickBox = new GUITickBox(new RectTransform(tickBoxScale / 0.18f, debugTickBoxes.RectTransform, scaleBasis: ScaleBasis.BothHeight), "Splash screen enabled", style: "GUITickBox");
|
addDebugTickBox(
|
||||||
showSplashScreenTickBox.Selected = EnableSplashScreen;
|
AutomaticCampaignLoadEnabled,
|
||||||
showSplashScreenTickBox.ToolTip = "Are the splash screens shown when the game is launched";
|
(b) => AutomaticCampaignLoadEnabled = b,
|
||||||
showSplashScreenTickBox.OnSelected = (tickBox) =>
|
"Automatic campaign load enabled",
|
||||||
{
|
"Will the game automatically load the latest campaign save when the game is launched");
|
||||||
EnableSplashScreen = tickBox.Selected;
|
|
||||||
UnsavedSettings = true;
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
var verboseLoggingTickBox = new GUITickBox(new RectTransform(tickBoxScale / 0.18f, debugTickBoxes.RectTransform, scaleBasis: ScaleBasis.BothHeight), "Verbose logging enabled", style: "GUITickBox");
|
addDebugTickBox(
|
||||||
verboseLoggingTickBox.Selected = VerboseLogging;
|
EnableSplashScreen,
|
||||||
verboseLoggingTickBox.ToolTip = "Should verbose logging be used";
|
(b) => EnableSplashScreen = b,
|
||||||
verboseLoggingTickBox.OnSelected = (tickBox) =>
|
"Splash screen enabled",
|
||||||
{
|
"Are the splash screens shown when the game is launched");
|
||||||
VerboseLogging = tickBox.Selected;
|
|
||||||
UnsavedSettings = true;
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
var textManagerDebugModeTickBox = new GUITickBox(new RectTransform(tickBoxScale / 0.18f, debugTickBoxes.RectTransform, scaleBasis: ScaleBasis.BothHeight), "TextManager debug mode enabled", style: "GUITickBox");
|
addDebugTickBox(
|
||||||
textManagerDebugModeTickBox.Selected = TextManagerDebugModeEnabled;
|
VerboseLogging,
|
||||||
textManagerDebugModeTickBox.ToolTip = "Does the TextManager return the text tags for debug purposes?";
|
(b) => VerboseLogging = b,
|
||||||
textManagerDebugModeTickBox.OnSelected = (tickBox) =>
|
"Verbose logging enabled",
|
||||||
{
|
"Should verbose logging be used");
|
||||||
TextManagerDebugModeEnabled = tickBox.Selected;
|
|
||||||
UnsavedSettings = true;
|
addDebugTickBox(
|
||||||
return true;
|
TextManagerDebugModeEnabled,
|
||||||
};
|
(b) => TextManagerDebugModeEnabled = b,
|
||||||
|
"TextManager debug mode enabled",
|
||||||
|
"Does the TextManager return the text tags for debug purposes?");
|
||||||
|
|
||||||
|
addDebugTickBox(
|
||||||
|
ModBreakerMode,
|
||||||
|
(b) => ModBreakerMode = b,
|
||||||
|
"Mod breaker mode enabled",
|
||||||
|
"Do horrible things when loading mods to see if it breaks?");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
UnsavedSettings = false; // Reset unsaved settings to false once the UI has been created
|
UnsavedSettings = false; // Reset unsaved settings to false once the UI has been created
|
||||||
|
|||||||
@@ -160,13 +160,6 @@ namespace Barotrauma
|
|||||||
CreateSlots();
|
CreateSlots();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void RemoveItem(Item item)
|
|
||||||
{
|
|
||||||
if (!Contains(item)) { return; }
|
|
||||||
base.RemoveItem(item);
|
|
||||||
CreateSlots();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void CreateSlots()
|
public override void CreateSlots()
|
||||||
{
|
{
|
||||||
if (visualSlots == null) { visualSlots = new VisualSlot[capacity]; }
|
if (visualSlots == null) { visualSlots = new VisualSlot[capacity]; }
|
||||||
@@ -639,10 +632,16 @@ namespace Barotrauma
|
|||||||
foreach (Item doubleClickedItem in doubleClickedItems)
|
foreach (Item doubleClickedItem in doubleClickedItems)
|
||||||
{
|
{
|
||||||
QuickUseItem(doubleClickedItem, true, true, true, quickUseAction, playSound: doubleClickedItem == doubleClickedItems.First());
|
QuickUseItem(doubleClickedItem, true, true, true, quickUseAction, playSound: doubleClickedItem == doubleClickedItems.First());
|
||||||
|
//only use one item if we're equipping or using it as a treatment
|
||||||
if (quickUseAction == QuickUseAction.Equip || quickUseAction == QuickUseAction.UseTreatment)
|
if (quickUseAction == QuickUseAction.Equip || quickUseAction == QuickUseAction.UseTreatment)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
//if the item was put in a limb slot, only put one item from the stack
|
||||||
|
if (doubleClickedItem.ParentInventory == this && !IsInLimbSlot(doubleClickedItem, InvSlotType.Any))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -696,6 +695,7 @@ namespace Barotrauma
|
|||||||
if (firstItem != null && !DraggingItems.Contains(firstItem) && Character.Controlled?.Inventory == this &&
|
if (firstItem != null && !DraggingItems.Contains(firstItem) && Character.Controlled?.Inventory == this &&
|
||||||
GUI.KeyboardDispatcher.Subscriber == null && !CrewManager.IsCommandInterfaceOpen && PlayerInput.InventoryKeyHit(visualSlots[i].InventoryKeyIndex))
|
GUI.KeyboardDispatcher.Subscriber == null && !CrewManager.IsCommandInterfaceOpen && PlayerInput.InventoryKeyHit(visualSlots[i].InventoryKeyIndex))
|
||||||
{
|
{
|
||||||
|
if (SubEditorScreen.IsSubEditor() && SubEditorScreen.SkipInventorySlotUpdate) { continue; }
|
||||||
#if LINUX
|
#if LINUX
|
||||||
// some window managers on Linux use windows key + number to change workspaces or perform other actions
|
// some window managers on Linux use windows key + number to change workspaces or perform other actions
|
||||||
if (PlayerInput.KeyDown(Keys.RightWindows) || PlayerInput.KeyDown(Keys.LeftWindows)) { continue; }
|
if (PlayerInput.KeyDown(Keys.RightWindows) || PlayerInput.KeyDown(Keys.LeftWindows)) { continue; }
|
||||||
@@ -810,6 +810,8 @@ namespace Barotrauma
|
|||||||
highlightedSubInventorySlot.Inventory.HideTimer = 0.0f;
|
highlightedSubInventorySlot.Inventory.HideTimer = 0.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HintManager.OnShowSubInventory(slotRef?.Item);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AssignQuickUseNumKeys()
|
public void AssignQuickUseNumKeys()
|
||||||
@@ -835,6 +837,13 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (item.ParentInventory != this)
|
if (item.ParentInventory != this)
|
||||||
{
|
{
|
||||||
|
if (Screen.Selected == GameMain.GameScreen)
|
||||||
|
{
|
||||||
|
if (item.NonInteractable || item.NonPlayerTeamInteractable)
|
||||||
|
{
|
||||||
|
return QuickUseAction.None;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (item.ParentInventory == null || item.ParentInventory.Locked)
|
if (item.ParentInventory == null || item.ParentInventory.Locked)
|
||||||
{
|
{
|
||||||
return QuickUseAction.None;
|
return QuickUseAction.None;
|
||||||
|
|||||||
@@ -70,17 +70,15 @@ namespace Barotrauma.Items.Components
|
|||||||
public override void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
public override void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
||||||
{
|
{
|
||||||
base.ClientRead(type, msg, sendingTime);
|
base.ClientRead(type, msg, sendingTime);
|
||||||
|
|
||||||
|
bool readAttachData = msg.ReadBoolean();
|
||||||
|
if (!readAttachData) { return; }
|
||||||
|
|
||||||
bool shouldBeAttached = msg.ReadBoolean();
|
bool shouldBeAttached = msg.ReadBoolean();
|
||||||
Vector2 simPosition = new Vector2(msg.ReadSingle(), msg.ReadSingle());
|
Vector2 simPosition = new Vector2(msg.ReadSingle(), msg.ReadSingle());
|
||||||
UInt16 submarineID = msg.ReadUInt16();
|
UInt16 submarineID = msg.ReadUInt16();
|
||||||
Submarine sub = Entity.FindEntityByID(submarineID) as Submarine;
|
Submarine sub = Entity.FindEntityByID(submarineID) as Submarine;
|
||||||
|
|
||||||
if (!attachable)
|
|
||||||
{
|
|
||||||
DebugConsole.ThrowError("Received an attachment event for an item that's not attachable.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shouldBeAttached)
|
if (shouldBeAttached)
|
||||||
{
|
{
|
||||||
if (!attached)
|
if (!attached)
|
||||||
@@ -96,7 +94,6 @@ namespace Barotrauma.Items.Components
|
|||||||
if (attached)
|
if (attached)
|
||||||
{
|
{
|
||||||
DropConnectedWires(null);
|
DropConnectedWires(null);
|
||||||
|
|
||||||
if (body != null)
|
if (body != null)
|
||||||
{
|
{
|
||||||
item.body = body;
|
item.body = body;
|
||||||
@@ -106,6 +103,11 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
DeattachFromWall();
|
DeattachFromWall();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
item.SetTransform(simPosition, 0.0f);
|
||||||
|
item.Submarine = sub;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -179,6 +179,23 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
CanBeFocused = false
|
CanBeFocused = false
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Expand the frame vertically if it's too small to fit the text
|
||||||
|
if (label != null && label.RectTransform.RelativeSize.Y > 0.5f)
|
||||||
|
{
|
||||||
|
int newHeight = (int)(GuiFrame.Rect.Height + (2 * (label.RectTransform.RelativeSize.Y - 0.5f) * content.Rect.Height));
|
||||||
|
if (newHeight > GuiFrame.RectTransform.MaxSize.Y)
|
||||||
|
{
|
||||||
|
Point newMaxSize = GuiFrame.RectTransform.MaxSize;
|
||||||
|
newMaxSize.Y = newHeight;
|
||||||
|
GuiFrame.RectTransform.MaxSize = newMaxSize;
|
||||||
|
}
|
||||||
|
GuiFrame.RectTransform.Resize(new Point(GuiFrame.Rect.Width, newHeight));
|
||||||
|
content.RectTransform.Resize(GuiFrame.Rect.Size - GUIStyle.ItemFrameMargin);
|
||||||
|
label.CalculateHeightFromText();
|
||||||
|
guiCustomComponent.RectTransform.Resize(new Vector2(1.0f, Math.Max(1.0f - label.RectTransform.RelativeSize.Y, minInventoryAreaSize)));
|
||||||
|
}
|
||||||
|
|
||||||
Inventory.RectTransform = guiCustomComponent.RectTransform;
|
Inventory.RectTransform = guiCustomComponent.RectTransform;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
private Pair<Rectangle, string> tooltip;
|
private Pair<Rectangle, string> tooltip;
|
||||||
|
|
||||||
|
private GUITextBlock requiredTimeBlock;
|
||||||
|
|
||||||
partial void InitProjSpecific()
|
partial void InitProjSpecific()
|
||||||
{
|
{
|
||||||
CreateGUI();
|
CreateGUI();
|
||||||
@@ -384,8 +386,6 @@ namespace Barotrauma.Items.Components
|
|||||||
FabricationRecipe targetItem = fabricatedItem ?? selectedItem;
|
FabricationRecipe targetItem = fabricatedItem ?? selectedItem;
|
||||||
if (targetItem != null)
|
if (targetItem != null)
|
||||||
{
|
{
|
||||||
var itemIcon = targetItem.TargetItem.InventoryIcon ?? targetItem.TargetItem.sprite;
|
|
||||||
|
|
||||||
Rectangle slotRect = outputContainer.Inventory.visualSlots[0].Rect;
|
Rectangle slotRect = outputContainer.Inventory.visualSlots[0].Rect;
|
||||||
|
|
||||||
if (fabricatedItem != null)
|
if (fabricatedItem != null)
|
||||||
@@ -398,11 +398,15 @@ namespace Barotrauma.Items.Components
|
|||||||
GUI.Style.Green * 0.5f, isFilled: true);
|
GUI.Style.Green * 0.5f, isFilled: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
itemIcon.Draw(
|
if (outputContainer.Inventory.IsEmpty())
|
||||||
spriteBatch,
|
{
|
||||||
slotRect.Center.ToVector2(),
|
var itemIcon = targetItem.TargetItem.InventoryIcon ?? targetItem.TargetItem.sprite;
|
||||||
color: targetItem.TargetItem.InventoryIconColor * 0.4f,
|
itemIcon.Draw(
|
||||||
scale: Math.Min(slotRect.Width / itemIcon.size.X, slotRect.Height / itemIcon.size.Y) * 0.9f);
|
spriteBatch,
|
||||||
|
slotRect.Center.ToVector2(),
|
||||||
|
color: targetItem.TargetItem.InventoryIconColor * 0.4f,
|
||||||
|
scale: Math.Min(slotRect.Width / itemIcon.size.X, slotRect.Height / itemIcon.size.Y) * 0.9f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tooltip != null)
|
if (tooltip != null)
|
||||||
@@ -522,7 +526,7 @@ namespace Barotrauma.Items.Components
|
|||||||
AutoScaleHorizontal = true,
|
AutoScaleHorizontal = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedReqFrame.RectTransform), ToolBox.SecondsToReadableTime(requiredTime),
|
requiredTimeBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedReqFrame.RectTransform), ToolBox.SecondsToReadableTime(requiredTime),
|
||||||
font: GUI.SmallFont);
|
font: GUI.SmallFont);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -606,6 +610,12 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
partial void UpdateRequiredTimeProjSpecific()
|
||||||
|
{
|
||||||
|
if (requiredTimeBlock == null) { return; }
|
||||||
|
requiredTimeBlock.Text = ToolBox.SecondsToReadableTime(timeUntilReady > 0.0f ? timeUntilReady : requiredTime);
|
||||||
|
}
|
||||||
|
|
||||||
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
|
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
|
||||||
{
|
{
|
||||||
int itemIndex = pendingFabricatedItem == null ? -1 : fabricationRecipes.IndexOf(pendingFabricatedItem);
|
int itemIndex = pendingFabricatedItem == null ? -1 : fabricationRecipes.IndexOf(pendingFabricatedItem);
|
||||||
|
|||||||
@@ -21,18 +21,14 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
private readonly List<Submarine> displayedSubs = new List<Submarine>();
|
private readonly List<Submarine> displayedSubs = new List<Submarine>();
|
||||||
|
|
||||||
|
private Point prevResolution;
|
||||||
|
|
||||||
partial void InitProjSpecific(XElement element)
|
partial void InitProjSpecific(XElement element)
|
||||||
{
|
{
|
||||||
noPowerTip = TextManager.Get("SteeringNoPowerTip");
|
noPowerTip = TextManager.Get("SteeringNoPowerTip");
|
||||||
CreateGUI();
|
CreateGUI();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnResolutionChanged()
|
|
||||||
{
|
|
||||||
base.OnResolutionChanged();
|
|
||||||
CreateHUD();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void CreateGUI()
|
protected override void CreateGUI()
|
||||||
{
|
{
|
||||||
GuiFrame.RectTransform.RelativeOffset = new Vector2(0.05f, 0.0f);
|
GuiFrame.RectTransform.RelativeOffset = new Vector2(0.05f, 0.0f);
|
||||||
@@ -76,15 +72,10 @@ namespace Barotrauma.Items.Components
|
|||||||
hullInfoFrame.AddToGUIUpdateList(order: 1);
|
hullInfoFrame.AddToGUIUpdateList(order: 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnMapLoaded()
|
|
||||||
{
|
|
||||||
base.OnMapLoaded();
|
|
||||||
CreateHUD();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CreateHUD()
|
private void CreateHUD()
|
||||||
{
|
{
|
||||||
submarineContainer.ClearChildren();
|
prevResolution = new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
|
||||||
|
submarineContainer?.ClearChildren();
|
||||||
|
|
||||||
if (item.Submarine == null) { return; }
|
if (item.Submarine == null) { return; }
|
||||||
|
|
||||||
@@ -94,19 +85,15 @@ namespace Barotrauma.Items.Components
|
|||||||
displayedSubs.AddRange(item.Submarine.DockedTo);
|
displayedSubs.AddRange(item.Submarine.DockedTo);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void FlipX(bool relativeToSub)
|
|
||||||
{
|
|
||||||
CreateHUD();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void UpdateHUD(Character character, float deltaTime, Camera cam)
|
public override void UpdateHUD(Character character, float deltaTime, Camera cam)
|
||||||
{
|
{
|
||||||
//recreate HUD if the subs we should display have changed
|
//recreate HUD if the subs we should display have changed
|
||||||
if ((item.Submarine == null && displayedSubs.Count > 0) || //item not inside a sub anymore, but display is still showing subs
|
if ((item.Submarine == null && displayedSubs.Count > 0) || //item not inside a sub anymore, but display is still showing subs
|
||||||
!displayedSubs.Contains(item.Submarine) || //current sub not displayer
|
!displayedSubs.Contains(item.Submarine) || //current sub not displayer
|
||||||
item.Submarine.DockedTo.Any(s => !displayedSubs.Contains(s)) || //some of the docked subs not diplayed
|
prevResolution.X != GameMain.GraphicsWidth || prevResolution.Y != GameMain.GraphicsHeight || //resolution changed
|
||||||
!submarineContainer.Children.Any() || // We lack a GUI
|
item.Submarine.DockedTo.Any(s => !displayedSubs.Contains(s)) || //some of the docked subs not diplayed
|
||||||
displayedSubs.Any(s => s != item.Submarine && !item.Submarine.DockedTo.Contains(s))) //displaying a sub that shouldn't be displayed
|
!submarineContainer.Children.Any() || // We lack a GUI
|
||||||
|
displayedSubs.Any(s => s != item.Submarine && !item.Submarine.DockedTo.Contains(s))) //displaying a sub that shouldn't be displayed
|
||||||
{
|
{
|
||||||
CreateHUD();
|
CreateHUD();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,8 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
Default,
|
Default,
|
||||||
Disruption,
|
Disruption,
|
||||||
Destructible
|
Destructible,
|
||||||
|
LongRange
|
||||||
}
|
}
|
||||||
|
|
||||||
private PathFinder pathFinder;
|
private PathFinder pathFinder;
|
||||||
@@ -69,6 +70,9 @@ namespace Barotrauma.Items.Components
|
|||||||
private const float DisruptionUpdateInterval = 0.2f;
|
private const float DisruptionUpdateInterval = 0.2f;
|
||||||
private float disruptionUpdateTimer;
|
private float disruptionUpdateTimer;
|
||||||
|
|
||||||
|
private const float LongRangeUpdateInterval = 10.0f;
|
||||||
|
private float longRangeUpdateTimer;
|
||||||
|
|
||||||
private float showDirectionalIndicatorTimer;
|
private float showDirectionalIndicatorTimer;
|
||||||
|
|
||||||
private readonly List<LevelObject> nearbyObjects = new List<LevelObject>();
|
private readonly List<LevelObject> nearbyObjects = new List<LevelObject>();
|
||||||
@@ -122,6 +126,10 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
BlipType.Destructible,
|
BlipType.Destructible,
|
||||||
new Color[] { Color.TransparentBlack, new Color(74, 113, 75) * 0.8f, new Color(151, 236, 172) * 0.8f, new Color(153, 217, 234) * 0.8f }
|
new Color[] { Color.TransparentBlack, new Color(74, 113, 75) * 0.8f, new Color(151, 236, 172) * 0.8f, new Color(153, 217, 234) * 0.8f }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
BlipType.LongRange,
|
||||||
|
new Color[] { Color.TransparentBlack, Color.TransparentBlack, new Color(254, 68, 19) * 0.8f, Color.TransparentBlack }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -133,7 +141,7 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
public static Vector2 GUISizeCalculation => Vector2.One * Math.Min(GUI.RelativeHorizontalAspectRatio, 1f) * sonarAreaSize;
|
public static Vector2 GUISizeCalculation => Vector2.One * Math.Min(GUI.RelativeHorizontalAspectRatio, 1f) * sonarAreaSize;
|
||||||
|
|
||||||
private List<Tuple<Vector2, List<Item>>> MineralClusters { get; set; }
|
private List<(Vector2 center, List<Item> resources)> MineralClusters { get; set; }
|
||||||
|
|
||||||
private readonly List<GUITextBlock> textBlocksToScaleAndNormalize = new List<GUITextBlock>();
|
private readonly List<GUITextBlock> textBlocksToScaleAndNormalize = new List<GUITextBlock>();
|
||||||
|
|
||||||
@@ -471,25 +479,26 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
if (MineralClusters == null)
|
if (MineralClusters == null)
|
||||||
{
|
{
|
||||||
MineralClusters = new List<Tuple<Vector2, List<Item>>>();
|
MineralClusters = new List<(Vector2, List<Item>)>();
|
||||||
foreach (var p in Level.Loaded.PathPoints)
|
Level.Loaded.PathPoints.ForEach(p => p.ClusterLocations.ForEach(c => AddIfValid(c)));
|
||||||
|
Level.Loaded.AbyssResources.ForEach(c => AddIfValid(c));
|
||||||
|
|
||||||
|
void AddIfValid(Level.ClusterLocation c)
|
||||||
{
|
{
|
||||||
foreach (var c in p.ClusterLocations)
|
if (c.Resources == null) { return; }
|
||||||
|
if (c.Resources.None(i => i != null && !i.Removed && i.Tags.Contains("ore"))) { return; }
|
||||||
|
var pos = Vector2.Zero;
|
||||||
|
foreach (var r in c.Resources)
|
||||||
{
|
{
|
||||||
if (c.Resources.None(i => i != null && !i.Removed && i.Tags.Contains("ore"))) { continue; }
|
pos += r.WorldPosition;
|
||||||
var pos = Vector2.Zero;
|
|
||||||
foreach (var r in c.Resources)
|
|
||||||
{
|
|
||||||
pos += r.WorldPosition;
|
|
||||||
}
|
|
||||||
pos /= c.Resources.Count;
|
|
||||||
MineralClusters.Add(new Tuple<Vector2, List<Item>>(pos, c.Resources));
|
|
||||||
}
|
}
|
||||||
|
pos /= c.Resources.Count;
|
||||||
|
MineralClusters.Add((center: pos, resources: c.Resources));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MineralClusters.RemoveAll(t => t.Item2 == null || t.Item2.None() || t.Item2.All(i => i == null || i.Removed));
|
MineralClusters.RemoveAll(c => c.resources == null || c.resources.None() || c.resources.All(i => i == null || i.Removed));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -673,7 +682,6 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
|
|
||||||
disruptionUpdateTimer -= deltaTime;
|
disruptionUpdateTimer -= deltaTime;
|
||||||
|
|
||||||
for (var pingIndex = 0; pingIndex < activePingsCount; ++pingIndex)
|
for (var pingIndex = 0; pingIndex < activePingsCount; ++pingIndex)
|
||||||
{
|
{
|
||||||
var activePing = activePings[pingIndex];
|
var activePing = activePings[pingIndex];
|
||||||
@@ -683,12 +691,46 @@ namespace Barotrauma.Items.Components
|
|||||||
pingRadius, activePing.PrevPingRadius, displayScale, range / zoom, passive: false, pingStrength: 2.0f);
|
pingRadius, activePing.PrevPingRadius, displayScale, range / zoom, passive: false, pingStrength: 2.0f);
|
||||||
activePing.PrevPingRadius = pingRadius;
|
activePing.PrevPingRadius = pingRadius;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (disruptionUpdateTimer <= 0.0f)
|
if (disruptionUpdateTimer <= 0.0f)
|
||||||
{
|
{
|
||||||
disruptionUpdateTimer = DisruptionUpdateInterval;
|
disruptionUpdateTimer = DisruptionUpdateInterval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
longRangeUpdateTimer -= deltaTime;
|
||||||
|
if (longRangeUpdateTimer <= 0.0f)
|
||||||
|
{
|
||||||
|
foreach (Character c in Character.CharacterList)
|
||||||
|
{
|
||||||
|
if (c.AnimController.CurrentHull != null || !c.Enabled) { continue; }
|
||||||
|
if (c.Params.HideInSonar) { continue; }
|
||||||
|
|
||||||
|
if (!c.IsUnconscious && c.Params.DistantSonarRange > 0.0f &&
|
||||||
|
((c.WorldPosition - transducerCenter) * displayScale).LengthSquared() > DisplayRadius * DisplayRadius)
|
||||||
|
{
|
||||||
|
Vector2 targetVector = c.WorldPosition - transducerCenter;
|
||||||
|
if (targetVector.LengthSquared() > MathUtils.Pow2(c.Params.DistantSonarRange)) { continue; }
|
||||||
|
float dist = targetVector.Length();
|
||||||
|
Vector2 targetDir = targetVector / dist;
|
||||||
|
int blipCount = (int)MathHelper.Clamp(c.Mass, 50, 200);
|
||||||
|
for (int i = 0; i < blipCount; i++)
|
||||||
|
{
|
||||||
|
float angle = Rand.Range(-0.5f, 0.5f);
|
||||||
|
Vector2 blipDir = MathUtils.RotatePoint(targetDir, angle);
|
||||||
|
Vector2 invBlipDir = MathUtils.RotatePoint(targetDir, -angle);
|
||||||
|
var longRangeBlip = new SonarBlip(transducerCenter + blipDir * Range * 0.9f, Rand.Range(1.9f, 2.1f), Rand.Range(1.0f, 1.5f), BlipType.LongRange)
|
||||||
|
{
|
||||||
|
Velocity = -invBlipDir * (MathUtils.Round(Rand.Range(8000.0f, 15000.0f), 2000.0f) - Math.Abs(angle * angle * 10000.0f)),
|
||||||
|
Rotation = (float)Math.Atan2(-invBlipDir.Y, invBlipDir.X),
|
||||||
|
Alpha = MathUtils.Pow2((c.Params.DistantSonarRange - dist) / c.Params.DistantSonarRange)
|
||||||
|
};
|
||||||
|
longRangeBlip.Size.Y *= 5.0f;
|
||||||
|
sonarBlips.Add(longRangeBlip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
longRangeUpdateTimer = LongRangeUpdateInterval;
|
||||||
|
}
|
||||||
|
|
||||||
if (currentMode == Mode.Active && currentPingIndex != -1)
|
if (currentMode == Mode.Active && currentPingIndex != -1)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -828,8 +870,8 @@ namespace Barotrauma.Items.Components
|
|||||||
float directionalPingVisibility = useDirectionalPing && currentMode == Mode.Active ? 1.0f : showDirectionalIndicatorTimer;
|
float directionalPingVisibility = useDirectionalPing && currentMode == Mode.Active ? 1.0f : showDirectionalIndicatorTimer;
|
||||||
if (directionalPingVisibility > 0.0f)
|
if (directionalPingVisibility > 0.0f)
|
||||||
{
|
{
|
||||||
Vector2 sector1 = MathUtils.RotatePointAroundTarget(pingDirection * DisplayRadius, Vector2.Zero, DirectionalPingSector * 0.5f);
|
Vector2 sector1 = MathUtils.RotatePointAroundTarget(pingDirection * DisplayRadius, Vector2.Zero, MathHelper.ToRadians(DirectionalPingSector * 0.5f));
|
||||||
Vector2 sector2 = MathUtils.RotatePointAroundTarget(pingDirection * DisplayRadius, Vector2.Zero, -DirectionalPingSector * 0.5f);
|
Vector2 sector2 = MathUtils.RotatePointAroundTarget(pingDirection * DisplayRadius, Vector2.Zero, MathHelper.ToRadians(-DirectionalPingSector * 0.5f));
|
||||||
DrawLine(spriteBatch, Vector2.Zero, sector1, Color.LightCyan * 0.2f * directionalPingVisibility, width: 3);
|
DrawLine(spriteBatch, Vector2.Zero, sector1, Color.LightCyan * 0.2f * directionalPingVisibility, width: 3);
|
||||||
DrawLine(spriteBatch, Vector2.Zero, sector2, Color.LightCyan * 0.2f * directionalPingVisibility, width: 3);
|
DrawLine(spriteBatch, Vector2.Zero, sector2, Color.LightCyan * 0.2f * directionalPingVisibility, width: 3);
|
||||||
}
|
}
|
||||||
@@ -862,9 +904,9 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
DrawMarker(spriteBatch,
|
DrawMarker(spriteBatch,
|
||||||
Level.Loaded.StartLocation.Name,
|
Level.Loaded.StartLocation.Name,
|
||||||
"outpost",
|
Level.Loaded.StartOutpost != null ? "outpost" : "location",
|
||||||
Level.Loaded.StartLocation.Name,
|
Level.Loaded.StartLocation.Name,
|
||||||
Level.Loaded.StartPosition, transducerCenter,
|
Level.Loaded.StartExitPosition, transducerCenter,
|
||||||
displayScale, center, DisplayRadius);
|
displayScale, center, DisplayRadius);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -872,9 +914,9 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
DrawMarker(spriteBatch,
|
DrawMarker(spriteBatch,
|
||||||
Level.Loaded.EndLocation.Name,
|
Level.Loaded.EndLocation.Name,
|
||||||
"outpost",
|
Level.Loaded.EndOutpost != null ? "outpost" : "location",
|
||||||
Level.Loaded.EndLocation.Name,
|
Level.Loaded.EndLocation.Name,
|
||||||
Level.Loaded.EndPosition, transducerCenter,
|
Level.Loaded.EndExitPosition, transducerCenter,
|
||||||
displayScale, center, DisplayRadius);
|
displayScale, center, DisplayRadius);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -906,10 +948,8 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GameMain.GameSession.Mission != null)
|
foreach (Mission mission in GameMain.GameSession.Missions)
|
||||||
{
|
{
|
||||||
var mission = GameMain.GameSession.Mission;
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(mission.SonarLabel))
|
if (!string.IsNullOrWhiteSpace(mission.SonarLabel))
|
||||||
{
|
{
|
||||||
foreach (Vector2 sonarPosition in mission.SonarPositions)
|
foreach (Vector2 sonarPosition in mission.SonarPositions)
|
||||||
@@ -926,16 +966,16 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
if (AllowUsingMineralScanner && useMineralScanner && CurrentMode == Mode.Active && MineralClusters != null)
|
if (AllowUsingMineralScanner && useMineralScanner && CurrentMode == Mode.Active && MineralClusters != null)
|
||||||
{
|
{
|
||||||
foreach (var t in MineralClusters)
|
foreach (var c in MineralClusters)
|
||||||
{
|
{
|
||||||
var unobtainedMinerals = t.Item2.Where(i => i != null && i.GetRootInventoryOwner() == i);
|
var unobtainedMinerals = c.resources.Where(i => i != null && i.GetRootInventoryOwner() == i);
|
||||||
if (unobtainedMinerals.None()) { continue; }
|
if (unobtainedMinerals.None()) { continue; }
|
||||||
if (!CheckResourceMarkerVisibility(t.Item1, transducerCenter)) { continue; }
|
if (!CheckResourceMarkerVisibility(c.center, transducerCenter)) { continue; }
|
||||||
var i = unobtainedMinerals.FirstOrDefault();
|
var i = unobtainedMinerals.FirstOrDefault();
|
||||||
if (i == null) { continue; }
|
if (i == null) { continue; }
|
||||||
DrawMarker(spriteBatch,
|
DrawMarker(spriteBatch,
|
||||||
i.Name, "mineral", i,
|
i.Name, "mineral", i,
|
||||||
t.Item1, transducerCenter,
|
c.center, transducerCenter,
|
||||||
displayScale, center, DisplayRadius * 0.95f,
|
displayScale, center, DisplayRadius * 0.95f,
|
||||||
onlyShowTextOnMouseOver: true);
|
onlyShowTextOnMouseOver: true);
|
||||||
}
|
}
|
||||||
@@ -947,6 +987,19 @@ namespace Barotrauma.Items.Components
|
|||||||
if (connectedSubs.Contains(sub)) { continue; }
|
if (connectedSubs.Contains(sub)) { continue; }
|
||||||
if (sub.WorldPosition.Y > Level.Loaded.Size.Y) { continue; }
|
if (sub.WorldPosition.Y > Level.Loaded.Size.Y) { continue; }
|
||||||
|
|
||||||
|
if (item.Submarine != null)
|
||||||
|
{
|
||||||
|
//hide enemy team
|
||||||
|
if (sub.TeamID == CharacterTeamType.Team1 && (item.Submarine.TeamID == CharacterTeamType.Team2 || Character.Controlled?.TeamID == CharacterTeamType.Team2))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (sub.TeamID == CharacterTeamType.Team2 && (item.Submarine.TeamID == CharacterTeamType.Team1 || Character.Controlled?.TeamID == CharacterTeamType.Team1))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DrawMarker(spriteBatch,
|
DrawMarker(spriteBatch,
|
||||||
sub.Info.DisplayName,
|
sub.Info.DisplayName,
|
||||||
sub.Info.HasTag(SubmarineTag.Shuttle) ? "shuttle" : "submarine",
|
sub.Info.HasTag(SubmarineTag.Shuttle) ? "shuttle" : "submarine",
|
||||||
@@ -1046,15 +1099,18 @@ namespace Barotrauma.Items.Components
|
|||||||
foreach (DockingPort dockingPort in DockingPort.List)
|
foreach (DockingPort dockingPort in DockingPort.List)
|
||||||
{
|
{
|
||||||
if (Level.Loaded != null && dockingPort.Item.Submarine.WorldPosition.Y > Level.Loaded.Size.Y) { continue; }
|
if (Level.Loaded != null && dockingPort.Item.Submarine.WorldPosition.Y > Level.Loaded.Size.Y) { continue; }
|
||||||
|
|
||||||
if (dockingPort.Item.Submarine == null) { continue; }
|
if (dockingPort.Item.Submarine == null) { continue; }
|
||||||
if (dockingPort.Item.Submarine.Info.IsWreck) { continue; }
|
if (dockingPort.Item.Submarine.Info.IsWreck) { continue; }
|
||||||
|
if (!dockingPort.Item.Submarine.ShowSonarMarker && !dockingPort.Item.Submarine.Info.IsOutpost) { continue; }
|
||||||
|
|
||||||
//don't show the docking ports of the opposing team on the sonar
|
//don't show the docking ports of the opposing team on the sonar
|
||||||
if (item.Submarine != null)
|
if (item.Submarine != null)
|
||||||
{
|
{
|
||||||
if ((dockingPort.Item.Submarine.TeamID == CharacterTeamType.Team1 && item.Submarine.TeamID == CharacterTeamType.Team2) ||
|
if (dockingPort.Item.Submarine.TeamID == CharacterTeamType.Team1 && (item.Submarine.TeamID == CharacterTeamType.Team2 || Character.Controlled?.TeamID == CharacterTeamType.Team2))
|
||||||
(dockingPort.Item.Submarine.TeamID == CharacterTeamType.Team2 && item.Submarine.TeamID == CharacterTeamType.Team1))
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (dockingPort.Item.Submarine.TeamID == CharacterTeamType.Team2 && (item.Submarine.TeamID == CharacterTeamType.Team1 || Character.Controlled?.TeamID == CharacterTeamType.Team1))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -1382,6 +1438,7 @@ namespace Barotrauma.Items.Components
|
|||||||
MathHelper.Clamp(c.Mass * 0.03f, 0.1f, 2.0f));
|
MathHelper.Clamp(c.Mass * 0.03f, 0.1f, 2.0f));
|
||||||
if (!passive && !CheckBlipVisibility(blip, transducerPos)) { continue; }
|
if (!passive && !CheckBlipVisibility(blip, transducerPos)) { continue; }
|
||||||
sonarBlips.Add(blip);
|
sonarBlips.Add(blip);
|
||||||
|
HintManager.OnSonarSpottedCharacter(Item, c);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -1401,6 +1458,7 @@ namespace Barotrauma.Items.Components
|
|||||||
MathHelper.Clamp(limb.Mass * 0.1f, 0.1f, 2.0f));
|
MathHelper.Clamp(limb.Mass * 0.1f, 0.1f, 2.0f));
|
||||||
if (!passive && !CheckBlipVisibility(blip, transducerPos)) { continue; }
|
if (!passive && !CheckBlipVisibility(blip, transducerPos)) { continue; }
|
||||||
sonarBlips.Add(blip);
|
sonarBlips.Add(blip);
|
||||||
|
HintManager.OnSonarSpottedCharacter(Item, c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1554,12 +1612,12 @@ namespace Barotrauma.Items.Components
|
|||||||
float scale = (strength + 3.0f) * blip.Scale * blipScale;
|
float scale = (strength + 3.0f) * blip.Scale * blipScale;
|
||||||
Color color = ToolBox.GradientLerp(strength, blipColorGradient[blip.BlipType]);
|
Color color = ToolBox.GradientLerp(strength, blipColorGradient[blip.BlipType]);
|
||||||
|
|
||||||
sonarBlip.Draw(spriteBatch, center + pos, color, sonarBlip.Origin, blip.Rotation ?? MathUtils.VectorToAngle(pos),
|
sonarBlip.Draw(spriteBatch, center + pos, color * blip.Alpha, sonarBlip.Origin, blip.Rotation ?? MathUtils.VectorToAngle(pos),
|
||||||
blip.Size * scale * 0.5f, SpriteEffects.None, 0);
|
blip.Size * scale * 0.5f, SpriteEffects.None, 0);
|
||||||
|
|
||||||
pos += Rand.Range(0.0f, 1.0f) * dir + Rand.Range(-scale, scale) * normal;
|
pos += Rand.Range(0.0f, 1.0f) * dir + Rand.Range(-scale, scale) * normal;
|
||||||
|
|
||||||
sonarBlip.Draw(spriteBatch, center + pos, color * 0.5f, sonarBlip.Origin, 0, scale, SpriteEffects.None, 0);
|
sonarBlip.Draw(spriteBatch, center + pos, color * 0.5f * blip.Alpha, sonarBlip.Origin, 0, scale, SpriteEffects.None, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawMarker(SpriteBatch spriteBatch, string label, string iconIdentifier, object targetIdentifier, Vector2 worldPosition, Vector2 transducerPosition, float scale, Vector2 center, float radius,
|
private void DrawMarker(SpriteBatch spriteBatch, string label, string iconIdentifier, object targetIdentifier, Vector2 worldPosition, Vector2 transducerPosition, float scale, Vector2 center, float radius,
|
||||||
@@ -1644,7 +1702,7 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(iconIdentifier) || !targetIcons.ContainsKey(iconIdentifier))
|
if (iconIdentifier == null || !targetIcons.ContainsKey(iconIdentifier))
|
||||||
{
|
{
|
||||||
GUI.DrawRectangle(spriteBatch, new Rectangle((int)markerPos.X - 3, (int)markerPos.Y - 3, 6, 6), markerColor, thickness: 2);
|
GUI.DrawRectangle(spriteBatch, new Rectangle((int)markerPos.X - 3, (int)markerPos.Y - 3, 6, 6), markerColor, thickness: 2);
|
||||||
}
|
}
|
||||||
@@ -1777,6 +1835,7 @@ namespace Barotrauma.Items.Components
|
|||||||
public float? Rotation;
|
public float? Rotation;
|
||||||
public Vector2 Size;
|
public Vector2 Size;
|
||||||
public Sonar.BlipType BlipType;
|
public Sonar.BlipType BlipType;
|
||||||
|
public float Alpha = 1.0f;
|
||||||
|
|
||||||
public SonarBlip(Vector2 pos, float fadeTimer, float scale, Sonar.BlipType blipType = Sonar.BlipType.Default)
|
public SonarBlip(Vector2 pos, float fadeTimer, float scale, Sonar.BlipType blipType = Sonar.BlipType.Default)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -351,14 +351,19 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
OnClicked = (btn, userdata) =>
|
OnClicked = (btn, userdata) =>
|
||||||
{
|
{
|
||||||
if (GameMain.GameSession?.Campaign is CampaignMode campaign)
|
if (GameMain.GameSession?.Missions.Any(m => !m.AllowUndocking) ?? false)
|
||||||
|
{
|
||||||
|
new GUIMessageBox("", TextManager.Get("undockingdisabledbymission"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (GameMain.GameSession?.Campaign is CampaignMode campaign)
|
||||||
{
|
{
|
||||||
if (Level.IsLoadedOutpost &&
|
if (Level.IsLoadedOutpost &&
|
||||||
DockingSources.Any(d => d.Docked && (d.DockingTarget?.Item.Submarine?.Info?.IsOutpost ?? false)))
|
DockingSources.Any(d => d.Docked && (d.DockingTarget?.Item.Submarine?.Info?.IsOutpost ?? false)))
|
||||||
{
|
{
|
||||||
// Undocking from an outpost
|
// Undocking from an outpost
|
||||||
campaign.CampaignUI.SelectTab(CampaignMode.InteractionType.Map);
|
|
||||||
campaign.ShowCampaignUI = true;
|
campaign.ShowCampaignUI = true;
|
||||||
|
campaign.CampaignUI.SelectTab(CampaignMode.InteractionType.Map);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (!Level.IsLoadedOutpost && DockingModeEnabled && ActiveDockingSource != null &&
|
else if (!Level.IsLoadedOutpost && DockingModeEnabled && ActiveDockingSource != null &&
|
||||||
@@ -398,7 +403,7 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
if (GameMain.Client == null)
|
if (GameMain.Client == null)
|
||||||
{
|
{
|
||||||
item.SendSignal(0, "1", "toggle_docking", sender: null);
|
item.SendSignal("1", "toggle_docking");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -722,7 +727,19 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pressureWarningText.Visible = item.Submarine != null && item.Submarine.AtDamageDepth && Timing.TotalTime % 1.0f < 0.8f;
|
pressureWarningText.Visible = item.Submarine != null && Timing.TotalTime % 1.0f < 0.8f;
|
||||||
|
float depthEffectThreshold = 500.0f;
|
||||||
|
if (Level.Loaded != null && pressureWarningText.Visible &&
|
||||||
|
item.Submarine.RealWorldDepth > Level.Loaded.RealWorldCrushDepth - depthEffectThreshold && item.Submarine.RealWorldDepth > item.Submarine.RealWorldCrushDepth - depthEffectThreshold)
|
||||||
|
{
|
||||||
|
pressureWarningText.Visible = true;
|
||||||
|
pressureWarningText.Text = item.Submarine.AtDamageDepth ? TextManager.Get("SteeringDepthWarning") : TextManager.Get("SteeringDepthWarningLow").Replace("[crushdepth]", ((int)item.Submarine.RealWorldCrushDepth).ToString());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pressureWarningText.Visible = false;
|
||||||
|
}
|
||||||
|
|
||||||
iceSpireWarningText.Visible = item.Submarine != null && !pressureWarningText.Visible && showIceSpireWarning && Timing.TotalTime % 1.0f < 0.8f;
|
iceSpireWarningText.Visible = item.Submarine != null && !pressureWarningText.Visible && showIceSpireWarning && Timing.TotalTime % 1.0f < 0.8f;
|
||||||
|
|
||||||
if (Vector2.DistanceSquared(PlayerInput.MousePosition, steerArea.Rect.Center.ToVector2()) < steerRadius * steerRadius)
|
if (Vector2.DistanceSquared(PlayerInput.MousePosition, steerArea.Rect.Center.ToVector2()) < steerRadius * steerRadius)
|
||||||
@@ -748,7 +765,7 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
if (!AutoPilot && Character.DisableControls && GUI.KeyboardDispatcher.Subscriber == null)
|
if (!AutoPilot && Character.DisableControls && GUI.KeyboardDispatcher.Subscriber == null)
|
||||||
{
|
{
|
||||||
steeringAdjustSpeed = character == null ? 0.2f : MathHelper.Lerp(0.2f, 1.0f, character.GetSkillLevel("helm") / 100.0f);
|
steeringAdjustSpeed = character == null ? DefaultSteeringAdjustSpeed : MathHelper.Lerp(0.2f, 1.0f, character.GetSkillLevel("helm") / 100.0f);
|
||||||
Vector2 input = Vector2.Zero;
|
Vector2 input = Vector2.Zero;
|
||||||
if (PlayerInput.KeyDown(InputType.Left)) { input -= Vector2.UnitX; }
|
if (PlayerInput.KeyDown(InputType.Left)) { input -= Vector2.UnitX; }
|
||||||
if (PlayerInput.KeyDown(InputType.Right)) { input += Vector2.UnitX; }
|
if (PlayerInput.KeyDown(InputType.Right)) { input += Vector2.UnitX; }
|
||||||
@@ -914,7 +931,7 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
if (dockingButtonClicked)
|
if (dockingButtonClicked)
|
||||||
{
|
{
|
||||||
item.SendSignal(0, "1", "toggle_docking", sender: null);
|
item.SendSignal("1", "toggle_docking");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (autoPilot)
|
if (autoPilot)
|
||||||
|
|||||||
@@ -98,8 +98,11 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
public override void UpdateHUD(Character character, float deltaTime, Camera cam)
|
public override void UpdateHUD(Character character, float deltaTime, Camera cam)
|
||||||
{
|
{
|
||||||
float chargeRatio = charge / capacity;
|
if (chargeIndicator != null)
|
||||||
chargeIndicator.Color = ToolBox.GradientLerp(chargeRatio, Color.Red, Color.Orange, Color.Green);
|
{
|
||||||
|
float chargeRatio = charge / capacity;
|
||||||
|
chargeIndicator.Color = ToolBox.GradientLerp(chargeRatio, Color.Red, Color.Orange, Color.Green);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Draw(SpriteBatch spriteBatch, bool editing = false, float itemDepth = -1)
|
public void Draw(SpriteBatch spriteBatch, bool editing = false, float itemDepth = -1)
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using Barotrauma.Networking;
|
using Microsoft.Xna.Framework;
|
||||||
using Microsoft.Xna.Framework;
|
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -28,15 +27,7 @@ namespace Barotrauma.Items.Components
|
|||||||
int x = panelRect.X, y = panelRect.Y;
|
int x = panelRect.X, y = panelRect.Y;
|
||||||
int width = panelRect.Width, height = panelRect.Height;
|
int width = panelRect.Width, height = panelRect.Height;
|
||||||
|
|
||||||
Vector2 scale = new Vector2(GUI.Scale);
|
Vector2 scale = GetScale(panel.GuiFrame.RectTransform.MaxSize, panel.GuiFrame.Rect.Size);
|
||||||
if (panel.GuiFrame.RectTransform.MaxSize.X < int.MaxValue)
|
|
||||||
{
|
|
||||||
scale.X = panel.GuiFrame.RectTransform.MaxSize.X / panel.GuiFrame.Rect.Width;
|
|
||||||
}
|
|
||||||
if (panel.GuiFrame.RectTransform.MaxSize.Y < int.MaxValue)
|
|
||||||
{
|
|
||||||
scale.Y = panel.GuiFrame.RectTransform.MaxSize.Y / panel.GuiFrame.Rect.Height;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool mouseInRect = panelRect.Contains(PlayerInput.MousePosition);
|
bool mouseInRect = panelRect.Contains(PlayerInput.MousePosition);
|
||||||
|
|
||||||
@@ -66,15 +57,15 @@ namespace Barotrauma.Items.Components
|
|||||||
//two passes: first the connector, then the wires to get the wires to render in front
|
//two passes: first the connector, then the wires to get the wires to render in front
|
||||||
for (int i = 0; i < 2; i++)
|
for (int i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
Vector2 rightPos = new Vector2(x + width - 80 * scale.X, y + 60 * scale.Y);
|
Vector2 rightPos = GetRightPos(x, y, width, scale);
|
||||||
Vector2 leftPos = new Vector2(x + 80 * scale.X, y + 60 * scale.Y);
|
Vector2 leftPos = GetLeftPos(x, y, scale);
|
||||||
|
|
||||||
Vector2 rightWirePos = new Vector2(x + width - 5 * scale.X, y + 30 * scale.Y);
|
Vector2 rightWirePos = new Vector2(x + width - 5 * scale.X, y + 30 * scale.Y);
|
||||||
Vector2 leftWirePos = new Vector2(x + 5 * scale.X, y + 30 * scale.Y);
|
Vector2 leftWirePos = new Vector2(x + 5 * scale.X, y + 30 * scale.Y);
|
||||||
|
|
||||||
int wireInterval = (height - (int)(20 * scale.Y)) / Math.Max(totalWireCount, 1);
|
int wireInterval = (height - (int)(20 * scale.Y)) / Math.Max(totalWireCount, 1);
|
||||||
int connectorIntervalLeft = (height - (int)(100 * scale.Y)) / Math.Max(panel.Connections.Count(c => c.IsOutput), 1);
|
int connectorIntervalLeft = GetConnectorIntervalLeft(height, scale, panel);
|
||||||
int connectorIntervalRight = (height - (int)(100 * scale.Y)) / Math.Max(panel.Connections.Count(c => !c.IsOutput), 1);
|
int connectorIntervalRight = GetConnectorIntervalRight(height, scale, panel);
|
||||||
|
|
||||||
foreach (Connection c in panel.Connections)
|
foreach (Connection c in panel.Connections)
|
||||||
{
|
{
|
||||||
@@ -101,15 +92,12 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
{
|
{
|
||||||
c.DrawConnection(spriteBatch, panel, rightPos,
|
c.DrawConnection(spriteBatch, panel, rightPos, GetOutputLabelPosition(rightPos, panel, c), scale);
|
||||||
new Vector2(rightPos.X - GUI.SmallFont.MeasureString(c.DisplayName.ToUpper()).X - 25 * panel.Scale, rightPos.Y + 5 * panel.Scale),
|
|
||||||
scale);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
c.DrawWires(spriteBatch, panel, rightPos, rightWirePos, mouseInRect, equippedWire, wireInterval);
|
c.DrawWires(spriteBatch, panel, rightPos, rightWirePos, mouseInRect, equippedWire, wireInterval);
|
||||||
}
|
}
|
||||||
|
|
||||||
rightPos.Y += connectorIntervalLeft;
|
rightPos.Y += connectorIntervalLeft;
|
||||||
rightWirePos.Y += c.Wires.Count(w => w != null) * wireInterval;
|
rightWirePos.Y += c.Wires.Count(w => w != null) * wireInterval;
|
||||||
}
|
}
|
||||||
@@ -117,15 +105,12 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
{
|
{
|
||||||
c.DrawConnection(spriteBatch, panel, leftPos,
|
c.DrawConnection(spriteBatch, panel, leftPos, GetInputLabelPosition(leftPos, panel, c), scale);
|
||||||
new Vector2(leftPos.X + 25 * panel.Scale, leftPos.Y - 5 * panel.Scale - GUI.SmallFont.MeasureString(c.DisplayName.ToUpper()).Y),
|
|
||||||
scale);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
c.DrawWires(spriteBatch, panel, leftPos, leftWirePos, mouseInRect, equippedWire, wireInterval);
|
c.DrawWires(spriteBatch, panel, leftPos, leftWirePos, mouseInRect, equippedWire, wireInterval);
|
||||||
}
|
}
|
||||||
|
|
||||||
leftPos.Y += connectorIntervalRight;
|
leftPos.Y += connectorIntervalRight;
|
||||||
leftWirePos.Y += c.Wires.Count(w => w != null) * wireInterval;
|
leftWirePos.Y += c.Wires.Count(w => w != null) * wireInterval;
|
||||||
}
|
}
|
||||||
@@ -215,14 +200,11 @@ namespace Barotrauma.Items.Components
|
|||||||
private void DrawConnection(SpriteBatch spriteBatch, ConnectionPanel panel, Vector2 position, Vector2 labelPos, Vector2 scale)
|
private void DrawConnection(SpriteBatch spriteBatch, ConnectionPanel panel, Vector2 position, Vector2 labelPos, Vector2 scale)
|
||||||
{
|
{
|
||||||
string text = DisplayName.ToUpper();
|
string text = DisplayName.ToUpper();
|
||||||
Vector2 textSize = GUI.SmallFont.MeasureString(text);
|
|
||||||
|
|
||||||
//nasty
|
//nasty
|
||||||
var labelSprite = GUI.Style.GetComponentStyle("ConnectionPanelLabel")?.Sprites.Values.First().First();
|
if (GUI.Style.GetComponentStyle("ConnectionPanelLabel")?.Sprites.Values.First().First() is UISprite labelSprite)
|
||||||
if (labelSprite != null)
|
|
||||||
{
|
{
|
||||||
Rectangle labelArea = new Rectangle(labelPos.ToPoint(), textSize.ToPoint());
|
Rectangle labelArea = GetLabelArea(labelPos, text, scale);
|
||||||
labelArea.Inflate(10 * scale.X, 3 * scale.Y);
|
|
||||||
labelSprite.Draw(spriteBatch, labelArea, IsPower ? GUI.Style.Red : Color.SteelBlue);
|
labelSprite.Draw(spriteBatch, labelArea, IsPower ? GUI.Style.Red : Color.SteelBlue);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,7 +238,8 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
if (!PlayerInput.PrimaryMouseButtonHeld())
|
if (!PlayerInput.PrimaryMouseButtonHeld())
|
||||||
{
|
{
|
||||||
if (GameMain.NetworkMember != null || panel.CheckCharacterSuccess(Character.Controlled))
|
if ((GameMain.NetworkMember != null || panel.CheckCharacterSuccess(Character.Controlled)) &&
|
||||||
|
Wires.Count(w => w != null) < MaxPlayerConnectableWires)
|
||||||
{
|
{
|
||||||
//find an empty cell for the new connection
|
//find an empty cell for the new connection
|
||||||
int index = FindEmptyIndex();
|
int index = FindEmptyIndex();
|
||||||
@@ -390,5 +373,115 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool CheckConnectionLabelOverlap(ConnectionPanel panel, out Point newRectSize)
|
||||||
|
{
|
||||||
|
Rectangle panelRect = panel.GuiFrame.Rect;
|
||||||
|
int x = panelRect.X, y = panelRect.Y;
|
||||||
|
Vector2 scale = GetScale(panel.GuiFrame.RectTransform.MaxSize, panel.GuiFrame.Rect.Size);
|
||||||
|
Vector2 rightPos = GetRightPos(x, y, panelRect.Width, scale);
|
||||||
|
Vector2 leftPos = GetLeftPos(x, y, scale);
|
||||||
|
int connectorIntervalLeft = GetConnectorIntervalLeft(panelRect.Height, scale, panel);
|
||||||
|
int connectorIntervalRight = GetConnectorIntervalRight(panelRect.Height, scale, panel);
|
||||||
|
newRectSize = panelRect.Size;
|
||||||
|
var labelAreas = new List<Rectangle>();
|
||||||
|
for (int i = 0; i < 100; i++)
|
||||||
|
{
|
||||||
|
labelAreas.Clear();
|
||||||
|
foreach (var c in panel.Connections)
|
||||||
|
{
|
||||||
|
if (c.IsOutput)
|
||||||
|
{
|
||||||
|
var labelArea = GetLabelArea(GetOutputLabelPosition(rightPos, panel, c), c.DisplayName.ToUpper(), scale);
|
||||||
|
labelAreas.Add(labelArea);
|
||||||
|
rightPos.Y += connectorIntervalLeft;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var labelArea = GetLabelArea(GetInputLabelPosition(leftPos, panel, c), c.DisplayName.ToUpper(), scale);
|
||||||
|
labelAreas.Add(labelArea);
|
||||||
|
leftPos.Y += connectorIntervalRight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool foundOverlap = false;
|
||||||
|
for (int j = 0; j < labelAreas.Count; j++)
|
||||||
|
{
|
||||||
|
for (int k = 0; k < labelAreas.Count; k++)
|
||||||
|
{
|
||||||
|
if (k == j) { continue; }
|
||||||
|
if (!labelAreas[j].Intersects(labelAreas[k])) { continue; }
|
||||||
|
newRectSize += new Point(10);
|
||||||
|
Point maxSize = new Point(
|
||||||
|
Math.Max(panel.GuiFrame.RectTransform.MaxSize.X, newRectSize.X),
|
||||||
|
Math.Max(panel.GuiFrame.RectTransform.MaxSize.Y, newRectSize.Y));
|
||||||
|
scale = GetScale(maxSize, newRectSize);
|
||||||
|
rightPos = GetRightPos(x, y, newRectSize.X, scale);
|
||||||
|
leftPos = GetLeftPos(x, y, scale);
|
||||||
|
connectorIntervalLeft = GetConnectorIntervalLeft(newRectSize.Y, scale, panel);
|
||||||
|
connectorIntervalRight = GetConnectorIntervalRight(newRectSize.Y, scale, panel);
|
||||||
|
foundOverlap = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!foundOverlap) { break; }
|
||||||
|
}
|
||||||
|
return newRectSize.X != panel.GuiFrame.Rect.Width || newRectSize.Y > panel.GuiFrame.Rect.Height;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Vector2 GetScale(Point maxSize, Point size)
|
||||||
|
{
|
||||||
|
Vector2 scale = new Vector2(GUI.Scale);
|
||||||
|
if (maxSize.X < int.MaxValue)
|
||||||
|
{
|
||||||
|
scale.X = maxSize.X / size.X;
|
||||||
|
}
|
||||||
|
if (maxSize.Y < int.MaxValue)
|
||||||
|
{
|
||||||
|
scale.Y = maxSize.Y / size.Y;
|
||||||
|
}
|
||||||
|
return scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Vector2 GetInputLabelPosition(Vector2 connectorPosition, ConnectionPanel panel, Connection connection)
|
||||||
|
{
|
||||||
|
return new Vector2(
|
||||||
|
connectorPosition.X + 25 * panel.Scale,
|
||||||
|
connectorPosition.Y - 5 * panel.Scale - GUI.SmallFont.MeasureString(connection.DisplayName.ToUpper()).Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Vector2 GetOutputLabelPosition(Vector2 connectorPosition, ConnectionPanel panel, Connection connection)
|
||||||
|
{
|
||||||
|
return new Vector2(
|
||||||
|
connectorPosition.X - 25 * panel.Scale - GUI.SmallFont.MeasureString(connection.DisplayName.ToUpper()).X,
|
||||||
|
connectorPosition.Y + 5 * panel.Scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Rectangle GetLabelArea(Vector2 labelPos, string text, Vector2 scale)
|
||||||
|
{
|
||||||
|
Vector2 textSize = GUI.SmallFont.MeasureString(text);
|
||||||
|
Rectangle labelArea = new Rectangle(labelPos.ToPoint(), textSize.ToPoint());
|
||||||
|
labelArea.Inflate(10 * scale.X, 3 * scale.Y);
|
||||||
|
return labelArea;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Vector2 GetLeftPos(int x, int y, Vector2 scale)
|
||||||
|
{
|
||||||
|
return new Vector2(x + 80 * scale.X, y + 60 * scale.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Vector2 GetRightPos(int x, int y, int width, Vector2 scale)
|
||||||
|
{
|
||||||
|
return new Vector2(x + width - 80 * scale.X, y + 60 * scale.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int GetConnectorIntervalLeft(int height, Vector2 scale, ConnectionPanel panel)
|
||||||
|
{
|
||||||
|
return (height - (int)(100 * scale.Y)) / Math.Max(panel.Connections.Count(c => c.IsOutput), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int GetConnectorIntervalRight(int height, Vector2 scale, ConnectionPanel panel)
|
||||||
|
{
|
||||||
|
return (height - (int)(100 * scale.Y)) / Math.Max(panel.Connections.Count(c => !c.IsOutput), 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+34
-2
@@ -24,9 +24,15 @@ namespace Barotrauma.Items.Components
|
|||||||
get { return GuiFrame.Rect.Width / 400.0f; }
|
get { return GuiFrame.Rect.Width / 400.0f; }
|
||||||
}
|
}
|
||||||
|
|
||||||
partial void InitProjSpecific(XElement element)
|
private Point originalMaxSize;
|
||||||
|
private Vector2 originalRelativeSize;
|
||||||
|
|
||||||
|
partial void InitProjSpecific()
|
||||||
{
|
{
|
||||||
if (GuiFrame == null) { return; }
|
if (GuiFrame == null) { return; }
|
||||||
|
originalMaxSize = GuiFrame.RectTransform.MaxSize;
|
||||||
|
originalRelativeSize = GuiFrame.RectTransform.RelativeSize;
|
||||||
|
CheckForLabelOverlap();
|
||||||
new GUICustomComponent(new RectTransform(Vector2.One, GuiFrame.RectTransform), DrawConnections, null)
|
new GUICustomComponent(new RectTransform(Vector2.One, GuiFrame.RectTransform), DrawConnections, null)
|
||||||
{
|
{
|
||||||
UserData = this
|
UserData = this
|
||||||
@@ -40,7 +46,7 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
partial void UpdateProjSpecific(float deltaTime)
|
partial void UpdateProjSpecific(float deltaTime)
|
||||||
{
|
{
|
||||||
foreach (Wire wire in DisconnectedWires)
|
foreach (var _ in DisconnectedWires)
|
||||||
{
|
{
|
||||||
if (Rand.Range(0.0f, 500.0f) < 1.0f)
|
if (Rand.Range(0.0f, 500.0f) < 1.0f)
|
||||||
{
|
{
|
||||||
@@ -112,6 +118,32 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void OnResolutionChanged()
|
||||||
|
{
|
||||||
|
base.OnResolutionChanged();
|
||||||
|
if (GuiFrame == null) { return; }
|
||||||
|
CheckForLabelOverlap();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CheckForLabelOverlap()
|
||||||
|
{
|
||||||
|
GuiFrame.RectTransform.MaxSize = originalMaxSize;
|
||||||
|
GuiFrame.RectTransform.Resize(originalRelativeSize);
|
||||||
|
if (Connection.CheckConnectionLabelOverlap(this, out Point newRectSize))
|
||||||
|
{
|
||||||
|
int xCenter = (int)(GameMain.GraphicsWidth / 2.0f);
|
||||||
|
int maxNewWidth = 2 * Math.Min(xCenter - HUDLayoutSettings.CrewArea.Right, xCenter - HUDLayoutSettings.ChatBoxArea.Right);
|
||||||
|
int yCenter = (int)(GameMain.GraphicsHeight / 2.0f);
|
||||||
|
int maxNewHeight = 2 * Math.Min(yCenter - HUDLayoutSettings.MessageAreaTop.Bottom, HUDLayoutSettings.InventoryTopY - yCenter);
|
||||||
|
// Make sure we don't expand the panel interface too much
|
||||||
|
newRectSize = new Point(Math.Min(newRectSize.X, maxNewWidth), Math.Min(newRectSize.Y, maxNewHeight));
|
||||||
|
GuiFrame.RectTransform.MaxSize = new Point(
|
||||||
|
Math.Max(GuiFrame.RectTransform.MaxSize.X, newRectSize.X),
|
||||||
|
Math.Max(GuiFrame.RectTransform.MaxSize.Y, newRectSize.Y));
|
||||||
|
GuiFrame.RectTransform.Resize(newRectSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
||||||
{
|
{
|
||||||
if (GameMain.Client.MidRoundSyncing)
|
if (GameMain.Client.MidRoundSyncing)
|
||||||
|
|||||||
@@ -50,7 +50,8 @@ namespace Barotrauma.Items.Components
|
|||||||
var textBox = new GUITextBox(new RectTransform(new Vector2(0.5f, 1.0f), layoutGroup.RectTransform), ciElement.Signal, style: "GUITextBoxNoIcon")
|
var textBox = new GUITextBox(new RectTransform(new Vector2(0.5f, 1.0f), layoutGroup.RectTransform), ciElement.Signal, style: "GUITextBoxNoIcon")
|
||||||
{
|
{
|
||||||
OverflowClip = true,
|
OverflowClip = true,
|
||||||
UserData = ciElement
|
UserData = ciElement,
|
||||||
|
MaxTextLength = ciElement.MaxTextLength
|
||||||
};
|
};
|
||||||
//reset size restrictions set by the Style to make sure the elements can fit the interface
|
//reset size restrictions set by the Style to make sure the elements can fit the interface
|
||||||
textBox.RectTransform.MinSize = textBox.Frame.RectTransform.MinSize = new Point(0, 0);
|
textBox.RectTransform.MinSize = textBox.Frame.RectTransform.MinSize = new Point(0, 0);
|
||||||
|
|||||||
@@ -63,21 +63,23 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
|
|
||||||
OutputValue = input;
|
OutputValue = input;
|
||||||
item.SendSignal(0, input, "signal_out", null);
|
|
||||||
ShowOnDisplay(input);
|
ShowOnDisplay(input);
|
||||||
|
item.SendSignal(input, "signal_out");
|
||||||
}
|
}
|
||||||
|
|
||||||
partial void ShowOnDisplay(string input)
|
partial void ShowOnDisplay(string input, bool addToHistory = true)
|
||||||
{
|
{
|
||||||
messageHistory.Add(input);
|
if (addToHistory)
|
||||||
while (messageHistory.Count > MaxMessages)
|
|
||||||
{
|
{
|
||||||
messageHistory.RemoveAt(0);
|
messageHistory.Add(input);
|
||||||
}
|
while (messageHistory.Count > MaxMessages)
|
||||||
|
{
|
||||||
while (historyBox.Content.CountChildren > MaxMessages)
|
messageHistory.RemoveAt(0);
|
||||||
{
|
}
|
||||||
historyBox.RemoveChild(historyBox.Content.Children.First());
|
while (historyBox.Content.CountChildren > MaxMessages)
|
||||||
|
{
|
||||||
|
historyBox.RemoveChild(historyBox.Content.Children.First());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GUITextBlock newBlock = new GUITextBlock(
|
GUITextBlock newBlock = new GUITextBlock(
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ namespace Barotrauma.Items.Components
|
|||||||
SpriteEffects.None,
|
SpriteEffects.None,
|
||||||
depth);
|
depth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private static Sprite defaultWireSprite;
|
private static Sprite defaultWireSprite;
|
||||||
private Sprite overrideSprite;
|
private Sprite overrideSprite;
|
||||||
private Sprite wireSprite;
|
private Sprite wireSprite;
|
||||||
@@ -156,7 +156,8 @@ namespace Barotrauma.Items.Components
|
|||||||
drawOffset = sub.DrawPosition + sub.HiddenSubPosition;
|
drawOffset = sub.DrawPosition + sub.HiddenSubPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
float depth = item.IsSelected ? 0.0f : SubEditorScreen.IsWiringMode() ? 0.02f : wireSprite.Depth + (item.ID % 100) * 0.000001f;// item.GetDrawDepth(wireSprite.Depth, wireSprite);
|
float baseDepth = UseSpriteDepth ? item.SpriteDepth : wireSprite.Depth;
|
||||||
|
float depth = item.IsSelected ? 0.0f : SubEditorScreen.IsWiringMode() ? 0.02f : baseDepth + (item.ID % 100) * 0.000001f;// item.GetDrawDepth(wireSprite.Depth, wireSprite);
|
||||||
|
|
||||||
if (item.IsHighlighted)
|
if (item.IsHighlighted)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -225,7 +225,7 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
foreach (AfflictionPrefab affliction in combinedAfflictionStrengths.Keys)
|
foreach (AfflictionPrefab affliction in combinedAfflictionStrengths.Keys)
|
||||||
{
|
{
|
||||||
texts.Add(TextManager.AddPunctuation(':', affliction.Name, ((int)combinedAfflictionStrengths[affliction]).ToString() + " %"));
|
texts.Add(TextManager.AddPunctuation(':', affliction.Name, Math.Max(((int)combinedAfflictionStrengths[affliction]), 1).ToString() + " %"));
|
||||||
textColors.Add(Color.Lerp(GUI.Style.Orange, GUI.Style.Red, combinedAfflictionStrengths[affliction] / affliction.MaxStrength));
|
textColors.Add(Color.Lerp(GUI.Style.Orange, GUI.Style.Red, combinedAfflictionStrengths[affliction] / affliction.MaxStrength));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -130,12 +130,15 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
powerIndicator = new GUIProgressBar(new RectTransform(new Vector2(0.18f, 0.03f), GUI.Canvas, Anchor.TopCenter)
|
powerIndicator = new GUIProgressBar(new RectTransform(new Vector2(0.18f, 0.03f), GUI.Canvas, Anchor.BottomCenter)
|
||||||
{
|
{
|
||||||
MinSize = new Point(100,20),
|
MinSize = new Point(100, 20),
|
||||||
RelativeOffset = new Vector2(0.0f, 0.01f)
|
RelativeOffset = new Vector2(0.0f, 0.01f)
|
||||||
},
|
},
|
||||||
barSize: 0.0f, style: "DeviceProgressBar");
|
barSize: 0.0f, style: "DeviceProgressBar")
|
||||||
|
{
|
||||||
|
CanBeFocused = false
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Move(Vector2 amount)
|
public override void Move(Vector2 amount)
|
||||||
@@ -497,9 +500,15 @@ namespace Barotrauma.Items.Components
|
|||||||
foreach (MapEntity e in item.linkedTo)
|
foreach (MapEntity e in item.linkedTo)
|
||||||
{
|
{
|
||||||
if (!(e is Item linkedItem)) { continue; }
|
if (!(e is Item linkedItem)) { continue; }
|
||||||
availableAmmo.AddRange(linkedItem.ContainedItems);
|
var itemContainer = linkedItem.GetComponent<ItemContainer>();
|
||||||
}
|
if (itemContainer == null) { continue; }
|
||||||
|
availableAmmo.AddRange(itemContainer.Inventory.AllItems);
|
||||||
|
for (int i = 0; i < itemContainer.Inventory.Capacity - itemContainer.Inventory.AllItems.Count(); i++)
|
||||||
|
{
|
||||||
|
availableAmmo.Add(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
float chargeRate =
|
float chargeRate =
|
||||||
powerConsumption <= 0.0f ?
|
powerConsumption <= 0.0f ?
|
||||||
1.0f :
|
1.0f :
|
||||||
@@ -531,15 +540,16 @@ namespace Barotrauma.Items.Components
|
|||||||
if (ShowProjectileIndicator)
|
if (ShowProjectileIndicator)
|
||||||
{
|
{
|
||||||
Point slotSize = (Inventory.SlotSpriteSmall.size * Inventory.UIScale).ToPoint();
|
Point slotSize = (Inventory.SlotSpriteSmall.size * Inventory.UIScale).ToPoint();
|
||||||
int spacing = 5;
|
Point spacing = new Point(GUI.IntScale(5), GUI.IntScale(20));
|
||||||
int slotsPerRow = Math.Min(availableAmmo.Count, 6);
|
int slotsPerRow = Math.Min(availableAmmo.Count, 6);
|
||||||
int totalWidth = slotSize.X * slotsPerRow + spacing * (slotsPerRow - 1);
|
int totalWidth = slotSize.X * slotsPerRow + spacing.X * (slotsPerRow - 1);
|
||||||
Point invSlotPos = new Point(GameMain.GraphicsWidth / 2 - totalWidth / 2, (int)(60 * GUI.Scale));
|
int rows = (int)Math.Ceiling(availableAmmo.Count / (float)slotsPerRow);
|
||||||
|
Point invSlotPos = new Point(GameMain.GraphicsWidth / 2 - totalWidth / 2, powerIndicator.Rect.Y - (slotSize.Y + spacing.Y) * rows);
|
||||||
for (int i = 0; i < availableAmmo.Count; i++)
|
for (int i = 0; i < availableAmmo.Count; i++)
|
||||||
{
|
{
|
||||||
// TODO: Optimize? Creates multiple new objects per frame?
|
// TODO: Optimize? Creates multiple new objects per frame?
|
||||||
Inventory.DrawSlot(spriteBatch, null,
|
Inventory.DrawSlot(spriteBatch, null,
|
||||||
new VisualSlot(new Rectangle(invSlotPos + new Point((i % slotsPerRow) * (slotSize.X + spacing), (int)Math.Floor(i / (float)slotsPerRow) * (slotSize.Y + spacing)), slotSize)),
|
new VisualSlot(new Rectangle(invSlotPos + new Point((i % slotsPerRow) * (slotSize.X + spacing.X), (int)Math.Floor(i / (float)slotsPerRow) * (slotSize.Y + spacing.Y)), slotSize)),
|
||||||
availableAmmo[i], -1, true);
|
availableAmmo[i], -1, true);
|
||||||
}
|
}
|
||||||
if (flashNoAmmo)
|
if (flashNoAmmo)
|
||||||
@@ -578,7 +588,7 @@ namespace Barotrauma.Items.Components
|
|||||||
//ID ushort.MaxValue = launched without a projectile
|
//ID ushort.MaxValue = launched without a projectile
|
||||||
if (projectileID == ushort.MaxValue)
|
if (projectileID == ushort.MaxValue)
|
||||||
{
|
{
|
||||||
Launch(null);
|
Launch(null, user);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -587,7 +597,7 @@ namespace Barotrauma.Items.Components
|
|||||||
DebugConsole.ThrowError("Failed to launch a projectile - item with the ID \"" + projectileID + " not found");
|
DebugConsole.ThrowError("Failed to launch a projectile - item with the ID \"" + projectileID + " not found");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Launch(projectile, launchRotation: newTargetRotation);
|
Launch(projectile, user, launchRotation: newTargetRotation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -165,7 +165,14 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
if (isLocked)
|
if (isLocked)
|
||||||
{
|
{
|
||||||
Lock(isNetworkMessage: true, forcePosition: true);
|
if (DockingTarget.joint != null)
|
||||||
|
{
|
||||||
|
DockingTarget.Lock(isNetworkMessage: true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Lock(isNetworkMessage: true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -215,8 +215,10 @@ namespace Barotrauma
|
|||||||
public Inventory Inventory;
|
public Inventory Inventory;
|
||||||
public readonly Item Item;
|
public readonly Item Item;
|
||||||
public readonly bool IsSubSlot;
|
public readonly bool IsSubSlot;
|
||||||
public string Tooltip;
|
public string Tooltip { get; private set; }
|
||||||
public List<RichTextData> TooltipRichTextData;
|
public List<RichTextData> TooltipRichTextData { get; private set;}
|
||||||
|
|
||||||
|
public int tooltipDisplayedCondition;
|
||||||
|
|
||||||
public SlotReference(Inventory parentInventory, VisualSlot slot, int slotIndex, bool isSubSlot, Inventory subInventory = null)
|
public SlotReference(Inventory parentInventory, VisualSlot slot, int slotIndex, bool isSubSlot, Inventory subInventory = null)
|
||||||
{
|
{
|
||||||
@@ -227,16 +229,29 @@ namespace Barotrauma
|
|||||||
IsSubSlot = isSubSlot;
|
IsSubSlot = isSubSlot;
|
||||||
Item = ParentInventory.GetItemAt(slotIndex);
|
Item = ParentInventory.GetItemAt(slotIndex);
|
||||||
|
|
||||||
int stackCount = 1;
|
RefreshTooltip();
|
||||||
if (parentInventory != null && Item != null)
|
|
||||||
{
|
|
||||||
stackCount = parentInventory.GetItemsAt(slotIndex).Count();
|
|
||||||
}
|
|
||||||
|
|
||||||
TooltipRichTextData = RichTextData.GetRichTextData(GetTooltip(Item, stackCount), out Tooltip);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetTooltip(Item item, int stackCount)
|
public bool TooltipNeedsRefresh()
|
||||||
|
{
|
||||||
|
if (Item == null) { return false; }
|
||||||
|
return (int)Item.ConditionPercentage != tooltipDisplayedCondition;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RefreshTooltip()
|
||||||
|
{
|
||||||
|
if (Item == null) { return; }
|
||||||
|
IEnumerable<Item> itemsInSlot = null;
|
||||||
|
if (ParentInventory != null && Item != null)
|
||||||
|
{
|
||||||
|
itemsInSlot = ParentInventory.GetItemsAt(SlotIndex);
|
||||||
|
}
|
||||||
|
TooltipRichTextData = RichTextData.GetRichTextData(GetTooltip(Item, itemsInSlot), out string newTooltip);
|
||||||
|
Tooltip = newTooltip;
|
||||||
|
tooltipDisplayedCondition = (int)Item.ConditionPercentage;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetTooltip(Item item, IEnumerable<Item> itemsInSlot)
|
||||||
{
|
{
|
||||||
if (item == null) { return null; }
|
if (item == null) { return null; }
|
||||||
|
|
||||||
@@ -288,9 +303,13 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
string colorStr = XMLExtensions.ColorToString(item.SpawnedInOutpost ? GUI.Style.Red : Color.White);
|
string colorStr = XMLExtensions.ColorToString(!item.AllowStealing ? GUI.Style.Red : Color.White);
|
||||||
|
|
||||||
toolTip = $"‖color:{colorStr}‖{item.Name}‖color:end‖";
|
toolTip = $"‖color:{colorStr}‖{item.Name}‖color:end‖";
|
||||||
|
if (itemsInSlot.All(it => it.NonInteractable || it.NonPlayerTeamInteractable))
|
||||||
|
{
|
||||||
|
toolTip += " " + TextManager.Get("connectionlocked");
|
||||||
|
}
|
||||||
if (!item.IsFullCondition && !item.Prefab.HideConditionBar)
|
if (!item.IsFullCondition && !item.Prefab.HideConditionBar)
|
||||||
{
|
{
|
||||||
string conditionColorStr = XMLExtensions.ColorToString(ToolBox.GradientLerp(item.Condition / item.MaxCondition, GUI.Style.ColorInventoryEmpty, GUI.Style.ColorInventoryHalf, GUI.Style.ColorInventoryFull));
|
string conditionColorStr = XMLExtensions.ColorToString(ToolBox.GradientLerp(item.Condition / item.MaxCondition, GUI.Style.ColorInventoryEmpty, GUI.Style.ColorInventoryHalf, GUI.Style.ColorInventoryFull));
|
||||||
@@ -298,7 +317,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
if (!string.IsNullOrEmpty(description)) { toolTip += '\n' + description; }
|
if (!string.IsNullOrEmpty(description)) { toolTip += '\n' + description; }
|
||||||
}
|
}
|
||||||
if (stackCount > 2)
|
if (itemsInSlot.Count() > 1)
|
||||||
{
|
{
|
||||||
string colorStr = XMLExtensions.ColorToString(GUI.Style.Blue);
|
string colorStr = XMLExtensions.ColorToString(GUI.Style.Blue);
|
||||||
toolTip += $"\n‖color:{colorStr}‖[{GameMain.Config.KeyBindText(InputType.TakeOneFromInventorySlot)}] {TextManager.Get("inputtype.takeonefrominventoryslot")}‖color:end‖";
|
toolTip += $"\n‖color:{colorStr}‖[{GameMain.Config.KeyBindText(InputType.TakeOneFromInventorySlot)}] {TextManager.Get("inputtype.takeonefrominventoryslot")}‖color:end‖";
|
||||||
@@ -315,10 +334,10 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return DraggingItems.Any() &&
|
return Character.Controlled != null &&
|
||||||
Character.Controlled != null &&
|
|
||||||
Character.Controlled.SelectedConstruction == null &&
|
Character.Controlled.SelectedConstruction == null &&
|
||||||
CharacterHealth.OpenHealthWindow == null;
|
CharacterHealth.OpenHealthWindow == null &&
|
||||||
|
DraggingItems.Any();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -565,39 +584,41 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (!DraggingItems.Any())
|
if (!DraggingItems.Any())
|
||||||
{
|
{
|
||||||
if (PlayerInput.PrimaryMouseButtonDown() && slots[slotIndex].Any())
|
var interactableItems = Screen.Selected == GameMain.GameScreen ? slots[slotIndex].Items.Where(it => !it.NonInteractable && !it.NonPlayerTeamInteractable) : slots[slotIndex].Items;
|
||||||
|
if (PlayerInput.PrimaryMouseButtonDown() && interactableItems.Any())
|
||||||
{
|
{
|
||||||
if (PlayerInput.KeyDown(InputType.TakeHalfFromInventorySlot))
|
if (PlayerInput.KeyDown(InputType.TakeHalfFromInventorySlot))
|
||||||
{
|
{
|
||||||
DraggingItems.AddRange(slots[slotIndex].Items.Skip(slots[slotIndex].ItemCount / 2));
|
DraggingItems.AddRange(interactableItems.Skip(interactableItems.Count() / 2));
|
||||||
}
|
}
|
||||||
else if (PlayerInput.KeyDown(InputType.TakeOneFromInventorySlot))
|
else if (PlayerInput.KeyDown(InputType.TakeOneFromInventorySlot))
|
||||||
{
|
{
|
||||||
DraggingItems.Add(slots[slotIndex].First());
|
DraggingItems.Add(interactableItems.First());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DraggingItems.AddRange(slots[slotIndex].Items);
|
DraggingItems.AddRange(interactableItems);
|
||||||
}
|
}
|
||||||
DraggingSlot = slot;
|
DraggingSlot = slot;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (PlayerInput.PrimaryMouseButtonReleased())
|
else if (PlayerInput.PrimaryMouseButtonReleased())
|
||||||
{
|
{
|
||||||
if (PlayerInput.DoubleClicked() && slots[slotIndex].Any())
|
var interactableItems = Screen.Selected == GameMain.GameScreen ? slots[slotIndex].Items.Where(it => !it.NonInteractable && !it.NonPlayerTeamInteractable) : slots[slotIndex].Items;
|
||||||
|
if (PlayerInput.DoubleClicked() && interactableItems.Any())
|
||||||
{
|
{
|
||||||
doubleClickedItems.Clear();
|
doubleClickedItems.Clear();
|
||||||
if (PlayerInput.KeyDown(InputType.TakeHalfFromInventorySlot))
|
if (PlayerInput.KeyDown(InputType.TakeHalfFromInventorySlot))
|
||||||
{
|
{
|
||||||
doubleClickedItems.AddRange(slots[slotIndex].Items.Skip(slots[slotIndex].ItemCount / 2));
|
doubleClickedItems.AddRange(interactableItems.Skip(interactableItems.Count() / 2));
|
||||||
}
|
}
|
||||||
else if (PlayerInput.KeyDown(InputType.TakeOneFromInventorySlot))
|
else if (PlayerInput.KeyDown(InputType.TakeOneFromInventorySlot))
|
||||||
{
|
{
|
||||||
doubleClickedItems.Add(slots[slotIndex].First());
|
doubleClickedItems.Add(interactableItems.First());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
doubleClickedItems.AddRange(slots[slotIndex].Items);
|
doubleClickedItems.AddRange(interactableItems);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1241,9 +1262,11 @@ namespace Barotrauma
|
|||||||
if (selectedSlot.ParentInventory?.Owner != Character.Controlled &&
|
if (selectedSlot.ParentInventory?.Owner != Character.Controlled &&
|
||||||
selectedSlot.ParentInventory?.Owner != Character.Controlled.SelectedCharacter &&
|
selectedSlot.ParentInventory?.Owner != Character.Controlled.SelectedCharacter &&
|
||||||
selectedSlot.ParentInventory?.Owner != Character.Controlled.SelectedConstruction &&
|
selectedSlot.ParentInventory?.Owner != Character.Controlled.SelectedConstruction &&
|
||||||
|
!(Character.Controlled.SelectedConstruction?.linkedTo.Contains(selectedSlot.ParentInventory?.Owner) ?? false) &&
|
||||||
rootOwner != Character.Controlled &&
|
rootOwner != Character.Controlled &&
|
||||||
rootOwner != Character.Controlled.SelectedCharacter &&
|
rootOwner != Character.Controlled.SelectedCharacter &&
|
||||||
rootOwner != Character.Controlled.SelectedConstruction)
|
rootOwner != Character.Controlled.SelectedConstruction &&
|
||||||
|
!(Character.Controlled.SelectedConstruction?.linkedTo.Contains(rootOwner) ?? false))
|
||||||
{
|
{
|
||||||
selectedSlot = null;
|
selectedSlot = null;
|
||||||
}
|
}
|
||||||
@@ -1362,6 +1385,10 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
Rectangle slotRect = selectedSlot.Slot.Rect;
|
Rectangle slotRect = selectedSlot.Slot.Rect;
|
||||||
slotRect.Location += selectedSlot.Slot.DrawOffset.ToPoint();
|
slotRect.Location += selectedSlot.Slot.DrawOffset.ToPoint();
|
||||||
|
if (selectedSlot.TooltipNeedsRefresh())
|
||||||
|
{
|
||||||
|
selectedSlot.RefreshTooltip();
|
||||||
|
}
|
||||||
DrawToolTip(spriteBatch, selectedSlot.Tooltip, slotRect, selectedSlot.TooltipRichTextData);
|
DrawToolTip(spriteBatch, selectedSlot.Tooltip, slotRect, selectedSlot.TooltipRichTextData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1533,7 +1560,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
Color spriteColor = sprite == item.Sprite ? item.GetSpriteColor() : item.GetInventoryIconColor();
|
Color spriteColor = sprite == item.Sprite ? item.GetSpriteColor() : item.GetInventoryIconColor();
|
||||||
if (inventory != null && inventory.Locked) { spriteColor *= 0.5f; }
|
if (inventory != null && (inventory.Locked || inventory.slots[slotIndex].Items.All(it => it.NonInteractable || it.NonPlayerTeamInteractable))) { spriteColor *= 0.5f; }
|
||||||
if (CharacterHealth.OpenHealthWindow != null && !item.UseInHealthInterface)
|
if (CharacterHealth.OpenHealthWindow != null && !item.UseInHealthInterface)
|
||||||
{
|
{
|
||||||
spriteColor = Color.Lerp(spriteColor, Color.TransparentBlack, 0.5f);
|
spriteColor = Color.Lerp(spriteColor, Color.TransparentBlack, 0.5f);
|
||||||
@@ -1544,7 +1571,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
sprite.Draw(spriteBatch, itemPos, spriteColor, rotation, scale);
|
sprite.Draw(spriteBatch, itemPos, spriteColor, rotation, scale);
|
||||||
|
|
||||||
if (item.SpawnedInOutpost && CharacterInventory.LimbSlotIcons.ContainsKey(InvSlotType.LeftHand))
|
if (!item.AllowStealing && CharacterInventory.LimbSlotIcons.ContainsKey(InvSlotType.LeftHand))
|
||||||
{
|
{
|
||||||
var stealIcon = CharacterInventory.LimbSlotIcons[InvSlotType.LeftHand];
|
var stealIcon = CharacterInventory.LimbSlotIcons[InvSlotType.LeftHand];
|
||||||
Vector2 iconSize = new Vector2(25 * GUI.Scale);
|
Vector2 iconSize = new Vector2(25 * GUI.Scale);
|
||||||
@@ -1559,7 +1586,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
maxStackSize = Math.Min(maxStackSize, item.Container.GetComponent<ItemContainer>()?.MaxStackSize ?? maxStackSize);
|
maxStackSize = Math.Min(maxStackSize, item.Container.GetComponent<ItemContainer>()?.MaxStackSize ?? maxStackSize);
|
||||||
}
|
}
|
||||||
if (maxStackSize > 1)
|
if (maxStackSize > 1 && inventory != null)
|
||||||
{
|
{
|
||||||
int itemCount = slot.MouseOn() ? inventory.slots[slotIndex].ItemCount : inventory.slots[slotIndex].Items.Where(it => !DraggingItems.Contains(it)).Count();
|
int itemCount = slot.MouseOn() ? inventory.slots[slotIndex].ItemCount : inventory.slots[slotIndex].Items.Where(it => !DraggingItems.Contains(it)).Count();
|
||||||
if (item.IsFullCondition || MathUtils.NearlyEqual(item.Condition, 0.0f) || itemCount > 1)
|
if (item.IsFullCondition || MathUtils.NearlyEqual(item.Condition, 0.0f) || itemCount > 1)
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (!GameMain.SubEditorScreen.ShowThalamus && prefab.Category.HasFlag(MapEntityCategory.Thalamus))
|
if (GameMain.SubEditorScreen.IsSubcategoryHidden(prefab.Subcategory))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -618,6 +618,7 @@ namespace Barotrauma
|
|||||||
editingHUD = new GUIFrame(new RectTransform(new Vector2(0.3f, 0.25f), GUI.Canvas, Anchor.CenterRight) { MinSize = new Point(400, 0) }) { UserData = this };
|
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)
|
GUIListBox listBox = new GUIListBox(new RectTransform(new Vector2(0.95f, 0.8f), editingHUD.RectTransform, Anchor.Center), style: null)
|
||||||
{
|
{
|
||||||
|
CanTakeKeyBoardFocus = false,
|
||||||
Spacing = (int)(25 * GUI.Scale)
|
Spacing = (int)(25 * GUI.Scale)
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1463,6 +1464,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
byte bodyType = msg.ReadByte();
|
byte bodyType = msg.ReadByte();
|
||||||
bool spawnedInOutpost = msg.ReadBoolean();
|
bool spawnedInOutpost = msg.ReadBoolean();
|
||||||
|
bool allowStealing = msg.ReadBoolean();
|
||||||
byte teamID = msg.ReadByte();
|
byte teamID = msg.ReadByte();
|
||||||
bool tagsChanged = msg.ReadBoolean();
|
bool tagsChanged = msg.ReadBoolean();
|
||||||
string tags = "";
|
string tags = "";
|
||||||
@@ -1534,7 +1536,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
var item = new Item(itemPrefab, pos, sub, id: itemId)
|
var item = new Item(itemPrefab, pos, sub, id: itemId)
|
||||||
{
|
{
|
||||||
SpawnedInOutpost = spawnedInOutpost
|
SpawnedInOutpost = spawnedInOutpost,
|
||||||
|
AllowStealing = allowStealing
|
||||||
};
|
};
|
||||||
|
|
||||||
if (item.body != null)
|
if (item.body != null)
|
||||||
|
|||||||
@@ -22,47 +22,47 @@ namespace Barotrauma
|
|||||||
var underwaterExplosion = GameMain.ParticleManager.CreateParticle("underwaterexplosion", worldPosition, Vector2.Zero, 0.0f, hull);
|
var underwaterExplosion = GameMain.ParticleManager.CreateParticle("underwaterexplosion", worldPosition, Vector2.Zero, 0.0f, hull);
|
||||||
if (underwaterExplosion != null)
|
if (underwaterExplosion != null)
|
||||||
{
|
{
|
||||||
underwaterExplosion.Size *= MathHelper.Clamp(attack.Range / 150.0f, 0.5f, 10.0f);
|
underwaterExplosion.Size *= MathHelper.Clamp(Attack.Range / 150.0f, 0.5f, 10.0f);
|
||||||
underwaterExplosion.StartDelay = 0.0f;
|
underwaterExplosion.StartDelay = 0.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < attack.Range * 0.1f; i++)
|
for (int i = 0; i < Attack.Range * 0.1f; i++)
|
||||||
{
|
{
|
||||||
if (!underwater)
|
if (!underwater)
|
||||||
{
|
{
|
||||||
float particleSpeed = Rand.Range(0.0f, 1.0f);
|
float particleSpeed = Rand.Range(0.0f, 1.0f);
|
||||||
particleSpeed = particleSpeed * particleSpeed * attack.Range;
|
particleSpeed = particleSpeed * particleSpeed * Attack.Range;
|
||||||
|
|
||||||
if (flames)
|
if (flames)
|
||||||
{
|
{
|
||||||
float particleScale = MathHelper.Clamp(attack.Range * 0.0025f, 0.5f, 2.0f);
|
float particleScale = MathHelper.Clamp(Attack.Range * 0.0025f, 0.5f, 2.0f);
|
||||||
var flameParticle = GameMain.ParticleManager.CreateParticle("explosionfire",
|
var flameParticle = GameMain.ParticleManager.CreateParticle("explosionfire",
|
||||||
ClampParticlePos(worldPosition + Rand.Vector((float)System.Math.Sqrt(Rand.Range(0.0f, attack.Range))), hull),
|
ClampParticlePos(worldPosition + Rand.Vector((float)System.Math.Sqrt(Rand.Range(0.0f, Attack.Range))), hull),
|
||||||
Rand.Vector(Rand.Range(0.0f, particleSpeed)), 0.0f, hull);
|
Rand.Vector(Rand.Range(0.0f, particleSpeed)), 0.0f, hull);
|
||||||
if (flameParticle != null) flameParticle.Size *= particleScale;
|
if (flameParticle != null) flameParticle.Size *= particleScale;
|
||||||
}
|
}
|
||||||
if (smoke)
|
if (smoke)
|
||||||
{
|
{
|
||||||
GameMain.ParticleManager.CreateParticle(Rand.Range(0.0f, 1.0f) < 0.5f ? "explosionsmoke" : "smoke",
|
GameMain.ParticleManager.CreateParticle(Rand.Range(0.0f, 1.0f) < 0.5f ? "explosionsmoke" : "smoke",
|
||||||
ClampParticlePos(worldPosition + Rand.Vector((float)System.Math.Sqrt(Rand.Range(0.0f, attack.Range))), hull),
|
ClampParticlePos(worldPosition + Rand.Vector((float)System.Math.Sqrt(Rand.Range(0.0f, Attack.Range))), hull),
|
||||||
Rand.Vector(Rand.Range(0.0f, particleSpeed)), 0.0f, hull);
|
Rand.Vector(Rand.Range(0.0f, particleSpeed)), 0.0f, hull);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (underwaterBubble)
|
else if (underwaterBubble)
|
||||||
{
|
{
|
||||||
Vector2 bubblePos = Rand.Vector(Rand.Range(0.0f, attack.Range * 0.5f));
|
Vector2 bubblePos = Rand.Vector(Rand.Range(0.0f, Attack.Range * 0.5f));
|
||||||
|
|
||||||
GameMain.ParticleManager.CreateParticle("risingbubbles", worldPosition + bubblePos,
|
GameMain.ParticleManager.CreateParticle("risingbubbles", worldPosition + bubblePos,
|
||||||
Vector2.Zero, 0.0f, hull);
|
Vector2.Zero, 0.0f, hull);
|
||||||
|
|
||||||
if (i < attack.Range * 0.02f)
|
if (i < Attack.Range * 0.02f)
|
||||||
{
|
{
|
||||||
var underwaterExplosion = GameMain.ParticleManager.CreateParticle("underwaterexplosion", worldPosition + bubblePos,
|
var underwaterExplosion = GameMain.ParticleManager.CreateParticle("underwaterexplosion", worldPosition + bubblePos,
|
||||||
Vector2.Zero, 0.0f, hull);
|
Vector2.Zero, 0.0f, hull);
|
||||||
if (underwaterExplosion != null)
|
if (underwaterExplosion != null)
|
||||||
{
|
{
|
||||||
underwaterExplosion.Size *= MathHelper.Clamp(attack.Range / 300.0f, 0.5f, 2.0f) * Rand.Range(0.8f, 1.2f);
|
underwaterExplosion.Size *= MathHelper.Clamp(Attack.Range / 300.0f, 0.5f, 2.0f) * Rand.Range(0.8f, 1.2f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,7 +77,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (flash)
|
if (flash)
|
||||||
{
|
{
|
||||||
float displayRange = flashRange.HasValue ? flashRange.Value : attack.Range;
|
float displayRange = flashRange.HasValue ? flashRange.Value : Attack.Range;
|
||||||
if (displayRange < 0.1f) { return; }
|
if (displayRange < 0.1f) { return; }
|
||||||
var light = new LightSource(worldPosition, displayRange, Color.LightYellow, null);
|
var light = new LightSource(worldPosition, displayRange, Color.LightYellow, null);
|
||||||
CoroutineManager.StartCoroutine(DimLight(light));
|
CoroutineManager.StartCoroutine(DimLight(light));
|
||||||
|
|||||||
@@ -90,7 +90,10 @@ namespace Barotrauma
|
|||||||
private 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 };
|
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);
|
GUIListBox listBox = new GUIListBox(new RectTransform(new Vector2(0.95f, 0.8f), editingHUD.RectTransform, Anchor.Center), style: null)
|
||||||
|
{
|
||||||
|
CanTakeKeyBoardFocus = false
|
||||||
|
};
|
||||||
new SerializableEntityEditor(listBox.Content.RectTransform, this, inGame, showName: true, titleFont: GUI.LargeFont);
|
new SerializableEntityEditor(listBox.Content.RectTransform, this, inGame, showName: true, titleFont: GUI.LargeFont);
|
||||||
|
|
||||||
PositionEditingHUD();
|
PositionEditingHUD();
|
||||||
|
|||||||
@@ -302,7 +302,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
GUI.DrawLine(spriteBatch, new Vector2(edge.Point1.X + cell.Translation.X, -(edge.Point1.Y + cell.Translation.Y)),
|
GUI.DrawLine(spriteBatch, new Vector2(edge.Point1.X + cell.Translation.X, -(edge.Point1.Y + cell.Translation.Y)),
|
||||||
new Vector2(edge.Point2.X + cell.Translation.X, -(edge.Point2.Y + cell.Translation.Y)), edge.NextToCave ? Color.Red : (cell.Body == null ? Color.Cyan * 0.5f : (edge.IsSolid ? Color.White : Color.Gray)),
|
new Vector2(edge.Point2.X + cell.Translation.X, -(edge.Point2.Y + cell.Translation.Y)), edge.NextToCave ? Color.Red : (cell.Body == null ? Color.Cyan * 0.5f : (edge.IsSolid ? Color.White : Color.Gray)),
|
||||||
width: edge.NextToCave ? 8 :1);
|
width: edge.NextToCave ? 8 : 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (Vector2 point in cell.BodyVertices)
|
foreach (Vector2 point in cell.BodyVertices)
|
||||||
@@ -322,6 +322,11 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
foreach (var abyssIsland in level.AbyssIslands)
|
||||||
|
{
|
||||||
|
GUI.DrawRectangle(spriteBatch, new Vector2(abyssIsland.Area.X, -abyssIsland.Area.Y - abyssIsland.Area.Height), abyssIsland.Area.Size.ToVector2(), Color.Cyan, thickness: 5);
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var ruin in level.Ruins)
|
foreach (var ruin in level.Ruins)
|
||||||
{
|
{
|
||||||
ruin.DebugDraw(spriteBatch);
|
ruin.DebugDraw(spriteBatch);
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ namespace Barotrauma.Lights
|
|||||||
private readonly List<LightSource> lights;
|
private readonly List<LightSource> lights;
|
||||||
|
|
||||||
public bool LosEnabled = true;
|
public bool LosEnabled = true;
|
||||||
|
public float LosAlpha = 1f;
|
||||||
public LosMode LosMode = LosMode.Transparent;
|
public LosMode LosMode = LosMode.Transparent;
|
||||||
|
|
||||||
public bool LightingEnabled = true;
|
public bool LightingEnabled = true;
|
||||||
@@ -497,7 +498,6 @@ namespace Barotrauma.Lights
|
|||||||
|
|
||||||
graphics.SetRenderTarget(LosTexture);
|
graphics.SetRenderTarget(LosTexture);
|
||||||
|
|
||||||
spriteBatch.Begin(SpriteSortMode.Deferred, transformMatrix: cam.Transform * Matrix.CreateScale(new Vector3(GameMain.Config.LightMapScale, GameMain.Config.LightMapScale, 1.0f)));
|
|
||||||
if (ObstructVision)
|
if (ObstructVision)
|
||||||
{
|
{
|
||||||
graphics.Clear(Color.Black);
|
graphics.Clear(Color.Black);
|
||||||
@@ -507,16 +507,17 @@ namespace Barotrauma.Lights
|
|||||||
float rotation = MathUtils.VectorToAngle(losOffset);
|
float rotation = MathUtils.VectorToAngle(losOffset);
|
||||||
|
|
||||||
Vector2 scale = new Vector2(
|
Vector2 scale = new Vector2(
|
||||||
MathHelper.Clamp(losOffset.Length() / 256.0f, 2.0f, 5.0f), 2.0f);
|
MathHelper.Clamp(losOffset.Length() / 256.0f, 4.0f, 5.0f), 3.0f);
|
||||||
|
|
||||||
|
spriteBatch.Begin(SpriteSortMode.Deferred, transformMatrix: cam.Transform * Matrix.CreateScale(new Vector3(GameMain.Config.LightMapScale, GameMain.Config.LightMapScale, 1.0f)));
|
||||||
spriteBatch.Draw(visionCircle, new Vector2(ViewTarget.WorldPosition.X, -ViewTarget.WorldPosition.Y), null, Color.White, rotation,
|
spriteBatch.Draw(visionCircle, new Vector2(ViewTarget.WorldPosition.X, -ViewTarget.WorldPosition.Y), null, Color.White, rotation,
|
||||||
new Vector2(visionCircle.Width * 0.2f, visionCircle.Height / 2), scale, SpriteEffects.None, 0.0f);
|
new Vector2(visionCircle.Width * 0.2f, visionCircle.Height / 2), scale, SpriteEffects.None, 0.0f);
|
||||||
|
spriteBatch.End();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
graphics.Clear(Color.White);
|
graphics.Clear(Color.White);
|
||||||
}
|
}
|
||||||
spriteBatch.End();
|
|
||||||
|
|
||||||
|
|
||||||
//--------------------------------------
|
//--------------------------------------
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Microsoft.Xna.Framework.Input;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
@@ -63,7 +63,19 @@ namespace Barotrauma
|
|||||||
private Sprite[,] mapTiles;
|
private Sprite[,] mapTiles;
|
||||||
private bool[,] tileDiscovered;
|
private bool[,] tileDiscovered;
|
||||||
|
|
||||||
private Pair<Rectangle, string> connectionTooltip;
|
private float connectionHighlightState;
|
||||||
|
|
||||||
|
private (Rectangle targetArea, string tip)? tooltip;
|
||||||
|
private string sanitizedTooltip;
|
||||||
|
private List<RichTextData> tooltipRichTextData;
|
||||||
|
private string prevTooltip;
|
||||||
|
|
||||||
|
private (SubmarineInfo pendingSub, float realWorldCrushDepth) pendingSubInfo;
|
||||||
|
|
||||||
|
/*private (Rectangle targetArea, string tip)? connectionTooltip;
|
||||||
|
private string sanitizedConnectionTooltip;
|
||||||
|
private List<RichTextData> connectionTooltipRichTextData;
|
||||||
|
private string prevConnectionTooltip;*/
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
private GUIComponent editor;
|
private GUIComponent editor;
|
||||||
@@ -93,13 +105,6 @@ namespace Barotrauma
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
public Location CurrentDisplayLocation
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return GameMain.GameSession.Campaign.CurrentDisplayLocation;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
partial void InitProjectSpecific()
|
partial void InitProjectSpecific()
|
||||||
{
|
{
|
||||||
@@ -120,7 +125,6 @@ namespace Barotrauma
|
|||||||
DrawOffset = -CurrentLocation.MapPosition;
|
DrawOffset = -CurrentLocation.MapPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Vector2 tileSize = generationParams.MapTiles.Values.First().First().size * generationParams.MapTileScale;
|
Vector2 tileSize = generationParams.MapTiles.Values.First().First().size * generationParams.MapTileScale;
|
||||||
int tilesX = (int)Math.Ceiling(Width / tileSize.X);
|
int tilesX = (int)Math.Ceiling(Width / tileSize.X);
|
||||||
int tilesY = (int)Math.Ceiling(Height / tileSize.Y);
|
int tilesY = (int)Math.Ceiling(Height / tileSize.Y);
|
||||||
@@ -227,8 +231,8 @@ namespace Barotrauma
|
|||||||
if (change.Messages.Any())
|
if (change.Messages.Any())
|
||||||
{
|
{
|
||||||
string msg = change.Messages[Rand.Range(0, change.Messages.Count)]
|
string msg = change.Messages[Rand.Range(0, change.Messages.Count)]
|
||||||
.Replace("[previousname]", prevName)
|
.Replace("[previousname]", $"‖color:gui.orange‖{prevName}‖end‖")
|
||||||
.Replace("[name]", location.Name);
|
.Replace("[name]", $"‖color:gui.orange‖{location.Name}‖end‖");
|
||||||
location.LastTypeChangeMessage = msg;
|
location.LastTypeChangeMessage = msg;
|
||||||
if (GameMain.Client != null)
|
if (GameMain.Client != null)
|
||||||
{
|
{
|
||||||
@@ -254,28 +258,52 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
Rectangle rect = mapContainer.Rect;
|
Rectangle rect = mapContainer.Rect;
|
||||||
|
|
||||||
if (CurrentDisplayLocation != null)
|
var currentDisplayLocation = GameMain.GameSession?.Campaign?.GetCurrentDisplayLocation();
|
||||||
|
|
||||||
|
if (currentDisplayLocation != null)
|
||||||
{
|
{
|
||||||
if (!CurrentDisplayLocation.Discovered)
|
if (!currentDisplayLocation.Discovered)
|
||||||
{
|
{
|
||||||
RemoveFogOfWar(CurrentDisplayLocation);
|
RemoveFogOfWar(currentDisplayLocation);
|
||||||
CurrentDisplayLocation.Discovered = true;
|
currentDisplayLocation.Discovered = true;
|
||||||
if (CurrentDisplayLocation.MapPosition.X > furthestDiscoveredLocation.MapPosition.X)
|
if (currentDisplayLocation.MapPosition.X > furthestDiscoveredLocation.MapPosition.X)
|
||||||
{
|
{
|
||||||
furthestDiscoveredLocation = CurrentDisplayLocation;
|
furthestDiscoveredLocation = currentDisplayLocation;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
currLocationIndicatorPos = Vector2.Lerp(currLocationIndicatorPos, CurrentDisplayLocation.MapPosition, deltaTime);
|
Vector2 currentPosition = currentDisplayLocation.MapPosition;
|
||||||
|
if (Level.Loaded?.Type == LevelData.LevelType.LocationConnection && Level.Loaded.StartLocation != null && Level.Loaded.EndLocation != null)
|
||||||
|
{
|
||||||
|
Vector2 startPos = currentDisplayLocation == Level.Loaded.StartLocation ? Level.Loaded.StartLocation.MapPosition : Level.Loaded.EndLocation.MapPosition;
|
||||||
|
int moveDir = currentDisplayLocation == Level.Loaded.StartLocation ? 1 : -1;
|
||||||
|
|
||||||
|
Vector2 diff = Level.Loaded.EndLocation.MapPosition - Level.Loaded.StartLocation.MapPosition;
|
||||||
|
currentPosition = startPos +
|
||||||
|
Vector2.Normalize(diff) * Math.Min(100, diff.Length() * 0.2f) * moveDir;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
currentPosition += Vector2.UnitY * 35;
|
||||||
|
}
|
||||||
|
|
||||||
|
currLocationIndicatorPos = Vector2.Lerp(currLocationIndicatorPos, currentPosition, deltaTime);
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
if (GameMain.DebugDraw)
|
if (GameMain.DebugDraw)
|
||||||
{
|
{
|
||||||
if (editor == null) CreateEditor();
|
if (editor == null) CreateEditor();
|
||||||
editor.AddToGUIUpdateList(order: 1);
|
editor.AddToGUIUpdateList(order: 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (PlayerInput.KeyHit(Keys.Space))
|
||||||
|
{
|
||||||
|
Radiation?.OnStep();
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Radiation?.MapUpdate(deltaTime);
|
||||||
|
|
||||||
if (mapAnimQueue.Count > 0)
|
if (mapAnimQueue.Count > 0)
|
||||||
{
|
{
|
||||||
hudVisibility = Math.Max(hudVisibility - deltaTime, 0.0f);
|
hudVisibility = Math.Max(hudVisibility - deltaTime, 0.0f);
|
||||||
@@ -299,15 +327,16 @@ namespace Barotrauma
|
|||||||
for (int i = 0; i < Locations.Count; i++)
|
for (int i = 0; i < Locations.Count; i++)
|
||||||
{
|
{
|
||||||
Location location = Locations[i];
|
Location location = Locations[i];
|
||||||
if (IsInFogOfWar(location) && !(CurrentDisplayLocation?.Connections.Any(c => c.Locations.Contains(location)) ?? false) && !GameMain.DebugDraw) { continue; }
|
if (IsInFogOfWar(location) && !(currentDisplayLocation?.Connections.Any(c => c.Locations.Contains(location)) ?? false) && !GameMain.DebugDraw) { continue; }
|
||||||
|
|
||||||
Vector2 pos = rectCenter + (location.MapPosition + viewOffset) * zoom;
|
Vector2 pos = rectCenter + (location.MapPosition + viewOffset) * zoom;
|
||||||
if (!rect.Contains(pos)) { continue; }
|
if (!rect.Contains(pos)) { continue; }
|
||||||
|
|
||||||
float iconScale = generationParams.LocationIconSize / location.Type.Sprite.size.X;
|
Sprite locationSprite = location.IsCriticallyRadiated() ? location.Type.RadiationSprite ?? location.Type.Sprite : location.Type.Sprite;
|
||||||
if (location == CurrentDisplayLocation) { iconScale *= 1.2f; }
|
float iconScale = generationParams.LocationIconSize / locationSprite.size.X;
|
||||||
|
if (location == currentDisplayLocation) { iconScale *= 1.2f; }
|
||||||
|
|
||||||
Rectangle drawRect = location.Type.Sprite.SourceRect;
|
Rectangle drawRect = locationSprite.SourceRect;
|
||||||
drawRect.Width = (int)(drawRect.Width * iconScale * zoom * 1.4f);
|
drawRect.Width = (int)(drawRect.Width * iconScale * zoom * 1.4f);
|
||||||
drawRect.Height = (int)(drawRect.Height * iconScale * zoom * 1.4f);
|
drawRect.Height = (int)(drawRect.Height * iconScale * zoom * 1.4f);
|
||||||
drawRect.X = (int)pos.X - drawRect.Width / 2;
|
drawRect.X = (int)pos.X - drawRect.Width / 2;
|
||||||
@@ -324,6 +353,15 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (SelectedConnection != null)
|
||||||
|
{
|
||||||
|
connectionHighlightState = Math.Min(connectionHighlightState + deltaTime, 1.0f);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
connectionHighlightState = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
if (GUI.KeyboardDispatcher.Subscriber == null)
|
if (GUI.KeyboardDispatcher.Subscriber == null)
|
||||||
{
|
{
|
||||||
float moveSpeed = 1000.0f;
|
float moveSpeed = 1000.0f;
|
||||||
@@ -336,21 +374,27 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
targetZoom = MathHelper.Clamp(targetZoom, generationParams.MinZoom, generationParams.MaxZoom);
|
targetZoom = MathHelper.Clamp(targetZoom, generationParams.MinZoom, generationParams.MaxZoom);
|
||||||
zoom = MathHelper.Lerp(zoom, targetZoom, 0.1f);
|
zoom = MathHelper.Lerp(zoom, targetZoom * GUI.Scale, 0.1f);
|
||||||
|
|
||||||
if (GUI.MouseOn == mapContainer)
|
if (GUI.MouseOn == mapContainer)
|
||||||
{
|
{
|
||||||
foreach (LocationConnection connection in Connections)
|
foreach (LocationConnection connection in Connections)
|
||||||
{
|
{
|
||||||
if (HighlightedLocation != CurrentDisplayLocation &&
|
if (HighlightedLocation != currentDisplayLocation &&
|
||||||
connection.Locations.Contains(HighlightedLocation) && connection.Locations.Contains(CurrentDisplayLocation))
|
connection.Locations.Contains(HighlightedLocation) &&
|
||||||
|
connection.Locations.Contains(currentDisplayLocation))
|
||||||
{
|
{
|
||||||
if (PlayerInput.PrimaryMouseButtonClicked() &&
|
if (PlayerInput.PrimaryMouseButtonClicked() &&
|
||||||
SelectedLocation != HighlightedLocation && HighlightedLocation != null)
|
SelectedLocation != HighlightedLocation && HighlightedLocation != null)
|
||||||
{
|
{
|
||||||
//clients aren't allowed to select the location without a permission
|
if (connection.Locked)
|
||||||
if ((GameMain.GameSession?.GameMode as CampaignMode)?.AllowedToManageCampaign() ?? false)
|
|
||||||
{
|
{
|
||||||
|
new GUIMessageBox(string.Empty, TextManager.Get("LockedPathTooltip"));
|
||||||
|
}
|
||||||
|
//clients aren't allowed to select the location without a permission
|
||||||
|
else if ((GameMain.GameSession?.GameMode as CampaignMode)?.AllowedToManageCampaign() ?? false)
|
||||||
|
{
|
||||||
|
connectionHighlightState = 0.0f;
|
||||||
SelectedConnection = connection;
|
SelectedConnection = connection;
|
||||||
SelectedLocation = HighlightedLocation;
|
SelectedLocation = HighlightedLocation;
|
||||||
|
|
||||||
@@ -371,13 +415,13 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (PlayerInput.DoubleClicked() && HighlightedLocation != null)
|
if (PlayerInput.DoubleClicked() && HighlightedLocation != null)
|
||||||
{
|
{
|
||||||
var passedConnection = CurrentDisplayLocation.Connections.Find(c => c.OtherLocation(CurrentDisplayLocation) == HighlightedLocation);
|
var passedConnection = currentDisplayLocation.Connections.Find(c => c.OtherLocation(currentDisplayLocation) == HighlightedLocation);
|
||||||
if (passedConnection != null)
|
if (passedConnection != null)
|
||||||
{
|
{
|
||||||
passedConnection.Passed = true;
|
passedConnection.Passed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Location prevLocation = CurrentDisplayLocation;
|
Location prevLocation = currentDisplayLocation;
|
||||||
CurrentLocation = HighlightedLocation;
|
CurrentLocation = HighlightedLocation;
|
||||||
Level.Loaded.DebugSetStartLocation(CurrentLocation);
|
Level.Loaded.DebugSetStartLocation(CurrentLocation);
|
||||||
Level.Loaded.DebugSetEndLocation(null);
|
Level.Loaded.DebugSetEndLocation(null);
|
||||||
@@ -389,6 +433,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
CurrentLocation.CreateStore();
|
CurrentLocation.CreateStore();
|
||||||
ProgressWorld();
|
ProgressWorld();
|
||||||
|
Radiation?.OnStep(1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -412,12 +457,13 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public void Draw(SpriteBatch spriteBatch, GUICustomComponent mapContainer)
|
public void Draw(SpriteBatch spriteBatch, GUICustomComponent mapContainer)
|
||||||
{
|
{
|
||||||
connectionTooltip = null;
|
tooltip = null;
|
||||||
|
var currentDisplayLocation = GameMain.GameSession?.Campaign?.GetCurrentDisplayLocation();
|
||||||
|
|
||||||
Rectangle rect = mapContainer.Rect;
|
Rectangle rect = mapContainer.Rect;
|
||||||
|
|
||||||
Vector2 viewSize = new Vector2(rect.Width / zoom, rect.Height / zoom);
|
Vector2 viewSize = new Vector2(rect.Width / zoom, rect.Height / zoom);
|
||||||
Vector2 edgeBuffer = rect.Size.ToVector2() / 2;
|
Vector2 edgeBuffer = new Vector2(rect.Width * 0.05f);
|
||||||
DrawOffset.X = MathHelper.Clamp(DrawOffset.X, -Width - edgeBuffer.X + viewSize.X / 2.0f, edgeBuffer.X - viewSize.X / 2.0f);
|
DrawOffset.X = MathHelper.Clamp(DrawOffset.X, -Width - edgeBuffer.X + viewSize.X / 2.0f, edgeBuffer.X - viewSize.X / 2.0f);
|
||||||
DrawOffset.Y = MathHelper.Clamp(DrawOffset.Y, -Height - edgeBuffer.Y + viewSize.Y / 2.0f, edgeBuffer.Y - viewSize.Y / 2.0f);
|
DrawOffset.Y = MathHelper.Clamp(DrawOffset.Y, -Height - edgeBuffer.Y + viewSize.Y / 2.0f, edgeBuffer.Y - viewSize.Y / 2.0f);
|
||||||
|
|
||||||
@@ -481,30 +527,16 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
float rawNoiseScale = 1.0f + PerlinNoise.GetPerlin((int)(Timing.TotalTime * 1 - 1), (int)(Timing.TotalTime * 1 - 1));
|
float rawNoiseScale = 1.0f + PerlinNoise.GetPerlin((int)(Timing.TotalTime * 1 - 1), (int)(Timing.TotalTime * 1 - 1));
|
||||||
cameraNoiseStrength = PerlinNoise.GetPerlin((int)(Timing.TotalTime * 1 - 1), (int)(Timing.TotalTime * 1 - 1));
|
DrawNoise(spriteBatch, rect, rawNoiseScale);
|
||||||
|
|
||||||
noiseOverlay.DrawTiled(spriteBatch, rect.Location.ToVector2(), rect.Size.ToVector2(),
|
Radiation?.Draw(spriteBatch, rect, zoom);
|
||||||
startOffset: new Vector2(Rand.Range(0.0f, noiseOverlay.SourceRect.Width), Rand.Range(0.0f, noiseOverlay.SourceRect.Height)),
|
|
||||||
color : Color.White * cameraNoiseStrength * 0.1f,
|
|
||||||
textureScale: Vector2.One * rawNoiseScale);
|
|
||||||
|
|
||||||
noiseOverlay.DrawTiled(spriteBatch, rect.Location.ToVector2(), rect.Size.ToVector2(),
|
|
||||||
startOffset: new Vector2(Rand.Range(0.0f, noiseOverlay.SourceRect.Width), Rand.Range(0.0f, noiseOverlay.SourceRect.Height)),
|
|
||||||
color: new Color(20,20,20,50),
|
|
||||||
textureScale: Vector2.One * rawNoiseScale * 2);
|
|
||||||
|
|
||||||
noiseOverlay.DrawTiled(spriteBatch, Vector2.Zero, new Vector2(GameMain.GraphicsWidth, GameMain.GraphicsHeight),
|
|
||||||
startOffset: new Vector2(Rand.Range(0.0f, noiseOverlay.SourceRect.Width), Rand.Range(0.0f, noiseOverlay.SourceRect.Height)),
|
|
||||||
color: Color.White * cameraNoiseStrength * 0.1f,
|
|
||||||
textureScale: Vector2.One * noiseScale);
|
|
||||||
|
|
||||||
Pair<Rectangle, string> tooltip = null;
|
|
||||||
if (generationParams.ShowLocations)
|
if (generationParams.ShowLocations)
|
||||||
{
|
{
|
||||||
foreach (LocationConnection connection in Connections)
|
foreach (LocationConnection connection in Connections)
|
||||||
{
|
{
|
||||||
if (IsInFogOfWar(connection.Locations[0]) && IsInFogOfWar(connection.Locations[1])) { continue; }
|
if (IsInFogOfWar(connection.Locations[0]) && IsInFogOfWar(connection.Locations[1])) { continue; }
|
||||||
DrawConnection(spriteBatch, connection, rect, viewOffset);
|
DrawConnection(spriteBatch, connection, rect, viewOffset, currentDisplayLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < Locations.Count; i++)
|
for (int i = 0; i < Locations.Count; i++)
|
||||||
@@ -512,19 +544,48 @@ namespace Barotrauma
|
|||||||
Location location = Locations[i];
|
Location location = Locations[i];
|
||||||
if (IsInFogOfWar(location)) { continue; }
|
if (IsInFogOfWar(location)) { continue; }
|
||||||
Vector2 pos = rectCenter + (location.MapPosition + viewOffset) * zoom;
|
Vector2 pos = rectCenter + (location.MapPosition + viewOffset) * zoom;
|
||||||
|
|
||||||
Rectangle drawRect = location.Type.Sprite.SourceRect;
|
Sprite locationSprite = location.IsCriticallyRadiated() ? location.Type.RadiationSprite ?? location.Type.Sprite : location.Type.Sprite;
|
||||||
|
|
||||||
|
Rectangle drawRect = locationSprite.SourceRect;
|
||||||
drawRect.X = (int)pos.X - drawRect.Width / 2;
|
drawRect.X = (int)pos.X - drawRect.Width / 2;
|
||||||
drawRect.Y = (int)pos.Y - drawRect.Width / 2;
|
drawRect.Y = (int)pos.Y - drawRect.Width / 2;
|
||||||
|
|
||||||
if (!rect.Intersects(drawRect)) { continue; }
|
if (!rect.Intersects(drawRect)) { continue; }
|
||||||
|
|
||||||
if (location == CurrentDisplayLocation )
|
Color color = location.Type.SpriteColor;
|
||||||
|
if (!location.Discovered) { color = Color.White; }
|
||||||
|
if (location.Connections.Find(c => c.Locations.Contains(currentDisplayLocation)) == null)
|
||||||
{
|
{
|
||||||
|
color *= 0.5f;
|
||||||
|
}
|
||||||
|
|
||||||
|
float iconScale = location == currentDisplayLocation ? 1.2f : 1.0f;
|
||||||
|
if (location == HighlightedLocation)
|
||||||
|
{
|
||||||
|
iconScale *= 1.2f;
|
||||||
|
}
|
||||||
|
|
||||||
|
locationSprite.Draw(spriteBatch, pos, color,
|
||||||
|
scale: generationParams.LocationIconSize / locationSprite.size.X * iconScale * zoom);
|
||||||
|
|
||||||
|
if (location == currentDisplayLocation)
|
||||||
|
{
|
||||||
|
if (SelectedLocation != null)
|
||||||
|
{
|
||||||
|
Vector2 dir = Vector2.Normalize(SelectedLocation.MapPosition - currLocationIndicatorPos);
|
||||||
|
GUI.Arrow.Draw(spriteBatch,
|
||||||
|
rectCenter + (currLocationIndicatorPos + viewOffset) * zoom + dir * generationParams.LocationIconSize * 0.6f * zoom,
|
||||||
|
generationParams.IndicatorColor,
|
||||||
|
GUI.Arrow.Origin,
|
||||||
|
rotate: MathUtils.VectorToAngle(dir) + MathHelper.PiOver2,
|
||||||
|
new Vector2(0.5f, 1.0f) * zoom);
|
||||||
|
}
|
||||||
generationParams.CurrentLocationIndicator.Draw(spriteBatch,
|
generationParams.CurrentLocationIndicator.Draw(spriteBatch,
|
||||||
rectCenter + (currLocationIndicatorPos + viewOffset) * zoom,
|
rectCenter + (currLocationIndicatorPos + viewOffset) * zoom,
|
||||||
generationParams.IndicatorColor,
|
generationParams.IndicatorColor,
|
||||||
generationParams.CurrentLocationIndicator.Origin, 0, Vector2.One * (generationParams.LocationIconSize / generationParams.CurrentLocationIndicator.size.X) * 1.7f * zoom);
|
generationParams.CurrentLocationIndicator.Origin, 0, Vector2.One * (generationParams.LocationIconSize / generationParams.CurrentLocationIndicator.size.X) * 0.8f * zoom);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (location == SelectedLocation)
|
if (location == SelectedLocation)
|
||||||
@@ -535,31 +596,15 @@ namespace Barotrauma
|
|||||||
generationParams.SelectedLocationIndicator.Origin, 0, Vector2.One * (generationParams.LocationIconSize / generationParams.SelectedLocationIndicator.size.X) * 1.7f * zoom);
|
generationParams.SelectedLocationIndicator.Origin, 0, Vector2.One * (generationParams.LocationIconSize / generationParams.SelectedLocationIndicator.size.X) * 1.7f * zoom);
|
||||||
}
|
}
|
||||||
|
|
||||||
Color color = location.Type.SpriteColor;
|
|
||||||
if (!location.Discovered) { color = Color.White; }
|
|
||||||
if (location.Connections.Find(c => c.Locations.Contains(CurrentDisplayLocation)) == null)
|
|
||||||
{
|
|
||||||
color *= 0.5f;
|
|
||||||
}
|
|
||||||
|
|
||||||
float iconScale = location == CurrentDisplayLocation ? 1.2f : 1.0f;
|
|
||||||
if (location == HighlightedLocation)
|
|
||||||
{
|
|
||||||
iconScale *= 1.2f;
|
|
||||||
}
|
|
||||||
|
|
||||||
location.Type.Sprite.Draw(spriteBatch, pos, color,
|
|
||||||
scale: generationParams.LocationIconSize / location.Type.Sprite.size.X * iconScale * zoom);
|
|
||||||
if (location.TimeSinceLastTypeChange < 1 && !string.IsNullOrEmpty(location.LastTypeChangeMessage) && generationParams.TypeChangeIcon != null)
|
if (location.TimeSinceLastTypeChange < 1 && !string.IsNullOrEmpty(location.LastTypeChangeMessage) && generationParams.TypeChangeIcon != null)
|
||||||
{
|
{
|
||||||
Vector2 typeChangeIconPos = pos + new Vector2(1.35f, -0.35f) * generationParams.LocationIconSize * 0.5f * zoom;
|
Vector2 typeChangeIconPos = pos + new Vector2(1.35f, -0.35f) * generationParams.LocationIconSize * 0.5f * zoom;
|
||||||
float typeChangeIconScale = 18.0f / generationParams.TypeChangeIcon.SourceRect.Width;
|
float typeChangeIconScale = 18.0f / generationParams.TypeChangeIcon.SourceRect.Width;
|
||||||
generationParams.TypeChangeIcon.Draw(spriteBatch, typeChangeIconPos, GUI.Style.Red, scale: typeChangeIconScale * zoom);
|
generationParams.TypeChangeIcon.Draw(spriteBatch, typeChangeIconPos, GUI.Style.Red, scale: typeChangeIconScale * zoom);
|
||||||
if (Vector2.Distance(PlayerInput.MousePosition, typeChangeIconPos) < generationParams.TypeChangeIcon.SourceRect.Width * zoom)
|
if (Vector2.Distance(PlayerInput.MousePosition, typeChangeIconPos) < generationParams.TypeChangeIcon.SourceRect.Width * zoom &&
|
||||||
|
(tooltip == null || IsPreferredTooltip(typeChangeIconPos)))
|
||||||
{
|
{
|
||||||
tooltip = new Pair<Rectangle, string>(
|
tooltip = (new Rectangle(typeChangeIconPos.ToPoint(), new Point(30)), location.LastTypeChangeMessage);
|
||||||
new Rectangle(typeChangeIconPos.ToPoint(), new Point(30)),
|
|
||||||
location.LastTypeChangeMessage);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (location != CurrentLocation && CurrentLocation.AvailableMissions.Any(m => m.Locations.Contains(location)) && generationParams.MissionIcon != null)
|
if (location != CurrentLocation && CurrentLocation.AvailableMissions.Any(m => m.Locations.Contains(location)) && generationParams.MissionIcon != null)
|
||||||
@@ -567,16 +612,14 @@ namespace Barotrauma
|
|||||||
Vector2 missionIconPos = pos + new Vector2(1.35f, 0.35f) * generationParams.LocationIconSize * 0.5f * zoom;
|
Vector2 missionIconPos = pos + new Vector2(1.35f, 0.35f) * generationParams.LocationIconSize * 0.5f * zoom;
|
||||||
float missionIconScale = 18.0f / generationParams.MissionIcon.SourceRect.Width;
|
float missionIconScale = 18.0f / generationParams.MissionIcon.SourceRect.Width;
|
||||||
generationParams.MissionIcon.Draw(spriteBatch, missionIconPos, generationParams.IndicatorColor, scale: missionIconScale * zoom);
|
generationParams.MissionIcon.Draw(spriteBatch, missionIconPos, generationParams.IndicatorColor, scale: missionIconScale * zoom);
|
||||||
if (Vector2.Distance(PlayerInput.MousePosition, missionIconPos) < generationParams.MissionIcon.SourceRect.Width * zoom)
|
if (Vector2.Distance(PlayerInput.MousePosition, missionIconPos) < generationParams.MissionIcon.SourceRect.Width * zoom && IsPreferredTooltip(missionIconPos))
|
||||||
{
|
{
|
||||||
var availableMissions = CurrentLocation.AvailableMissions.Where(m => m.Locations.Contains(location));
|
var availableMissions = CurrentLocation.AvailableMissions.Where(m => m.Locations.Contains(location));
|
||||||
tooltip = new Pair<Rectangle, string>(
|
tooltip = (new Rectangle(missionIconPos.ToPoint(), new Point(30)), TextManager.Get("mission") + '\n'+ string.Join('\n', availableMissions.Select(m => "- " + m.Name)));
|
||||||
new Rectangle(missionIconPos.ToPoint(), new Point(30)),
|
|
||||||
TextManager.Get("mission") + '\n'+ string.Join('\n', availableMissions.Select(m => "- " + m.Name)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GameMain.DebugDraw && location == HighlightedLocation && (!location.Discovered || !location.Type.HasOutpost))
|
if (GameMain.DebugDraw && location == HighlightedLocation && (!location.Discovered || !location.HasOutpost()))
|
||||||
{
|
{
|
||||||
if (location.Reputation != null)
|
if (location.Reputation != null)
|
||||||
{
|
{
|
||||||
@@ -603,12 +646,27 @@ namespace Barotrauma
|
|||||||
|
|
||||||
DrawDecorativeHUD(spriteBatch, rect);
|
DrawDecorativeHUD(spriteBatch, rect);
|
||||||
|
|
||||||
if (HighlightedLocation != null)
|
bool drawRadiationTooltip = true;
|
||||||
|
|
||||||
|
if (tooltip != null)
|
||||||
{
|
{
|
||||||
|
if (tooltip.Value.tip != prevTooltip)
|
||||||
|
{
|
||||||
|
prevTooltip = tooltip.Value.tip;
|
||||||
|
tooltipRichTextData = RichTextData.GetRichTextData(tooltip.Value.tip, out sanitizedTooltip);
|
||||||
|
}
|
||||||
|
GUIComponent.DrawToolTip(spriteBatch, sanitizedTooltip, tooltip.Value.targetArea, tooltipRichTextData);
|
||||||
|
drawRadiationTooltip = false;
|
||||||
|
}
|
||||||
|
else if (HighlightedLocation != null)
|
||||||
|
{
|
||||||
|
drawRadiationTooltip = false;
|
||||||
Vector2 pos = rectCenter + (HighlightedLocation.MapPosition + viewOffset) * zoom;
|
Vector2 pos = rectCenter + (HighlightedLocation.MapPosition + viewOffset) * zoom;
|
||||||
pos.X += 50 * zoom;
|
pos.X += 50 * zoom;
|
||||||
|
pos.X = (int)pos.X;
|
||||||
|
pos.Y = (int)pos.Y;
|
||||||
Vector2 nameSize = GUI.LargeFont.MeasureString(HighlightedLocation.Name);
|
Vector2 nameSize = GUI.LargeFont.MeasureString(HighlightedLocation.Name);
|
||||||
Vector2 typeSize = GUI.Font.MeasureString(HighlightedLocation.Type.Name);
|
Vector2 typeSize = string.IsNullOrEmpty(HighlightedLocation.Type.Name) ? Vector2.Zero : GUI.Font.MeasureString(HighlightedLocation.Type.Name);
|
||||||
Vector2 size = new Vector2(Math.Max(nameSize.X, typeSize.X), nameSize.Y + typeSize.Y);
|
Vector2 size = new Vector2(Math.Max(nameSize.X, typeSize.X), nameSize.Y + typeSize.Y);
|
||||||
bool showReputation = hudVisibility > 0.0f && HighlightedLocation.Discovered && HighlightedLocation.Type.HasOutpost && HighlightedLocation.Reputation != null;
|
bool showReputation = hudVisibility > 0.0f && HighlightedLocation.Discovered && HighlightedLocation.Type.HasOutpost && HighlightedLocation.Reputation != null;
|
||||||
string repLabelText = null, repValueText = null;
|
string repLabelText = null, repValueText = null;
|
||||||
@@ -616,15 +674,14 @@ namespace Barotrauma
|
|||||||
if (showReputation)
|
if (showReputation)
|
||||||
{
|
{
|
||||||
repLabelText = TextManager.Get("reputation");
|
repLabelText = TextManager.Get("reputation");
|
||||||
repLabelSize = GUI.Font.MeasureString(repLabelText);
|
repLabelSize = GUI.Font.MeasureString(repLabelText);
|
||||||
size.X = Math.Max(size.X, repLabelSize.X);
|
repBarSize = new Vector2(GUI.IntScale(200), repLabelSize.Y);
|
||||||
repBarSize = new Vector2(Math.Max(0.75f * size.X, 100), repLabelSize.Y);
|
size.Y += 2 * repLabelSize.Y + GUI.IntScale(5) + repBarSize.Y;
|
||||||
size.X = Math.Max(size.X, (4.0f / 3.0f) * repBarSize.X);
|
repValueText = HighlightedLocation.Reputation.GetFormattedReputationText(addColorTags: false);
|
||||||
size.Y += 2 * repLabelSize.Y + 4 + repBarSize.Y;
|
size.X = Math.Max(size.X, repBarSize.X + GUI.Font.MeasureString(repValueText).X + GUI.IntScale(10));
|
||||||
repValueText = ((int)HighlightedLocation.Reputation.Value).ToString();
|
|
||||||
}
|
}
|
||||||
GUI.Style.GetComponentStyle("OuterGlow").Sprites[GUIComponent.ComponentState.None][0].Draw(
|
GUI.Style.GetComponentStyle("OuterGlow").Sprites[GUIComponent.ComponentState.None][0].Draw(
|
||||||
spriteBatch, new Rectangle((int)(pos.X - 60 * GUI.Scale), (int)(pos.Y - size.Y), (int)(size.X + 120 * GUI.Scale), (int)(size.Y * 2.2f)), Color.Black * hudVisibility);
|
spriteBatch, new Rectangle((int)(pos.X - 60 * GUI.Scale), (int)(pos.Y - size.Y), (int)(size.X + 120 * GUI.Scale), (int)(size.Y * 2.2f)), Color.Black * hudVisibility);
|
||||||
var topLeftPos = pos - new Vector2(0.0f, size.Y / 2);
|
var topLeftPos = pos - new Vector2(0.0f, size.Y / 2);
|
||||||
GUI.DrawString(spriteBatch, topLeftPos, HighlightedLocation.Name, GUI.Style.TextColor * hudVisibility * 1.5f, font: GUI.LargeFont);
|
GUI.DrawString(spriteBatch, topLeftPos, HighlightedLocation.Name, GUI.Style.TextColor * hudVisibility * 1.5f, font: GUI.LargeFont);
|
||||||
topLeftPos += new Vector2(0.0f, nameSize.Y);
|
topLeftPos += new Vector2(0.0f, nameSize.Y);
|
||||||
@@ -633,26 +690,51 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
topLeftPos += new Vector2(0.0f, typeSize.Y + repLabelSize.Y);
|
topLeftPos += new Vector2(0.0f, typeSize.Y + repLabelSize.Y);
|
||||||
GUI.DrawString(spriteBatch, topLeftPos, repLabelText, GUI.Style.TextColor * hudVisibility * 1.5f);
|
GUI.DrawString(spriteBatch, topLeftPos, repLabelText, GUI.Style.TextColor * hudVisibility * 1.5f);
|
||||||
topLeftPos += new Vector2(0.0f, repLabelSize.Y + 4);
|
topLeftPos += new Vector2(0.0f, repLabelSize.Y + GUI.IntScale(10));
|
||||||
Rectangle repBarRect = new Rectangle(new Point((int)topLeftPos.X, (int)topLeftPos.Y), new Point((int)repBarSize.X, (int)repBarSize.Y));
|
Rectangle repBarRect = new Rectangle(new Point((int)topLeftPos.X, (int)topLeftPos.Y), new Point((int)repBarSize.X, (int)repBarSize.Y));
|
||||||
RoundSummary.DrawReputationBar(spriteBatch, repBarRect, HighlightedLocation.Reputation.NormalizedValue);
|
RoundSummary.DrawReputationBar(spriteBatch, repBarRect, HighlightedLocation.Reputation.NormalizedValue);
|
||||||
GUI.DrawString(spriteBatch, new Vector2(repBarRect.Right + 4, repBarRect.Top), repValueText, GUI.Style.TextColor);
|
GUI.DrawString(spriteBatch, new Vector2(repBarRect.Right + GUI.IntScale(5), repBarRect.Top), repValueText, Reputation.GetReputationColor(HighlightedLocation.Reputation.NormalizedValue));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (tooltip != null)
|
|
||||||
|
if (drawRadiationTooltip)
|
||||||
{
|
{
|
||||||
GUIComponent.DrawToolTip(spriteBatch, tooltip.Second, tooltip.First);
|
Radiation?.DrawFront(spriteBatch);
|
||||||
}
|
|
||||||
if (connectionTooltip != null)
|
|
||||||
{
|
|
||||||
GUIComponent.DrawToolTip(spriteBatch, connectionTooltip.Second, connectionTooltip.First);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
spriteBatch.End();
|
spriteBatch.End();
|
||||||
GameMain.Instance.GraphicsDevice.ScissorRectangle = prevScissorRect;
|
GameMain.Instance.GraphicsDevice.ScissorRectangle = prevScissorRect;
|
||||||
spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: GUI.SamplerState, rasterizerState: GameMain.ScissorTestEnable);
|
spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: GUI.SamplerState, rasterizerState: GameMain.ScissorTestEnable);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawConnection(SpriteBatch spriteBatch, LocationConnection connection, Rectangle viewArea, Vector2 viewOffset, Color? overrideColor = null)
|
public static void DrawNoise(SpriteBatch spriteBatch, Rectangle rect, float strength)
|
||||||
|
{
|
||||||
|
noiseOverlay ??= new Sprite("Content/UI/noise.png", Vector2.Zero);
|
||||||
|
|
||||||
|
float noiseT = (float)(Timing.TotalTime * 0.01f);
|
||||||
|
float noiseScale = (float)PerlinNoise.CalculatePerlin(noiseT * 5.0f, noiseT * 2.0f, 0) * 5.0f;
|
||||||
|
|
||||||
|
float rawNoiseScale = 1.0f + GetPerlinNoise();
|
||||||
|
|
||||||
|
noiseOverlay.DrawTiled(spriteBatch, rect.Location.ToVector2(), rect.Size.ToVector2(),
|
||||||
|
startOffset: new Vector2(Rand.Range(0.0f, noiseOverlay.SourceRect.Width), Rand.Range(0.0f, noiseOverlay.SourceRect.Height)),
|
||||||
|
color : Color.White * strength * 0.1f,
|
||||||
|
textureScale: Vector2.One * rawNoiseScale);
|
||||||
|
|
||||||
|
noiseOverlay.DrawTiled(spriteBatch, rect.Location.ToVector2(), rect.Size.ToVector2(),
|
||||||
|
startOffset: new Vector2(Rand.Range(0.0f, noiseOverlay.SourceRect.Width), Rand.Range(0.0f, noiseOverlay.SourceRect.Height)),
|
||||||
|
color: new Color(20,20,20,50),
|
||||||
|
textureScale: Vector2.One * rawNoiseScale * 2);
|
||||||
|
|
||||||
|
noiseOverlay.DrawTiled(spriteBatch, Vector2.Zero, new Vector2(GameMain.GraphicsWidth, GameMain.GraphicsHeight),
|
||||||
|
startOffset: new Vector2(Rand.Range(0.0f, noiseOverlay.SourceRect.Width), Rand.Range(0.0f, noiseOverlay.SourceRect.Height)),
|
||||||
|
color: Color.White * strength * 0.1f,
|
||||||
|
textureScale: Vector2.One * noiseScale);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static float GetPerlinNoise() => PerlinNoise.GetPerlin((int)(Timing.TotalTime * 1 - 1), (int)(Timing.TotalTime * 1 - 1));
|
||||||
|
|
||||||
|
private void DrawConnection(SpriteBatch spriteBatch, LocationConnection connection, Rectangle viewArea, Vector2 viewOffset, Location currentDisplayLocation, Color? overrideColor = null)
|
||||||
{
|
{
|
||||||
Color connectionColor;
|
Color connectionColor;
|
||||||
if (GameMain.DebugDraw)
|
if (GameMain.DebugDraw)
|
||||||
@@ -674,19 +756,22 @@ namespace Barotrauma
|
|||||||
|
|
||||||
int width = (int)(generationParams.LocationConnectionWidth * zoom);
|
int width = (int)(generationParams.LocationConnectionWidth * zoom);
|
||||||
|
|
||||||
|
//current level
|
||||||
if (Level.Loaded?.LevelData == connection.LevelData)
|
if (Level.Loaded?.LevelData == connection.LevelData)
|
||||||
{
|
{
|
||||||
connectionColor = generationParams.HighlightedConnectionColor;
|
connectionColor = generationParams.HighlightedConnectionColor;
|
||||||
width = (int)(width * 1.5f);
|
width = (int)(width * 1.5f);
|
||||||
}
|
}
|
||||||
if (SelectedLocation != CurrentDisplayLocation &&
|
//selected connection
|
||||||
(connection.Locations.Contains(SelectedLocation) && connection.Locations.Contains(CurrentDisplayLocation)))
|
if (SelectedLocation != currentDisplayLocation &&
|
||||||
|
connection.Locations.Contains(SelectedLocation) && connection.Locations.Contains(currentDisplayLocation))
|
||||||
{
|
{
|
||||||
connectionColor = generationParams.HighlightedConnectionColor;
|
connectionColor = generationParams.HighlightedConnectionColor;
|
||||||
width *= 2;
|
width *= 2;
|
||||||
}
|
}
|
||||||
else if (HighlightedLocation != CurrentDisplayLocation &&
|
//highlighted connection
|
||||||
(connection.Locations.Contains(HighlightedLocation) && connection.Locations.Contains(CurrentDisplayLocation)))
|
else if (HighlightedLocation != currentDisplayLocation &&
|
||||||
|
connection.Locations.Contains(HighlightedLocation) && connection.Locations.Contains(currentDisplayLocation))
|
||||||
{
|
{
|
||||||
connectionColor = generationParams.HighlightedConnectionColor;
|
connectionColor = generationParams.HighlightedConnectionColor;
|
||||||
width *= 2;
|
width *= 2;
|
||||||
@@ -741,16 +826,52 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
float dist = Vector2.Distance(start, end);
|
float dist = Vector2.Distance(start, end);
|
||||||
var connectionSprite = connection.Passed ? generationParams.PassedConnectionSprite : generationParams.ConnectionSprite;
|
var connectionSprite = connection.Passed ? generationParams.PassedConnectionSprite : generationParams.ConnectionSprite;
|
||||||
|
|
||||||
|
Color segmentColor = connectionColor;
|
||||||
|
int segmentWidth = width;
|
||||||
|
if (connection == SelectedConnection)
|
||||||
|
{
|
||||||
|
float t = (i - startIndex) / (float)(endIndex - startIndex - 1);
|
||||||
|
if (currentDisplayLocation == connection.Locations[1]) { t = 1.0f - t; }
|
||||||
|
if (t > connectionHighlightState)
|
||||||
|
{
|
||||||
|
segmentWidth /= 2;
|
||||||
|
segmentColor = connection.Passed ? generationParams.ConnectionColor : generationParams.UnvisitedConnectionColor;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
spriteBatch.Draw(connectionSprite.Texture,
|
spriteBatch.Draw(connectionSprite.Texture,
|
||||||
new Rectangle((int)start.X, (int)start.Y, (int)(dist - 1 * zoom), width),
|
new Rectangle((int)start.X, (int)start.Y, (int)(dist - 1 * zoom), segmentWidth),
|
||||||
connectionSprite.SourceRect, connectionColor * a, MathUtils.VectorToAngle(end - start),
|
connectionSprite.SourceRect, segmentColor * a,
|
||||||
|
MathUtils.VectorToAngle(end - start),
|
||||||
new Vector2(0, connectionSprite.size.Y / 2), SpriteEffects.None, 0.01f);
|
new Vector2(0, connectionSprite.size.Y / 2), SpriteEffects.None, 0.01f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int iconCount = 0, iconIndex = 0;
|
||||||
if (connectionStart.HasValue && connectionEnd.HasValue)
|
if (connectionStart.HasValue && connectionEnd.HasValue)
|
||||||
{
|
{
|
||||||
GUIComponentStyle crushDepthWarningIconStyle = null;
|
if (connection.LevelData.HasBeaconStation) { iconCount++; }
|
||||||
|
if (connection.LevelData.HasHuntingGrounds) { iconCount++; }
|
||||||
|
if (connection.Locked) { iconCount++; }
|
||||||
string tooltip = null;
|
string tooltip = null;
|
||||||
var subCrushDepth = Submarine.MainSub?.RealWorldCrushDepth ?? Level.DefaultRealWorldCrushDepth;
|
float subCrushDepth = Level.DefaultRealWorldCrushDepth;
|
||||||
|
var currentOrPendingSub = SubmarineSelection.CurrentOrPendingSubmarine();
|
||||||
|
if (Submarine.MainSub != null && Submarine.MainSub.Info == currentOrPendingSub)
|
||||||
|
{
|
||||||
|
subCrushDepth = Submarine.MainSub.RealWorldCrushDepth;
|
||||||
|
}
|
||||||
|
else if (currentOrPendingSub != null)
|
||||||
|
{
|
||||||
|
if (pendingSubInfo.pendingSub != currentOrPendingSub)
|
||||||
|
{
|
||||||
|
// Store the real world crush depth for the pending sub so that we don't have to calculate it again every time
|
||||||
|
pendingSubInfo = (currentOrPendingSub, currentOrPendingSub.GetRealWorldCrushDepth());
|
||||||
|
}
|
||||||
|
subCrushDepth = pendingSubInfo.realWorldCrushDepth;
|
||||||
|
}
|
||||||
if (GameMain.GameSession?.Campaign?.UpgradeManager != null)
|
if (GameMain.GameSession?.Campaign?.UpgradeManager != null)
|
||||||
{
|
{
|
||||||
var hullUpgradePrefab = UpgradePrefab.Find("increasewallhealth");
|
var hullUpgradePrefab = UpgradePrefab.Find("increasewallhealth");
|
||||||
@@ -769,38 +890,71 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string crushDepthWarningIconStyle = null;
|
||||||
if (connection.LevelData.InitialDepth * Physics.DisplayToRealWorldRatio > subCrushDepth)
|
if (connection.LevelData.InitialDepth * Physics.DisplayToRealWorldRatio > subCrushDepth)
|
||||||
{
|
{
|
||||||
crushDepthWarningIconStyle = GUI.Style.GetComponentStyle("CrushDepthWarningHighIcon");
|
iconCount++;
|
||||||
|
crushDepthWarningIconStyle = "CrushDepthWarningHighIcon";
|
||||||
tooltip = "crushdepthwarninghigh";
|
tooltip = "crushdepthwarninghigh";
|
||||||
}
|
}
|
||||||
else if ((connection.LevelData.InitialDepth + connection.LevelData.Size.Y) * Physics.DisplayToRealWorldRatio > subCrushDepth)
|
else if ((connection.LevelData.InitialDepth + connection.LevelData.Size.Y) * Physics.DisplayToRealWorldRatio > subCrushDepth)
|
||||||
{
|
{
|
||||||
crushDepthWarningIconStyle = GUI.Style.GetComponentStyle("CrushDepthWarningLowIcon");
|
iconCount++;
|
||||||
|
crushDepthWarningIconStyle = "CrushDepthWarningLowIcon";
|
||||||
tooltip = "crushdepthwarninglow";
|
tooltip = "crushdepthwarninglow";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (connection.LevelData.HasBeaconStation)
|
||||||
|
{
|
||||||
|
var beaconStationIconStyle = connection.LevelData.IsBeaconActive ? "BeaconStationActive" : "BeaconStationInactive";
|
||||||
|
DrawIcon(beaconStationIconStyle, (int)(28 * zoom), TextManager.Get(connection.LevelData.IsBeaconActive ? "BeaconStationActiveTooltip" : "BeaconStationInactiveTooltip"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (connection.Locked)
|
||||||
|
{
|
||||||
|
var gateLocation = connection.Locations[0].IsGateBetweenBiomes ? connection.Locations[0] : connection.Locations[1];
|
||||||
|
var unlockEvent =
|
||||||
|
EventSet.PrefabList.Find(ep => ep.UnlockPathEvent && ep.BiomeIdentifier == gateLocation.LevelData.Biome.Identifier) ??
|
||||||
|
EventSet.PrefabList.Find(ep => ep.UnlockPathEvent && string.IsNullOrEmpty(ep.BiomeIdentifier));
|
||||||
|
|
||||||
|
if (unlockEvent != null)
|
||||||
|
{
|
||||||
|
Reputation unlockReputation = CurrentLocation.Reputation;
|
||||||
|
Faction unlockFaction = null;
|
||||||
|
if (!string.IsNullOrEmpty(unlockEvent.UnlockPathFaction))
|
||||||
|
{
|
||||||
|
unlockFaction = GameMain.GameSession.Campaign.Factions.Find(f => f.Prefab.Identifier.Equals(unlockEvent.UnlockPathFaction, StringComparison.OrdinalIgnoreCase));
|
||||||
|
unlockReputation = unlockFaction?.Reputation;
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawIcon(
|
||||||
|
"LockedLocationConnection", (int)(28 * zoom),
|
||||||
|
TextManager.GetWithVariables(unlockEvent.UnlockPathTooltip ?? "LockedPathTooltip",
|
||||||
|
new string[] { "[requiredreputation]", "[currentreputation]" },
|
||||||
|
new string[] { Reputation.GetFormattedReputationText(MathUtils.InverseLerp(unlockReputation.MinReputation, unlockReputation.MaxReputation, unlockEvent.UnlockPathReputation), unlockEvent.UnlockPathReputation, addColorTags: true), unlockReputation.GetFormattedReputationText(addColorTags: true) }));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DrawIcon("LockedLocationConnection", (int)(28 * zoom), TextManager.Get("LockedPathTooltip"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (connection.LevelData.HasHuntingGrounds)
|
||||||
|
{
|
||||||
|
DrawIcon("HuntingGrounds", (int)(28 * zoom), TextManager.Get("HuntingGroundsTooltip"));
|
||||||
|
}
|
||||||
|
|
||||||
if (crushDepthWarningIconStyle != null)
|
if (crushDepthWarningIconStyle != null)
|
||||||
{
|
{
|
||||||
Vector2 iconPos = (connectionStart.Value + connectionEnd.Value) / 2;
|
DrawIcon(crushDepthWarningIconStyle, (int)(32 * zoom),
|
||||||
float iconSize = 32.0f * GUI.Scale;
|
TextManager.Get(tooltip)
|
||||||
bool mouseOn = HighlightedLocation == null && Vector2.DistanceSquared(iconPos, PlayerInput.MousePosition) < iconSize * iconSize;
|
.Replace("[initialdepth]", $"‖color:gui.orange‖{(int)(connection.LevelData.InitialDepth * Physics.DisplayToRealWorldRatio)}‖end‖")
|
||||||
Sprite crushDepthWarningIcon = crushDepthWarningIconStyle.GetDefaultSprite();
|
.Replace("[submarinecrushdepth]", $"‖color:gui.orange‖{(int)subCrushDepth}‖end‖"));
|
||||||
crushDepthWarningIcon.Draw(spriteBatch, iconPos,
|
|
||||||
mouseOn ? crushDepthWarningIconStyle.HoverColor : crushDepthWarningIconStyle.Color,
|
|
||||||
scale: iconSize / crushDepthWarningIcon.size.X);
|
|
||||||
if (mouseOn)
|
|
||||||
{
|
|
||||||
connectionTooltip = new Pair<Rectangle, string>(
|
|
||||||
new Rectangle(iconPos.ToPoint(), new Point((int)iconSize)),
|
|
||||||
TextManager.Get(tooltip)
|
|
||||||
.Replace("[initialdepth]", ((int)(connection.LevelData.InitialDepth * Physics.DisplayToRealWorldRatio)).ToString())
|
|
||||||
.Replace("[submarinecrushdepth]", ((int)subCrushDepth).ToString()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GameMain.DebugDraw && zoom > 1.0f && generationParams.ShowLevelTypeNames)
|
if (GameMain.DebugDraw && zoom > (1.0f * GUI.Scale) && generationParams.ShowLevelTypeNames)
|
||||||
{
|
{
|
||||||
Vector2 center = rectCenter + (connection.CenterPos + viewOffset) * zoom;
|
Vector2 center = rectCenter + (connection.CenterPos + viewOffset) * zoom;
|
||||||
if (viewArea.Contains(center) && connection.Biome != null)
|
if (viewArea.Contains(center) && connection.Biome != null)
|
||||||
@@ -808,6 +962,30 @@ namespace Barotrauma
|
|||||||
GUI.DrawString(spriteBatch, center, connection.Biome.Identifier + " (" + connection.Difficulty + ")", Color.White);
|
GUI.DrawString(spriteBatch, center, connection.Biome.Identifier + " (" + connection.Difficulty + ")", Color.White);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DrawIcon(string iconStyle, int iconSize, string tooltipText)
|
||||||
|
{
|
||||||
|
Vector2 iconPos = (connectionStart.Value + connectionEnd.Value) / 2;
|
||||||
|
Vector2 iconDiff = Vector2.Normalize(connectionEnd.Value - connectionStart.Value) * iconSize;
|
||||||
|
|
||||||
|
iconPos += (iconDiff * -(iconCount - 1) / 2.0f) + iconDiff * iconIndex;
|
||||||
|
|
||||||
|
var style = GUI.Style.GetComponentStyle(iconStyle);
|
||||||
|
bool mouseOn = Vector2.DistanceSquared(iconPos, PlayerInput.MousePosition) < iconSize * iconSize && IsPreferredTooltip(iconPos);
|
||||||
|
Sprite iconSprite = style.GetDefaultSprite();
|
||||||
|
iconSprite.Draw(spriteBatch, iconPos, (mouseOn ? style.HoverColor : style.Color) * 0.7f,
|
||||||
|
scale: iconSize / iconSprite.size.X);
|
||||||
|
if (mouseOn)
|
||||||
|
{
|
||||||
|
tooltip = (new Rectangle((iconPos - Vector2.One * iconSize / 2).ToPoint(), new Point(iconSize)), tooltipText);
|
||||||
|
}
|
||||||
|
iconIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsPreferredTooltip(Vector2 tooltipPos)
|
||||||
|
{
|
||||||
|
return tooltip == null || Vector2.DistanceSquared(tooltipPos, PlayerInput.MousePosition) < Vector2.DistanceSquared(tooltip.Value.targetArea.Center.ToVector2(), PlayerInput.MousePosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
private float hudVisibility;
|
private float hudVisibility;
|
||||||
@@ -828,8 +1006,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private void UpdateMapAnim(MapAnim anim, float deltaTime)
|
private void UpdateMapAnim(MapAnim anim, float deltaTime)
|
||||||
{
|
{
|
||||||
//pause animation while there are messageboxes on screen
|
//pause animation while there are messageboxes (other than hints) on screen
|
||||||
if (GUIMessageBox.MessageBoxes.Count > 0) return;
|
if (GUIMessageBox.MessageBoxes.Count(c => !(c is GUIMessageBox mb) || mb.MessageBoxType != GUIMessageBox.Type.Hint) > 0) { return; }
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(anim.StartMessage))
|
if (!string.IsNullOrEmpty(anim.StartMessage))
|
||||||
{
|
{
|
||||||
@@ -838,8 +1016,9 @@ namespace Barotrauma
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (anim.StartZoom == null) { anim.StartZoom = MathUtils.InverseLerp(generationParams.MinZoom, generationParams.MaxZoom, zoom); }
|
float unscaledZoom = zoom / GUI.Scale;
|
||||||
if (anim.EndZoom == null) { anim.EndZoom = MathUtils.InverseLerp(generationParams.MinZoom, generationParams.MaxZoom, zoom); }
|
if (anim.StartZoom == null) { anim.StartZoom = MathUtils.InverseLerp(generationParams.MinZoom, generationParams.MaxZoom, unscaledZoom); }
|
||||||
|
if (anim.EndZoom == null) { anim.EndZoom = MathUtils.InverseLerp(generationParams.MinZoom, generationParams.MaxZoom, unscaledZoom); }
|
||||||
|
|
||||||
anim.StartPos = (anim.StartLocation == null) ? -DrawOffset : anim.StartLocation.MapPosition;
|
anim.StartPos = (anim.StartLocation == null) ? -DrawOffset : anim.StartLocation.MapPosition;
|
||||||
|
|
||||||
@@ -852,7 +1031,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
zoom =
|
zoom =
|
||||||
MathHelper.Lerp(generationParams.MinZoom, generationParams.MaxZoom,
|
MathHelper.Lerp(generationParams.MinZoom, generationParams.MaxZoom,
|
||||||
MathHelper.SmoothStep(anim.StartZoom.Value, anim.EndZoom.Value, t));
|
MathHelper.SmoothStep(anim.StartZoom.Value, anim.EndZoom.Value, t))
|
||||||
|
* GUI.Scale;
|
||||||
|
|
||||||
if (anim.Timer >= anim.Duration)
|
if (anim.Timer >= anim.Duration)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,68 @@
|
|||||||
|
#nullable enable
|
||||||
|
using System;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
|
||||||
|
namespace Barotrauma
|
||||||
|
{
|
||||||
|
internal partial class Radiation
|
||||||
|
{
|
||||||
|
private static readonly string radiationTooltip = TextManager.Get("RadiationTooltip");
|
||||||
|
private static float spriteIndex;
|
||||||
|
private readonly SpriteSheet sheet = GUI.Style.RadiationAnimSpriteSheet;
|
||||||
|
private int maxFrames => sheet.FrameCount + 1;
|
||||||
|
|
||||||
|
private bool isHovingOver;
|
||||||
|
|
||||||
|
public void Draw(SpriteBatch spriteBatch, Rectangle container, float zoom)
|
||||||
|
{
|
||||||
|
if (!Enabled) { return; }
|
||||||
|
|
||||||
|
UISprite uiSprite = GUI.Style.RadiationSprite;
|
||||||
|
var (offsetX, offsetY) = Map.DrawOffset * zoom;
|
||||||
|
var (centerX, centerY) = container.Center.ToVector2();
|
||||||
|
var (halfSizeX, halfSizeY) = new Vector2(container.Width / 2f, container.Height / 2f) * zoom;
|
||||||
|
float viewBottom = centerY + Map.Height * zoom;
|
||||||
|
Vector2 topLeft = new Vector2(centerX + offsetX - halfSizeX, centerY + offsetY - halfSizeY);
|
||||||
|
Vector2 size = new Vector2((Amount - increasedAmount) * zoom + halfSizeX, viewBottom - topLeft.Y);
|
||||||
|
if (size.X < 0) { return; }
|
||||||
|
|
||||||
|
Vector2 spriteScale = new Vector2(zoom);
|
||||||
|
|
||||||
|
uiSprite.Sprite.DrawTiled(spriteBatch, topLeft, size, Params.RadiationAreaColor, Vector2.Zero, textureScale: spriteScale);
|
||||||
|
|
||||||
|
Vector2 topRight = topLeft + Vector2.UnitX * size.X;
|
||||||
|
|
||||||
|
int index = 0;
|
||||||
|
for (float i = 0; i <= size.Y; i += sheet.FrameSize.Y / 2f * zoom)
|
||||||
|
{
|
||||||
|
bool isEven = ++index % 2 == 0;
|
||||||
|
Vector2 origin = new Vector2(0.5f, 0) * sheet.FrameSize.X;
|
||||||
|
// every other sprite's animation is reversed to make it seem more chaotic
|
||||||
|
int sprite = (int) MathF.Floor(isEven ? spriteIndex : maxFrames - spriteIndex);
|
||||||
|
sheet.Draw(spriteBatch, sprite, topRight + new Vector2(0, i), Params.RadiationBorderTint, origin, 0f, spriteScale);
|
||||||
|
}
|
||||||
|
|
||||||
|
isHovingOver = container.Contains(PlayerInput.MousePosition) && PlayerInput.MousePosition.X < topLeft.X + size.X;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DrawFront(SpriteBatch spriteBatch)
|
||||||
|
{
|
||||||
|
if (isHovingOver)
|
||||||
|
{
|
||||||
|
GUIComponent.DrawToolTip(spriteBatch, radiationTooltip, PlayerInput.MousePosition + new Vector2(18 * GUI.Scale));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void MapUpdate(float deltaTime)
|
||||||
|
{
|
||||||
|
float spriteStep = Params.BorderAnimationSpeed * deltaTime;
|
||||||
|
spriteIndex = (spriteIndex + spriteStep) % maxFrames;
|
||||||
|
|
||||||
|
if (increasedAmount > 0)
|
||||||
|
{
|
||||||
|
increasedAmount -= (lastIncrease / Params.AnimationSpeed) * deltaTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,9 +20,6 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public static Vector2 StartMovingPos => startMovingPos;
|
public static Vector2 StartMovingPos => startMovingPos;
|
||||||
|
|
||||||
// Quick undo/redo for size and movement only. TODO: Remove if we do a more general implementation.
|
|
||||||
private Memento<Rectangle> rectMemento;
|
|
||||||
|
|
||||||
public event Action<Rectangle> Resized;
|
public event Action<Rectangle> Resized;
|
||||||
|
|
||||||
private static bool resizing;
|
private static bool resizing;
|
||||||
@@ -65,8 +62,6 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//protected bool isSelected;
|
|
||||||
|
|
||||||
private static bool disableSelect;
|
private static bool disableSelect;
|
||||||
public static bool DisableSelect
|
public static bool DisableSelect
|
||||||
{
|
{
|
||||||
@@ -805,7 +800,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
if (selectionPos != null && selectionPos != Vector2.Zero)
|
if (selectionPos != null && selectionPos != Vector2.Zero)
|
||||||
{
|
{
|
||||||
GUI.DrawRectangle(spriteBatch, new Vector2(selectionPos.X, -selectionPos.Y), selectionSize, Color.DarkRed, false, 0, (int)Math.Max(1.5f / GameScreen.Selected.Cam.Zoom, 1.0f));
|
GUI.DrawRectangle(spriteBatch, new Vector2(selectionPos.X, -selectionPos.Y), selectionSize, Color.DarkRed, false, 0, 2f / GameScreen.Selected.Cam.Zoom);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,20 +24,23 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (!GameMain.SubEditorScreen.ShowThalamus && prefab.Category.HasFlag(MapEntityCategory.Thalamus))
|
if (GameMain.SubEditorScreen.IsSubcategoryHidden(prefab.Subcategory))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return HasBody ? ShowWalls : ShowStructures;
|
return HasBody ? ShowWalls : ShowStructures;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private string specialTag;
|
#if DEBUG
|
||||||
[Editable, Serialize("", true)]
|
[Editable, Serialize("", true)]
|
||||||
|
#else
|
||||||
|
[Serialize("", true)]
|
||||||
|
#endif
|
||||||
public string SpecialTag
|
public string SpecialTag
|
||||||
{
|
{
|
||||||
get { return specialTag; }
|
get;
|
||||||
set { specialTag = value; }
|
set;
|
||||||
}
|
}
|
||||||
|
|
||||||
partial void InitProjSpecific()
|
partial void InitProjSpecific()
|
||||||
@@ -92,7 +95,10 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
int heightScaled = (int)(20 * GUI.Scale);
|
int heightScaled = (int)(20 * GUI.Scale);
|
||||||
editingHUD = new GUIFrame(new RectTransform(new Vector2(0.3f, 0.25f), GUI.Canvas, Anchor.CenterRight) { MinSize = new Point(400, 0) }) { UserData = this };
|
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);
|
GUIListBox listBox = new GUIListBox(new RectTransform(new Vector2(0.95f, 0.8f), editingHUD.RectTransform, Anchor.Center), style: null)
|
||||||
|
{
|
||||||
|
CanTakeKeyBoardFocus = false
|
||||||
|
};
|
||||||
var editor = new SerializableEntityEditor(listBox.Content.RectTransform, this, inGame, showName: true, titleFont: GUI.LargeFont) { UserData = this };
|
var editor = new SerializableEntityEditor(listBox.Content.RectTransform, this, inGame, showName: true, titleFont: GUI.LargeFont) { UserData = this };
|
||||||
|
|
||||||
if (Submarine.MainSub?.Info?.Type == SubmarineType.OutpostModule)
|
if (Submarine.MainSub?.Info?.Type == SubmarineType.OutpostModule)
|
||||||
|
|||||||
@@ -79,14 +79,22 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (maxDamageStructure != null)
|
if (maxDamageStructure != null)
|
||||||
{
|
{
|
||||||
SoundPlayer.PlayDamageSound(
|
PlayDamageSound(impactSimPos, impact, soundTag, maxDamageStructure);
|
||||||
soundTag,
|
|
||||||
impact * 10.0f,
|
|
||||||
ConvertUnits.ToDisplayUnits(impactSimPos),
|
|
||||||
MathHelper.Lerp(2000.0f, 10000.0f, (impact - MinCollisionImpact) / 2.0f),
|
|
||||||
maxDamageStructure.Tags);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void PlayDamageSound(Vector2 impactSimPos, float impact, string soundTag, Structure hitStructure = null)
|
||||||
|
{
|
||||||
|
if (impact < MinCollisionImpact) { return; }
|
||||||
|
|
||||||
|
SoundPlayer.PlayDamageSound(
|
||||||
|
soundTag,
|
||||||
|
impact * 10.0f,
|
||||||
|
ConvertUnits.ToDisplayUnits(impactSimPos),
|
||||||
|
MathHelper.Lerp(2000.0f, 10000.0f, (impact - MinCollisionImpact) / 2.0f),
|
||||||
|
hitStructure?.Tags);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
@@ -19,7 +20,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
var texture = TextureLoader.FromStream(mem, path: FilePath, compress: false);
|
var texture = TextureLoader.FromStream(mem, path: FilePath, compress: false);
|
||||||
if (texture == null) { throw new Exception("PreviewImage texture returned null"); }
|
if (texture == null) { throw new Exception("PreviewImage texture returned null"); }
|
||||||
PreviewImage = new Sprite(texture, null, null);
|
PreviewImage = new Sprite(texture, sourceRectangle: null, newOffset: null, path: FilePath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
@@ -32,21 +33,49 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void CreatePreviewWindow(GUIComponent parent)
|
public void CreatePreviewWindow(GUIComponent parent)
|
||||||
{
|
{
|
||||||
var content = new GUIFrame(new RectTransform(Vector2.One, parent.RectTransform), style: null);
|
var content = new GUIFrame(new RectTransform(Vector2.One, parent.RectTransform), style: null);
|
||||||
|
|
||||||
if (PreviewImage == null)
|
var previewButton = new GUIButton(new RectTransform(new Vector2(1f, 0.5f), content.RectTransform), style: null)
|
||||||
{
|
{
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), content.RectTransform), TextManager.Get(SavedSubmarines.Contains(this) ? "SubPreviewImageNotFound" : "SubNotDownloaded"));
|
CanBeFocused = SubmarineElement != null,
|
||||||
|
OnClicked = (btn, obj) => { SubmarinePreview.Create(this); return false; },
|
||||||
|
};
|
||||||
|
|
||||||
|
var previewImage = PreviewImage ?? savedSubmarines.Find(s => s.Name.Equals(Name, StringComparison.OrdinalIgnoreCase))?.PreviewImage;
|
||||||
|
if (previewImage == null)
|
||||||
|
{
|
||||||
|
new GUITextBlock(new RectTransform(Vector2.One, previewButton.RectTransform), TextManager.Get(SavedSubmarines.Contains(this) ? "SubPreviewImageNotFound" : "SubNotDownloaded"));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var submarinePreviewBackground = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.5f), content.RectTransform), style: null) { Color = Color.Black };
|
var submarinePreviewBackground = new GUIFrame(new RectTransform(Vector2.One, previewButton.RectTransform), style: null)
|
||||||
new GUIImage(new RectTransform(new Vector2(0.98f), submarinePreviewBackground.RectTransform, Anchor.Center), PreviewImage, scaleToFit: true);
|
{
|
||||||
new GUIFrame(new RectTransform(Vector2.One, submarinePreviewBackground.RectTransform), "InnerGlow", color: Color.Black);
|
Color = Color.Black,
|
||||||
|
HoverColor = Color.Black,
|
||||||
|
SelectedColor = Color.Black,
|
||||||
|
PressedColor = Color.Black,
|
||||||
|
CanBeFocused = false,
|
||||||
|
};
|
||||||
|
new GUIImage(new RectTransform(new Vector2(0.98f), submarinePreviewBackground.RectTransform, Anchor.Center), previewImage, scaleToFit: true) { CanBeFocused = false };
|
||||||
|
new GUIFrame(new RectTransform(Vector2.One, submarinePreviewBackground.RectTransform), "InnerGlow", color: Color.Black) { CanBeFocused = false };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (SubmarineElement != null)
|
||||||
|
{
|
||||||
|
new GUIFrame(new RectTransform(Vector2.One * 0.12f, previewButton.RectTransform, anchor: Anchor.BottomRight, pivot: Pivot.BottomRight, scaleBasis: ScaleBasis.BothHeight)
|
||||||
|
{
|
||||||
|
AbsoluteOffset = new Point((int)(0.03f * previewButton.Rect.Height))
|
||||||
|
},
|
||||||
|
"ExpandButton", Color.White)
|
||||||
|
{
|
||||||
|
Color = Color.White,
|
||||||
|
HoverColor = Color.White,
|
||||||
|
PressedColor = Color.White
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
var descriptionBox = new GUIListBox(new RectTransform(new Vector2(1, 0.5f), content.RectTransform, Anchor.BottomCenter))
|
var descriptionBox = new GUIListBox(new RectTransform(new Vector2(1, 0.5f), content.RectTransform, Anchor.BottomCenter))
|
||||||
{
|
{
|
||||||
UserData = "descriptionbox",
|
UserData = "descriptionbox",
|
||||||
@@ -56,39 +85,31 @@ namespace Barotrauma
|
|||||||
|
|
||||||
ScalableFont font = parent.Rect.Width < 350 ? GUI.SmallFont : GUI.Font;
|
ScalableFont font = parent.Rect.Width < 350 ? GUI.SmallFont : GUI.Font;
|
||||||
|
|
||||||
CreateSpecsWindow(descriptionBox, font);
|
CreateSpecsWindow(descriptionBox, font, includeDescription: true);
|
||||||
|
|
||||||
//space
|
|
||||||
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.05f), descriptionBox.Content.RectTransform), style: null);
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(Description))
|
|
||||||
{
|
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1, 0), descriptionBox.Content.RectTransform),
|
|
||||||
TextManager.Get("SaveSubDialogDescription", fallBackTag: "WorkshopItemDescription"), font: GUI.Font, wrap: true)
|
|
||||||
{ CanBeFocused = false, ForceUpperCase = true };
|
|
||||||
}
|
|
||||||
|
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1, 0), descriptionBox.Content.RectTransform), Description, font: font, wrap: true)
|
|
||||||
{
|
|
||||||
CanBeFocused = false
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CreateSpecsWindow(GUIListBox parent, ScalableFont font)
|
public void CreateSpecsWindow(GUIListBox parent, ScalableFont font, bool includeTitle = true, bool includeClass = true, bool includeDescription = false)
|
||||||
{
|
{
|
||||||
float leftPanelWidth = 0.6f;
|
float leftPanelWidth = 0.6f;
|
||||||
float rightPanelWidth = 0.4f / leftPanelWidth;
|
float rightPanelWidth = 0.4f;
|
||||||
string className = !HasTag(SubmarineTag.Shuttle) ? TextManager.Get($"submarineclass.{SubmarineClass}") : TextManager.Get("shuttle");
|
string className = !HasTag(SubmarineTag.Shuttle) ? TextManager.Get($"submarineclass.{SubmarineClass}") : TextManager.Get("shuttle");
|
||||||
|
|
||||||
int nameHeight = (int)GUI.LargeFont.MeasureString(DisplayName, true).Y;
|
|
||||||
int classHeight = (int)GUI.SubHeadingFont.MeasureString(className).Y;
|
int classHeight = (int)GUI.SubHeadingFont.MeasureString(className).Y;
|
||||||
int leftPanelWidthInt = (int)(parent.Rect.Width * leftPanelWidth);
|
int leftPanelWidthInt = (int)(parent.Rect.Width * leftPanelWidth);
|
||||||
|
|
||||||
var submarineNameText = new GUITextBlock(new RectTransform(new Point(leftPanelWidthInt, nameHeight + HUDLayoutSettings.Padding / 2), parent.Content.RectTransform), DisplayName, textAlignment: Alignment.CenterLeft, font: GUI.LargeFont) { CanBeFocused = false };
|
GUITextBlock submarineNameText = null;
|
||||||
submarineNameText.RectTransform.MinSize = new Point(0, (int)submarineNameText.TextSize.Y);
|
GUITextBlock submarineClassText = null;
|
||||||
var submarineClassText = new GUITextBlock(new RectTransform(new Point(leftPanelWidthInt, classHeight), parent.Content.RectTransform), className, textAlignment: Alignment.CenterLeft, font: GUI.SubHeadingFont) { CanBeFocused = false };
|
if (includeTitle)
|
||||||
submarineClassText.RectTransform.MinSize = new Point(0, (int)submarineClassText.TextSize.Y);
|
{
|
||||||
|
int nameHeight = (int)GUI.LargeFont.MeasureString(DisplayName, true).Y;
|
||||||
|
submarineNameText = new GUITextBlock(new RectTransform(new Point(leftPanelWidthInt, nameHeight + HUDLayoutSettings.Padding / 2), parent.Content.RectTransform), DisplayName, textAlignment: Alignment.CenterLeft, font: GUI.LargeFont) { CanBeFocused = false };
|
||||||
|
submarineNameText.RectTransform.MinSize = new Point(0, (int)submarineNameText.TextSize.Y);
|
||||||
|
}
|
||||||
|
if (includeClass)
|
||||||
|
{
|
||||||
|
submarineClassText = new GUITextBlock(new RectTransform(new Point(leftPanelWidthInt, classHeight), parent.Content.RectTransform), className, textAlignment: Alignment.CenterLeft, font: GUI.SubHeadingFont) { CanBeFocused = false };
|
||||||
|
submarineClassText.RectTransform.MinSize = new Point(0, (int)submarineClassText.TextSize.Y);
|
||||||
|
}
|
||||||
Vector2 realWorldDimensions = Dimensions * Physics.DisplayToRealWorldRatio;
|
Vector2 realWorldDimensions = Dimensions * Physics.DisplayToRealWorldRatio;
|
||||||
if (realWorldDimensions != Vector2.Zero)
|
if (realWorldDimensions != Vector2.Zero)
|
||||||
{
|
{
|
||||||
@@ -149,8 +170,30 @@ namespace Barotrauma
|
|||||||
versionText.RectTransform.MinSize = new Point(0, versionText.Children.First().Rect.Height);
|
versionText.RectTransform.MinSize = new Point(0, versionText.Children.First().Rect.Height);
|
||||||
}
|
}
|
||||||
|
|
||||||
submarineNameText.AutoScaleHorizontal = true;
|
if (submarineNameText != null)
|
||||||
GUITextBlock.AutoScaleAndNormalize(parent.Content.Children.Where(c => c is GUITextBlock && c != submarineNameText).Cast<GUITextBlock>());
|
{
|
||||||
|
submarineNameText.AutoScaleHorizontal = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
GUITextBlock descBlock = null;
|
||||||
|
if (includeDescription)
|
||||||
|
{
|
||||||
|
//space
|
||||||
|
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.05f), parent.Content.RectTransform), style: null);
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(Description))
|
||||||
|
{
|
||||||
|
var wsItemDesc = new GUITextBlock(new RectTransform(new Vector2(1, 0), parent.Content.RectTransform),
|
||||||
|
TextManager.Get("SaveSubDialogDescription", fallBackTag: "WorkshopItemDescription"), font: GUI.Font, wrap: true)
|
||||||
|
{ CanBeFocused = false, ForceUpperCase = true };
|
||||||
|
|
||||||
|
descBlock = new GUITextBlock(new RectTransform(new Vector2(1, 0), parent.Content.RectTransform), Description, font: font, wrap: true)
|
||||||
|
{
|
||||||
|
CanBeFocused = false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GUITextBlock.AutoScaleAndNormalize(parent.Content.GetAllChildren<GUITextBlock>().Where(c => c != submarineNameText && c != descBlock));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,648 @@
|
|||||||
|
using Barotrauma.Extensions;
|
||||||
|
using Barotrauma.IO;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Xml.Linq;
|
||||||
|
|
||||||
|
namespace Barotrauma
|
||||||
|
{
|
||||||
|
class SubmarinePreview : IDisposable
|
||||||
|
{
|
||||||
|
private SpriteRecorder spriteRecorder;
|
||||||
|
private SubmarineInfo submarineInfo;
|
||||||
|
private Camera camera;
|
||||||
|
private Task loadTask;
|
||||||
|
private volatile bool isDisposed;
|
||||||
|
|
||||||
|
private GUIFrame previewFrame;
|
||||||
|
|
||||||
|
private class HullCollection
|
||||||
|
{
|
||||||
|
public readonly List<Rectangle> Rects;
|
||||||
|
public readonly string Name;
|
||||||
|
|
||||||
|
public HullCollection(string identifier)
|
||||||
|
{
|
||||||
|
Rects = new List<Rectangle>();
|
||||||
|
Name = TextManager.Get(identifier, returnNull: true) ?? identifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddRect(XElement element)
|
||||||
|
{
|
||||||
|
Rectangle rect = element.GetAttributeRect("rect", Rectangle.Empty);
|
||||||
|
rect.Y = -rect.Y;
|
||||||
|
Rects.Add(rect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private struct Door
|
||||||
|
{
|
||||||
|
public readonly Rectangle Rect;
|
||||||
|
|
||||||
|
public Door(Rectangle rect)
|
||||||
|
{
|
||||||
|
rect.Y = -rect.Y;
|
||||||
|
Rect = rect;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Dictionary<string,HullCollection> hullCollections;
|
||||||
|
private List<Door> doors;
|
||||||
|
|
||||||
|
|
||||||
|
private static SubmarinePreview instance = null;
|
||||||
|
|
||||||
|
public static void Create(SubmarineInfo submarineInfo)
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
instance = new SubmarinePreview(submarineInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Close()
|
||||||
|
{
|
||||||
|
instance?.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
private SubmarinePreview(SubmarineInfo subInfo)
|
||||||
|
{
|
||||||
|
camera = new Camera();
|
||||||
|
submarineInfo = subInfo;
|
||||||
|
spriteRecorder = new SpriteRecorder();
|
||||||
|
isDisposed = false;
|
||||||
|
loadTask = null;
|
||||||
|
|
||||||
|
hullCollections = new Dictionary<string, HullCollection>();
|
||||||
|
doors = new List<Door>();
|
||||||
|
|
||||||
|
previewFrame = new GUIFrame(new RectTransform(Vector2.One, GUI.Canvas, Anchor.Center), style: null);
|
||||||
|
new GUIFrame(new RectTransform(GUI.Canvas.RelativeSize, previewFrame.RectTransform, Anchor.Center), style: "GUIBackgroundBlocker");
|
||||||
|
|
||||||
|
new GUIButton(new RectTransform(Vector2.One, previewFrame.RectTransform), "", style: null)
|
||||||
|
{
|
||||||
|
OnClicked = (btn, obj) => { Dispose(); return false; }
|
||||||
|
};
|
||||||
|
|
||||||
|
var innerFrame = new GUIFrame(new RectTransform(Vector2.One * 0.9f, previewFrame.RectTransform, Anchor.Center));
|
||||||
|
int innerPadding = GUI.IntScale(100f);
|
||||||
|
var innerPadded = new GUIFrame(new RectTransform(new Point(innerFrame.Rect.Width - innerPadding, innerFrame.Rect.Height - innerPadding), previewFrame.RectTransform, Anchor.Center), style: null)
|
||||||
|
{
|
||||||
|
OutlineColor = Color.Black,
|
||||||
|
OutlineThickness = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
GUITextBlock titleText = null;
|
||||||
|
GUIListBox specsContainer = null;
|
||||||
|
|
||||||
|
new GUICustomComponent(new RectTransform(Vector2.One, innerPadded.RectTransform, Anchor.Center),
|
||||||
|
(spriteBatch, component) => {
|
||||||
|
camera.UpdateTransform(interpolate: true, updateListener: false);
|
||||||
|
Rectangle drawRect = new Rectangle(component.Rect.X + 1, component.Rect.Y + 1, component.Rect.Width - 2, component.Rect.Height - 2);
|
||||||
|
RenderSubmarine(spriteBatch, drawRect);
|
||||||
|
},
|
||||||
|
(deltaTime, component) => {
|
||||||
|
bool isMouseOnComponent = GUI.MouseOn == component;
|
||||||
|
camera.MoveCamera(deltaTime, allowZoom: isMouseOnComponent, followSub: false);
|
||||||
|
if (isMouseOnComponent &&
|
||||||
|
(PlayerInput.MidButtonHeld() || PlayerInput.LeftButtonHeld()))
|
||||||
|
{
|
||||||
|
Vector2 moveSpeed = PlayerInput.MouseSpeed * (float)deltaTime * 60.0f / camera.Zoom;
|
||||||
|
moveSpeed.X = -moveSpeed.X;
|
||||||
|
camera.Position += moveSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (titleText != null && specsContainer != null)
|
||||||
|
{
|
||||||
|
specsContainer.Visible = GUI.IsMouseOn(titleText);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var topContainer = new GUIFrame(new RectTransform(new Vector2(1f, 0.07f), innerPadded.RectTransform, Anchor.TopLeft), style: null)
|
||||||
|
{
|
||||||
|
Color = Color.Black * 0.65f
|
||||||
|
};
|
||||||
|
var topLayout = new GUILayoutGroup(new RectTransform(new Vector2(0.97f, 5f / 7f), topContainer.RectTransform, Anchor.Center), isHorizontal: true, childAnchor: Anchor.CenterLeft);
|
||||||
|
|
||||||
|
titleText = new GUITextBlock(new RectTransform(new Vector2(0.95f, 1f), topLayout.RectTransform), subInfo.DisplayName, font: GUI.LargeFont);
|
||||||
|
new GUIButton(new RectTransform(new Vector2(0.05f, 1f), topLayout.RectTransform), TextManager.Get("Close"))
|
||||||
|
{
|
||||||
|
OnClicked = (btn, obj) => { Dispose(); return false; }
|
||||||
|
};
|
||||||
|
|
||||||
|
specsContainer = new GUIListBox(new RectTransform(new Vector2(0.4f, 1f), innerPadded.RectTransform, Anchor.TopLeft) { RelativeOffset = new Vector2(0.015f, 0.07f) })
|
||||||
|
{
|
||||||
|
Color = Color.Black * 0.65f,
|
||||||
|
ScrollBarEnabled = false,
|
||||||
|
ScrollBarVisible = false,
|
||||||
|
Spacing = 5
|
||||||
|
};
|
||||||
|
subInfo.CreateSpecsWindow(specsContainer, GUI.Font, includeTitle: false, includeDescription: true);
|
||||||
|
int width = specsContainer.Rect.Width;
|
||||||
|
void recalculateSpecsContainerHeight()
|
||||||
|
{
|
||||||
|
int totalSize = 0;
|
||||||
|
var children = specsContainer.Content.Children.Where(c => c.Visible);
|
||||||
|
foreach (GUIComponent child in children)
|
||||||
|
{
|
||||||
|
totalSize += child.Rect.Height;
|
||||||
|
}
|
||||||
|
totalSize += specsContainer.Content.CountChildren * specsContainer.Spacing;
|
||||||
|
if (specsContainer.PadBottom)
|
||||||
|
{
|
||||||
|
GUIComponent last = specsContainer.Content.Children.LastOrDefault();
|
||||||
|
if (last != null)
|
||||||
|
{
|
||||||
|
totalSize += specsContainer.Rect.Height - last.Rect.Height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
specsContainer.RectTransform.Resize(new Point(width, totalSize), true);
|
||||||
|
specsContainer.RecalculateChildren();
|
||||||
|
}
|
||||||
|
//hell
|
||||||
|
recalculateSpecsContainerHeight();
|
||||||
|
specsContainer.Content.GetAllChildren<GUITextBlock>().ForEach(c =>
|
||||||
|
{
|
||||||
|
var firstChild = c.Children.FirstOrDefault() as GUITextBlock;
|
||||||
|
if (firstChild != null)
|
||||||
|
{
|
||||||
|
firstChild.CalculateHeightFromText(); firstChild.SetTextPos();
|
||||||
|
c.RectTransform.MinSize = new Point(0, firstChild.Rect.Height);
|
||||||
|
}
|
||||||
|
c.CalculateHeightFromText(); c.SetTextPos();
|
||||||
|
});
|
||||||
|
recalculateSpecsContainerHeight();
|
||||||
|
|
||||||
|
GeneratePreviewMeshes();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void AddToGUIUpdateList()
|
||||||
|
{
|
||||||
|
instance?.previewFrame?.AddToGUIUpdateList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task GeneratePreviewMeshes()
|
||||||
|
{
|
||||||
|
if (loadTask != null) { throw new InvalidOperationException("Tried to start SubmarinePreview loadTask more than once!"); }
|
||||||
|
loadTask = Task.Run(GeneratePreviewMeshesInternal);
|
||||||
|
return loadTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task GeneratePreviewMeshesInternal()
|
||||||
|
{
|
||||||
|
await Task.Yield();
|
||||||
|
spriteRecorder.Begin(SpriteSortMode.BackToFront);
|
||||||
|
|
||||||
|
HashSet<int> toIgnore = new HashSet<int>();
|
||||||
|
|
||||||
|
foreach (var subElement in submarineInfo.SubmarineElement.Elements())
|
||||||
|
{
|
||||||
|
switch (subElement.Name.LocalName.ToLowerInvariant())
|
||||||
|
{
|
||||||
|
case "item":
|
||||||
|
foreach (var component in subElement.Elements())
|
||||||
|
{
|
||||||
|
switch (component.Name.LocalName.ToLowerInvariant())
|
||||||
|
{
|
||||||
|
case "itemcontainer":
|
||||||
|
ExtractItemContainerIds(component, toIgnore);
|
||||||
|
break;
|
||||||
|
case "connectionpanel":
|
||||||
|
ExtractConnectionPanelLinks(component, toIgnore);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (isDisposed) { return; }
|
||||||
|
await Task.Yield();
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var subElement in submarineInfo.SubmarineElement.Elements())
|
||||||
|
{
|
||||||
|
switch (subElement.Name.LocalName.ToLowerInvariant())
|
||||||
|
{
|
||||||
|
case "item":
|
||||||
|
if (!toIgnore.Contains(subElement.GetAttributeInt("ID", 0)))
|
||||||
|
{
|
||||||
|
BakeMapEntity(subElement);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "structure":
|
||||||
|
BakeMapEntity(subElement);
|
||||||
|
break;
|
||||||
|
case "hull":
|
||||||
|
string identifier = subElement.GetAttributeString("roomname", "").ToLowerInvariant();
|
||||||
|
if (!string.IsNullOrEmpty(identifier))
|
||||||
|
{
|
||||||
|
HullCollection hullCollection = null;
|
||||||
|
if (!hullCollections.TryGetValue(identifier, out hullCollection))
|
||||||
|
{
|
||||||
|
hullCollection = new HullCollection(identifier);
|
||||||
|
hullCollections.Add(identifier, hullCollection);
|
||||||
|
}
|
||||||
|
hullCollection.AddRect(subElement);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (isDisposed) { return; }
|
||||||
|
await Task.Yield();
|
||||||
|
}
|
||||||
|
spriteRecorder.End();
|
||||||
|
|
||||||
|
camera.Position = (spriteRecorder.Min + spriteRecorder.Max) * 0.5f;
|
||||||
|
float scaledSpan = (spriteRecorder.Max - spriteRecorder.Min).X / camera.Resolution.X;
|
||||||
|
camera.Zoom = 0.8f / scaledSpan;
|
||||||
|
camera.StopMovement();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ExtractItemContainerIds(XElement component, HashSet<int> ids)
|
||||||
|
{
|
||||||
|
string containedString = component.GetAttributeString("contained", "");
|
||||||
|
string[] itemIdStrings = containedString.Split(',');
|
||||||
|
for (int i = 0; i < itemIdStrings.Length; i++)
|
||||||
|
{
|
||||||
|
foreach (string idStr in itemIdStrings[i].Split(';'))
|
||||||
|
{
|
||||||
|
if (!int.TryParse(idStr, NumberStyles.Any, CultureInfo.InvariantCulture, out int id)) { continue; }
|
||||||
|
if (id != 0 && !ids.Contains(id)) { ids.Add(id); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ExtractConnectionPanelLinks(XElement component, HashSet<int> ids)
|
||||||
|
{
|
||||||
|
var pins = component.Elements("input").Concat(component.Elements("output"));
|
||||||
|
foreach (var pin in pins)
|
||||||
|
{
|
||||||
|
var links = pin.Elements("link");
|
||||||
|
foreach (var link in links)
|
||||||
|
{
|
||||||
|
int id = link.GetAttributeInt("w", 0);
|
||||||
|
if (id != 0 && !ids.Contains(id)) { ids.Add(id); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BakeMapEntity(XElement element)
|
||||||
|
{
|
||||||
|
string identifier = element.GetAttributeString("identifier", "");
|
||||||
|
if (string.IsNullOrEmpty(identifier)) { return; }
|
||||||
|
Rectangle rect = element.GetAttributeRect("rect", Rectangle.Empty);
|
||||||
|
if (rect.Equals(Rectangle.Empty)) { return; }
|
||||||
|
|
||||||
|
float depth = element.GetAttributeFloat("spritedepth", 1f);
|
||||||
|
bool flippedX = element.GetAttributeBool("flippedx", false);
|
||||||
|
bool flippedY = element.GetAttributeBool("flippedy", false);
|
||||||
|
|
||||||
|
float scale = element.GetAttributeFloat("scale", 1f);
|
||||||
|
Color color = element.GetAttributeColor("spritecolor", Color.White);
|
||||||
|
|
||||||
|
float rotation = element.GetAttributeFloat("rotation", 0f);
|
||||||
|
|
||||||
|
MapEntityPrefab prefab = MapEntityPrefab.List.FirstOrDefault(p => p.Identifier.Equals(identifier, StringComparison.OrdinalIgnoreCase));
|
||||||
|
if (prefab == null) { return; }
|
||||||
|
|
||||||
|
var texture = prefab.sprite.Texture;
|
||||||
|
var srcRect = prefab.sprite.SourceRect;
|
||||||
|
|
||||||
|
SpriteEffects spriteEffects = SpriteEffects.None;
|
||||||
|
if (flippedX)
|
||||||
|
{
|
||||||
|
spriteEffects |= SpriteEffects.FlipHorizontally;
|
||||||
|
}
|
||||||
|
if (flippedY)
|
||||||
|
{
|
||||||
|
spriteEffects |= SpriteEffects.FlipVertically;
|
||||||
|
}
|
||||||
|
|
||||||
|
var prevEffects = prefab.sprite.effects;
|
||||||
|
prefab.sprite.effects ^= spriteEffects;
|
||||||
|
|
||||||
|
bool overrideSprite = false;
|
||||||
|
ItemPrefab itemPrefab = prefab as ItemPrefab;
|
||||||
|
StructurePrefab structurePrefab = prefab as StructurePrefab;
|
||||||
|
if (itemPrefab != null)
|
||||||
|
{
|
||||||
|
BakeItemComponents(itemPrefab, rect, color, scale, rotation, depth, out overrideSprite);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!overrideSprite)
|
||||||
|
{
|
||||||
|
if (structurePrefab != null)
|
||||||
|
{
|
||||||
|
ParseUpgrades(structurePrefab.ConfigElement, ref scale);
|
||||||
|
|
||||||
|
if (!prefab.ResizeVertical)
|
||||||
|
{
|
||||||
|
rect.Height = (int)(rect.Height * scale / prefab.Scale);
|
||||||
|
}
|
||||||
|
if (!prefab.ResizeHorizontal)
|
||||||
|
{
|
||||||
|
rect.Width = (int)(rect.Width * scale / prefab.Scale);
|
||||||
|
}
|
||||||
|
var textureScale = element.GetAttributeVector2("texturescale", Vector2.One);
|
||||||
|
|
||||||
|
Vector2 backGroundOffset = Vector2.Zero;
|
||||||
|
|
||||||
|
Vector2 textureOffset = element.GetAttributeVector2("textureoffset", Vector2.Zero);
|
||||||
|
if (flippedX) { textureOffset.X = -textureOffset.X; }
|
||||||
|
if (flippedY) { textureOffset.Y = -textureOffset.Y; }
|
||||||
|
|
||||||
|
backGroundOffset = new Vector2(
|
||||||
|
MathUtils.PositiveModulo((int)-textureOffset.X, prefab.sprite.SourceRect.Width),
|
||||||
|
MathUtils.PositiveModulo((int)-textureOffset.Y, prefab.sprite.SourceRect.Height));
|
||||||
|
|
||||||
|
prefab.sprite.DrawTiled(
|
||||||
|
spriteRecorder,
|
||||||
|
rect.Location.ToVector2() * new Vector2(1f, -1f),
|
||||||
|
rect.Size.ToVector2(),
|
||||||
|
color: color,
|
||||||
|
startOffset: backGroundOffset,
|
||||||
|
textureScale: textureScale * scale,
|
||||||
|
depth: depth);
|
||||||
|
}
|
||||||
|
else if (itemPrefab != null)
|
||||||
|
{
|
||||||
|
bool usePrefabValues = element.GetAttributeBool("isoverride", false) != itemPrefab.IsOverride;
|
||||||
|
if (usePrefabValues)
|
||||||
|
{
|
||||||
|
scale = itemPrefab.ConfigElement.GetAttributeFloat(scale, "scale", "Scale");
|
||||||
|
}
|
||||||
|
|
||||||
|
ParseUpgrades(itemPrefab.ConfigElement, ref scale);
|
||||||
|
|
||||||
|
if (prefab.ResizeVertical || prefab.ResizeHorizontal)
|
||||||
|
{
|
||||||
|
if (!prefab.ResizeHorizontal)
|
||||||
|
{
|
||||||
|
rect.Width = (int)(prefab.sprite.size.X * scale);
|
||||||
|
}
|
||||||
|
if (!prefab.ResizeVertical)
|
||||||
|
{
|
||||||
|
rect.Height = (int)(prefab.sprite.size.Y * scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
var spritePos = rect.Center.ToVector2();
|
||||||
|
//spritePos.Y = rect.Height - spritePos.Y;
|
||||||
|
|
||||||
|
prefab.sprite.DrawTiled(
|
||||||
|
spriteRecorder,
|
||||||
|
rect.Location.ToVector2() * new Vector2(1f, -1f),
|
||||||
|
rect.Size.ToVector2(),
|
||||||
|
color: color,
|
||||||
|
textureScale: Vector2.One * scale,
|
||||||
|
depth: depth);
|
||||||
|
|
||||||
|
foreach (var decorativeSprite in itemPrefab.DecorativeSprites)
|
||||||
|
{
|
||||||
|
float offsetState = 0f;
|
||||||
|
Vector2 offset = decorativeSprite.GetOffset(ref offsetState, Vector2.Zero) * scale;
|
||||||
|
if (flippedX && itemPrefab.CanSpriteFlipX) { offset.X = -offset.X; }
|
||||||
|
if (flippedY && itemPrefab.CanSpriteFlipY) { offset.Y = -offset.Y; }
|
||||||
|
decorativeSprite.Sprite.DrawTiled(spriteRecorder,
|
||||||
|
new Vector2(spritePos.X + offset.X - rect.Width / 2, -(spritePos.Y + offset.Y + rect.Height / 2)),
|
||||||
|
rect.Size.ToVector2(), color: color,
|
||||||
|
textureScale: Vector2.One * scale,
|
||||||
|
depth: Math.Min(depth + (decorativeSprite.Sprite.Depth - prefab.sprite.Depth), 0.999f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rect.Width = (int)(rect.Width * scale / prefab.Scale);
|
||||||
|
rect.Height = (int)(rect.Height * scale / prefab.Scale);
|
||||||
|
|
||||||
|
var spritePos = rect.Center.ToVector2();
|
||||||
|
spritePos.Y -= rect.Height;
|
||||||
|
//spritePos.Y = rect.Height - spritePos.Y;
|
||||||
|
|
||||||
|
prefab.sprite.Draw(
|
||||||
|
spriteRecorder,
|
||||||
|
spritePos * new Vector2(1f, -1f),
|
||||||
|
color,
|
||||||
|
prefab.sprite.Origin,
|
||||||
|
rotation,
|
||||||
|
scale,
|
||||||
|
prefab.sprite.effects, depth);
|
||||||
|
|
||||||
|
foreach (var decorativeSprite in itemPrefab.DecorativeSprites)
|
||||||
|
{
|
||||||
|
float rotationState = 0f; float offsetState = 0f;
|
||||||
|
float rot = decorativeSprite.GetRotation(ref rotationState, 0f);
|
||||||
|
Vector2 offset = decorativeSprite.GetOffset(ref offsetState, Vector2.Zero) * scale;
|
||||||
|
if (flippedX && itemPrefab.CanSpriteFlipX) { offset.X = -offset.X; }
|
||||||
|
if (flippedY && itemPrefab.CanSpriteFlipY) { offset.Y = -offset.Y; }
|
||||||
|
decorativeSprite.Sprite.Draw(spriteRecorder, new Vector2(spritePos.X + offset.X, -(spritePos.Y + offset.Y)), color,
|
||||||
|
MathHelper.ToRadians(rotation) + rot, decorativeSprite.GetScale(0f) * scale, prefab.sprite.effects,
|
||||||
|
depth: Math.Min(depth + (decorativeSprite.Sprite.Depth - prefab.sprite.Depth), 0.999f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
prefab.sprite.effects = prevEffects;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BakeItemComponents(
|
||||||
|
ItemPrefab prefab,
|
||||||
|
Rectangle rect, Color color,
|
||||||
|
float scale, float rotation, float depth,
|
||||||
|
out bool overrideSprite)
|
||||||
|
{
|
||||||
|
overrideSprite = false;
|
||||||
|
|
||||||
|
foreach (var subElement in prefab.ConfigElement.Elements())
|
||||||
|
{
|
||||||
|
switch (subElement.Name.LocalName.ToLowerInvariant())
|
||||||
|
{
|
||||||
|
case "turret":
|
||||||
|
Sprite barrelSprite = null;
|
||||||
|
Sprite railSprite = null;
|
||||||
|
foreach (XElement turretSubElem in subElement.Elements())
|
||||||
|
{
|
||||||
|
switch (turretSubElem.Name.ToString().ToLowerInvariant())
|
||||||
|
{
|
||||||
|
case "barrelsprite":
|
||||||
|
barrelSprite = new Sprite(turretSubElem);
|
||||||
|
break;
|
||||||
|
case "railsprite":
|
||||||
|
railSprite = new Sprite(turretSubElem);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var transformedBarrelPos = MathUtils.RotatePointAroundTarget(
|
||||||
|
subElement.GetAttributeVector2("barrelpos", Vector2.Zero) * scale,
|
||||||
|
new Vector2(rect.Width / 2, rect.Height / 2),
|
||||||
|
MathHelper.ToRadians(rotation));
|
||||||
|
|
||||||
|
Vector2 drawPos = new Vector2(rect.X + transformedBarrelPos.X, rect.Y - transformedBarrelPos.Y);
|
||||||
|
drawPos.Y = -drawPos.Y;
|
||||||
|
|
||||||
|
railSprite?.Draw(spriteRecorder,
|
||||||
|
drawPos,
|
||||||
|
color,
|
||||||
|
rotation + MathHelper.PiOver2, scale,
|
||||||
|
SpriteEffects.None, depth + (railSprite.Depth - prefab.sprite.Depth));
|
||||||
|
|
||||||
|
barrelSprite?.Draw(spriteRecorder,
|
||||||
|
drawPos - new Vector2((float)Math.Cos(MathHelper.ToRadians(rotation)), (float)Math.Sin(MathHelper.ToRadians(rotation))) * scale,
|
||||||
|
color,
|
||||||
|
rotation + MathHelper.PiOver2, scale,
|
||||||
|
SpriteEffects.None, depth + (barrelSprite.Depth - prefab.sprite.Depth));
|
||||||
|
|
||||||
|
break;
|
||||||
|
case "door":
|
||||||
|
doors.Add(new Door(rect));
|
||||||
|
|
||||||
|
var doorSpriteElem = subElement.Elements().FirstOrDefault(e => e.Name.LocalName.Equals("sprite", StringComparison.OrdinalIgnoreCase));
|
||||||
|
if (doorSpriteElem != null)
|
||||||
|
{
|
||||||
|
string texturePath = doorSpriteElem.GetAttributeString("texture", "");
|
||||||
|
Vector2 pos = rect.Location.ToVector2() * new Vector2(1f, -1f);
|
||||||
|
if (subElement.GetAttributeBool("horizontal", false))
|
||||||
|
{
|
||||||
|
pos.Y += (float)rect.Height * 0.5f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pos.X += (float)rect.Width * 0.5f;
|
||||||
|
}
|
||||||
|
Sprite doorSprite = new Sprite(doorSpriteElem, texturePath.Contains("/") ? "" : Path.GetDirectoryName(prefab.FilePath));
|
||||||
|
spriteRecorder.Draw(doorSprite.Texture, pos,
|
||||||
|
new Rectangle((int)doorSprite.SourceRect.X,
|
||||||
|
(int)doorSprite.SourceRect.Y,
|
||||||
|
(int)doorSprite.size.X, (int)doorSprite.size.Y),
|
||||||
|
color, 0.0f, doorSprite.Origin, new Vector2(scale), SpriteEffects.None, doorSprite.Depth);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "ladder":
|
||||||
|
var backgroundSprElem = subElement.Elements().FirstOrDefault(e => e.Name.LocalName.Equals("backgroundsprite", StringComparison.OrdinalIgnoreCase));
|
||||||
|
if (backgroundSprElem != null)
|
||||||
|
{
|
||||||
|
Sprite backgroundSprite = new Sprite(backgroundSprElem);
|
||||||
|
backgroundSprite.DrawTiled(spriteRecorder,
|
||||||
|
new Vector2(rect.Left, -rect.Top) - backgroundSprite.Origin * scale,
|
||||||
|
new Vector2(backgroundSprite.size.X * scale, rect.Height), color: color,
|
||||||
|
textureScale: Vector2.One * scale,
|
||||||
|
depth: depth + 0.1f);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ParseUpgrades(XElement prefabConfigElement, ref float scale)
|
||||||
|
{
|
||||||
|
foreach (var upgrade in prefabConfigElement.Elements("Upgrade"))
|
||||||
|
{
|
||||||
|
var upgradeVersion = new Version(upgrade.GetAttributeString("gameversion", "0.0.0.0"));
|
||||||
|
if (upgradeVersion >= submarineInfo.GameVersion)
|
||||||
|
{
|
||||||
|
string scaleModifier = upgrade.GetAttributeString("scale", "*1");
|
||||||
|
|
||||||
|
if (scaleModifier.StartsWith("*"))
|
||||||
|
{
|
||||||
|
if (float.TryParse(scaleModifier.Substring(1), NumberStyles.Any, CultureInfo.InvariantCulture, out float parsedScale))
|
||||||
|
{
|
||||||
|
scale *= parsedScale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (float.TryParse(scaleModifier, NumberStyles.Any, CultureInfo.InvariantCulture, out float parsedScale))
|
||||||
|
{
|
||||||
|
scale = parsedScale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RenderSubmarine(SpriteBatch spriteBatch, Rectangle scissorRectangle)
|
||||||
|
{
|
||||||
|
if (spriteRecorder == null) { return; }
|
||||||
|
|
||||||
|
GUI.DrawRectangle(spriteBatch, scissorRectangle, new Color(0.051f, 0.149f, 0.271f, 1.0f), isFilled: true);
|
||||||
|
|
||||||
|
if (!spriteRecorder.ReadyToRender)
|
||||||
|
{
|
||||||
|
string waitText = !loadTask.IsCompleted ?
|
||||||
|
"Generating preview..." :
|
||||||
|
(loadTask.Exception?.ToString() ?? "Task completed without marking as ready to render");
|
||||||
|
Vector2 origin = (GUI.Font.MeasureString(waitText) * 0.5f);
|
||||||
|
origin.X = MathF.Round(origin.X);
|
||||||
|
origin.Y = MathF.Round(origin.Y);
|
||||||
|
GUI.Font.DrawString(
|
||||||
|
spriteBatch,
|
||||||
|
waitText,
|
||||||
|
scissorRectangle.Center.ToVector2(),
|
||||||
|
Color.White,
|
||||||
|
0f,
|
||||||
|
origin,
|
||||||
|
1f,
|
||||||
|
SpriteEffects.None,
|
||||||
|
0f);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
spriteBatch.End();
|
||||||
|
|
||||||
|
var prevScissorRect = GameMain.Instance.GraphicsDevice.ScissorRectangle;
|
||||||
|
GameMain.Instance.GraphicsDevice.ScissorRectangle = scissorRectangle;
|
||||||
|
|
||||||
|
spriteRecorder.Render(camera);
|
||||||
|
|
||||||
|
var mousePos = camera.ScreenToWorld(PlayerInput.MousePosition);
|
||||||
|
mousePos.Y = -mousePos.Y;
|
||||||
|
|
||||||
|
spriteBatch.Begin(SpriteSortMode.BackToFront, rasterizerState: GameMain.ScissorTestEnable, transformMatrix: camera.Transform);
|
||||||
|
GameMain.Instance.GraphicsDevice.ScissorRectangle = scissorRectangle;
|
||||||
|
foreach (var hullCollection in hullCollections.Values)
|
||||||
|
{
|
||||||
|
bool mouseOver = false;
|
||||||
|
|
||||||
|
foreach (var rect in hullCollection.Rects)
|
||||||
|
{
|
||||||
|
mouseOver = rect.Contains(mousePos);
|
||||||
|
if (mouseOver) { break; }
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var rect in hullCollection.Rects)
|
||||||
|
{
|
||||||
|
GUI.DrawRectangle(spriteBatch, rect, mouseOver ? Color.Red : Color.Blue, depth: mouseOver ? 0.45f : 0.5f, thickness: (mouseOver ? 4f : 2f) / camera.Zoom);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mouseOver)
|
||||||
|
{
|
||||||
|
string str = hullCollection.Name;
|
||||||
|
Vector2 strSize = GUI.Font.MeasureString(str) / camera.Zoom;
|
||||||
|
Vector2 padding = new Vector2(30, 30) / camera.Zoom;
|
||||||
|
Vector2 shift = new Vector2(10, 0) / camera.Zoom;
|
||||||
|
|
||||||
|
GUI.DrawRectangle(spriteBatch, mousePos + shift, strSize + padding, Color.Black, isFilled: true, depth: 0.25f);
|
||||||
|
GUI.Font.DrawString(spriteBatch, str, mousePos + shift + (strSize + padding) * 0.5f, Color.White, 0f, strSize * camera.Zoom * 0.5f, 1f / camera.Zoom, SpriteEffects.None, 0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach (var door in doors)
|
||||||
|
{
|
||||||
|
GUI.DrawRectangle(spriteBatch, door.Rect, GUI.Style.Green * 0.5f, isFilled: true, depth: 0.4f);
|
||||||
|
}
|
||||||
|
spriteBatch.End();
|
||||||
|
|
||||||
|
GameMain.Instance.GraphicsDevice.ScissorRectangle = prevScissorRect;
|
||||||
|
spriteBatch.Begin(SpriteSortMode.Deferred);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
previewFrame = null;
|
||||||
|
spriteRecorder?.Dispose();
|
||||||
|
isDisposed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -222,18 +222,20 @@ namespace Barotrauma
|
|||||||
private bool ChangeSpawnType(GUIButton button, object obj)
|
private bool ChangeSpawnType(GUIButton button, object obj)
|
||||||
{
|
{
|
||||||
GUITextBlock spawnTypeText = button.Parent.GetChildByUserData("spawntypetext") as GUITextBlock;
|
GUITextBlock spawnTypeText = button.Parent.GetChildByUserData("spawntypetext") as GUITextBlock;
|
||||||
spawnType += (int)button.UserData;
|
var values = (SpawnType[])Enum.GetValues(typeof(SpawnType));
|
||||||
var values = Enum.GetValues(typeof(SpawnType));
|
int currIndex = values.IndexOf(spawnType);
|
||||||
|
currIndex += (int)button.UserData;
|
||||||
int firstIndex = 1;
|
int firstIndex = 1;
|
||||||
int lastIndex = values.Length - 1;
|
int lastIndex = values.Length - 1;
|
||||||
if ((int)spawnType > lastIndex)
|
if (currIndex > lastIndex)
|
||||||
{
|
{
|
||||||
spawnType = (SpawnType)firstIndex;
|
currIndex = firstIndex;
|
||||||
}
|
}
|
||||||
if ((int)spawnType < firstIndex)
|
if (currIndex < firstIndex)
|
||||||
{
|
{
|
||||||
spawnType = (SpawnType)values.GetValue(lastIndex);
|
currIndex = lastIndex;
|
||||||
}
|
}
|
||||||
|
spawnType = values[currIndex];
|
||||||
spawnTypeText.Text = spawnType.ToString();
|
spawnTypeText.Text = spawnType.ToString();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,12 +3,13 @@ using Microsoft.Xna.Framework;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
namespace Barotrauma.Networking
|
namespace Barotrauma.Networking
|
||||||
{
|
{
|
||||||
partial class BannedPlayer
|
partial class BannedPlayer
|
||||||
{
|
{
|
||||||
public BannedPlayer(string name, UInt16 uniqueIdentifier, bool isRangeBan, string endPoint, ulong steamID)
|
public BannedPlayer(string name, UInt16 uniqueIdentifier, bool isRangeBan, string endPoint, ulong steamID, string reason, DateTime? expiration)
|
||||||
{
|
{
|
||||||
this.Name = name;
|
this.Name = name;
|
||||||
this.EndPoint = endPoint;
|
this.EndPoint = endPoint;
|
||||||
@@ -16,6 +17,8 @@ namespace Barotrauma.Networking
|
|||||||
ParseEndPointAsSteamId();
|
ParseEndPointAsSteamId();
|
||||||
this.IsRangeBan = isRangeBan;
|
this.IsRangeBan = isRangeBan;
|
||||||
this.UniqueIdentifier = uniqueIdentifier;
|
this.UniqueIdentifier = uniqueIdentifier;
|
||||||
|
this.Reason = reason;
|
||||||
|
this.ExpirationTime = expiration;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,12 +155,24 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
bannedPlayers.Clear();
|
bannedPlayers.Clear();
|
||||||
UInt32 bannedPlayerCount = incMsg.ReadVariableUInt32();
|
UInt32 bannedPlayerCount = incMsg.ReadVariableUInt32();
|
||||||
|
|
||||||
for (int i = 0; i < (int)bannedPlayerCount; i++)
|
for (int i = 0; i < (int)bannedPlayerCount; i++)
|
||||||
{
|
{
|
||||||
string name = incMsg.ReadString();
|
string name = incMsg.ReadString();
|
||||||
UInt16 uniqueIdentifier = incMsg.ReadUInt16();
|
UInt16 uniqueIdentifier = incMsg.ReadUInt16();
|
||||||
bool isRangeBan = incMsg.ReadBoolean(); incMsg.ReadPadBits();
|
bool isRangeBan = incMsg.ReadBoolean();
|
||||||
|
bool includesExpiration = incMsg.ReadBoolean();
|
||||||
|
incMsg.ReadPadBits();
|
||||||
|
|
||||||
|
DateTime? expiration = null;
|
||||||
|
if (includesExpiration)
|
||||||
|
{
|
||||||
|
double hoursFromNow = incMsg.ReadDouble();
|
||||||
|
expiration = DateTime.Now + TimeSpan.FromHours(hoursFromNow);
|
||||||
|
}
|
||||||
|
|
||||||
|
string reason = incMsg.ReadString();
|
||||||
|
|
||||||
string endPoint = "";
|
string endPoint = "";
|
||||||
UInt64 steamID = 0;
|
UInt64 steamID = 0;
|
||||||
if (isOwner)
|
if (isOwner)
|
||||||
@@ -170,7 +185,7 @@ namespace Barotrauma.Networking
|
|||||||
endPoint = "Endpoint concealed by host";
|
endPoint = "Endpoint concealed by host";
|
||||||
steamID = 0;
|
steamID = 0;
|
||||||
}
|
}
|
||||||
bannedPlayers.Add(new BannedPlayer(name, uniqueIdentifier, isRangeBan, endPoint, steamID));
|
bannedPlayers.Add(new BannedPlayer(name, uniqueIdentifier, isRangeBan, endPoint, steamID, reason, expiration));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (banFrame != null)
|
if (banFrame != null)
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
public static void ClientRead(IReadMessage msg)
|
public static void ClientRead(IReadMessage msg)
|
||||||
{
|
{
|
||||||
UInt16 ID = msg.ReadUInt16();
|
UInt16 id = msg.ReadUInt16();
|
||||||
ChatMessageType type = (ChatMessageType)msg.ReadByte();
|
ChatMessageType type = (ChatMessageType)msg.ReadByte();
|
||||||
PlayerConnectionChangeType changeType = PlayerConnectionChangeType.None;
|
PlayerConnectionChangeType changeType = PlayerConnectionChangeType.None;
|
||||||
string txt = "";
|
string txt = "";
|
||||||
@@ -29,6 +29,14 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
string senderName = msg.ReadString();
|
string senderName = msg.ReadString();
|
||||||
Character senderCharacter = null;
|
Character senderCharacter = null;
|
||||||
|
Client senderClient = null;
|
||||||
|
bool hasSenderClient = msg.ReadBoolean();
|
||||||
|
if (hasSenderClient)
|
||||||
|
{
|
||||||
|
UInt64 clientId = msg.ReadUInt64();
|
||||||
|
senderClient = GameMain.Client.ConnectedClients.Find(c => c.SteamID == clientId || c.ID == clientId);
|
||||||
|
if (senderClient != null) { senderName = senderClient.Name; }
|
||||||
|
}
|
||||||
bool hasSenderCharacter = msg.ReadBoolean();
|
bool hasSenderCharacter = msg.ReadBoolean();
|
||||||
if (hasSenderCharacter)
|
if (hasSenderCharacter)
|
||||||
{
|
{
|
||||||
@@ -38,6 +46,7 @@ namespace Barotrauma.Networking
|
|||||||
senderName = senderCharacter.Name;
|
senderName = senderCharacter.Name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
msg.ReadPadBits();
|
||||||
|
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
@@ -48,7 +57,54 @@ namespace Barotrauma.Networking
|
|||||||
UInt16 targetCharacterID = msg.ReadUInt16();
|
UInt16 targetCharacterID = msg.ReadUInt16();
|
||||||
Character targetCharacter = Entity.FindEntityByID(targetCharacterID) as Character;
|
Character targetCharacter = Entity.FindEntityByID(targetCharacterID) as Character;
|
||||||
Entity targetEntity = Entity.FindEntityByID(msg.ReadUInt16());
|
Entity targetEntity = Entity.FindEntityByID(msg.ReadUInt16());
|
||||||
int optionIndex = msg.ReadByte();
|
|
||||||
|
Order orderPrefab = null;
|
||||||
|
int? optionIndex = null;
|
||||||
|
string orderOption = null;
|
||||||
|
|
||||||
|
// The option of a Dismiss order is written differently so we know what order we target
|
||||||
|
// now that the game supports multiple current orders simultaneously
|
||||||
|
if (orderIndex >= 0 && orderIndex < Order.PrefabList.Count)
|
||||||
|
{
|
||||||
|
orderPrefab = Order.PrefabList[orderIndex];
|
||||||
|
if (orderPrefab.Identifier != "dismissed")
|
||||||
|
{
|
||||||
|
optionIndex = msg.ReadByte();
|
||||||
|
}
|
||||||
|
// Does the dismiss order have a specified target?
|
||||||
|
else if (msg.ReadBoolean())
|
||||||
|
{
|
||||||
|
int identifierCount = msg.ReadByte();
|
||||||
|
if (identifierCount > 0)
|
||||||
|
{
|
||||||
|
int dismissedOrderIndex = msg.ReadByte();
|
||||||
|
Order dismissedOrderPrefab = null;
|
||||||
|
if (dismissedOrderIndex >= 0 && dismissedOrderIndex < Order.PrefabList.Count)
|
||||||
|
{
|
||||||
|
dismissedOrderPrefab = Order.PrefabList[dismissedOrderIndex];
|
||||||
|
orderOption = dismissedOrderPrefab.Identifier;
|
||||||
|
}
|
||||||
|
if (identifierCount > 1)
|
||||||
|
{
|
||||||
|
int dismissedOrderOptionIndex = msg.ReadByte();
|
||||||
|
if (dismissedOrderPrefab != null)
|
||||||
|
{
|
||||||
|
var options = dismissedOrderPrefab.Options;
|
||||||
|
if (options != null && dismissedOrderOptionIndex >= 0 && dismissedOrderOptionIndex < options.Length)
|
||||||
|
{
|
||||||
|
orderOption += $".{options[dismissedOrderOptionIndex]}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
optionIndex = msg.ReadByte();
|
||||||
|
}
|
||||||
|
|
||||||
|
int orderPriority = msg.ReadByte();
|
||||||
OrderTarget orderTargetPosition = null;
|
OrderTarget orderTargetPosition = null;
|
||||||
Order.OrderTargetType orderTargetType = (Order.OrderTargetType)msg.ReadByte();
|
Order.OrderTargetType orderTargetType = (Order.OrderTargetType)msg.ReadByte();
|
||||||
int wallSectionIndex = 0;
|
int wallSectionIndex = 0;
|
||||||
@@ -64,22 +120,18 @@ namespace Barotrauma.Networking
|
|||||||
wallSectionIndex = msg.ReadByte();
|
wallSectionIndex = msg.ReadByte();
|
||||||
}
|
}
|
||||||
|
|
||||||
Order orderPrefab;
|
|
||||||
if (orderIndex < 0 || orderIndex >= Order.PrefabList.Count)
|
if (orderIndex < 0 || orderIndex >= Order.PrefabList.Count)
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError("Invalid order message - order index out of bounds.");
|
DebugConsole.ThrowError("Invalid order message - order index out of bounds.");
|
||||||
if (NetIdUtils.IdMoreRecent(ID, LastID)) { LastID = ID; }
|
if (NetIdUtils.IdMoreRecent(id, LastID)) { LastID = id; }
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
orderPrefab = Order.PrefabList[orderIndex];
|
orderPrefab ??= Order.PrefabList[orderIndex];
|
||||||
}
|
|
||||||
string orderOption = "";
|
|
||||||
if (optionIndex >= 0 && optionIndex < orderPrefab.Options.Length)
|
|
||||||
{
|
|
||||||
orderOption = orderPrefab.Options[optionIndex];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
orderOption ??= optionIndex.HasValue && optionIndex >= 0 && optionIndex < orderPrefab.Options.Length ? orderPrefab.Options[optionIndex.Value] : "";
|
||||||
txt = orderPrefab.GetChatMessage(targetCharacter?.Name, senderCharacter?.CurrentHull?.DisplayName, givingOrderToSelf: targetCharacter == senderCharacter, orderOption: orderOption);
|
txt = orderPrefab.GetChatMessage(targetCharacter?.Name, senderCharacter?.CurrentHull?.DisplayName, givingOrderToSelf: targetCharacter == senderCharacter, orderOption: orderOption);
|
||||||
|
|
||||||
if (GameMain.Client.GameStarted && Screen.Selected == GameMain.GameScreen)
|
if (GameMain.Client.GameStarted && Screen.Selected == GameMain.GameScreen)
|
||||||
@@ -107,16 +159,16 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
else if (targetCharacter != null)
|
else if (targetCharacter != null)
|
||||||
{
|
{
|
||||||
targetCharacter.SetOrder(order, orderOption, senderCharacter);
|
targetCharacter.SetOrder(order, orderOption, orderPriority, senderCharacter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NetIdUtils.IdMoreRecent(ID, LastID))
|
if (NetIdUtils.IdMoreRecent(id, LastID))
|
||||||
{
|
{
|
||||||
GameMain.Client.AddChatMessage(
|
GameMain.Client.AddChatMessage(
|
||||||
new OrderChatMessage(orderPrefab, orderOption, txt, orderTargetPosition ?? targetEntity as ISpatialEntity, targetCharacter, senderCharacter));
|
new OrderChatMessage(orderPrefab, orderOption, orderPriority, txt, orderTargetPosition ?? targetEntity as ISpatialEntity, targetCharacter, senderCharacter));
|
||||||
LastID = ID;
|
LastID = id;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case ChatMessageType.ServerMessageBox:
|
case ChatMessageType.ServerMessageBox:
|
||||||
@@ -128,7 +180,7 @@ namespace Barotrauma.Networking
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NetIdUtils.IdMoreRecent(ID, LastID))
|
if (NetIdUtils.IdMoreRecent(id, LastID))
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
@@ -154,10 +206,10 @@ namespace Barotrauma.Networking
|
|||||||
GameMain.Client.ServerSettings.ServerLog?.WriteLine(txt, messageType);
|
GameMain.Client.ServerSettings.ServerLog?.WriteLine(txt, messageType);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
GameMain.Client.AddChatMessage(txt, type, senderName, senderCharacter, changeType);
|
GameMain.Client.AddChatMessage(txt, type, senderName, senderClient, senderCharacter, changeType);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
LastID = ID;
|
LastID = id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ namespace Barotrauma.Networking
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Permissions = permissions;
|
Permissions = permissions;
|
||||||
PermittedConsoleCommands = new List<DebugConsole.Command>(permittedConsoleCommands);
|
PermittedConsoleCommands.Clear(); PermittedConsoleCommands.AddRange(permittedConsoleCommands);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void GivePermission(ClientPermissions permission)
|
public void GivePermission(ClientPermissions permission)
|
||||||
|
|||||||
@@ -56,6 +56,11 @@ namespace Barotrauma.Networking
|
|||||||
public readonly NetStats NetStats;
|
public readonly NetStats NetStats;
|
||||||
|
|
||||||
protected GUITickBox cameraFollowsSub;
|
protected GUITickBox cameraFollowsSub;
|
||||||
|
public GUITickBox FollowSubTickBox => cameraFollowsSub;
|
||||||
|
|
||||||
|
public bool IsFollowSubTickBoxVisible =>
|
||||||
|
gameStarted && Screen.Selected == GameMain.GameScreen &&
|
||||||
|
cameraFollowsSub != null && cameraFollowsSub.Visible;
|
||||||
|
|
||||||
public CameraTransition EndCinematic;
|
public CameraTransition EndCinematic;
|
||||||
|
|
||||||
@@ -159,6 +164,12 @@ namespace Barotrauma.Networking
|
|||||||
get { return entityEventManager; }
|
get { return entityEventManager; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool? WaitForNextRoundRespawn
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
private readonly object serverEndpoint;
|
private readonly object serverEndpoint;
|
||||||
private readonly int ownerKey;
|
private readonly int ownerKey;
|
||||||
private readonly bool steamP2POwner;
|
private readonly bool steamP2POwner;
|
||||||
@@ -185,10 +196,10 @@ namespace Barotrauma.Networking
|
|||||||
CanBeFocused = false
|
CanBeFocused = false
|
||||||
};
|
};
|
||||||
|
|
||||||
cameraFollowsSub = new GUITickBox(new RectTransform(new Vector2(0.05f, 0.05f), inGameHUD.RectTransform, anchor: Anchor.TopCenter)
|
cameraFollowsSub = new GUITickBox(new RectTransform(new Vector2(0.05f, 0.05f), inGameHUD.RectTransform, anchor: Anchor.TopCenter, pivot: Pivot.CenterLeft)
|
||||||
{
|
{
|
||||||
AbsoluteOffset = new Point(0, 5),
|
AbsoluteOffset = new Point(0, HUDLayoutSettings.ButtonAreaTop.Y + HUDLayoutSettings.ButtonAreaTop.Height / 2),
|
||||||
MaxSize = new Point(25, 25)
|
MaxSize = new Point(GUI.IntScale(25))
|
||||||
}, TextManager.Get("CamFollowSubmarine"))
|
}, TextManager.Get("CamFollowSubmarine"))
|
||||||
{
|
{
|
||||||
Selected = Camera.FollowSub,
|
Selected = Camera.FollowSub,
|
||||||
@@ -857,12 +868,25 @@ namespace Barotrauma.Networking
|
|||||||
string endMessage = string.Empty;
|
string endMessage = string.Empty;
|
||||||
|
|
||||||
endMessage = inc.ReadString();
|
endMessage = inc.ReadString();
|
||||||
bool missionSuccessful = inc.ReadBoolean();
|
byte missionCount = inc.ReadByte();
|
||||||
|
for (int i = 0; i < missionCount; i++)
|
||||||
|
{
|
||||||
|
bool missionSuccessful = inc.ReadBoolean();
|
||||||
|
var mission = GameMain.GameSession?.GetMission(i);
|
||||||
|
if (mission != null)
|
||||||
|
{
|
||||||
|
mission.Completed = missionSuccessful;
|
||||||
|
}
|
||||||
|
}
|
||||||
CharacterTeamType winningTeam = (CharacterTeamType)inc.ReadByte();
|
CharacterTeamType winningTeam = (CharacterTeamType)inc.ReadByte();
|
||||||
if (missionSuccessful && GameMain.GameSession?.Mission != null)
|
if (winningTeam != CharacterTeamType.None)
|
||||||
{
|
{
|
||||||
GameMain.GameSession.WinningTeam = winningTeam;
|
GameMain.GameSession.WinningTeam = winningTeam;
|
||||||
GameMain.GameSession.Mission.Completed = true;
|
var combatMission = GameMain.GameSession.Missions.FirstOrDefault(m => m is CombatMission);
|
||||||
|
if (combatMission != null)
|
||||||
|
{
|
||||||
|
combatMission.Completed = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
byte traitorCount = inc.ReadByte();
|
byte traitorCount = inc.ReadByte();
|
||||||
@@ -928,7 +952,11 @@ namespace Barotrauma.Networking
|
|||||||
ReadTraitorMessage(inc);
|
ReadTraitorMessage(inc);
|
||||||
break;
|
break;
|
||||||
case ServerPacketHeader.MISSION:
|
case ServerPacketHeader.MISSION:
|
||||||
GameMain.GameSession?.Mission?.ClientRead(inc);
|
{
|
||||||
|
int missionIndex = inc.ReadByte();
|
||||||
|
Mission mission = GameMain.GameSession?.GetMission(missionIndex);
|
||||||
|
mission?.ClientRead(inc);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case ServerPacketHeader.EVENTACTION:
|
case ServerPacketHeader.EVENTACTION:
|
||||||
GameMain.GameSession?.EventManager.ClientRead(inc);
|
GameMain.GameSession?.EventManager.ClientRead(inc);
|
||||||
@@ -959,17 +987,26 @@ namespace Barotrauma.Networking
|
|||||||
throw new Exception(errorMsg);
|
throw new Exception(errorMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
string missionIdentifier = inc.ReadString() ?? "";
|
byte missionCount = inc.ReadByte();
|
||||||
if (missionIdentifier != (GameMain.GameSession.Mission?.Prefab.Identifier ?? ""))
|
if (missionCount != GameMain.GameSession.Missions.Count())
|
||||||
{
|
{
|
||||||
string errorMsg = $"Mission equality check failed. The mission selected at your end doesn't match the one loaded by the server (server: {missionIdentifier ?? "null"}, client: {GameMain.GameSession.Mission?.Prefab.Identifier ?? ""})";
|
string errorMsg = $"Mission equality check failed. Mission count doesn't match the server (server: {missionCount}, client: {GameMain.GameSession.Missions.Count()})";
|
||||||
GameAnalyticsManager.AddErrorEventOnce("GameClient.StartGame:MissionsDontMatch" + Level.Loaded.Seed, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
|
||||||
throw new Exception(errorMsg);
|
throw new Exception(errorMsg);
|
||||||
}
|
}
|
||||||
|
foreach (Mission mission in GameMain.GameSession.Missions)
|
||||||
|
{
|
||||||
|
string missionIdentifier = inc.ReadString() ?? "";
|
||||||
|
if (missionIdentifier != mission.Prefab.Identifier)
|
||||||
|
{
|
||||||
|
string errorMsg = $"Mission equality check failed. The mission selected at your end doesn't match the one loaded by the server (server: {missionIdentifier ?? "null"}, client: {mission.Prefab.Identifier})";
|
||||||
|
GameAnalyticsManager.AddErrorEventOnce("GameClient.StartGame:MissionsDontMatch" + Level.Loaded.Seed, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||||
|
throw new Exception(errorMsg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
byte equalityCheckValueCount = inc.ReadByte();
|
byte equalityCheckValueCount = inc.ReadByte();
|
||||||
List<int> levelEqualityCheckValues = new List<int>();
|
List<int> levelEqualityCheckValues = new List<int>();
|
||||||
for (int i = 0; i<equalityCheckValueCount; i++)
|
for (int i = 0; i < equalityCheckValueCount; i++)
|
||||||
{
|
{
|
||||||
levelEqualityCheckValues.Add(inc.ReadInt32());
|
levelEqualityCheckValues.Add(inc.ReadInt32());
|
||||||
}
|
}
|
||||||
@@ -1004,7 +1041,10 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GameMain.GameSession.Mission?.ClientReadInitial(inc);
|
foreach (Mission mission in GameMain.GameSession.Missions)
|
||||||
|
{
|
||||||
|
mission.ClientReadInitial(inc);
|
||||||
|
}
|
||||||
|
|
||||||
roundInitStatus = RoundInitStatus.Started;
|
roundInitStatus = RoundInitStatus.Started;
|
||||||
}
|
}
|
||||||
@@ -1395,6 +1435,8 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
EndVoteTickBox.Selected = false;
|
EndVoteTickBox.Selected = false;
|
||||||
|
|
||||||
|
WaitForNextRoundRespawn = null;
|
||||||
|
|
||||||
roundInitStatus = RoundInitStatus.Starting;
|
roundInitStatus = RoundInitStatus.Starting;
|
||||||
|
|
||||||
int seed = inc.ReadInt32();
|
int seed = inc.ReadInt32();
|
||||||
@@ -1411,6 +1453,7 @@ namespace Barotrauma.Networking
|
|||||||
bool respawnAllowed = inc.ReadBoolean();
|
bool respawnAllowed = inc.ReadBoolean();
|
||||||
serverSettings.AllowDisguises = inc.ReadBoolean();
|
serverSettings.AllowDisguises = inc.ReadBoolean();
|
||||||
serverSettings.AllowRewiring = inc.ReadBoolean();
|
serverSettings.AllowRewiring = inc.ReadBoolean();
|
||||||
|
serverSettings.LockAllDefaultWires = inc.ReadBoolean();
|
||||||
serverSettings.AllowRagdollButton = inc.ReadBoolean();
|
serverSettings.AllowRagdollButton = inc.ReadBoolean();
|
||||||
GameMain.NetLobbyScreen.UsingShuttle = inc.ReadBoolean();
|
GameMain.NetLobbyScreen.UsingShuttle = inc.ReadBoolean();
|
||||||
GameMain.LightManager.LosMode = (LosMode)inc.ReadByte();
|
GameMain.LightManager.LosMode = (LosMode)inc.ReadByte();
|
||||||
@@ -1432,7 +1475,12 @@ namespace Barotrauma.Networking
|
|||||||
string subHash = inc.ReadString();
|
string subHash = inc.ReadString();
|
||||||
string shuttleName = inc.ReadString();
|
string shuttleName = inc.ReadString();
|
||||||
string shuttleHash = inc.ReadString();
|
string shuttleHash = inc.ReadString();
|
||||||
int missionIndex = inc.ReadInt16();
|
List<int> missionIndices = new List<int>();
|
||||||
|
int missionCount = inc.ReadByte();
|
||||||
|
for (int i = 0; i < missionCount; i++)
|
||||||
|
{
|
||||||
|
missionIndices.Add(inc.ReadInt16());
|
||||||
|
}
|
||||||
if (!GameMain.NetLobbyScreen.TrySelectSub(subName, subHash, GameMain.NetLobbyScreen.SubList))
|
if (!GameMain.NetLobbyScreen.TrySelectSub(subName, subHash, GameMain.NetLobbyScreen.SubList))
|
||||||
{
|
{
|
||||||
roundInitStatus = RoundInitStatus.Interrupted;
|
roundInitStatus = RoundInitStatus.Interrupted;
|
||||||
@@ -1486,7 +1534,9 @@ namespace Barotrauma.Networking
|
|||||||
yield return CoroutineStatus.Failure;
|
yield return CoroutineStatus.Failure;
|
||||||
}
|
}
|
||||||
|
|
||||||
GameMain.GameSession = new GameSession(GameMain.NetLobbyScreen.SelectedSub, gameMode, missionPrefab: missionIndex < 0 ? null : MissionPrefab.List[missionIndex]);
|
var selectedMissions = missionIndices.Select(i => MissionPrefab.List[i]);
|
||||||
|
|
||||||
|
GameMain.GameSession = new GameSession(GameMain.NetLobbyScreen.SelectedSub, gameMode, missionPrefabs: selectedMissions);
|
||||||
GameMain.GameSession.StartRound(levelSeed, levelDifficulty);
|
GameMain.GameSession.StartRound(levelSeed, levelDifficulty);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1653,13 +1703,15 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
foreach (Submarine sub in Submarine.MainSubs[i].DockedTo)
|
foreach (Submarine sub in Submarine.MainSubs[i].DockedTo)
|
||||||
{
|
{
|
||||||
|
if (sub.Info.Type == SubmarineType.Outpost) { continue; }
|
||||||
sub.TeamID = teamID;
|
sub.TeamID = teamID;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (respawnAllowed)
|
if (respawnAllowed)
|
||||||
{
|
{
|
||||||
respawnManager = new RespawnManager(this, GameMain.NetLobbyScreen.UsingShuttle && gameMode != GameModePreset.MultiPlayerCampaign ? GameMain.NetLobbyScreen.SelectedShuttle : null);
|
bool isOutpost = GameMain.GameSession?.GameMode is MultiPlayerCampaign campaign && Level.Loaded?.Type == LevelData.LevelType.Outpost;
|
||||||
|
respawnManager = new RespawnManager(this, GameMain.NetLobbyScreen.UsingShuttle && !isOutpost ? GameMain.NetLobbyScreen.SelectedShuttle : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
gameStarted = true;
|
gameStarted = true;
|
||||||
@@ -1702,6 +1754,7 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
gameStarted = false;
|
gameStarted = false;
|
||||||
Character.Controlled = null;
|
Character.Controlled = null;
|
||||||
|
WaitForNextRoundRespawn = null;
|
||||||
SpawnAsTraitor = false;
|
SpawnAsTraitor = false;
|
||||||
GameMain.GameScreen.Cam.TargetPos = Vector2.Zero;
|
GameMain.GameScreen.Cam.TargetPos = Vector2.Zero;
|
||||||
GameMain.LightManager.LosEnabled = false;
|
GameMain.LightManager.LosEnabled = false;
|
||||||
@@ -1712,7 +1765,7 @@ namespace Barotrauma.Networking
|
|||||||
// Enable characters near the main sub for the endCinematic
|
// Enable characters near the main sub for the endCinematic
|
||||||
foreach (Character c in Character.CharacterList)
|
foreach (Character c in Character.CharacterList)
|
||||||
{
|
{
|
||||||
if (Vector2.DistanceSquared(Submarine.MainSub.WorldPosition, c.WorldPosition) < NetConfig.EnableCharacterDistSqr)
|
if (Vector2.DistanceSquared(Submarine.MainSub.WorldPosition, c.WorldPosition) < MathUtils.Pow2(c.Params.DisableDistance))
|
||||||
{
|
{
|
||||||
c.Enabled = true;
|
c.Enabled = true;
|
||||||
}
|
}
|
||||||
@@ -1757,8 +1810,10 @@ namespace Barotrauma.Networking
|
|||||||
var matchingSub = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.Name == subName && s.MD5Hash.Hash == subHash);
|
var matchingSub = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.Name == subName && s.MD5Hash.Hash == subHash);
|
||||||
if (matchingSub == null)
|
if (matchingSub == null)
|
||||||
{
|
{
|
||||||
matchingSub = new SubmarineInfo(Path.Combine(SubmarineInfo.SavePath, subName) + ".sub", subHash, tryLoad: false);
|
matchingSub = new SubmarineInfo(Path.Combine(SubmarineInfo.SavePath, subName) + ".sub", subHash, tryLoad: false)
|
||||||
matchingSub.SubmarineClass = (SubmarineClass)subClass;
|
{
|
||||||
|
SubmarineClass = (SubmarineClass)subClass
|
||||||
|
};
|
||||||
}
|
}
|
||||||
matchingSub.RequiredContentPackagesInstalled = requiredContentPackagesInstalled;
|
matchingSub.RequiredContentPackagesInstalled = requiredContentPackagesInstalled;
|
||||||
ServerSubmarines.Add(matchingSub);
|
ServerSubmarines.Add(matchingSub);
|
||||||
@@ -1928,14 +1983,19 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
foreach (Client client in ConnectedClients)
|
foreach (Client client in ConnectedClients)
|
||||||
{
|
{
|
||||||
if (!previouslyConnectedClients.Any(c => c.ID == client.ID))
|
int index = previouslyConnectedClients.FindIndex(c => c.ID == client.ID);
|
||||||
|
if (index < 0)
|
||||||
{
|
{
|
||||||
while (previouslyConnectedClients.Count > 100)
|
if (previouslyConnectedClients.Count > 100)
|
||||||
{
|
{
|
||||||
previouslyConnectedClients.RemoveAt(0);
|
previouslyConnectedClients.RemoveRange(0, previouslyConnectedClients.Count - 100);
|
||||||
}
|
}
|
||||||
previouslyConnectedClients.Add(client);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
previouslyConnectedClients.RemoveAt(index);
|
||||||
|
}
|
||||||
|
previouslyConnectedClients.Add(client);
|
||||||
}
|
}
|
||||||
if (updateClientListId) { LastClientListUpdateID = listId; }
|
if (updateClientListId) { LastClientListUpdateID = listId; }
|
||||||
|
|
||||||
@@ -2028,6 +2088,8 @@ namespace Barotrauma.Networking
|
|||||||
bool autoRestartEnabled = inc.ReadBoolean();
|
bool autoRestartEnabled = inc.ReadBoolean();
|
||||||
float autoRestartTimer = autoRestartEnabled ? inc.ReadSingle() : 0.0f;
|
float autoRestartTimer = autoRestartEnabled ? inc.ReadSingle() : 0.0f;
|
||||||
|
|
||||||
|
bool radiationEnabled = inc.ReadBoolean();
|
||||||
|
|
||||||
//ignore the message if we already a more up-to-date one
|
//ignore the message if we already a more up-to-date one
|
||||||
//or if we're still waiting for the initial update
|
//or if we're still waiting for the initial update
|
||||||
if (NetIdUtils.IdMoreRecent(updateID, GameMain.NetLobbyScreen.LastUpdateID) &&
|
if (NetIdUtils.IdMoreRecent(updateID, GameMain.NetLobbyScreen.LastUpdateID) &&
|
||||||
@@ -2038,8 +2100,14 @@ namespace Barotrauma.Networking
|
|||||||
serverSettings.ClientRead(settingsBuf);
|
serverSettings.ClientRead(settingsBuf);
|
||||||
if (!IsServerOwner)
|
if (!IsServerOwner)
|
||||||
{
|
{
|
||||||
ServerInfo info = GameMain.ServerListScreen.UpdateServerInfoWithServerSettings(serverEndpoint, serverSettings);
|
ServerInfo info = serverSettings.GetServerListInfo();
|
||||||
GameMain.ServerListScreen.AddToRecentServers(info);
|
GameMain.ServerListScreen.AddToRecentServers(info);
|
||||||
|
GameMain.NetLobbyScreen.Favorite.Visible = true;
|
||||||
|
GameMain.NetLobbyScreen.Favorite.Selected = GameMain.ServerListScreen.IsFavorite(info);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GameMain.NetLobbyScreen.Favorite.Visible = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
GameMain.NetLobbyScreen.LastUpdateID = updateID;
|
GameMain.NetLobbyScreen.LastUpdateID = updateID;
|
||||||
@@ -2083,8 +2151,9 @@ namespace Barotrauma.Networking
|
|||||||
GameMain.NetLobbyScreen.SetAllowSpectating(allowSpectating);
|
GameMain.NetLobbyScreen.SetAllowSpectating(allowSpectating);
|
||||||
GameMain.NetLobbyScreen.LevelSeed = levelSeed;
|
GameMain.NetLobbyScreen.LevelSeed = levelSeed;
|
||||||
GameMain.NetLobbyScreen.SetLevelDifficulty(levelDifficulty);
|
GameMain.NetLobbyScreen.SetLevelDifficulty(levelDifficulty);
|
||||||
GameMain.NetLobbyScreen.SetBotCount(botCount);
|
GameMain.NetLobbyScreen.SetRadiationEnabled(radiationEnabled);
|
||||||
GameMain.NetLobbyScreen.SetBotSpawnMode(botSpawnMode);
|
GameMain.NetLobbyScreen.SetBotSpawnMode(botSpawnMode);
|
||||||
|
GameMain.NetLobbyScreen.SetBotCount(botCount);
|
||||||
GameMain.NetLobbyScreen.SetAutoRestart(autoRestartEnabled, autoRestartTimer);
|
GameMain.NetLobbyScreen.SetAutoRestart(autoRestartEnabled, autoRestartTimer);
|
||||||
|
|
||||||
serverSettings.VoiceChatEnabled = voiceChatEnabled;
|
serverSettings.VoiceChatEnabled = voiceChatEnabled;
|
||||||
@@ -2325,7 +2394,7 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
if (outmsg.LengthBytes > MsgConstants.MTU)
|
if (outmsg.LengthBytes > MsgConstants.MTU)
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError("Maximum packet size exceeded (" + outmsg.LengthBytes + " > " + MsgConstants.MTU);
|
DebugConsole.ThrowError($"Maximum packet size exceeded ({outmsg.LengthBytes} > {MsgConstants.MTU})");
|
||||||
}
|
}
|
||||||
|
|
||||||
clientPeer.Send(outmsg, DeliveryMethod.Unreliable);
|
clientPeer.Send(outmsg, DeliveryMethod.Unreliable);
|
||||||
@@ -2376,7 +2445,7 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
if (outmsg.LengthBytes > MsgConstants.MTU)
|
if (outmsg.LengthBytes > MsgConstants.MTU)
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError("Maximum packet size exceeded (" + outmsg.LengthBytes + " > " + MsgConstants.MTU);
|
DebugConsole.ThrowError($"Maximum packet size exceeded ({outmsg.LengthBytes} > {MsgConstants.MTU})");
|
||||||
}
|
}
|
||||||
|
|
||||||
clientPeer.Send(outmsg, DeliveryMethod.Unreliable);
|
clientPeer.Send(outmsg, DeliveryMethod.Unreliable);
|
||||||
@@ -2406,6 +2475,15 @@ namespace Barotrauma.Networking
|
|||||||
chatMsgQueue.Add(chatMessage);
|
chatMsgQueue.Add(chatMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SendRespawnPromptResponse(bool waitForNextRoundRespawn)
|
||||||
|
{
|
||||||
|
WaitForNextRoundRespawn = waitForNextRoundRespawn;
|
||||||
|
IWriteMessage msg = new WriteOnlyMessage();
|
||||||
|
msg.Write((byte)ClientPacketHeader.READY_TO_SPAWN);
|
||||||
|
msg.Write((bool)waitForNextRoundRespawn);
|
||||||
|
clientPeer?.Send(msg, DeliveryMethod.Reliable);
|
||||||
|
}
|
||||||
|
|
||||||
public void RequestFile(FileTransferType fileType, string file, string fileHash)
|
public void RequestFile(FileTransferType fileType, string file, string fileHash)
|
||||||
{
|
{
|
||||||
IWriteMessage msg = new WriteOnlyMessage();
|
IWriteMessage msg = new WriteOnlyMessage();
|
||||||
@@ -2528,7 +2606,7 @@ namespace Barotrauma.Networking
|
|||||||
if (!(GameMain.GameSession?.GameMode is MultiPlayerCampaign campaign) || campaign.CampaignID != campaignID)
|
if (!(GameMain.GameSession?.GameMode is MultiPlayerCampaign campaign) || campaign.CampaignID != campaignID)
|
||||||
{
|
{
|
||||||
string savePath = transfer.FilePath;
|
string savePath = transfer.FilePath;
|
||||||
GameMain.GameSession = new GameSession(null, savePath, GameModePreset.MultiPlayerCampaign);
|
GameMain.GameSession = new GameSession(null, savePath, GameModePreset.MultiPlayerCampaign, CampaignSettings.Unsure);
|
||||||
campaign = (MultiPlayerCampaign)GameMain.GameSession.GameMode;
|
campaign = (MultiPlayerCampaign)GameMain.GameSession.GameMode;
|
||||||
campaign.CampaignID = campaignID;
|
campaign.CampaignID = campaignID;
|
||||||
GameMain.NetLobbyScreen.ToggleCampaignMode(true);
|
GameMain.NetLobbyScreen.ToggleCampaignMode(true);
|
||||||
@@ -2876,7 +2954,7 @@ namespace Barotrauma.Networking
|
|||||||
clientPeer.Send(msg, DeliveryMethod.Reliable);
|
clientPeer.Send(msg, DeliveryMethod.Reliable);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetupNewCampaign(SubmarineInfo sub, string saveName, string mapSeed)
|
public void SetupNewCampaign(SubmarineInfo sub, string saveName, string mapSeed, CampaignSettings settings)
|
||||||
{
|
{
|
||||||
GameMain.NetLobbyScreen.CampaignSetupFrame.Visible = false;
|
GameMain.NetLobbyScreen.CampaignSetupFrame.Visible = false;
|
||||||
GameMain.NetLobbyScreen.CampaignFrame.Visible = false;
|
GameMain.NetLobbyScreen.CampaignFrame.Visible = false;
|
||||||
@@ -2891,6 +2969,7 @@ namespace Barotrauma.Networking
|
|||||||
msg.Write(mapSeed);
|
msg.Write(mapSeed);
|
||||||
msg.Write(sub.Name);
|
msg.Write(sub.Name);
|
||||||
msg.Write(sub.MD5Hash.Hash);
|
msg.Write(sub.MD5Hash.Hash);
|
||||||
|
settings.Serialize(msg);
|
||||||
|
|
||||||
clientPeer.Send(msg, DeliveryMethod.Reliable);
|
clientPeer.Send(msg, DeliveryMethod.Reliable);
|
||||||
}
|
}
|
||||||
@@ -3096,11 +3175,11 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
cameraFollowsSub.Visible = Character.Controlled == null;
|
cameraFollowsSub.Visible = Character.Controlled == null;
|
||||||
}
|
}
|
||||||
if (Character.Controlled == null || Character.Controlled.IsDead)
|
/*if (Character.Controlled == null || Character.Controlled.IsDead)
|
||||||
{
|
{
|
||||||
GameMain.GameScreen.Cam.TargetPos = Vector2.Zero;
|
GameMain.GameScreen.Cam.TargetPos = Vector2.Zero;
|
||||||
GameMain.LightManager.LosEnabled = false;
|
GameMain.LightManager.LosEnabled = false;
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
//tab doesn't autoselect the chatbox when debug console is open,
|
//tab doesn't autoselect the chatbox when debug console is open,
|
||||||
@@ -3208,9 +3287,13 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
if (respawnManager != null)
|
if (respawnManager != null)
|
||||||
{
|
{
|
||||||
string respawnText = "";
|
string respawnText = string.Empty;
|
||||||
float textScale = 1.0f;
|
|
||||||
Color textColor = Color.White;
|
Color textColor = Color.White;
|
||||||
|
bool canChooseRespawn =
|
||||||
|
GameMain.GameSession.GameMode is CampaignMode &&
|
||||||
|
Character.Controlled == null &&
|
||||||
|
Level.Loaded?.Type != LevelData.LevelType.Outpost &&
|
||||||
|
(characterInfo == null || HasSpawned);
|
||||||
if (respawnManager.CurrentState == RespawnManager.State.Waiting &&
|
if (respawnManager.CurrentState == RespawnManager.State.Waiting &&
|
||||||
respawnManager.RespawnCountdownStarted)
|
respawnManager.RespawnCountdownStarted)
|
||||||
{
|
{
|
||||||
@@ -3228,18 +3311,18 @@ namespace Barotrauma.Networking
|
|||||||
{
|
{
|
||||||
//oscillate between 0-1
|
//oscillate between 0-1
|
||||||
float phase = (float)(Math.Sin(timeLeft * MathHelper.Pi) + 1.0f) * 0.5f;
|
float phase = (float)(Math.Sin(timeLeft * MathHelper.Pi) + 1.0f) * 0.5f;
|
||||||
textScale = 1.0f + phase * 0.5f;
|
//textScale = 1.0f + phase * 0.5f;
|
||||||
textColor = Color.Lerp(GUI.Style.Red, Color.White, 1.0f - phase);
|
textColor = Color.Lerp(GUI.Style.Red, Color.White, 1.0f - phase);
|
||||||
}
|
}
|
||||||
|
canChooseRespawn = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(respawnText))
|
GameMain.GameSession?.SetRespawnInfo(
|
||||||
{
|
visible: !string.IsNullOrEmpty(respawnText) || canChooseRespawn, text: respawnText, textColor: textColor,
|
||||||
GUI.SmallFont.DrawString(spriteBatch, respawnText, new Vector2(120.0f, 10), textColor, 0.0f, Vector2.Zero, textScale, Microsoft.Xna.Framework.Graphics.SpriteEffects.None, 0.0f);
|
buttonsVisible: canChooseRespawn, waitForNextRoundRespawn: (WaitForNextRoundRespawn ?? true));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ShowNetStats) return;
|
if (!ShowNetStats) { return; }
|
||||||
|
|
||||||
NetStats.Draw(spriteBatch, new Rectangle(300, 10, 300, 150));
|
NetStats.Draw(spriteBatch, new Rectangle(300, 10, 300, 150));
|
||||||
|
|
||||||
@@ -3367,9 +3450,12 @@ namespace Barotrauma.Networking
|
|||||||
{
|
{
|
||||||
var banReasonPrompt = new GUIMessageBox(
|
var banReasonPrompt = new GUIMessageBox(
|
||||||
TextManager.Get(ban ? "BanReasonPrompt" : "KickReasonPrompt"),
|
TextManager.Get(ban ? "BanReasonPrompt" : "KickReasonPrompt"),
|
||||||
"", new string[] { TextManager.Get("OK"), TextManager.Get("Cancel") }, new Vector2(0.25f, 0.22f), new Point(400, 220));
|
"", new string[] { TextManager.Get("OK"), TextManager.Get("Cancel") }, new Vector2(0.25f, 0.25f), new Point(400, 260));
|
||||||
|
|
||||||
var content = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.6f), banReasonPrompt.InnerFrame.RectTransform, Anchor.Center));
|
var content = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.6f), banReasonPrompt.InnerFrame.RectTransform, Anchor.Center))
|
||||||
|
{
|
||||||
|
AbsoluteSpacing = GUI.IntScale(5)
|
||||||
|
};
|
||||||
var banReasonBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.3f), content.RectTransform))
|
var banReasonBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.3f), content.RectTransform))
|
||||||
{
|
{
|
||||||
Wrap = true,
|
Wrap = true,
|
||||||
@@ -3380,10 +3466,9 @@ namespace Barotrauma.Networking
|
|||||||
GUITickBox permaBanTickBox = null;
|
GUITickBox permaBanTickBox = null;
|
||||||
|
|
||||||
if (ban)
|
if (ban)
|
||||||
{
|
{
|
||||||
|
|
||||||
var labelContainer = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.25f), content.RectTransform), isHorizontal: false);
|
var labelContainer = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.25f), content.RectTransform), isHorizontal: false);
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1f, 0.5f), labelContainer.RectTransform), TextManager.Get("BanDuration")) { Padding = Vector4.Zero };
|
new GUITextBlock(new RectTransform(new Vector2(1f, 0.0f), labelContainer.RectTransform), TextManager.Get("BanDuration"), font: GUI.SubHeadingFont) { Padding = Vector4.Zero };
|
||||||
var buttonContent = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.5f), labelContainer.RectTransform), isHorizontal: true);
|
var buttonContent = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.5f), labelContainer.RectTransform), isHorizontal: true);
|
||||||
permaBanTickBox = new GUITickBox(new RectTransform(new Vector2(0.4f, 0.15f), buttonContent.RectTransform), TextManager.Get("BanPermanent"))
|
permaBanTickBox = new GUITickBox(new RectTransform(new Vector2(0.4f, 0.15f), buttonContent.RectTransform), TextManager.Get("BanPermanent"))
|
||||||
{
|
{
|
||||||
@@ -3494,12 +3579,19 @@ namespace Barotrauma.Networking
|
|||||||
errorLines.Add("Campaign ID: " + campaign.CampaignID);
|
errorLines.Add("Campaign ID: " + campaign.CampaignID);
|
||||||
errorLines.Add("Campaign save ID: " + campaign.LastSaveID + "(pending: " + campaign.PendingSaveID + ")");
|
errorLines.Add("Campaign save ID: " + campaign.LastSaveID + "(pending: " + campaign.PendingSaveID + ")");
|
||||||
}
|
}
|
||||||
errorLines.Add("Mission: " + (GameMain.GameSession?.Mission?.Prefab.Identifier ?? "none"));
|
foreach (Mission mission in GameMain.GameSession.Missions)
|
||||||
|
{
|
||||||
|
errorLines.Add("Mission: " + mission.Prefab.Identifier);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (GameMain.GameSession?.Submarine != null)
|
if (GameMain.GameSession?.Submarine != null)
|
||||||
{
|
{
|
||||||
errorLines.Add("Submarine: " + GameMain.GameSession.Submarine.Info.Name);
|
errorLines.Add("Submarine: " + GameMain.GameSession.Submarine.Info.Name);
|
||||||
}
|
}
|
||||||
|
if (GameMain.NetworkMember?.RespawnManager?.RespawnShuttle != null)
|
||||||
|
{
|
||||||
|
errorLines.Add("Respawn shuttle: " + GameMain.NetworkMember.RespawnManager.RespawnShuttle.Info.Name);
|
||||||
|
}
|
||||||
if (Level.Loaded != null)
|
if (Level.Loaded != null)
|
||||||
{
|
{
|
||||||
errorLines.Add("Level: " + Level.Loaded.Seed + ", " + string.Join(", ", Level.Loaded.EqualityCheckValues.Select(cv => cv.ToString("X"))));
|
errorLines.Add("Level: " + Level.Loaded.Seed + ", " + string.Join(", ", Level.Loaded.EqualityCheckValues.Select(cv => cv.ToString("X"))));
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
using System;
|
namespace Barotrauma.Networking
|
||||||
|
|
||||||
namespace Barotrauma.Networking
|
|
||||||
{
|
{
|
||||||
partial class OrderChatMessage : ChatMessage
|
partial class OrderChatMessage : ChatMessage
|
||||||
{
|
{
|
||||||
@@ -9,26 +7,7 @@ namespace Barotrauma.Networking
|
|||||||
msg.Write((byte)ClientNetObject.CHAT_MESSAGE);
|
msg.Write((byte)ClientNetObject.CHAT_MESSAGE);
|
||||||
msg.Write(NetStateID);
|
msg.Write(NetStateID);
|
||||||
msg.Write((byte)ChatMessageType.Order);
|
msg.Write((byte)ChatMessageType.Order);
|
||||||
msg.Write((byte)Order.PrefabList.IndexOf(Order.Prefab));
|
WriteOrder(msg);
|
||||||
msg.Write(TargetCharacter == null ? (UInt16)0 : TargetCharacter.ID);
|
|
||||||
msg.Write(TargetEntity is Entity ? (TargetEntity as Entity).ID : (UInt16)0);
|
|
||||||
msg.Write((byte)Array.IndexOf(Order.Prefab.Options, OrderOption));
|
|
||||||
msg.Write((byte)Order.TargetType);
|
|
||||||
if (Order.TargetType == Order.OrderTargetType.Position && TargetEntity is OrderTarget orderTarget)
|
|
||||||
{
|
|
||||||
msg.Write(true);
|
|
||||||
msg.Write(orderTarget.Position.X);
|
|
||||||
msg.Write(orderTarget.Position.Y);
|
|
||||||
msg.Write(orderTarget.Hull == null ? (UInt16)0 : orderTarget.Hull.ID);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
msg.Write(false);
|
|
||||||
if (Order.TargetType == Order.OrderTargetType.WallSection)
|
|
||||||
{
|
|
||||||
msg.Write((byte)(WallSectionIndex ?? Order.WallSectionIndex ?? 0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -147,13 +147,36 @@ namespace Barotrauma.Networking
|
|||||||
if (missingPackages.Count > 0)
|
if (missingPackages.Count > 0)
|
||||||
{
|
{
|
||||||
var nonDownloadable = missingPackages.Where(p => p.WorkshopId == 0);
|
var nonDownloadable = missingPackages.Where(p => p.WorkshopId == 0);
|
||||||
|
var mismatchedButDownloaded = missingPackages.Where(p =>
|
||||||
|
{
|
||||||
|
var localMatching = ContentPackage.RegularPackages.Find(l => l.SteamWorkshopId != 0 && p.WorkshopId == l.SteamWorkshopId);
|
||||||
|
localMatching ??= ContentPackage.CorePackages.Find(l => l.SteamWorkshopId != 0 && p.WorkshopId == l.SteamWorkshopId);
|
||||||
|
|
||||||
if (nonDownloadable.Any())
|
return localMatching != null;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (mismatchedButDownloaded.Any())
|
||||||
|
{
|
||||||
|
string disconnectMsg;
|
||||||
|
if (mismatchedButDownloaded.Count() == 1)
|
||||||
|
{
|
||||||
|
disconnectMsg = $"DisconnectMessage.MismatchedWorkshopMod~[incompatiblecontentpackage]={GetPackageStr(mismatchedButDownloaded.First())}";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
List<string> packageStrs = new List<string>();
|
||||||
|
mismatchedButDownloaded.ForEach(cp => packageStrs.Add(GetPackageStr(cp)));
|
||||||
|
disconnectMsg = $"DisconnectMessage.MismatchedWorkshopMods~[incompatiblecontentpackages]={string.Join(", ", packageStrs)}";
|
||||||
|
}
|
||||||
|
Close(disconnectMsg, disableReconnect: true);
|
||||||
|
OnDisconnectMessageReceived?.Invoke(DisconnectReason.MissingContentPackage + "/" + disconnectMsg);
|
||||||
|
}
|
||||||
|
else if (nonDownloadable.Any())
|
||||||
{
|
{
|
||||||
string disconnectMsg;
|
string disconnectMsg;
|
||||||
if (nonDownloadable.Count() == 1)
|
if (nonDownloadable.Count() == 1)
|
||||||
{
|
{
|
||||||
disconnectMsg = $"DisconnectMessage.MissingContentPackage~[missingcontentpackage]={GetPackageStr(missingPackages[0])}";
|
disconnectMsg = $"DisconnectMessage.MissingContentPackage~[missingcontentpackage]={GetPackageStr(nonDownloadable.First())}";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
+1
@@ -56,6 +56,7 @@ namespace Barotrauma.Networking
|
|||||||
Steamworks.SteamNetworking.AllowP2PPacketRelay(true);
|
Steamworks.SteamNetworking.AllowP2PPacketRelay(true);
|
||||||
|
|
||||||
ServerConnection = new SteamP2PConnection("Server", hostSteamId);
|
ServerConnection = new SteamP2PConnection("Server", hostSteamId);
|
||||||
|
ServerConnection.SetOwnerSteamIDIfUnknown(hostSteamId);
|
||||||
|
|
||||||
incomingInitializationMessages = new List<IReadMessage>();
|
incomingInitializationMessages = new List<IReadMessage>();
|
||||||
incomingDataMessages = new List<IReadMessage>();
|
incomingDataMessages = new List<IReadMessage>();
|
||||||
|
|||||||
+32
-25
@@ -17,6 +17,7 @@ namespace Barotrauma.Networking
|
|||||||
class RemotePeer
|
class RemotePeer
|
||||||
{
|
{
|
||||||
public UInt64 SteamID;
|
public UInt64 SteamID;
|
||||||
|
public UInt64 OwnerSteamID;
|
||||||
public double? DisconnectTime;
|
public double? DisconnectTime;
|
||||||
public bool Authenticating;
|
public bool Authenticating;
|
||||||
public bool Authenticated;
|
public bool Authenticated;
|
||||||
@@ -31,6 +32,7 @@ namespace Barotrauma.Networking
|
|||||||
public RemotePeer(UInt64 steamId)
|
public RemotePeer(UInt64 steamId)
|
||||||
{
|
{
|
||||||
SteamID = steamId;
|
SteamID = steamId;
|
||||||
|
OwnerSteamID = 0;
|
||||||
DisconnectTime = null;
|
DisconnectTime = null;
|
||||||
Authenticating = false;
|
Authenticating = false;
|
||||||
Authenticated = false;
|
Authenticated = false;
|
||||||
@@ -90,10 +92,19 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
if (status == Steamworks.AuthResponse.OK)
|
if (status == Steamworks.AuthResponse.OK)
|
||||||
{
|
{
|
||||||
|
remotePeer.OwnerSteamID = ownerID;
|
||||||
remotePeer.Authenticated = true;
|
remotePeer.Authenticated = true;
|
||||||
remotePeer.Authenticating = false;
|
remotePeer.Authenticating = false;
|
||||||
foreach (var msg in remotePeer.UnauthedMessages)
|
foreach (var msg in remotePeer.UnauthedMessages)
|
||||||
{
|
{
|
||||||
|
//rewrite the owner id before
|
||||||
|
//forwarding the messages to
|
||||||
|
//the server, since it's only
|
||||||
|
//known now
|
||||||
|
int prevBitPosition = msg.Message.BitPosition;
|
||||||
|
msg.Message.BitPosition = sizeof(ulong) * 8;
|
||||||
|
msg.Message.Write(ownerID);
|
||||||
|
msg.Message.BitPosition = prevBitPosition;
|
||||||
byte[] msgToSend = (byte[])msg.Message.Buffer.Clone();
|
byte[] msgToSend = (byte[])msg.Message.Buffer.Clone();
|
||||||
Array.Resize(ref msgToSend, msg.Message.LengthBytes);
|
Array.Resize(ref msgToSend, msg.Message.LengthBytes);
|
||||||
ChildServerRelay.Write(msgToSend);
|
ChildServerRelay.Write(msgToSend);
|
||||||
@@ -131,6 +142,7 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
IWriteMessage outMsg = new WriteOnlyMessage();
|
IWriteMessage outMsg = new WriteOnlyMessage();
|
||||||
outMsg.Write(steamId);
|
outMsg.Write(steamId);
|
||||||
|
outMsg.Write(remotePeer.OwnerSteamID);
|
||||||
outMsg.Write(data, 1, dataLength - 1);
|
outMsg.Write(data, 1, dataLength - 1);
|
||||||
|
|
||||||
DeliveryMethod deliveryMethod = (DeliveryMethod)data[0];
|
DeliveryMethod deliveryMethod = (DeliveryMethod)data[0];
|
||||||
@@ -142,34 +154,27 @@ namespace Barotrauma.Networking
|
|||||||
bool isServerMessage = (incByte & (byte)PacketHeader.IsServerMessage) != 0;
|
bool isServerMessage = (incByte & (byte)PacketHeader.IsServerMessage) != 0;
|
||||||
bool isHeartbeatMessage = (incByte & (byte)PacketHeader.IsHeartbeatMessage) != 0;
|
bool isHeartbeatMessage = (incByte & (byte)PacketHeader.IsHeartbeatMessage) != 0;
|
||||||
|
|
||||||
if (!remotePeer.Authenticated)
|
if (!remotePeer.Authenticated & !remotePeer.Authenticating && isConnectionInitializationStep)
|
||||||
{
|
{
|
||||||
if (!remotePeer.Authenticating)
|
remotePeer.DisconnectTime = null;
|
||||||
|
|
||||||
|
IReadMessage authMsg = new ReadOnlyMessage(data, isCompressed, 2, dataLength - 2, null);
|
||||||
|
ConnectionInitialization initializationStep = (ConnectionInitialization)authMsg.ReadByte();
|
||||||
|
if (initializationStep == ConnectionInitialization.SteamTicketAndVersion)
|
||||||
{
|
{
|
||||||
if (isConnectionInitializationStep)
|
remotePeer.Authenticating = true;
|
||||||
|
|
||||||
|
authMsg.ReadString(); //skip name
|
||||||
|
authMsg.ReadInt32(); //skip owner key
|
||||||
|
authMsg.ReadUInt64(); //skip steamid
|
||||||
|
UInt16 ticketLength = authMsg.ReadUInt16();
|
||||||
|
byte[] ticket = authMsg.ReadBytes(ticketLength);
|
||||||
|
|
||||||
|
Steamworks.BeginAuthResult authSessionStartState = Steam.SteamManager.StartAuthSession(ticket, steamId);
|
||||||
|
if (authSessionStartState != Steamworks.BeginAuthResult.OK)
|
||||||
{
|
{
|
||||||
remotePeer.DisconnectTime = null;
|
DisconnectPeer(remotePeer, DisconnectReason.SteamAuthenticationFailed.ToString() + "/ Steam auth session failed to start: " + authSessionStartState.ToString());
|
||||||
|
return;
|
||||||
IReadMessage authMsg = new ReadOnlyMessage(data, isCompressed, 2, dataLength - 2, null);
|
|
||||||
ConnectionInitialization initializationStep = (ConnectionInitialization)authMsg.ReadByte();
|
|
||||||
//Console.WriteLine("received init step from "+steamId.ToString()+" ("+initializationStep.ToString()+")");
|
|
||||||
if (initializationStep == ConnectionInitialization.SteamTicketAndVersion)
|
|
||||||
{
|
|
||||||
remotePeer.Authenticating = true;
|
|
||||||
|
|
||||||
authMsg.ReadString(); //skip name
|
|
||||||
authMsg.ReadInt32(); //skip owner key
|
|
||||||
authMsg.ReadUInt64(); //skip steamid
|
|
||||||
UInt16 ticketLength = authMsg.ReadUInt16();
|
|
||||||
byte[] ticket = authMsg.ReadBytes(ticketLength);
|
|
||||||
|
|
||||||
Steamworks.BeginAuthResult authSessionStartState = Steam.SteamManager.StartAuthSession(ticket, steamId);
|
|
||||||
if (authSessionStartState != Steamworks.BeginAuthResult.OK)
|
|
||||||
{
|
|
||||||
DisconnectPeer(remotePeer, DisconnectReason.SteamAuthenticationFailed.ToString() + "/ Steam auth session failed to start: " + authSessionStartState.ToString());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -336,6 +341,7 @@ namespace Barotrauma.Networking
|
|||||||
{
|
{
|
||||||
IWriteMessage outMsg = new WriteOnlyMessage();
|
IWriteMessage outMsg = new WriteOnlyMessage();
|
||||||
outMsg.Write(selfSteamID);
|
outMsg.Write(selfSteamID);
|
||||||
|
outMsg.Write(selfSteamID);
|
||||||
outMsg.Write((byte)(PacketHeader.IsConnectionInitializationStep));
|
outMsg.Write((byte)(PacketHeader.IsConnectionInitializationStep));
|
||||||
outMsg.Write(Name);
|
outMsg.Write(Name);
|
||||||
|
|
||||||
@@ -428,6 +434,7 @@ namespace Barotrauma.Networking
|
|||||||
byte[] msgData = new byte[msg.LengthBytes];
|
byte[] msgData = new byte[msg.LengthBytes];
|
||||||
msg.PrepareForSending(ref msgData, out bool isCompressed, out int length);
|
msg.PrepareForSending(ref msgData, out bool isCompressed, out int length);
|
||||||
msgToSend.Write(selfSteamID);
|
msgToSend.Write(selfSteamID);
|
||||||
|
msgToSend.Write(selfSteamID);
|
||||||
msgToSend.Write((byte)(isCompressed ? PacketHeader.IsCompressed : PacketHeader.None));
|
msgToSend.Write((byte)(isCompressed ? PacketHeader.IsCompressed : PacketHeader.None));
|
||||||
msgToSend.Write((UInt16)length);
|
msgToSend.Write((UInt16)length);
|
||||||
msgToSend.Write(msgData, 0, length);
|
msgToSend.Write(msgData, 0, length);
|
||||||
|
|||||||
@@ -159,6 +159,20 @@ namespace Barotrauma.Networking
|
|||||||
color: ServerListScreen.PlayStyleColors[(int)playStyle], style: "GUISlopedHeader");
|
color: ServerListScreen.PlayStyleColors[(int)playStyle], style: "GUISlopedHeader");
|
||||||
playStyleName.RectTransform.NonScaledSize = (playStyleName.Font.MeasureString(playStyleName.Text) + new Vector2(20, 5) * GUI.Scale).ToPoint();
|
playStyleName.RectTransform.NonScaledSize = (playStyleName.Font.MeasureString(playStyleName.Text) + new Vector2(20, 5) * GUI.Scale).ToPoint();
|
||||||
playStyleName.RectTransform.IsFixedSize = true;
|
playStyleName.RectTransform.IsFixedSize = true;
|
||||||
|
|
||||||
|
var serverTypeContainer = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.2f), playStyleBanner.RectTransform, Anchor.BottomLeft, Pivot.BottomLeft),
|
||||||
|
"MainMenuNotifBackground", Color.Black)
|
||||||
|
{
|
||||||
|
CanBeFocused = false,
|
||||||
|
};
|
||||||
|
|
||||||
|
var serverType = new GUITextBlock(new RectTransform(Vector2.One, serverTypeContainer.RectTransform, Anchor.CenterLeft),
|
||||||
|
TextManager.Get((OwnerID != 0 || LobbyID != 0) ? "SteamP2PServer" : "DedicatedServer"), textAlignment: Alignment.CenterLeft);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var serverType = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.1f), previewContainer.RectTransform, Anchor.CenterLeft),
|
||||||
|
TextManager.Get((OwnerID != 0 || LobbyID != 0) ? "SteamP2PServer" : "DedicatedServer"), textAlignment: Alignment.CenterLeft);
|
||||||
}
|
}
|
||||||
|
|
||||||
var content = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.6f), previewContainer.RectTransform))
|
var content = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.6f), previewContainer.RectTransform))
|
||||||
@@ -553,5 +567,10 @@ namespace Barotrauma.Networking
|
|||||||
(other.LobbyID == LobbyID || other.LobbyID == 0 || LobbyID == 0) &&
|
(other.LobbyID == LobbyID || other.LobbyID == 0 || LobbyID == 0) &&
|
||||||
((OwnerID == 0) ? (other.IP == IP && other.Port == Port) : true);
|
((OwnerID == 0) ? (other.IP == IP && other.Port == Port) : true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool MatchesByEndpoint(ServerInfo other)
|
||||||
|
{
|
||||||
|
return OwnerID == other.OwnerID && (OwnerID != 0 ? true : (IP == other.IP && Port == other.Port));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -242,16 +242,7 @@ namespace Barotrauma.Networking
|
|||||||
textBlock.ClickableAreas.Add(new GUITextBlock.ClickableArea()
|
textBlock.ClickableAreas.Add(new GUITextBlock.ClickableArea()
|
||||||
{
|
{
|
||||||
Data = data,
|
Data = data,
|
||||||
OnClick = (component, area) =>
|
OnClick = GameMain.NetLobbyScreen.SelectPlayer
|
||||||
{
|
|
||||||
if (!UInt64.TryParse(area.Data.Metadata, out UInt64 id)) { return; }
|
|
||||||
Client client = GameMain.Client.ConnectedClients.Find(c => c.SteamID == id)
|
|
||||||
?? GameMain.Client.ConnectedClients.Find(c => c.ID == id)
|
|
||||||
?? GameMain.Client.PreviouslyConnectedClients.FirstOrDefault(c => c.SteamID == id)
|
|
||||||
?? GameMain.Client.PreviouslyConnectedClients.FirstOrDefault(c => c.ID == id);
|
|
||||||
if (client == null) { return; }
|
|
||||||
GameMain.NetLobbyScreen.SelectPlayer(client);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -126,11 +126,15 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
public void ClientRead(IReadMessage incMsg)
|
public void ClientRead(IReadMessage incMsg)
|
||||||
{
|
{
|
||||||
|
cachedServerListInfo = null;
|
||||||
|
|
||||||
ServerName = incMsg.ReadString();
|
ServerName = incMsg.ReadString();
|
||||||
ServerMessageText = incMsg.ReadString();
|
ServerMessageText = incMsg.ReadString();
|
||||||
MaxPlayers = incMsg.ReadByte();
|
MaxPlayers = incMsg.ReadByte();
|
||||||
HasPassword = incMsg.ReadBoolean();
|
HasPassword = incMsg.ReadBoolean();
|
||||||
IsPublic = incMsg.ReadBoolean();
|
IsPublic = incMsg.ReadBoolean();
|
||||||
|
GameMain.NetLobbyScreen.SetPublic(IsPublic);
|
||||||
|
AllowFileTransfers = incMsg.ReadBoolean();
|
||||||
incMsg.ReadPadBits();
|
incMsg.ReadPadBits();
|
||||||
TickRate = incMsg.ReadRangedInteger(1, 60);
|
TickRate = incMsg.ReadRangedInteger(1, 60);
|
||||||
GameMain.NetworkMember.TickRate = TickRate;
|
GameMain.NetworkMember.TickRate = TickRate;
|
||||||
@@ -147,7 +151,7 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientAdminWrite(NetFlags dataToSend, int? missionTypeOr = null, int? missionTypeAnd = null, float? levelDifficulty = null, bool? autoRestart = null, int traitorSetting = 0, int botCount = 0, int botSpawnMode = 0, bool? useRespawnShuttle = null)
|
public void ClientAdminWrite(NetFlags dataToSend, int? missionTypeOr = null, int? missionTypeAnd = null, float? levelDifficulty = null, bool? autoRestart = null, int traitorSetting = 0, int botCount = 0, int botSpawnMode = 0, bool? radiationEnabled = null, bool? useRespawnShuttle = null)
|
||||||
{
|
{
|
||||||
if (!GameMain.Client.HasPermission(Networking.ClientPermissions.ManageSettings)) return;
|
if (!GameMain.Client.HasPermission(Networking.ClientPermissions.ManageSettings)) return;
|
||||||
|
|
||||||
@@ -212,6 +216,7 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
outMsg.Write(autoRestart != null);
|
outMsg.Write(autoRestart != null);
|
||||||
outMsg.Write(autoRestart ?? false);
|
outMsg.Write(autoRestart ?? false);
|
||||||
|
outMsg.Write(radiationEnabled ?? RadiationEnabled);
|
||||||
outMsg.WritePadBits();
|
outMsg.WritePadBits();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -274,7 +279,7 @@ namespace Barotrauma.Networking
|
|||||||
if (GUI.MouseOn == btn || GUI.MouseOn == btn.TextBlock) { ToggleSettingsFrame(btn, userData); }
|
if (GUI.MouseOn == btn || GUI.MouseOn == btn.TextBlock) { ToggleSettingsFrame(btn, userData); }
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
new GUIButton(new RectTransform(Vector2.One, settingsFrame.RectTransform), "", style: null)
|
new GUIButton(new RectTransform(Vector2.One, settingsFrame.RectTransform), "", style: null)
|
||||||
{
|
{
|
||||||
OnClicked = ToggleSettingsFrame
|
OnClicked = ToggleSettingsFrame
|
||||||
@@ -500,8 +505,8 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
CreateLabeledSlider(roundsTab, "ServerSettingsRespawnInterval", out slider, out sliderLabel);
|
CreateLabeledSlider(roundsTab, "ServerSettingsRespawnInterval", out slider, out sliderLabel);
|
||||||
string intervalLabel = sliderLabel.Text;
|
string intervalLabel = sliderLabel.Text;
|
||||||
slider.Step = 0.05f;
|
|
||||||
slider.Range = new Vector2(10.0f, 600.0f);
|
slider.Range = new Vector2(10.0f, 600.0f);
|
||||||
|
slider.StepValue = 10.0f;
|
||||||
GetPropertyData("RespawnInterval").AssignGUIComponent(slider);
|
GetPropertyData("RespawnInterval").AssignGUIComponent(slider);
|
||||||
slider.OnMoved = (GUIScrollBar scrollBar, float barScroll) =>
|
slider.OnMoved = (GUIScrollBar scrollBar, float barScroll) =>
|
||||||
{
|
{
|
||||||
@@ -646,7 +651,14 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
foreach (ItemPrefab ip in ItemPrefab.Prefabs)
|
foreach (ItemPrefab ip in ItemPrefab.Prefabs)
|
||||||
{
|
{
|
||||||
if (!ip.CanBeBought && !ip.Tags.Contains("smallitem")) continue;
|
if (ip.AllowAsExtraCargo.HasValue)
|
||||||
|
{
|
||||||
|
if (!ip.AllowAsExtraCargo.Value) { continue; }
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!ip.CanBeBought) { continue; }
|
||||||
|
}
|
||||||
|
|
||||||
var itemFrame = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.15f), cargoFrame.Content.RectTransform) { MinSize = new Point(0, 30) }, isHorizontal: true)
|
var itemFrame = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.15f), cargoFrame.Content.RectTransform) { MinSize = new Point(0, 30) }, isHorizontal: true)
|
||||||
{
|
{
|
||||||
@@ -725,6 +737,10 @@ namespace Barotrauma.Networking
|
|||||||
TextManager.Get("ServerSettingsDestructibleOutposts"));
|
TextManager.Get("ServerSettingsDestructibleOutposts"));
|
||||||
GetPropertyData("DestructibleOutposts").AssignGUIComponent(destructibleOutposts);
|
GetPropertyData("DestructibleOutposts").AssignGUIComponent(destructibleOutposts);
|
||||||
|
|
||||||
|
var lockAllDefaultWires = new GUITickBox(new RectTransform(new Vector2(0.48f, 0.05f), tickBoxContainer.Content.RectTransform),
|
||||||
|
TextManager.Get("ServerSettingsLockAllDefaultWires"));
|
||||||
|
GetPropertyData("LockAllDefaultWires").AssignGUIComponent(lockAllDefaultWires);
|
||||||
|
|
||||||
var allowRewiring = new GUITickBox(new RectTransform(new Vector2(0.48f, 0.05f), tickBoxContainer.Content.RectTransform),
|
var allowRewiring = new GUITickBox(new RectTransform(new Vector2(0.48f, 0.05f), tickBoxContainer.Content.RectTransform),
|
||||||
TextManager.Get("ServerSettingsAllowRewiring"));
|
TextManager.Get("ServerSettingsAllowRewiring"));
|
||||||
GetPropertyData("AllowRewiring").AssignGUIComponent(allowRewiring);
|
GetPropertyData("AllowRewiring").AssignGUIComponent(allowRewiring);
|
||||||
@@ -915,6 +931,7 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
public bool ToggleSettingsFrame(GUIButton button, object obj)
|
public bool ToggleSettingsFrame(GUIButton button, object obj)
|
||||||
{
|
{
|
||||||
|
if (GameMain.NetworkMember == null) { return false; }
|
||||||
if (settingsFrame == null)
|
if (settingsFrame == null)
|
||||||
{
|
{
|
||||||
CreateSettingsFrame();
|
CreateSettingsFrame();
|
||||||
@@ -936,5 +953,12 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ServerInfo cachedServerListInfo = null;
|
||||||
|
public ServerInfo GetServerListInfo()
|
||||||
|
{
|
||||||
|
cachedServerListInfo ??= GameMain.ServerListScreen.UpdateServerInfoWithServerSettings(GameMain.Client.ClientPeer.ServerConnection, this);
|
||||||
|
return cachedServerListInfo;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
using Microsoft.Xna.Framework;
|
using Barotrauma.Sounds;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
using OpenAL;
|
using OpenAL;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
@@ -56,7 +58,7 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
public bool Disconnected { get; private set; }
|
public bool Disconnected { get; private set; }
|
||||||
|
|
||||||
public static void Create(string deviceName, UInt16? storedBufferID=null)
|
public static void Create(string deviceName, UInt16? storedBufferID = null)
|
||||||
{
|
{
|
||||||
if (Instance != null)
|
if (Instance != null)
|
||||||
{
|
{
|
||||||
@@ -84,7 +86,7 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
if (captureDevice == IntPtr.Zero)
|
if (captureDevice == IntPtr.Zero)
|
||||||
{
|
{
|
||||||
DebugConsole.NewMessage("Alc.CaptureOpenDevice attempt 1 failed: error code " + Alc.GetError(IntPtr.Zero).ToString(),Color.Orange);
|
DebugConsole.NewMessage("Alc.CaptureOpenDevice attempt 1 failed: error code " + Alc.GetError(IntPtr.Zero).ToString(), Color.Orange);
|
||||||
//attempt using a smaller buffer size
|
//attempt using a smaller buffer size
|
||||||
captureDevice = Alc.CaptureOpenDevice(deviceName, VoipConfig.FREQUENCY, Al.FormatMono16, VoipConfig.BUFFER_SIZE * 2);
|
captureDevice = Alc.CaptureOpenDevice(deviceName, VoipConfig.FREQUENCY, Al.FormatMono16, VoipConfig.BUFFER_SIZE * 2);
|
||||||
}
|
}
|
||||||
@@ -162,6 +164,7 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IntPtr nativeBuffer;
|
||||||
short[] uncompressedBuffer = new short[VoipConfig.BUFFER_SIZE];
|
short[] uncompressedBuffer = new short[VoipConfig.BUFFER_SIZE];
|
||||||
short[] prevUncompressedBuffer = new short[VoipConfig.BUFFER_SIZE];
|
short[] prevUncompressedBuffer = new short[VoipConfig.BUFFER_SIZE];
|
||||||
bool prevCaptured = true;
|
bool prevCaptured = true;
|
||||||
@@ -171,143 +174,198 @@ namespace Barotrauma.Networking
|
|||||||
{
|
{
|
||||||
Array.Copy(uncompressedBuffer, 0, prevUncompressedBuffer, 0, VoipConfig.BUFFER_SIZE);
|
Array.Copy(uncompressedBuffer, 0, prevUncompressedBuffer, 0, VoipConfig.BUFFER_SIZE);
|
||||||
Array.Clear(uncompressedBuffer, 0, VoipConfig.BUFFER_SIZE);
|
Array.Clear(uncompressedBuffer, 0, VoipConfig.BUFFER_SIZE);
|
||||||
while (capturing && !Disconnected)
|
nativeBuffer = Marshal.AllocHGlobal(VoipConfig.BUFFER_SIZE * 2);
|
||||||
|
try
|
||||||
{
|
{
|
||||||
int alcError;
|
while (capturing)
|
||||||
|
|
||||||
if (CanDetectDisconnect)
|
|
||||||
{
|
{
|
||||||
Alc.GetInteger(captureDevice, Alc.EnumConnected, out int isConnected);
|
int alcError;
|
||||||
|
|
||||||
|
if (CanDetectDisconnect)
|
||||||
|
{
|
||||||
|
Alc.GetInteger(captureDevice, Alc.EnumConnected, out int isConnected);
|
||||||
|
alcError = Alc.GetError(captureDevice);
|
||||||
|
if (alcError != Alc.NoError)
|
||||||
|
{
|
||||||
|
throw new Exception("Failed to determine if capture device is connected: " + alcError.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isConnected == 0)
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError("Capture device has been disconnected. You can select another available device in the settings.");
|
||||||
|
Disconnected = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FillBuffer();
|
||||||
|
|
||||||
alcError = Alc.GetError(captureDevice);
|
alcError = Alc.GetError(captureDevice);
|
||||||
if (alcError != Alc.NoError)
|
if (alcError != Alc.NoError)
|
||||||
{
|
{
|
||||||
throw new Exception("Failed to determine if capture device is connected: " + alcError.ToString());
|
throw new Exception("Failed to capture samples: " + alcError.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isConnected == 0)
|
double maxAmplitude = 0.0f;
|
||||||
|
for (int i = 0; i < VoipConfig.BUFFER_SIZE; i++)
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError("Capture device has been disconnected. You can select another available device in the settings.");
|
uncompressedBuffer[i] = (short)MathHelper.Clamp((uncompressedBuffer[i] * Gain), -short.MaxValue, short.MaxValue);
|
||||||
Disconnected = true;
|
double sampleVal = uncompressedBuffer[i] / (double)short.MaxValue;
|
||||||
break;
|
maxAmplitude = Math.Max(maxAmplitude, Math.Abs(sampleVal));
|
||||||
}
|
}
|
||||||
}
|
double dB = Math.Min(20 * Math.Log10(maxAmplitude), 0.0);
|
||||||
|
|
||||||
Alc.GetInteger(captureDevice, Alc.EnumCaptureSamples, out int sampleCount);
|
LastdB = dB;
|
||||||
|
LastAmplitude = maxAmplitude;
|
||||||
|
|
||||||
alcError = Alc.GetError(captureDevice);
|
bool allowEnqueue = overrideSound != null;
|
||||||
if (alcError != Alc.NoError)
|
if (GameMain.WindowActive)
|
||||||
{
|
|
||||||
throw new Exception("Failed to determine sample count: " + alcError.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sampleCount < VoipConfig.BUFFER_SIZE)
|
|
||||||
{
|
|
||||||
int sleepMs = (VoipConfig.BUFFER_SIZE - sampleCount) * 800 / VoipConfig.FREQUENCY;
|
|
||||||
if (sleepMs < 5) sleepMs = 5;
|
|
||||||
Thread.Sleep(sleepMs);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
GCHandle handle = GCHandle.Alloc(uncompressedBuffer, GCHandleType.Pinned);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Alc.CaptureSamples(captureDevice, handle.AddrOfPinnedObject(), VoipConfig.BUFFER_SIZE);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
handle.Free();
|
|
||||||
}
|
|
||||||
|
|
||||||
alcError = Alc.GetError(captureDevice);
|
|
||||||
if (alcError != Alc.NoError)
|
|
||||||
{
|
|
||||||
throw new Exception("Failed to capture samples: " + alcError.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
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 dB = Math.Min(20 * Math.Log10(maxAmplitude), 0.0);
|
|
||||||
|
|
||||||
LastdB = dB;
|
|
||||||
LastAmplitude = maxAmplitude;
|
|
||||||
|
|
||||||
bool allowEnqueue = false;
|
|
||||||
if (GameMain.WindowActive)
|
|
||||||
{
|
|
||||||
ForceLocal = captureTimer > 0 ? ForceLocal : GameMain.Config.UseLocalVoiceByDefault;
|
|
||||||
bool pttDown = false;
|
|
||||||
if ((PlayerInput.KeyDown(InputType.Voice) || PlayerInput.KeyDown(InputType.LocalVoice)) &&
|
|
||||||
GUI.KeyboardDispatcher.Subscriber == null)
|
|
||||||
{
|
{
|
||||||
pttDown = true;
|
ForceLocal = captureTimer > 0 ? ForceLocal : GameMain.Config.UseLocalVoiceByDefault;
|
||||||
if (PlayerInput.KeyDown(InputType.LocalVoice))
|
bool pttDown = false;
|
||||||
|
if ((PlayerInput.KeyDown(InputType.Voice) || PlayerInput.KeyDown(InputType.LocalVoice)) &&
|
||||||
|
GUI.KeyboardDispatcher.Subscriber == null)
|
||||||
{
|
{
|
||||||
ForceLocal = true;
|
pttDown = true;
|
||||||
|
if (PlayerInput.KeyDown(InputType.LocalVoice))
|
||||||
|
{
|
||||||
|
ForceLocal = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ForceLocal = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
if (GameMain.Config.VoiceSetting == GameSettings.VoiceMode.Activity)
|
||||||
{
|
{
|
||||||
ForceLocal = false;
|
if (dB > GameMain.Config.NoiseGateThreshold)
|
||||||
|
{
|
||||||
|
allowEnqueue = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (GameMain.Config.VoiceSetting == GameSettings.VoiceMode.PushToTalk)
|
||||||
|
{
|
||||||
|
if (pttDown)
|
||||||
|
{
|
||||||
|
allowEnqueue = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (GameMain.Config.VoiceSetting == GameSettings.VoiceMode.Activity)
|
|
||||||
|
if (allowEnqueue || captureTimer > 0)
|
||||||
{
|
{
|
||||||
if (dB > GameMain.Config.NoiseGateThreshold)
|
LastEnqueueAudio = DateTime.Now;
|
||||||
|
if (GameMain.Client?.Character != null)
|
||||||
{
|
{
|
||||||
allowEnqueue = true;
|
var messageType = !ForceLocal && ChatMessage.CanUseRadio(GameMain.Client.Character, out _) ? ChatMessageType.Radio : ChatMessageType.Default;
|
||||||
|
GameMain.Client.Character.ShowSpeechBubble(1.25f, ChatMessage.MessageColor[(int)messageType]);
|
||||||
}
|
}
|
||||||
}
|
//encode audio and enqueue it
|
||||||
else if (GameMain.Config.VoiceSetting == GameSettings.VoiceMode.PushToTalk)
|
lock (buffers)
|
||||||
{
|
|
||||||
if (pttDown)
|
|
||||||
{
|
{
|
||||||
allowEnqueue = true;
|
if (!prevCaptured) //enqueue the previous buffer if not sent to avoid cutoff
|
||||||
|
{
|
||||||
|
int compressedCountPrev = VoipConfig.Encoder.Encode(prevUncompressedBuffer, 0, VoipConfig.BUFFER_SIZE, BufferToQueue, 0, VoipConfig.MAX_COMPRESSED_SIZE);
|
||||||
|
EnqueueBuffer(compressedCountPrev);
|
||||||
|
}
|
||||||
|
int compressedCount = VoipConfig.Encoder.Encode(uncompressedBuffer, 0, VoipConfig.BUFFER_SIZE, BufferToQueue, 0, VoipConfig.MAX_COMPRESSED_SIZE);
|
||||||
|
EnqueueBuffer(compressedCount);
|
||||||
|
}
|
||||||
|
captureTimer -= (VoipConfig.BUFFER_SIZE * 1000) / VoipConfig.FREQUENCY;
|
||||||
|
if (allowEnqueue)
|
||||||
|
{
|
||||||
|
captureTimer = GameMain.Config.VoiceChatCutoffPrevention;
|
||||||
|
}
|
||||||
|
prevCaptured = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
captureTimer = 0;
|
||||||
|
prevCaptured = false;
|
||||||
|
//enqueue silence
|
||||||
|
lock (buffers)
|
||||||
|
{
|
||||||
|
EnqueueBuffer(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError($"VoipCapture threw an exception. Disabling capture...", e);
|
||||||
|
capturing = false;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Marshal.FreeHGlobal(nativeBuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (allowEnqueue || captureTimer > 0)
|
private Sound overrideSound;
|
||||||
|
private int overridePos;
|
||||||
|
private short[] overrideBuf = new short[VoipConfig.BUFFER_SIZE];
|
||||||
|
|
||||||
|
private void FillBuffer()
|
||||||
|
{
|
||||||
|
if (overrideSound != null)
|
||||||
|
{
|
||||||
|
int totalSampleCount = 0;
|
||||||
|
while (totalSampleCount < VoipConfig.BUFFER_SIZE)
|
||||||
{
|
{
|
||||||
LastEnqueueAudio = DateTime.Now;
|
int sampleCount = overrideSound.FillStreamBuffer(overridePos, overrideBuf);
|
||||||
if (GameMain.Client?.Character != null)
|
overridePos += sampleCount * 2;
|
||||||
|
Array.Copy(overrideBuf, 0, uncompressedBuffer, totalSampleCount, sampleCount);
|
||||||
|
totalSampleCount += sampleCount;
|
||||||
|
|
||||||
|
if (sampleCount == 0)
|
||||||
{
|
{
|
||||||
var messageType = !ForceLocal && ChatMessage.CanUseRadio(GameMain.Client.Character, out _) ? ChatMessageType.Radio : ChatMessageType.Default;
|
overridePos = 0;
|
||||||
GameMain.Client.Character.ShowSpeechBubble(1.25f, ChatMessage.MessageColor[(int)messageType]);
|
|
||||||
}
|
}
|
||||||
//encode audio and enqueue it
|
}
|
||||||
lock (buffers)
|
int sleepMs = VoipConfig.BUFFER_SIZE * 800 / VoipConfig.FREQUENCY;
|
||||||
|
Thread.Sleep(sleepMs - 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int sampleCount = 0;
|
||||||
|
|
||||||
|
while (sampleCount < VoipConfig.BUFFER_SIZE)
|
||||||
|
{
|
||||||
|
Alc.GetInteger(captureDevice, Alc.EnumCaptureSamples, out sampleCount);
|
||||||
|
|
||||||
|
int alcError = Alc.GetError(captureDevice);
|
||||||
|
if (alcError != Alc.NoError)
|
||||||
{
|
{
|
||||||
if (!prevCaptured) //enqueue the previous buffer if not sent to avoid cutoff
|
throw new Exception("Failed to determine sample count: " + alcError.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sampleCount < VoipConfig.BUFFER_SIZE)
|
||||||
|
{
|
||||||
|
int sleepMs = (VoipConfig.BUFFER_SIZE - sampleCount) * 800 / VoipConfig.FREQUENCY;
|
||||||
|
if (sleepMs >= 1)
|
||||||
{
|
{
|
||||||
int compressedCountPrev = VoipConfig.Encoder.Encode(prevUncompressedBuffer, 0, VoipConfig.BUFFER_SIZE, BufferToQueue, 0, VoipConfig.MAX_COMPRESSED_SIZE);
|
Thread.Sleep(sleepMs);
|
||||||
EnqueueBuffer(compressedCountPrev);
|
|
||||||
}
|
}
|
||||||
int compressedCount = VoipConfig.Encoder.Encode(uncompressedBuffer, 0, VoipConfig.BUFFER_SIZE, BufferToQueue, 0, VoipConfig.MAX_COMPRESSED_SIZE);
|
|
||||||
EnqueueBuffer(compressedCount);
|
|
||||||
}
|
|
||||||
captureTimer -= (VoipConfig.BUFFER_SIZE * 1000) / VoipConfig.FREQUENCY;
|
|
||||||
if (allowEnqueue)
|
|
||||||
{
|
|
||||||
captureTimer = GameMain.Config.VoiceChatCutoffPrevention;
|
|
||||||
}
|
|
||||||
prevCaptured = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
captureTimer = 0;
|
|
||||||
prevCaptured = false;
|
|
||||||
//enqueue silence
|
|
||||||
lock (buffers)
|
|
||||||
{
|
|
||||||
EnqueueBuffer(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!capturing) { return; }
|
||||||
}
|
}
|
||||||
|
|
||||||
Thread.Sleep(10);
|
Alc.CaptureSamples(captureDevice, nativeBuffer, VoipConfig.BUFFER_SIZE);
|
||||||
|
Marshal.Copy(nativeBuffer, uncompressedBuffer, 0, uncompressedBuffer.Length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetOverrideSound(string fileName)
|
||||||
|
{
|
||||||
|
overrideSound?.Dispose();
|
||||||
|
if (string.IsNullOrEmpty(fileName))
|
||||||
|
{
|
||||||
|
overrideSound = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
overrideSound = GameMain.SoundManager.LoadSound(fileName, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -94,6 +94,7 @@ namespace Barotrauma.Networking
|
|||||||
DebugConsole.Log("Recreating voipsound " + queueId);
|
DebugConsole.Log("Recreating voipsound " + queueId);
|
||||||
client.VoipSound = new VoipSound(client.Name, GameMain.SoundManager, client.VoipQueue);
|
client.VoipSound = new VoipSound(client.Name, GameMain.SoundManager, client.VoipQueue);
|
||||||
}
|
}
|
||||||
|
GameMain.SoundManager.ForceStreamUpdate();
|
||||||
|
|
||||||
if (client.Character != null && !client.Character.IsDead && !client.Character.Removed && client.Character.SpeechImpediment <= 100.0f)
|
if (client.Character != null && !client.Character.IsDead && !client.Character.Removed && client.Character.SpeechImpediment <= 100.0f)
|
||||||
{
|
{
|
||||||
@@ -102,7 +103,7 @@ namespace Barotrauma.Networking
|
|||||||
client.Character.ShowSpeechBubble(1.25f, ChatMessage.MessageColor[(int)messageType]);
|
client.Character.ShowSpeechBubble(1.25f, ChatMessage.MessageColor[(int)messageType]);
|
||||||
|
|
||||||
client.VoipSound.UseRadioFilter = messageType == ChatMessageType.Radio && !GameMain.Config.DisableVoiceChatFilters;
|
client.VoipSound.UseRadioFilter = messageType == ChatMessageType.Radio && !GameMain.Config.DisableVoiceChatFilters;
|
||||||
if (client.VoipSound.UseRadioFilter)
|
if (messageType == ChatMessageType.Radio)
|
||||||
{
|
{
|
||||||
client.VoipSound.SetRange(radio.Range * 0.8f, radio.Range);
|
client.VoipSound.SetRange(radio.Range * 0.8f, radio.Range);
|
||||||
}
|
}
|
||||||
@@ -110,7 +111,7 @@ namespace Barotrauma.Networking
|
|||||||
{
|
{
|
||||||
client.VoipSound.SetRange(ChatMessage.SpeakRange * 0.4f, ChatMessage.SpeakRange);
|
client.VoipSound.SetRange(ChatMessage.SpeakRange * 0.4f, ChatMessage.SpeakRange);
|
||||||
}
|
}
|
||||||
if (!client.VoipSound.UseRadioFilter && Character.Controlled != null && !GameMain.Config.DisableVoiceChatFilters)
|
if (messageType != ChatMessageType.Radio && Character.Controlled != null && !GameMain.Config.DisableVoiceChatFilters)
|
||||||
{
|
{
|
||||||
client.VoipSound.UseMuffleFilter = SoundPlayer.ShouldMuffleSound(Character.Controlled, client.Character.WorldPosition, ChatMessage.SpeakRange, client.Character.CurrentHull);
|
client.VoipSound.UseMuffleFilter = SoundPlayer.ShouldMuffleSound(Character.Controlled, client.Character.WorldPosition, ChatMessage.SpeakRange, client.Character.CurrentHull);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ namespace Barotrauma.Networking
|
|||||||
{
|
{
|
||||||
public static bool Ready = false;
|
public static bool Ready = false;
|
||||||
|
|
||||||
public const int FREQUENCY = 48000; //not amazing, but not bad audio quality
|
public const int FREQUENCY = 48000;
|
||||||
public const int BUFFER_SIZE = 2880; //60ms window, the max Opus seems to support
|
public const int BUFFER_SIZE = 960; //20ms window
|
||||||
|
|
||||||
public static OpusEncoder Encoder
|
public static OpusEncoder Encoder
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -112,14 +112,17 @@ namespace Barotrauma
|
|||||||
|
|
||||||
switch (voteType)
|
switch (voteType)
|
||||||
{
|
{
|
||||||
case VoteType.Sub:
|
case VoteType.Sub:
|
||||||
SubmarineInfo sub = data as SubmarineInfo;
|
if (!(data is SubmarineInfo sub)) { return; }
|
||||||
if (sub == null) { return; }
|
|
||||||
msg.Write(sub.EqualityCheckVal);
|
msg.Write(sub.EqualityCheckVal);
|
||||||
|
if (sub.EqualityCheckVal == 0)
|
||||||
|
{
|
||||||
|
//sub doesn't exist client-side, use hash to let the server know which one we voted for
|
||||||
|
msg.Write(sub.MD5Hash.Hash);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case VoteType.Mode:
|
case VoteType.Mode:
|
||||||
GameModePreset gameMode = data as GameModePreset;
|
if (!(data is GameModePreset gameMode)) { return; }
|
||||||
if (gameMode == null) { return; }
|
|
||||||
msg.Write(gameMode.Identifier);
|
msg.Write(gameMode.Identifier);
|
||||||
break;
|
break;
|
||||||
case VoteType.EndRound:
|
case VoteType.EndRound:
|
||||||
@@ -127,8 +130,7 @@ namespace Barotrauma
|
|||||||
msg.Write((bool)data);
|
msg.Write((bool)data);
|
||||||
break;
|
break;
|
||||||
case VoteType.Kick:
|
case VoteType.Kick:
|
||||||
Client votedClient = data as Client;
|
if (!(data is Client votedClient)) { return; }
|
||||||
if (votedClient == null) return;
|
|
||||||
|
|
||||||
msg.Write(votedClient.ID);
|
msg.Write(votedClient.ID);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -27,7 +27,8 @@ namespace Barotrauma.Particles
|
|||||||
private float angularVelocity;
|
private float angularVelocity;
|
||||||
|
|
||||||
private Vector2 dragVec = Vector2.Zero;
|
private Vector2 dragVec = Vector2.Zero;
|
||||||
private int dragWait = 0;
|
private float dragWait = 0;
|
||||||
|
private float collisionIgnoreTimer = 0;
|
||||||
|
|
||||||
private Vector2 size;
|
private Vector2 size;
|
||||||
private Vector2 sizeChange;
|
private Vector2 sizeChange;
|
||||||
@@ -103,7 +104,7 @@ namespace Barotrauma.Particles
|
|||||||
return debugName;
|
return debugName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Init(ParticlePrefab prefab, Vector2 position, Vector2 speed, float rotation, Hull hullGuess = null, bool drawOnTop = false)
|
public void Init(ParticlePrefab prefab, Vector2 position, Vector2 speed, float rotation, Hull hullGuess = null, bool drawOnTop = false, float collisionIgnoreTimer = 0f)
|
||||||
{
|
{
|
||||||
this.prefab = prefab;
|
this.prefab = prefab;
|
||||||
debugName = $"Particle ({prefab.Name})";
|
debugName = $"Particle ({prefab.Name})";
|
||||||
@@ -174,14 +175,22 @@ namespace Barotrauma.Particles
|
|||||||
}
|
}
|
||||||
|
|
||||||
DrawOnTop = drawOnTop;
|
DrawOnTop = drawOnTop;
|
||||||
|
|
||||||
|
this.collisionIgnoreTimer = collisionIgnoreTimer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Update(float deltaTime)
|
public enum UpdateResult
|
||||||
|
{
|
||||||
|
Normal,
|
||||||
|
Delete
|
||||||
|
}
|
||||||
|
|
||||||
|
public UpdateResult Update(float deltaTime)
|
||||||
{
|
{
|
||||||
if (startDelay > 0.0f)
|
if (startDelay > 0.0f)
|
||||||
{
|
{
|
||||||
startDelay -= deltaTime;
|
startDelay -= deltaTime;
|
||||||
return true;
|
return UpdateResult.Normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
prevPosition = position;
|
prevPosition = position;
|
||||||
@@ -251,7 +260,7 @@ namespace Barotrauma.Particles
|
|||||||
}
|
}
|
||||||
|
|
||||||
lifeTime -= deltaTime;
|
lifeTime -= deltaTime;
|
||||||
if (lifeTime <= 0.0f || color.A <= 0 || size.X <= 0.0f || size.Y <= 0.0f) { return false; }
|
if (lifeTime <= 0.0f || color.A <= 0 || size.X <= 0.0f || size.Y <= 0.0f) { return UpdateResult.Delete; }
|
||||||
|
|
||||||
if (hasSubEmitters)
|
if (hasSubEmitters)
|
||||||
{
|
{
|
||||||
@@ -261,7 +270,13 @@ namespace Barotrauma.Particles
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!prefab.UseCollision) { return true; }
|
if (collisionIgnoreTimer > 0f)
|
||||||
|
{
|
||||||
|
collisionIgnoreTimer -= deltaTime;
|
||||||
|
if (collisionIgnoreTimer <= 0f) { currentHull ??= Hull.FindHull(position); }
|
||||||
|
return UpdateResult.Normal;
|
||||||
|
}
|
||||||
|
if (!prefab.UseCollision) { return UpdateResult.Normal; }
|
||||||
|
|
||||||
if (HighQualityCollisionDetection)
|
if (HighQualityCollisionDetection)
|
||||||
{
|
{
|
||||||
@@ -278,17 +293,17 @@ namespace Barotrauma.Particles
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return UpdateResult.Normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool CollisionUpdate()
|
private UpdateResult CollisionUpdate()
|
||||||
{
|
{
|
||||||
if (currentHull == null)
|
if (currentHull == null)
|
||||||
{
|
{
|
||||||
Hull collidedHull = Hull.FindHull(position);
|
Hull collidedHull = Hull.FindHull(position);
|
||||||
if (collidedHull != null)
|
if (collidedHull != null)
|
||||||
{
|
{
|
||||||
if (prefab.DeleteOnCollision) return false;
|
if (prefab.DeleteOnCollision) return UpdateResult.Delete;
|
||||||
OnWallCollisionOutside(collidedHull);
|
OnWallCollisionOutside(collidedHull);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -298,12 +313,12 @@ namespace Barotrauma.Particles
|
|||||||
Vector2 collisionNormal = Vector2.Zero;
|
Vector2 collisionNormal = Vector2.Zero;
|
||||||
if (velocity.Y < 0.0f && position.Y - prefab.CollisionRadius * size.Y < hullRect.Y - hullRect.Height)
|
if (velocity.Y < 0.0f && position.Y - prefab.CollisionRadius * size.Y < hullRect.Y - hullRect.Height)
|
||||||
{
|
{
|
||||||
if (prefab.DeleteOnCollision) { return false; }
|
if (prefab.DeleteOnCollision) { return UpdateResult.Delete; }
|
||||||
collisionNormal = new Vector2(0.0f, 1.0f);
|
collisionNormal = new Vector2(0.0f, 1.0f);
|
||||||
}
|
}
|
||||||
else if (velocity.Y > 0.0f && position.Y + prefab.CollisionRadius * size.Y > hullRect.Y)
|
else if (velocity.Y > 0.0f && position.Y + prefab.CollisionRadius * size.Y > hullRect.Y)
|
||||||
{
|
{
|
||||||
if (prefab.DeleteOnCollision) { return false; }
|
if (prefab.DeleteOnCollision) { return UpdateResult.Delete; }
|
||||||
collisionNormal = new Vector2(0.0f, -1.0f);
|
collisionNormal = new Vector2(0.0f, -1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -328,12 +343,12 @@ namespace Barotrauma.Particles
|
|||||||
|
|
||||||
if (velocity.X < 0.0f && position.X - prefab.CollisionRadius * size.X < hullRect.X)
|
if (velocity.X < 0.0f && position.X - prefab.CollisionRadius * size.X < hullRect.X)
|
||||||
{
|
{
|
||||||
if (prefab.DeleteOnCollision) { return false; }
|
if (prefab.DeleteOnCollision) { return UpdateResult.Delete; }
|
||||||
collisionNormal = new Vector2(1.0f, 0.0f);
|
collisionNormal = new Vector2(1.0f, 0.0f);
|
||||||
}
|
}
|
||||||
else if (velocity.X > 0.0f && position.X + prefab.CollisionRadius * size.X > hullRect.Right)
|
else if (velocity.X > 0.0f && position.X + prefab.CollisionRadius * size.X > hullRect.Right)
|
||||||
{
|
{
|
||||||
if (prefab.DeleteOnCollision) { return false; }
|
if (prefab.DeleteOnCollision) { return UpdateResult.Delete; }
|
||||||
collisionNormal = new Vector2(-1.0f, 0.0f);
|
collisionNormal = new Vector2(-1.0f, 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -374,7 +389,7 @@ namespace Barotrauma.Particles
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return UpdateResult.Normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ApplyDrag(float dragCoefficient, float deltaTime)
|
private void ApplyDrag(float dragCoefficient, float deltaTime)
|
||||||
@@ -389,10 +404,10 @@ namespace Barotrauma.Particles
|
|||||||
//TODO: some better way to handle particle drag
|
//TODO: some better way to handle particle drag
|
||||||
//this doesn't work that well because the drag vector is only updated every 0.5 seconds, allowing the particle to accelerate way more than it should
|
//this doesn't work that well because the drag vector is only updated every 0.5 seconds, allowing the particle to accelerate way more than it should
|
||||||
//(e.g. a falling particle can freely accelerate for 0.5 seconds before the drag takes effect)
|
//(e.g. a falling particle can freely accelerate for 0.5 seconds before the drag takes effect)
|
||||||
dragWait--;
|
dragWait-=deltaTime;
|
||||||
if (dragWait <= 0)
|
if (dragWait <= 0f)
|
||||||
{
|
{
|
||||||
dragWait = 30;
|
dragWait = 0.5f;
|
||||||
|
|
||||||
float speed = velocity.Length();
|
float speed = velocity.Length();
|
||||||
|
|
||||||
|
|||||||
@@ -115,12 +115,12 @@ namespace Barotrauma.Particles
|
|||||||
Prefabs.RemoveByFile(configFile);
|
Prefabs.RemoveByFile(configFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Particle CreateParticle(string prefabName, Vector2 position, float angle, float speed, Hull hullGuess = null)
|
public Particle CreateParticle(string prefabName, Vector2 position, float angle, float speed, Hull hullGuess = null, float collisionIgnoreTimer = 0f)
|
||||||
{
|
{
|
||||||
return CreateParticle(prefabName, position, new Vector2((float)Math.Cos(angle), (float)-Math.Sin(angle)) * speed, angle, hullGuess);
|
return CreateParticle(prefabName, position, new Vector2((float)Math.Cos(angle), (float)-Math.Sin(angle)) * speed, angle, hullGuess, collisionIgnoreTimer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Particle CreateParticle(string prefabName, Vector2 position, Vector2 velocity, float rotation = 0.0f, Hull hullGuess = null)
|
public Particle CreateParticle(string prefabName, Vector2 position, Vector2 velocity, float rotation = 0.0f, Hull hullGuess = null, float collisionIgnoreTimer = 0f)
|
||||||
{
|
{
|
||||||
ParticlePrefab prefab = FindPrefab(prefabName);
|
ParticlePrefab prefab = FindPrefab(prefabName);
|
||||||
|
|
||||||
@@ -130,10 +130,10 @@ namespace Barotrauma.Particles
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return CreateParticle(prefab, position, velocity, rotation, hullGuess);
|
return CreateParticle(prefab, position, velocity, rotation, hullGuess, collisionIgnoreTimer: collisionIgnoreTimer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Particle CreateParticle(ParticlePrefab prefab, Vector2 position, Vector2 velocity, float rotation = 0.0f, Hull hullGuess = null, bool drawOnTop = false)
|
public Particle CreateParticle(ParticlePrefab prefab, Vector2 position, Vector2 velocity, float rotation = 0.0f, Hull hullGuess = null, bool drawOnTop = false, float collisionIgnoreTimer = 0f)
|
||||||
{
|
{
|
||||||
if (particleCount >= MaxParticles || prefab == null || prefab.Sprites.Count == 0) { return null; }
|
if (particleCount >= MaxParticles || prefab == null || prefab.Sprites.Count == 0) { return null; }
|
||||||
|
|
||||||
@@ -149,7 +149,7 @@ namespace Barotrauma.Particles
|
|||||||
|
|
||||||
if (particles[particleCount] == null) particles[particleCount] = new Particle();
|
if (particles[particleCount] == null) particles[particleCount] = new Particle();
|
||||||
|
|
||||||
particles[particleCount].Init(prefab, position, velocity, rotation, hullGuess, drawOnTop);
|
particles[particleCount].Init(prefab, position, velocity, rotation, hullGuess, drawOnTop, collisionIgnoreTimer);
|
||||||
|
|
||||||
particleCount++;
|
particleCount++;
|
||||||
|
|
||||||
@@ -181,10 +181,10 @@ namespace Barotrauma.Particles
|
|||||||
|
|
||||||
for (int i = 0; i < particleCount; i++)
|
for (int i = 0; i < particleCount; i++)
|
||||||
{
|
{
|
||||||
bool remove = false;
|
bool remove;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
remove = !particles[i].Update(deltaTime);
|
remove = particles[i].Update(deltaTime) == Particle.UpdateResult.Delete;
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -476,6 +476,11 @@ namespace Barotrauma
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool IsAltDown()
|
||||||
|
{
|
||||||
|
return KeyDown(Keys.LeftAlt) || KeyDown(Keys.RightAlt);
|
||||||
|
}
|
||||||
|
|
||||||
public static void Update(double deltaTime)
|
public static void Update(double deltaTime)
|
||||||
{
|
{
|
||||||
timeSinceClick += deltaTime;
|
timeSinceClick += deltaTime;
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private GUIButton loadGameButton, deleteMpSaveButton;
|
private GUIButton loadGameButton, deleteMpSaveButton;
|
||||||
|
|
||||||
public Action<SubmarineInfo, string, string> StartNewGame;
|
public Action<SubmarineInfo, string, string, CampaignSettings> StartNewGame;
|
||||||
public Action<string> LoadGame;
|
public Action<string> LoadGame;
|
||||||
|
|
||||||
private enum CategoryFilter { All = 0, Vanilla = 1, Custom = 2 };
|
private enum CategoryFilter { All = 0, Vanilla = 1, Custom = 2 };
|
||||||
@@ -40,6 +40,8 @@ namespace Barotrauma
|
|||||||
get;
|
get;
|
||||||
private set;
|
private set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public GUITickBox EnableRadiationToggle { get; set; }
|
||||||
|
|
||||||
private readonly bool isMultiplayer;
|
private readonly bool isMultiplayer;
|
||||||
|
|
||||||
@@ -171,6 +173,16 @@ namespace Barotrauma
|
|||||||
string savePath = SaveUtil.CreateSavePath(isMultiplayer ? SaveUtil.SaveType.Multiplayer : SaveUtil.SaveType.Singleplayer, saveNameBox.Text);
|
string savePath = SaveUtil.CreateSavePath(isMultiplayer ? SaveUtil.SaveType.Multiplayer : SaveUtil.SaveType.Singleplayer, saveNameBox.Text);
|
||||||
bool hasRequiredContentPackages = selectedSub.RequiredContentPackagesInstalled;
|
bool hasRequiredContentPackages = selectedSub.RequiredContentPackagesInstalled;
|
||||||
|
|
||||||
|
CampaignSettings settings = new CampaignSettings();
|
||||||
|
if (isMultiplayer)
|
||||||
|
{
|
||||||
|
settings.RadiationEnabled = GameMain.NetLobbyScreen.IsRadiationEnabled();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
settings.RadiationEnabled = EnableRadiationToggle?.Selected ?? false;
|
||||||
|
}
|
||||||
|
|
||||||
if (selectedSub.HasTag(SubmarineTag.Shuttle) || !hasRequiredContentPackages)
|
if (selectedSub.HasTag(SubmarineTag.Shuttle) || !hasRequiredContentPackages)
|
||||||
{
|
{
|
||||||
if (!hasRequiredContentPackages)
|
if (!hasRequiredContentPackages)
|
||||||
@@ -184,7 +196,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (GUIMessageBox.MessageBoxes.Count == 0)
|
if (GUIMessageBox.MessageBoxes.Count == 0)
|
||||||
{
|
{
|
||||||
StartNewGame?.Invoke(selectedSub, savePath, seedBox.Text);
|
StartNewGame?.Invoke(selectedSub, savePath, seedBox.Text, settings);
|
||||||
if (isMultiplayer)
|
if (isMultiplayer)
|
||||||
{
|
{
|
||||||
CoroutineManager.StartCoroutine(WaitForCampaignSetup(), "WaitForCampaignSetup");
|
CoroutineManager.StartCoroutine(WaitForCampaignSetup(), "WaitForCampaignSetup");
|
||||||
@@ -204,7 +216,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
msgBox.Buttons[0].OnClicked = (button, obj) =>
|
msgBox.Buttons[0].OnClicked = (button, obj) =>
|
||||||
{
|
{
|
||||||
StartNewGame?.Invoke(selectedSub, savePath, seedBox.Text);
|
StartNewGame?.Invoke(selectedSub, savePath, seedBox.Text, settings);
|
||||||
if (isMultiplayer)
|
if (isMultiplayer)
|
||||||
{
|
{
|
||||||
CoroutineManager.StartCoroutine(WaitForCampaignSetup(), "WaitForCampaignSetup");
|
CoroutineManager.StartCoroutine(WaitForCampaignSetup(), "WaitForCampaignSetup");
|
||||||
@@ -219,7 +231,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
StartNewGame?.Invoke(selectedSub, savePath, seedBox.Text);
|
StartNewGame?.Invoke(selectedSub, savePath, seedBox.Text, settings);
|
||||||
if (isMultiplayer)
|
if (isMultiplayer)
|
||||||
{
|
{
|
||||||
CoroutineManager.StartCoroutine(WaitForCampaignSetup(), "WaitForCampaignSetup");
|
CoroutineManager.StartCoroutine(WaitForCampaignSetup(), "WaitForCampaignSetup");
|
||||||
@@ -230,8 +242,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
InitialMoneyText = new GUITextBlock(new RectTransform(new Vector2(0.6f, 1f), buttonContainer.RectTransform), "",
|
InitialMoneyText = new GUITextBlock(new RectTransform(new Vector2(isMultiplayer ? 0.6f : 0.3f, 1f), buttonContainer.RectTransform), "", font: isMultiplayer ? GUI.Style.SmallFont : GUI.Style.Font, textColor: GUI.Style.Green)
|
||||||
font: isMultiplayer ? GUI.Style.SmallFont : GUI.Style.Font, textColor: GUI.Style.Green)
|
|
||||||
{
|
{
|
||||||
TextGetter = () =>
|
TextGetter = () =>
|
||||||
{
|
{
|
||||||
@@ -254,6 +265,15 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (!isMultiplayer)
|
if (!isMultiplayer)
|
||||||
{
|
{
|
||||||
|
if (MapGenerationParams.Instance.RadiationParams != null)
|
||||||
|
{
|
||||||
|
EnableRadiationToggle = new GUITickBox(new RectTransform(new Vector2(0.3f, 1f), buttonContainer.RectTransform), TextManager.Get("CampaignOption.EnableRadiation"), font: GUI.Style.Font)
|
||||||
|
{
|
||||||
|
Selected = true,
|
||||||
|
ToolTip = TextManager.Get("campaignoption.enableradiation.tooltip")
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
var disclaimerBtn = new GUIButton(new RectTransform(new Vector2(1.0f, 0.8f), rightColumn.RectTransform, Anchor.TopRight) { AbsoluteOffset = new Point(5) }, style: "GUINotificationButton")
|
var disclaimerBtn = new GUIButton(new RectTransform(new Vector2(1.0f, 0.8f), rightColumn.RectTransform, Anchor.TopRight) { AbsoluteOffset = new Point(5) }, style: "GUINotificationButton")
|
||||||
{
|
{
|
||||||
IgnoreLayoutGroups = true,
|
IgnoreLayoutGroups = true,
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ namespace Barotrauma
|
|||||||
campaign.Map.OnLocationSelected += SelectLocation;
|
campaign.Map.OnLocationSelected += SelectLocation;
|
||||||
campaign.Map.OnMissionSelected += (connection, mission) =>
|
campaign.Map.OnMissionSelected += (connection, mission) =>
|
||||||
{
|
{
|
||||||
missionList.Select(mission);
|
missionList?.Select(mission);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -306,7 +306,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
var map = GameMain.GameSession?.Map;
|
var map = GameMain.GameSession?.Map;
|
||||||
if (map == null) { return; }
|
if (map == null) { return; }
|
||||||
if (selectedLocation != null && selectedLocation == map.CurrentDisplayLocation)
|
if (selectedLocation != null && selectedLocation == GameMain.GameSession.Campaign.GetCurrentDisplayLocation())
|
||||||
{
|
{
|
||||||
map.SelectLocation(-1);
|
map.SelectLocation(-1);
|
||||||
}
|
}
|
||||||
@@ -394,6 +394,42 @@ namespace Barotrauma
|
|||||||
var difficultyLabel = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), textContent.RectTransform),
|
var difficultyLabel = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), textContent.RectTransform),
|
||||||
TextManager.Get("LevelDifficulty"), font: GUI.SubHeadingFont, textAlignment: Alignment.CenterLeft);
|
TextManager.Get("LevelDifficulty"), font: GUI.SubHeadingFont, textAlignment: Alignment.CenterLeft);
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 1.0f), difficultyLabel.RectTransform), ((int)connection.LevelData.Difficulty) + " %", textAlignment: Alignment.CenterRight);
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 1.0f), difficultyLabel.RectTransform), ((int)connection.LevelData.Difficulty) + " %", textAlignment: Alignment.CenterRight);
|
||||||
|
|
||||||
|
if (connection.LevelData.HasBeaconStation)
|
||||||
|
{
|
||||||
|
var beaconStationContent = new GUILayoutGroup(new RectTransform(biomeLabel.RectTransform.NonScaledSize, textContent.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft);
|
||||||
|
string style = connection.LevelData.IsBeaconActive ? "BeaconStationActive" : "BeaconStationInactive";
|
||||||
|
var icon = new GUIImage(new RectTransform(new Point((int)(beaconStationContent.Rect.Height * 1.2f)), beaconStationContent.RectTransform),
|
||||||
|
style, scaleToFit: true)
|
||||||
|
{
|
||||||
|
Color = MapGenerationParams.Instance.IndicatorColor,
|
||||||
|
HoverColor = Color.Lerp(MapGenerationParams.Instance.IndicatorColor, Color.White, 0.5f),
|
||||||
|
ToolTip = TextManager.Get(connection.LevelData.IsBeaconActive ? "BeaconStationActiveTooltip" : "BeaconStationInactiveTooltip")
|
||||||
|
};
|
||||||
|
new GUITextBlock(new RectTransform(Vector2.One, beaconStationContent.RectTransform),
|
||||||
|
TextManager.Get("submarinetype.beaconstation"), font: GUI.SubHeadingFont, textAlignment: Alignment.CenterLeft)
|
||||||
|
{
|
||||||
|
Padding = Vector4.Zero,
|
||||||
|
ToolTip = icon.ToolTip
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (connection.LevelData.HasHuntingGrounds)
|
||||||
|
{
|
||||||
|
var huntingGroundsContent = new GUILayoutGroup(new RectTransform(biomeLabel.RectTransform.NonScaledSize, textContent.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft);
|
||||||
|
var icon = new GUIImage(new RectTransform(new Point((int)(huntingGroundsContent.Rect.Height * 1.5f)), huntingGroundsContent.RectTransform),
|
||||||
|
"HuntingGrounds", scaleToFit: true)
|
||||||
|
{
|
||||||
|
Color = MapGenerationParams.Instance.IndicatorColor,
|
||||||
|
HoverColor = Color.Lerp(MapGenerationParams.Instance.IndicatorColor, Color.White, 0.5f),
|
||||||
|
ToolTip = TextManager.Get("HuntingGroundsTooltip")
|
||||||
|
};
|
||||||
|
new GUITextBlock(new RectTransform(Vector2.One, huntingGroundsContent.RectTransform),
|
||||||
|
TextManager.Get("missionname.huntinggrounds"), font: GUI.SubHeadingFont, textAlignment: Alignment.CenterLeft)
|
||||||
|
{
|
||||||
|
Padding = Vector4.Zero,
|
||||||
|
ToolTip = icon.ToolTip
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
missionList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.4f), content.RectTransform))
|
missionList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.4f), content.RectTransform))
|
||||||
@@ -402,7 +438,7 @@ namespace Barotrauma
|
|||||||
};
|
};
|
||||||
|
|
||||||
SelectedLevel = connection?.LevelData;
|
SelectedLevel = connection?.LevelData;
|
||||||
Location currentDisplayLocation = Campaign.CurrentDisplayLocation;
|
Location currentDisplayLocation = Campaign.GetCurrentDisplayLocation();
|
||||||
if (connection != null && connection.Locations.Contains(currentDisplayLocation))
|
if (connection != null && connection.Locations.Contains(currentDisplayLocation))
|
||||||
{
|
{
|
||||||
List<Mission> availableMissions = currentDisplayLocation.GetMissionsInConnection(connection).ToList();
|
List<Mission> availableMissions = currentDisplayLocation.GetMissionsInConnection(connection).ToList();
|
||||||
@@ -437,11 +473,44 @@ namespace Barotrauma
|
|||||||
SelectedColor = MapGenerationParams.Instance.IndicatorColor,
|
SelectedColor = MapGenerationParams.Instance.IndicatorColor,
|
||||||
HoverColor = Color.Lerp(MapGenerationParams.Instance.IndicatorColor, Color.White, 0.5f)
|
HoverColor = Color.Lerp(MapGenerationParams.Instance.IndicatorColor, Color.White, 0.5f)
|
||||||
};
|
};
|
||||||
missionName.Padding = new Vector4(missionName.Padding.X + icon.Rect.Width * 1.5f, missionName.Padding.Y, missionName.Padding.Z, missionName.Padding.W);
|
icon.RectTransform.IsFixedSize = true;
|
||||||
|
|
||||||
|
GUILayoutGroup difficultyIndicatorGroup = null;
|
||||||
|
if (mission.Difficulty.HasValue)
|
||||||
|
{
|
||||||
|
difficultyIndicatorGroup = new GUILayoutGroup(new RectTransform(Vector2.One * 0.9f, missionName.RectTransform, anchor: Anchor.CenterRight, scaleBasis: ScaleBasis.Smallest) { AbsoluteOffset = new Point((int)missionName.Padding.Z, 0) },
|
||||||
|
isHorizontal: true, childAnchor: Anchor.CenterRight)
|
||||||
|
{
|
||||||
|
AbsoluteSpacing = 1,
|
||||||
|
UserData = "difficulty"
|
||||||
|
};
|
||||||
|
var difficultyColor = mission.GetDifficultyColor();
|
||||||
|
for (int i = 0; i < mission.Difficulty; i++)
|
||||||
|
{
|
||||||
|
new GUIImage(new RectTransform(Vector2.One, difficultyIndicatorGroup.RectTransform, scaleBasis: ScaleBasis.Smallest) { IsFixedSize = true }, "DifficultyIndicator", scaleToFit: true)
|
||||||
|
{
|
||||||
|
Color = difficultyColor * 0.5f,
|
||||||
|
SelectedColor = difficultyColor,
|
||||||
|
HoverColor = Color.Lerp(difficultyColor, Color.White, 0.5f)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float extraPadding = 0.5f * icon.Rect.Width;
|
||||||
|
float extraZPadding = difficultyIndicatorGroup != null ? mission.Difficulty.Value * (difficultyIndicatorGroup.Children.First().Rect.Width + difficultyIndicatorGroup.AbsoluteSpacing) : 0;
|
||||||
|
missionName.Padding = new Vector4(missionName.Padding.X + icon.Rect.Width + extraPadding,
|
||||||
|
missionName.Padding.Y,
|
||||||
|
missionName.Padding.Z + extraZPadding + extraPadding,
|
||||||
|
missionName.Padding.W);
|
||||||
|
missionName.CalculateHeightFromText();
|
||||||
}
|
}
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform),
|
|
||||||
TextManager.GetWithVariable("missionreward", "[reward]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", mission.Reward)), wrap: true);
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform), mission.GetMissionRewardText(), wrap: true, parseRichText: true);
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform), mission.Description, wrap: true);
|
|
||||||
|
string reputationText = mission.GetReputationRewardText(mission.Locations[0]);
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform), reputationText, wrap: true, parseRichText: true);
|
||||||
|
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform), mission.Description, wrap: true, parseRichText: true);
|
||||||
}
|
}
|
||||||
missionPanel.RectTransform.MinSize = new Point(0, (int)(missionTextContent.Children.Sum(c => c.Rect.Height) / missionTextContent.RectTransform.RelativeSize.Y) + GUI.IntScale(20));
|
missionPanel.RectTransform.MinSize = new Point(0, (int)(missionTextContent.Children.Sum(c => c.Rect.Height) / missionTextContent.RectTransform.RelativeSize.Y) + GUI.IntScale(20));
|
||||||
foreach (GUIComponent child in missionTextContent.Children)
|
foreach (GUIComponent child in missionTextContent.Children)
|
||||||
@@ -454,6 +523,10 @@ namespace Barotrauma
|
|||||||
missionPanel.OnAddedToGUIUpdateList = (c) =>
|
missionPanel.OnAddedToGUIUpdateList = (c) =>
|
||||||
{
|
{
|
||||||
missionTextContent.Children.ForEach(child => child.State = c.State);
|
missionTextContent.Children.ForEach(child => child.State = c.State);
|
||||||
|
if (missionTextContent.FindChild("difficulty", recursive: true) is GUILayoutGroup group)
|
||||||
|
{
|
||||||
|
group.State = c.State;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (mission != availableMissions.Last())
|
if (mission != availableMissions.Last())
|
||||||
@@ -491,7 +564,25 @@ namespace Barotrauma
|
|||||||
StartButton = new GUIButton(new RectTransform(new Vector2(0.5f, 0.1f), content.RectTransform),
|
StartButton = new GUIButton(new RectTransform(new Vector2(0.5f, 0.1f), content.RectTransform),
|
||||||
TextManager.Get("StartCampaignButton"), style: "GUIButtonLarge")
|
TextManager.Get("StartCampaignButton"), style: "GUIButtonLarge")
|
||||||
{
|
{
|
||||||
OnClicked = (GUIButton btn, object obj) => { StartRound?.Invoke(); return true; },
|
OnClicked = (GUIButton btn, object obj) =>
|
||||||
|
{
|
||||||
|
if (missionList.Content.Children.Any(c => c.UserData is Mission) && !(missionList.SelectedData is Mission))
|
||||||
|
{
|
||||||
|
var noMissionVerification = new GUIMessageBox(string.Empty, TextManager.Get("nomissionprompt"), new string[] { TextManager.Get("yes"), TextManager.Get("no") });
|
||||||
|
noMissionVerification.Buttons[0].OnClicked = (btn, userdata) =>
|
||||||
|
{
|
||||||
|
StartRound?.Invoke();
|
||||||
|
noMissionVerification.Close();
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
noMissionVerification.Buttons[1].OnClicked = noMissionVerification.Close;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
StartRound?.Invoke();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
Enabled = true,
|
Enabled = true,
|
||||||
Visible = Campaign.AllowedToEndRound()
|
Visible = Campaign.AllowedToEndRound()
|
||||||
};
|
};
|
||||||
@@ -507,6 +598,11 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public void SelectTab(CampaignMode.InteractionType tab)
|
public void SelectTab(CampaignMode.InteractionType tab)
|
||||||
{
|
{
|
||||||
|
if (Campaign.ShowCampaignUI || (Campaign.ForceMapUI && tab == CampaignMode.InteractionType.Map))
|
||||||
|
{
|
||||||
|
HintManager.OnShowCampaignInterface(tab);
|
||||||
|
}
|
||||||
|
|
||||||
selectedTab = tab;
|
selectedTab = tab;
|
||||||
for (int i = 0; i < tabs.Length; i++)
|
for (int i = 0; i < tabs.Length; i++)
|
||||||
{
|
{
|
||||||
|
|||||||
+4
-4
@@ -711,7 +711,7 @@ namespace Barotrauma.CharacterEditor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Camera
|
// Camera
|
||||||
Cam.MoveCamera((float)deltaTime, allowMove: false);
|
Cam.MoveCamera((float)deltaTime, allowMove: false, allowZoom: GUI.MouseOn == null);
|
||||||
Vector2 targetPos = character.WorldPosition;
|
Vector2 targetPos = character.WorldPosition;
|
||||||
if (PlayerInput.MidButtonHeld())
|
if (PlayerInput.MidButtonHeld())
|
||||||
{
|
{
|
||||||
@@ -766,7 +766,7 @@ namespace Barotrauma.CharacterEditor
|
|||||||
if (editLimbs && !spriteSheetRect.Contains(PlayerInput.MousePosition) &&
|
if (editLimbs && !spriteSheetRect.Contains(PlayerInput.MousePosition) &&
|
||||||
MathUtils.RectangleContainsPoint(GetLimbPhysicRect(limb), PlayerInput.MousePosition)) { return CursorState.Hand; }
|
MathUtils.RectangleContainsPoint(GetLimbPhysicRect(limb), PlayerInput.MousePosition)) { return CursorState.Hand; }
|
||||||
// spritesheet
|
// spritesheet
|
||||||
if (GetLimbSpritesheetRect(limb).Contains(PlayerInput.MousePosition)) { return CursorState.Hand; }
|
if (showSpritesheet && GetLimbSpritesheetRect(limb).Contains(PlayerInput.MousePosition)) { return CursorState.Hand; }
|
||||||
}
|
}
|
||||||
return CursorState.Default;
|
return CursorState.Default;
|
||||||
}
|
}
|
||||||
@@ -1761,9 +1761,9 @@ namespace Barotrauma.CharacterEditor
|
|||||||
#endif
|
#endif
|
||||||
// Add to the selected content package
|
// Add to the selected content package
|
||||||
contentPackage.AddFile(configFilePath, ContentType.Character);
|
contentPackage.AddFile(configFilePath, ContentType.Character);
|
||||||
Barotrauma.IO.Validation.DevException = true;
|
Barotrauma.IO.Validation.SkipValidationInDebugBuilds = true;
|
||||||
contentPackage.Save(contentPackage.Path);
|
contentPackage.Save(contentPackage.Path);
|
||||||
Barotrauma.IO.Validation.DevException = false;
|
Barotrauma.IO.Validation.SkipValidationInDebugBuilds = false;
|
||||||
DebugConsole.NewMessage(GetCharacterEditorTranslation("ContentPackageSaved").Replace("[path]", contentPackage.Path));
|
DebugConsole.NewMessage(GetCharacterEditorTranslation("ContentPackageSaved").Replace("[path]", contentPackage.Path));
|
||||||
|
|
||||||
// Ragdoll
|
// Ragdoll
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user